aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Frontend/CompilerInvocation.cpp
diff options
context:
space:
mode:
authorJan Svoboda <jan_svoboda@apple.com>2021-02-25 09:05:08 +0100
committerJan Svoboda <jan_svoboda@apple.com>2021-02-25 11:02:49 +0100
commita25e4a6da3fe43f631782b1668e0ac023f6b5848 (patch)
treefcbd71e7d327272b027afd514c6a078b0321c3d3 /clang/lib/Frontend/CompilerInvocation.cpp
parent30cb9c03b53ee03af2cdf16f4ee645e5dcff7e21 (diff)
downloadllvm-a25e4a6da3fe43f631782b1668e0ac023f6b5848.zip
llvm-a25e4a6da3fe43f631782b1668e0ac023f6b5848.tar.gz
llvm-a25e4a6da3fe43f631782b1668e0ac023f6b5848.tar.bz2
[clang][cli] Store additional optimization remarks info
After a revision of D96274 changed `DiagnosticOptions` to not store all remark arguments **as-written**, it is no longer possible to reconstruct the arguments accurately from the class. This is caused by the fact that for `-Rpass=regexp` and friends, `DiagnosticOptions` store only the group name `pass` and not `regexp`. This is the same representation used for the plain `-Rpass` argument. Note that each argument must be generated exactly once in `CompilerInvocation::generateCC1CommandLine`, otherwise each subsequent call would produce more arguments than the previous one. Currently this works out because of the way `RoundTrip` splits the responsibilities for certain arguments based on what arguments were queried during parsing. However, this invariant breaks when we move to single round-trip for the whole `CompilerInvocation`. This patch ensures that for one `-Rpass=regexp` argument, we don't generate two arguments (`-Rpass` from `DiagnosticOptions` and `-Rpass=regexp` from `CodeGenOptions`) by shifting the responsibility for handling both cases to `CodeGenOptions`. To distinguish between the cases correctly, additional information is stored in `CodeGenOptions`. The `CodeGenOptions` parser of `-Rpass[=regexp]` arguments also looks at `-Rno-pass` and `-R[no-]everything`, which is necessary for generating the correct argument regardless of the ordering of `CodeGenOptions`/`DiagnosticOptions` parsing/generation. Reviewed By: dexonsmith Differential Revision: https://reviews.llvm.org/D96847
Diffstat (limited to 'clang/lib/Frontend/CompilerInvocation.cpp')
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp127
1 files changed, 89 insertions, 38 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index b640981..20ac510 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1162,20 +1162,69 @@ static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
<< "a filename";
}
-/// Create a new Regex instance out of the string value in \p RpassArg.
-/// It returns the string and a pointer to the newly generated Regex instance.
-static CodeGenOptions::RemarkPattern
-GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args,
- Arg *RpassArg) {
- StringRef Val = RpassArg->getValue();
- std::string RegexError;
- std::shared_ptr<llvm::Regex> Pattern = std::make_shared<llvm::Regex>(Val);
- if (!Pattern->isValid(RegexError)) {
- Diags.Report(diag::err_drv_optimization_remark_pattern)
- << RegexError << RpassArg->getAsString(Args);
- Pattern.reset();
- }
- return {std::string(Val), Pattern};
+/// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`.
+static void
+GenerateOptimizationRemark(SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA,
+ OptSpecifier OptEQ, StringRef Name,
+ const CodeGenOptions::OptRemark &Remark) {
+ if (Remark.hasValidPattern()) {
+ GenerateArg(Args, OptEQ, Remark.Pattern, SA);
+ } else if (Remark.Kind == CodeGenOptions::RK_Enabled) {
+ GenerateArg(Args, OPT_R_Joined, Name, SA);
+ } else if (Remark.Kind == CodeGenOptions::RK_Disabled) {
+ GenerateArg(Args, OPT_R_Joined, StringRef("no-") + Name, SA);
+ }
+};
+
+/// Parse a remark command line argument. It may be missing, disabled/enabled by
+/// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'.
+/// On top of that, it can be disabled/enabled globally by '-R[no-]everything'.
+static CodeGenOptions::OptRemark
+ParseOptimizationRemark(DiagnosticsEngine &Diags, ArgList &Args,
+ OptSpecifier OptEQ, StringRef Name) {
+ CodeGenOptions::OptRemark Result;
+
+ auto InitializeResultPattern = [&Diags, &Args, &Result](const Arg *A) {
+ Result.Pattern = A->getValue();
+
+ std::string RegexError;
+ Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern);
+ if (!Result.Regex->isValid(RegexError)) {
+ Diags.Report(diag::err_drv_optimization_remark_pattern)
+ << RegexError << A->getAsString(Args);
+ return false;
+ }
+
+ return true;
+ };
+
+ for (Arg *A : Args) {
+ if (A->getOption().matches(OPT_R_Joined)) {
+ StringRef Value = A->getValue();
+
+ if (Value == Name)
+ Result.Kind = CodeGenOptions::RK_Enabled;
+ else if (Value == "everything")
+ Result.Kind = CodeGenOptions::RK_EnabledEverything;
+ else if (Value.split('-') == std::make_pair(StringRef("no"), Name))
+ Result.Kind = CodeGenOptions::RK_Disabled;
+ else if (Value == "no-everything")
+ Result.Kind = CodeGenOptions::RK_DisabledEverything;
+ } else if (A->getOption().matches(OptEQ)) {
+ Result.Kind = CodeGenOptions::RK_WithPattern;
+ if (!InitializeResultPattern(A))
+ return CodeGenOptions::OptRemark();
+ }
+ }
+
+ if (Result.Kind == CodeGenOptions::RK_Disabled ||
+ Result.Kind == CodeGenOptions::RK_DisabledEverything) {
+ Result.Pattern = "";
+ Result.Regex = nullptr;
+ }
+
+ return Result;
}
static bool parseDiagnosticLevelMask(StringRef FlagName,
@@ -1480,16 +1529,14 @@ void CompilerInvocation::GenerateCodeGenArgs(
if (!Opts.OptRecordFormat.empty())
GenerateArg(Args, OPT_opt_record_format, Opts.OptRecordFormat, SA);
- if (Opts.OptimizationRemarkPattern)
- GenerateArg(Args, OPT_Rpass_EQ, Opts.OptimizationRemarkPattern.Pattern, SA);
+ GenerateOptimizationRemark(Args, SA, OPT_Rpass_EQ, "pass",
+ Opts.OptimizationRemark);
- if (Opts.OptimizationRemarkMissedPattern)
- GenerateArg(Args, OPT_Rpass_missed_EQ,
- Opts.OptimizationRemarkMissedPattern.Pattern, SA);
+ GenerateOptimizationRemark(Args, SA, OPT_Rpass_missed_EQ, "pass-missed",
+ Opts.OptimizationRemarkMissed);
- if (Opts.OptimizationRemarkAnalysisPattern)
- GenerateArg(Args, OPT_Rpass_analysis_EQ,
- Opts.OptimizationRemarkAnalysisPattern.Pattern, SA);
+ GenerateOptimizationRemark(Args, SA, OPT_Rpass_analysis_EQ, "pass-analysis",
+ Opts.OptimizationRemarkAnalysis);
GenerateArg(Args, OPT_fdiagnostics_hotness_threshold_EQ,
Opts.DiagnosticsHotnessThreshold
@@ -1853,23 +1900,18 @@ bool CompilerInvocation::ParseCodeGenArgsImpl(CodeGenOptions &Opts,
NeedLocTracking = true;
}
- if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
- Opts.OptimizationRemarkPattern =
- GenerateOptimizationRemarkRegex(Diags, Args, A);
- NeedLocTracking = true;
- }
+ Opts.OptimizationRemark =
+ ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass");
- if (Arg *A = Args.getLastArg(OPT_Rpass_missed_EQ)) {
- Opts.OptimizationRemarkMissedPattern =
- GenerateOptimizationRemarkRegex(Diags, Args, A);
- NeedLocTracking = true;
- }
+ Opts.OptimizationRemarkMissed =
+ ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed");
- if (Arg *A = Args.getLastArg(OPT_Rpass_analysis_EQ)) {
- Opts.OptimizationRemarkAnalysisPattern =
- GenerateOptimizationRemarkRegex(Diags, Args, A);
- NeedLocTracking = true;
- }
+ Opts.OptimizationRemarkAnalysis = ParseOptimizationRemark(
+ Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis");
+
+ NeedLocTracking |= Opts.OptimizationRemark.hasValidPattern() ||
+ Opts.OptimizationRemarkMissed.hasValidPattern() ||
+ Opts.OptimizationRemarkAnalysis.hasValidPattern();
bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
bool UsingProfile = UsingSampleProfile ||
@@ -2288,8 +2330,17 @@ void CompilerInvocation::GenerateDiagnosticArgs(
Args.push_back(SA(StringRef("-W") + Warning));
}
- for (const auto &Remark : Opts.Remarks)
+ for (const auto &Remark : Opts.Remarks) {
+ // These arguments are generated from OptimizationRemark fields of
+ // CodeGenOptions.
+ StringRef IgnoredRemarks[] = {"pass", "no-pass",
+ "pass-analysis", "no-pass-analysis",
+ "pass-missed", "no-pass-missed"};
+ if (llvm::is_contained(IgnoredRemarks, Remark))
+ continue;
+
Args.push_back(SA(StringRef("-R") + Remark));
+ }
}
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,