diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -284,6 +284,15 @@ /// -fsymbol-partition (see https://lld.llvm.org/Partitions.html). std::string SymbolPartition; + enum RemarkKind { + RK_Missing, // Remark argument not present on the command line. + RK_Enabled, // Remark enabled via '-Rgroup'. + RK_EnabledEverything, // Remark enabled via '-Reverything'. + RK_Disabled, // Remark disabled via '-Rno-group'. + RK_DisabledEverything, // Remark disabled via '-Rno-everything'. + RK_Pattern, // Remark pattern specified via '-Rgroup=regexp'. + }; + /// Regular expression and the string it was created from. struct RemarkPattern { std::string Pattern; @@ -294,6 +303,8 @@ llvm::Regex *operator->() const { return Regex.get(); } }; + // The kind of optimization remark argument on the command line. + RemarkKind OptimizationRemarkKind; /// Regular expression to select optimizations for which we should enable /// optimization remarks. Transformation passes whose name matches this /// expression (and support this feature), will emit a diagnostic @@ -301,6 +312,8 @@ /// -Rpass=regexp flag. RemarkPattern OptimizationRemarkPattern; + // The kind of missed optimization remark argument on the command line. + RemarkKind OptimizationRemarkMissedKind; /// Regular expression to select optimizations for which we should enable /// missed optimization remarks. Transformation passes whose name matches this /// expression (and support this feature), will emit a diagnostic @@ -308,6 +321,8 @@ /// enabled by the -Rpass-missed=regexp flag. RemarkPattern OptimizationRemarkMissedPattern; + // The kind of optimization analyses remark argument on the command line. + RemarkKind OptimizationRemarkAnalysisKind; /// Regular expression to select optimizations for which we should enable /// optimization analyses. Transformation passes whose name matches this /// expression (and support this feature), will emit a diagnostic diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1162,20 +1162,70 @@ << "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 Pattern = std::make_shared(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 &Args, CompilerInvocation::StringAllocator SA, + OptSpecifier OptEQ, StringRef Name, const CodeGenOptions::RemarkKind &Kind, + const CodeGenOptions::RemarkPattern &Pattern) { + if (Pattern) { + GenerateArg(Args, OptEQ, Pattern.Pattern, SA); + } else if (Kind == CodeGenOptions::RK_Enabled) { + GenerateArg(Args, OPT_R_Joined, Name, SA); + } else if (Kind == CodeGenOptions::RK_Disabled) { + GenerateArg(Args, OPT_R_Joined, StringRef("no-") + Name, SA); + } +}; + +/// Parse a remark command line argument. It may be missing, disabled via +/// '-Rno-group', enabled via '-Rgroup' or specified with a regular expression +/// via '-Rgroup=regexp'. On top of that, it can be disabled/enabled globally by +/// '-R[no-]everything'. The \p Kind and \p Pattern are initialized accordingly. +static void ParseOptimizationRemark(DiagnosticsEngine &Diags, ArgList &Args, + OptSpecifier OptEQ, StringRef Name, + CodeGenOptions::RemarkKind &Kind, + CodeGenOptions::RemarkPattern &Pattern) { + auto InitializePattern = + [&Diags, &Args](const Arg *A, CodeGenOptions::RemarkPattern &Pattern) { + StringRef Value = A->getValue(); + std::string RegexError; + auto Regex = std::make_shared(Value); + + if (!Regex->isValid(RegexError)) { + Diags.Report(diag::err_drv_optimization_remark_pattern) + << RegexError << A->getAsString(Args); + return false; + } + + Pattern = CodeGenOptions::RemarkPattern{std::string(Value), Regex}; + return true; + }; + + CodeGenOptions::RemarkPattern ParsedPattern; + + Kind = CodeGenOptions::RK_Missing; + + for (Arg *A : Args) { + if (A->getOption().matches(OPT_R_Joined)) { + StringRef Value = A->getValue(); + + if (Value == Name) + Kind = CodeGenOptions::RK_Enabled; + else if (Value == "everything") + Kind = CodeGenOptions::RK_EnabledEverything; + else if (Value.split('-') == std::make_pair(StringRef("no"), Name)) + Kind = CodeGenOptions::RK_Disabled; + else if (Value == "no-everything") + Kind = CodeGenOptions::RK_DisabledEverything; + } else if (A->getOption().matches(OptEQ)) { + Kind = CodeGenOptions::RK_Pattern; + if (!InitializePattern(A, ParsedPattern)) + return; + } + } + + if (ParsedPattern && Kind != CodeGenOptions::RK_Disabled && + Kind != CodeGenOptions::RK_DisabledEverything) + Pattern = ParsedPattern; } static bool parseDiagnosticLevelMask(StringRef FlagName, @@ -1484,16 +1534,17 @@ 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.OptimizationRemarkKind, + Opts.OptimizationRemarkPattern); - if (Opts.OptimizationRemarkMissedPattern) - GenerateArg(Args, OPT_Rpass_missed_EQ, - Opts.OptimizationRemarkMissedPattern.Pattern, SA); + GenerateOptimizationRemark(Args, SA, OPT_Rpass_missed_EQ, "pass-missed", + Opts.OptimizationRemarkMissedKind, + Opts.OptimizationRemarkMissedPattern); - if (Opts.OptimizationRemarkAnalysisPattern) - GenerateArg(Args, OPT_Rpass_analysis_EQ, - Opts.OptimizationRemarkAnalysisPattern.Pattern, SA); + GenerateOptimizationRemark(Args, SA, OPT_Rpass_analysis_EQ, "pass-analysis", + Opts.OptimizationRemarkAnalysisKind, + Opts.OptimizationRemarkAnalysisPattern); GenerateArg(Args, OPT_fdiagnostics_hotness_threshold_EQ, Opts.DiagnosticsHotnessThreshold @@ -1862,23 +1913,21 @@ NeedLocTracking = true; } - if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) { - Opts.OptimizationRemarkPattern = - GenerateOptimizationRemarkRegex(Diags, Args, A); - NeedLocTracking = true; - } + ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass", + Opts.OptimizationRemarkKind, + Opts.OptimizationRemarkPattern); - if (Arg *A = Args.getLastArg(OPT_Rpass_missed_EQ)) { - Opts.OptimizationRemarkMissedPattern = - GenerateOptimizationRemarkRegex(Diags, Args, A); - NeedLocTracking = true; - } + ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed", + Opts.OptimizationRemarkMissedKind, + Opts.OptimizationRemarkMissedPattern); - if (Arg *A = Args.getLastArg(OPT_Rpass_analysis_EQ)) { - Opts.OptimizationRemarkAnalysisPattern = - GenerateOptimizationRemarkRegex(Diags, Args, A); - NeedLocTracking = true; - } + ParseOptimizationRemark(Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis", + Opts.OptimizationRemarkAnalysisKind, + Opts.OptimizationRemarkAnalysisPattern); + + NeedLocTracking |= Opts.OptimizationRemarkPattern || + Opts.OptimizationRemarkMissedPattern || + Opts.OptimizationRemarkAnalysisPattern; bool UsingSampleProfile = !Opts.SampleProfileFile.empty(); bool UsingProfile = UsingSampleProfile || @@ -2297,8 +2346,17 @@ 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,