llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-flang-driver Author: Tarun Prabhu (tarunprabhu) <details> <summary>Changes</summary> The underlying issue was caused by a file included in two different places which resulted in duplicate definition errors when linking individual shared libraries. This was fixed in c3201ddaeac02a2c86a38b [#<!-- -->109874]. ----------------------- Notes for reviewers: The only difference between this and #<!-- -->102975 is [`bbc/CMakeLists.txt`](https://github.com/llvm/llvm-project/compare/main...llvm-project-tlp:llvm-project:add-llvm-command-metadata?expand=1#diff-0c2fe0dc0aa6db98b75d8962d82094f5d592aca6bcc5d363db71be20899f3a97). --- Patch is 28.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110132.diff 23 Files Affected: - (modified) clang/include/clang/Driver/Options.td (+8-6) - (modified) clang/lib/Driver/ToolChains/Clang.cpp (+6-45) - (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+59) - (modified) clang/lib/Driver/ToolChains/CommonArgs.h (+25) - (modified) clang/lib/Driver/ToolChains/Flang.cpp (+14) - (modified) flang/include/flang/Frontend/CodeGenOptions.h (+3) - (modified) flang/include/flang/Lower/Bridge.h (+9-3) - (modified) flang/include/flang/Optimizer/Dialect/Support/FIRContext.h (+6) - (modified) flang/lib/Frontend/CompilerInvocation.cpp (+6) - (modified) flang/lib/Frontend/FrontendActions.cpp (+1-1) - (modified) flang/lib/Lower/Bridge.cpp (+6-2) - (modified) flang/lib/Optimizer/Dialect/Support/FIRContext.cpp (+16) - (added) flang/test/Driver/frecord-command-line.f90 (+16) - (added) flang/test/Lower/record-command-line.f90 (+9) - (modified) flang/tools/bbc/CMakeLists.txt (+1) - (modified) flang/tools/bbc/bbc.cpp (+4-2) - (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td (+1) - (modified) mlir/include/mlir/Target/LLVMIR/ModuleImport.h (+4) - (modified) mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h (+3) - (modified) mlir/lib/Target/LLVMIR/ModuleImport.cpp (+19) - (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+17) - (added) mlir/test/Target/LLVMIR/Import/commandline.ll (+6) - (added) mlir/test/Target/LLVMIR/commandline.mlir (+6) ``````````diff diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 23bd686a85f526..a905b355e368d3 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1994,16 +1994,18 @@ def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group<f_clang_Grou Visibility<[ClangOption, CC1Option]>, MarshallingInfoFlag<LangOpts<"CommentOpts.ParseAllComments">>; def frecord_command_line : Flag<["-"], "frecord-command-line">, - DocBrief<[{Generate a section named ".GCC.command.line" containing the clang + DocBrief<[{Generate a section named ".GCC.command.line" containing the driver command-line. After linking, the section may contain multiple command lines, which will be individually terminated by null bytes. Separate arguments within a command line are combined with spaces; spaces and backslashes within an argument are escaped with backslashes. This format differs from the format of the equivalent section produced by GCC with the -frecord-gcc-switches flag. This option is currently only supported on ELF targets.}]>, - Group<f_clang_Group>; + Group<f_Group>, + Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; def fno_record_command_line : Flag<["-"], "fno-record-command-line">, - Group<f_clang_Group>; + Group<f_Group>, + Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>; def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_line>; def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_command_line>; def fcommon : Flag<["-"], "fcommon">, Group<f_Group>, @@ -7149,6 +7151,9 @@ def mrelocation_model : Separate<["-"], "mrelocation-model">, NormalizedValues<["Static", "PIC_", "ROPI", "RWPI", "ROPI_RWPI", "DynamicNoPIC"]>, MarshallingInfoEnum<CodeGenOpts<"RelocationModel">, "PIC_">; def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; +def record_command_line : Separate<["-"], "record-command-line">, + HelpText<"The string to embed in the .LLVM.command.line section.">, + MarshallingInfoString<CodeGenOpts<"RecordCommandLine">>; } // let Visibility = [CC1Option, CC1AsOption, FC1Option] @@ -7169,9 +7174,6 @@ def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">, def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">, MarshallingInfoString<CodeGenOpts<"DwarfDebugFlags">>; -def record_command_line : Separate<["-"], "record-command-line">, - HelpText<"The string to embed in the .LLVM.command.line section.">, - MarshallingInfoString<CodeGenOpts<"RecordCommandLine">>; def compress_debug_sections_EQ : Joined<["-", "--"], "compress-debug-sections=">, HelpText<"DWARF debug sections compression type">, Values<"none,zlib,zstd">, NormalizedValuesScope<"llvm::DebugCompressionType">, NormalizedValues<["None", "Zlib", "Zstd"]>, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a883ba2a25412e..0ce8afbc917c93 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -94,24 +94,6 @@ static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) { << "-static"; } -// Add backslashes to escape spaces and other backslashes. -// This is used for the space-separated argument list specified with -// the -dwarf-debug-flags option. -static void EscapeSpacesAndBackslashes(const char *Arg, - SmallVectorImpl<char> &Res) { - for (; *Arg; ++Arg) { - switch (*Arg) { - default: - break; - case ' ': - case '\\': - Res.push_back('\\'); - break; - } - Res.push_back(*Arg); - } -} - /// Apply \a Work on the current tool chain \a RegularToolChain and any other /// offloading tool chain that is associated with the current action \a JA. static void @@ -7705,31 +7687,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Also record command line arguments into the debug info if // -grecord-gcc-switches options is set on. // By default, -gno-record-gcc-switches is set on and no recording. - auto GRecordSwitches = - Args.hasFlag(options::OPT_grecord_command_line, - options::OPT_gno_record_command_line, false); - auto FRecordSwitches = - Args.hasFlag(options::OPT_frecord_command_line, - options::OPT_fno_record_command_line, false); - if (FRecordSwitches && !Triple.isOSBinFormatELF() && - !Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO()) - D.Diag(diag::err_drv_unsupported_opt_for_target) - << Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args) - << TripleStr; - if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) { - ArgStringList OriginalArgs; - for (const auto &Arg : Args) - Arg->render(Args, OriginalArgs); - - SmallString<256> Flags; - EscapeSpacesAndBackslashes(Exec, Flags); - for (const char *OriginalArg : OriginalArgs) { - SmallString<128> EscapedArg; - EscapeSpacesAndBackslashes(OriginalArg, EscapedArg); - Flags += " "; - Flags += EscapedArg; - } - auto FlagsArgString = Args.MakeArgString(Flags); + auto GRecordSwitches = false; + auto FRecordSwitches = false; + if (shouldRecordCommandLine(TC, Args, FRecordSwitches, GRecordSwitches)) { + auto FlagsArgString = renderEscapedCommandLine(TC, Args); if (TC.UseDwarfDebugFlags() || GRecordSwitches) { CmdArgs.push_back("-dwarf-debug-flags"); CmdArgs.push_back(FlagsArgString); @@ -8729,10 +8690,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, SmallString<256> Flags; const char *Exec = getToolChain().getDriver().getClangProgramPath(); - EscapeSpacesAndBackslashes(Exec, Flags); + escapeSpacesAndBackslashes(Exec, Flags); for (const char *OriginalArg : OriginalArgs) { SmallString<128> EscapedArg; - EscapeSpacesAndBackslashes(OriginalArg, EscapedArg); + escapeSpacesAndBackslashes(OriginalArg, EscapedArg); Flags += " "; Flags += EscapedArg; } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 043d9e48764439..102e5231d31608 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2960,3 +2960,62 @@ void tools::addMCModel(const Driver &D, const llvm::opt::ArgList &Args, } } } + +void tools::escapeSpacesAndBackslashes(const char *Arg, + llvm::SmallVectorImpl<char> &Res) { + for (; *Arg; ++Arg) { + switch (*Arg) { + default: + break; + case ' ': + case '\\': + Res.push_back('\\'); + break; + } + Res.push_back(*Arg); + } +} + +const char *tools::renderEscapedCommandLine(const ToolChain &TC, + const llvm::opt::ArgList &Args) { + const Driver &D = TC.getDriver(); + const char *Exec = D.getClangProgramPath(); + + llvm::opt::ArgStringList OriginalArgs; + for (const auto &Arg : Args) + Arg->render(Args, OriginalArgs); + + llvm::SmallString<256> Flags; + escapeSpacesAndBackslashes(Exec, Flags); + for (const char *OriginalArg : OriginalArgs) { + llvm::SmallString<128> EscapedArg; + escapeSpacesAndBackslashes(OriginalArg, EscapedArg); + Flags += " "; + Flags += EscapedArg; + } + + return Args.MakeArgString(Flags); +} + +bool tools::shouldRecordCommandLine(const ToolChain &TC, + const llvm::opt::ArgList &Args, + bool &FRecordCommandLine, + bool &GRecordCommandLine) { + const Driver &D = TC.getDriver(); + const llvm::Triple &Triple = TC.getEffectiveTriple(); + const std::string &TripleStr = Triple.getTriple(); + + FRecordCommandLine = + Args.hasFlag(options::OPT_frecord_command_line, + options::OPT_fno_record_command_line, false); + GRecordCommandLine = + Args.hasFlag(options::OPT_grecord_command_line, + options::OPT_gno_record_command_line, false); + if (FRecordCommandLine && !Triple.isOSBinFormatELF() && + !Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args) + << TripleStr; + + return FRecordCommandLine || TC.UseDwarfDebugFlags() || GRecordCommandLine; +} diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index 8695d3fe5b55b8..e9b42bb872ed54 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -233,6 +233,31 @@ void addMCModel(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Reloc::Model &RelocationModel, llvm::opt::ArgStringList &CmdArgs); +/// Add backslashes to escape spaces and other backslashes. +/// This is used for the space-separated argument list specified with +/// the -dwarf-debug-flags option. +void escapeSpacesAndBackslashes(const char *Arg, + llvm::SmallVectorImpl<char> &Res); + +/// Join the args in the given ArgList, escape spaces and backslashes and +/// return the joined string. This is used when saving the command line as a +/// result of using either the -frecord-command-line or -grecord-command-line +/// options. The lifetime of the returned c-string will match that of the Args +/// argument. +const char *renderEscapedCommandLine(const ToolChain &TC, + const llvm::opt::ArgList &Args); + +/// Check if the command line should be recorded in the object file. This is +/// done if either -frecord-command-line or -grecord-command-line options have +/// been passed. This also does some error checking since -frecord-command-line +/// is currently only supported on ELF platforms. The last two boolean +/// arguments are out parameters and will be set depending on the command +/// line options that were passed. +bool shouldRecordCommandLine(const ToolChain &TC, + const llvm::opt::ArgList &Args, + bool &FRecordCommandLine, + bool &GRecordCommandLine); + } // end namespace tools } // end namespace driver } // end namespace clang diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 6ce79d27e98c48..65c29b3dd7f658 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -885,6 +885,20 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, addDashXForInput(Args, Input, CmdArgs); + bool FRecordCmdLine = false; + bool GRecordCmdLine = false; + if (shouldRecordCommandLine(TC, Args, FRecordCmdLine, GRecordCmdLine)) { + const char *CmdLine = renderEscapedCommandLine(TC, Args); + if (FRecordCmdLine) { + CmdArgs.push_back("-record-command-line"); + CmdArgs.push_back(CmdLine); + } + if (TC.UseDwarfDebugFlags() || GRecordCmdLine) { + CmdArgs.push_back("-dwarf-debug-flags"); + CmdArgs.push_back(CmdLine); + } + } + CmdArgs.push_back(Input.getFilename()); // TODO: Replace flang-new with flang once the new driver replaces the diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h index ac7fcbcba4f747..f19943335737b9 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.h +++ b/flang/include/flang/Frontend/CodeGenOptions.h @@ -63,6 +63,9 @@ class CodeGenOptions : public CodeGenOptionsBase { /// The directory where temp files are stored if specified by -save-temps std::optional<std::string> SaveTempsDir; + /// The string containing the commandline for the llvm.commandline metadata. + std::optional<std::string> RecordCommandLine; + /// The name of the file to which the backend should save YAML optimization /// records. std::string OptRecordFile; diff --git a/flang/include/flang/Lower/Bridge.h b/flang/include/flang/Lower/Bridge.h index 4379ed512cdf0a..8ea5ed52e28218 100644 --- a/flang/include/flang/Lower/Bridge.h +++ b/flang/include/flang/Lower/Bridge.h @@ -14,6 +14,8 @@ #define FORTRAN_LOWER_BRIDGE_H #include "flang/Common/Fortran.h" +#include "flang/Frontend/CodeGenOptions.h" +#include "flang/Frontend/TargetOptions.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/EnvironmentDefault.h" #include "flang/Lower/LoweringOptions.h" @@ -65,11 +67,13 @@ class LoweringBridge { const Fortran::lower::LoweringOptions &loweringOptions, const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults, const Fortran::common::LanguageFeatureControl &languageFeatures, - const llvm::TargetMachine &targetMachine, llvm::StringRef tuneCPU) { + const llvm::TargetMachine &targetMachine, + const Fortran::frontend::TargetOptions &targetOptions, + const Fortran::frontend::CodeGenOptions &codeGenOptions) { return LoweringBridge(ctx, semanticsContext, defaultKinds, intrinsics, targetCharacteristics, allCooked, triple, kindMap, loweringOptions, envDefaults, languageFeatures, - targetMachine, tuneCPU); + targetMachine, targetOptions, codeGenOptions); } //===--------------------------------------------------------------------===// @@ -148,7 +152,9 @@ class LoweringBridge { const Fortran::lower::LoweringOptions &loweringOptions, const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults, const Fortran::common::LanguageFeatureControl &languageFeatures, - const llvm::TargetMachine &targetMachine, const llvm::StringRef tuneCPU); + const llvm::TargetMachine &targetMachine, + const Fortran::frontend::TargetOptions &targetOptions, + const Fortran::frontend::CodeGenOptions &codeGenOptions); LoweringBridge() = delete; LoweringBridge(const LoweringBridge &) = delete; diff --git a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h index e45011c8e02a33..2df14f83c11e17 100644 --- a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h +++ b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h @@ -77,6 +77,12 @@ void setIdent(mlir::ModuleOp mod, llvm::StringRef ident); /// Get the compiler identifier from the Module. llvm::StringRef getIdent(mlir::ModuleOp mod); +/// Set the command line used in this invocation. +void setCommandline(mlir::ModuleOp mod, llvm::StringRef cmdLine); + +/// Get the command line used in this invocation. +llvm::StringRef getCommandline(mlir::ModuleOp mod); + /// Helper for determining the target from the host, etc. Tools may use this /// function to provide a consistent interpretation of the `--target=<string>` /// command-line option. diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 90c327546198b5..8441c7d8d2e9bc 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -348,6 +348,12 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ)) opts.SaveTempsDir = a->getValue(); + // -record-command-line option. + if (const llvm::opt::Arg *a = + args.getLastArg(clang::driver::options::OPT_record_command_line)) { + opts.RecordCommandLine = a->getValue(); + } + // -mlink-builtin-bitcode for (auto *a : args.filtered(clang::driver::options::OPT_mlink_builtin_bitcode)) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 4a52edc436e0ed..68cb730ed62534 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -301,7 +301,7 @@ bool CodeGenAction::beginSourceFileAction() { kindMap, ci.getInvocation().getLoweringOpts(), ci.getInvocation().getFrontendOpts().envDefaults, ci.getInvocation().getFrontendOpts().features, targetMachine, - ci.getInvocation().getTargetOpts().cpuToTuneFor); + ci.getInvocation().getTargetOpts(), ci.getInvocation().getCodeGenOpts()); // Fetch module from lb, so we can set mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule()); diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index ebcb7613969661..68dca219428280 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -6064,7 +6064,9 @@ Fortran::lower::LoweringBridge::LoweringBridge( const Fortran::lower::LoweringOptions &loweringOptions, const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults, const Fortran::common::LanguageFeatureControl &languageFeatures, - const llvm::TargetMachine &targetMachine, const llvm::StringRef tuneCPU) + const llvm::TargetMachine &targetMachine, + const Fortran::frontend::TargetOptions &targetOpts, + const Fortran::frontend::CodeGenOptions &cgOpts) : semanticsContext{semanticsContext}, defaultKinds{defaultKinds}, intrinsics{intrinsics}, targetCharacteristics{targetCharacteristics}, cooked{&cooked}, context{context}, kindMap{kindMap}, @@ -6121,11 +6123,13 @@ Fortran::lower::LoweringBridge::LoweringBridge( fir::setTargetTriple(*module.get(), triple); fir::setKindMapping(*module.get(), kindMap); fir::setTargetCPU(*module.get(), targetMachine.getTargetCPU()); - fir::setTuneCPU(*module.get(), tuneCPU); + fir::setTuneCPU(*module.get(), targetOpts.cpuToTuneFor); fir::setTargetFeatures(*module.get(), targetMachine.getTargetFeatureString()); fir::support::setMLIRDataLayout(*module.get(), targetMachine.createDataLayout()); fir::setIdent(*module.get(), Fortran::common::getFlangFullVersion()); + if (cgOpts.RecordCommandLine) + fir::setCommandline(*module.get(), *cgOpts.RecordCommandLine); } void Fortran::lower::genCleanUpInRegionIfAny( diff --git a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp index 5bd8e2d4336361..01c0be66d1ecc3 100644 --- a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp +++ b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp @@ -130,6 +130,22 @@ llvm::StringRef fir::getIdent(mlir::ModuleOp mod) { return {}; } +void fir::setCommandline(mlir::ModuleOp mod, llvm::StringRef cmdLine) { + if (cmdLine.empty()) + return; + + mlir::MLIRContext *ctx = mod.getContext(); + mod->setAttr(mlir::LLVM::LLVMDialect::getCommandlineAttrName(), + mlir::StringAttr::get(ctx, cmdLine)); +} + +llvm::StringRef fir::getCommandline(mlir::ModuleOp mod) { + if (auto attr = mod->getAttrOfType<mlir::StringAttr>( + mlir::LLVM::LLVMDialect::getCommandlineAttrName())) + return attr; + return {}; +} + std::string fir::determineTargetTriple(llvm::StringRef triple) { // Treat "" or "default" as stand-ins for the default machine. if (triple.empty() || triple == "default") diff --git a/flang/test/Driver/frecord-command-line.f90 b/flang/test/Driver/frecord-command-line.f90 new file mode 100644 index 00000000000000..bc4ce79e4a51c3 --- /dev/null +++ b/flang/test/Driver/frecord-command-line.f90 @@ -0,0 +1,16 @@ +! This only checks that the command line is correctly passed on to the +! -record-command-line option FC1 option and that the latter does not complain +! about anything. The correct lowering to a module attribute and beyond will +! be checked in other tests. +! +! RUN: %flang -### -target x86_64-unknown-linux -frecord-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-RECORD %s +! RUN: %flang -### -target x86_64-unknown-macosx -frecord-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-RECORD %s +! RUN: not %flang -### -target x86_64-unknown-windows -frecord-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-RECORD-ERROR %s + +! RUN: %flang -### -target x86_64-unknown-linux -fno-record-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-NO-RECORD %s +! RUN: %flang -### -target x86_64-unknown-macosx -fno-record-command-line %s 2>&1 | FileCheck --check-prefix=CHECK-NO-RECO... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/110132 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits