Author: Nico Weber Date: 2021-09-29T13:14:23-04:00 New Revision: b2de52bec17b67887456ede40ac7c6959ce26d6a
URL: https://github.com/llvm/llvm-project/commit/b2de52bec17b67887456ede40ac7c6959ce26d6a DIFF: https://github.com/llvm/llvm-project/commit/b2de52bec17b67887456ede40ac7c6959ce26d6a.diff LOG: [clang-cl] Accept `#pragma warning(disable : N)` for some N clang-cl maps /wdNNNN to -Wno-flags for a few warnings that map cleanly from cl.exe concepts to clang concepts. This patch adds support for the same numbers to `#pragma warning(disable : NNNN)`. It also lets `#pragma warning(push)` and `#pragma warning(pop)` have an effect, since these are used together with `warning(disable)`. The optional numeric argument to `warning(push)` is ignored, as are the other non-`disable` `pragma warning()` arguments. (Supporting `error` would be easy, but we also don't support `/we`, and those should probably be added together.) The motivating example is that a bunch of code (including in LLVM) uses this idiom to locally disable warnings about calls to deprecated functions in Windows-only code, and 4996 maps nicely to -Wno-deprecated-declarations: #pragma warning(push) #pragma warning(disable: 4996) f(); #pragma warning(pop) Implementation-wise: - Move `/wd` flag handling from Options.td to actual Driver-level code - Extract the function mapping cl.exe IDs to warning groups to the new file clang/lib/Basic/CLWarnings.cpp - Create a diag::Group enum so that CLWarnings.cpp can refer to existing groups by ID (and give DllexportExplicitInstantiationDecl a named group), and add a function to map a diag::Group to the spelling of it's associated commandline flag - Call that new function from PragmaWarningHandler Differential Revision: https://reviews.llvm.org/D110668 Added: clang/include/clang/Basic/CLWarnings.h clang/lib/Basic/CLWarnings.cpp clang/test/Sema/pragma-warning.cpp Modified: clang/include/clang/Basic/Diagnostic.h clang/include/clang/Basic/DiagnosticCategories.h clang/include/clang/Basic/DiagnosticGroups.td clang/include/clang/Basic/DiagnosticIDs.h clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Driver/Options.td clang/lib/Basic/CMakeLists.txt clang/lib/Basic/Diagnostic.cpp clang/lib/Basic/DiagnosticIDs.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Lex/Pragma.cpp clang/test/Driver/cl-options.c clang/tools/diagtool/DiagnosticNames.cpp clang/utils/TableGen/ClangDiagnosticsEmitter.cpp llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn Removed: ################################################################################ diff --git a/clang/include/clang/Basic/CLWarnings.h b/clang/include/clang/Basic/CLWarnings.h new file mode 100644 index 0000000000000..e3351f430c437 --- /dev/null +++ b/clang/include/clang/Basic/CLWarnings.h @@ -0,0 +1,26 @@ +//===--- CLWarnings.h - Maps some cl.exe warning ids -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_CLWARNINGS_H +#define LLVM_CLANG_BASIC_CLWARNINGS_H + +#include "llvm/ADT/Optional.h" + +namespace clang { + +namespace diag { +enum class Group; +} + +/// For cl.exe warning IDs that cleany map to clang diagnostic groups, +/// returns the corresponding group. Else, returns an empty Optional. +llvm::Optional<diag::Group> diagGroupFromCLWarningID(unsigned); + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_CLWARNINGS_H diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index 3b915fb15a891..efb725845d3e8 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -807,6 +807,9 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group, diag::Severity Map, SourceLocation Loc = SourceLocation()); + bool setSeverityForGroup(diag::Flavor Flavor, diag::Group Group, + diag::Severity Map, + SourceLocation Loc = SourceLocation()); /// Set the warning-as-error flag for the given diagnostic group. /// diff --git a/clang/include/clang/Basic/DiagnosticCategories.h b/clang/include/clang/Basic/DiagnosticCategories.h index 0decf15080a0c..2bbdeb31a7b7d 100644 --- a/clang/include/clang/Basic/DiagnosticCategories.h +++ b/clang/include/clang/Basic/DiagnosticCategories.h @@ -19,6 +19,13 @@ namespace clang { #undef GET_CATEGORY_TABLE DiagCat_NUM_CATEGORIES }; + + enum class Group { +#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) GroupName, +#include "clang/Basic/DiagnosticGroups.inc" +#undef CATEGORY +#undef DIAG_ENTRY + }; } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 23e9144ea0084..761b323d06166 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -396,6 +396,7 @@ def Dangling : DiagGroup<"dangling", [DanglingField, DanglingGsl, ReturnStackAddress]>; def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">; +def DllexportExplicitInstantiationDecl : DiagGroup<"dllexport-explicit-instantiation-decl">; def ExcessInitializers : DiagGroup<"excess-initializers">; def ExpansionToDefined : DiagGroup<"expansion-to-defined">; def FlagEnum : DiagGroup<"flag-enum">; diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h index 288504def5ebf..aef86516707c6 100644 --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/Basic/DiagnosticIDs.h @@ -25,6 +25,8 @@ namespace clang { // Import the diagnostic enums themselves. namespace diag { + enum class Group; + // Size of each of the diagnostic categories. enum { DIAG_SIZE_COMMON = 300, @@ -224,6 +226,10 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> { /// static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault); + /// Given a group ID, returns the flag that toggles the group. + /// For example, for Group::DeprecatedDeclarations, returns + /// "deprecated-declarations". + static StringRef getWarningOptionForGroup(diag::Group); /// Return the lowest-level warning option that enables the specified /// diagnostic. diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a3944f7a6054b..1d4ea92c65205 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3396,7 +3396,7 @@ def warn_attribute_dllimport_static_field_definition : Warning< InGroup<DiagGroup<"dllimport-static-field-def">>; def warn_attribute_dllexport_explicit_instantiation_decl : Warning< "explicit instantiation declaration should not be 'dllexport'">, - InGroup<DiagGroup<"dllexport-explicit-instantiation-decl">>; + InGroup<DllexportExplicitInstantiationDecl>; def warn_attribute_dllexport_explicit_instantiation_def : Warning< "'dllexport' attribute ignored on explicit instantiation definition">, InGroup<IgnoredAttributes>; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index f0420702a5cc8..f2c119ad3794c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6106,16 +6106,7 @@ def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors (default)">, Alias<W_Joined>, AliasArgs<["no-error"]>; def _SLASH_w_flag : CLFlag<"w">, HelpText<"Disable all warnings">, Alias<w>; -def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>, - AliasArgs<["no-macro-redefined"]>; -def _SLASH_wd4018 : CLFlag<"wd4018">, Alias<W_Joined>, - AliasArgs<["no-sign-compare"]>; -def _SLASH_wd4100 : CLFlag<"wd4100">, Alias<W_Joined>, - AliasArgs<["no-unused-parameter"]>; -def _SLASH_wd4910 : CLFlag<"wd4910">, Alias<W_Joined>, - AliasArgs<["no-dllexport-explicit-instantiation-decl"]>; -def _SLASH_wd4996 : CLFlag<"wd4996">, Alias<W_Joined>, - AliasArgs<["no-deprecated-declarations"]>; +def _SLASH_wd : CLCompileJoined<"wd">; def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">, Alias<vtordisp_mode_EQ>; def _SLASH_X : CLFlag<"X">, diff --git a/clang/lib/Basic/CLWarnings.cpp b/clang/lib/Basic/CLWarnings.cpp new file mode 100644 index 0000000000000..0cf367d9f7f62 --- /dev/null +++ b/clang/lib/Basic/CLWarnings.cpp @@ -0,0 +1,28 @@ +//===--- CLWarnings.h - Maps some cl.exe warning ids -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the Diagnostic-related interfaces. +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/CLWarnings.h" +#include "clang/Basic/DiagnosticCategories.h" + +using namespace clang; + +llvm::Optional<diag::Group> +clang::diagGroupFromCLWarningID(unsigned CLWarningID) { + switch (CLWarningID) { + case 4005: return diag::Group::MacroRedefined; + case 4018: return diag::Group::SignCompare; + case 4100: return diag::Group::UnusedParameter; + case 4910: return diag::Group::DllexportExplicitInstantiationDecl; + case 4996: return diag::Group::DeprecatedDeclarations; + } + return {}; +} diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt index d440f3b33dc9f..40de9433a4dde 100644 --- a/clang/lib/Basic/CMakeLists.txt +++ b/clang/lib/Basic/CMakeLists.txt @@ -39,6 +39,7 @@ endif() add_clang_library(clangBasic Attributes.cpp Builtins.cpp + CLWarnings.cpp CharInfo.cpp CodeGenOptions.cpp Cuda.cpp diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index d3b2122e9c59f..1b779afa0f310 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -408,6 +408,14 @@ bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor, return false; } +bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor, + diag::Group Group, + diag::Severity Map, + SourceLocation Loc) { + return setSeverityForGroup(Flavor, Diags->getWarningOptionForGroup(Group), + Map, Loc); +} + bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled) { // If we are enabling this feature, just set the diagnostic mappings to map to diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index c333076d2efcb..88801c683e8d8 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -609,17 +609,23 @@ namespace { // Second the table of options, sorted by name for fast binary lookup. static const WarningOption OptionTable[] = { -#define GET_DIAG_TABLE +#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) \ + {FlagNameOffset, Members, SubGroups}, #include "clang/Basic/DiagnosticGroups.inc" -#undef GET_DIAG_TABLE +#undef DIAG_ENTRY }; +StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) { + return OptionTable[static_cast<int>(Group)].getName(); +} + /// getWarningOptionForDiag - Return the lowest-level warning option that /// enables the specified diagnostic. If there is no -Wfoo flag that controls /// the diagnostic, this returns null. StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) - return OptionTable[Info->getOptionGroupIndex()].getName(); + return getWarningOptionForGroup( + static_cast<diag::Group>(Info->getOptionGroupIndex())); return StringRef(); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 23932bf9fd24e..463fb62b223da 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -22,6 +22,7 @@ #include "Hexagon.h" #include "MSP430.h" #include "PS4CPU.h" +#include "clang/Basic/CLWarnings.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/LangOptions.h" @@ -5438,7 +5439,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_R_Group); - Args.AddAllArgs(CmdArgs, options::OPT_W_Group); + for (const Arg *A : + Args.filtered(options::OPT_W_Group, options::OPT__SLASH_wd)) { + A->claim(); + if (A->getOption().getID() == options::OPT__SLASH_wd) { + unsigned WarningNumber; + if (StringRef(A->getValue()).getAsInteger(10, WarningNumber)) { + D.Diag(diag::err_drv_invalid_int_value) + << A->getAsString(Args) << A->getValue(); + continue; + } + + if (auto Group = diagGroupFromCLWarningID(WarningNumber)) { + CmdArgs.push_back(Args.MakeArgString( + Twine("-Wno-") + DiagnosticIDs::getWarningOptionForGroup(*Group))); + continue; + } + } + A->render(Args, CmdArgs); + } + if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false)) CmdArgs.push_back("-pedantic"); Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors); diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index df3080a3824a8..3cbe16e580171 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/Pragma.h" +#include "clang/Basic/CLWarnings.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticLex.h" #include "clang/Basic/FileManager.h" @@ -1413,12 +1414,15 @@ struct PragmaWarningHandler : public PragmaHandler { return; } } + PP.getDiagnostics().pushMappings(DiagLoc); if (Callbacks) Callbacks->PragmaWarningPush(DiagLoc, Level); } else if (II && II->isStr("pop")) { // #pragma warning( pop ) PP.Lex(Tok); - if (Callbacks) + if (!PP.getDiagnostics().popMappings(DiagLoc)) + PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop); + else if (Callbacks) Callbacks->PragmaWarningPop(DiagLoc); } else { // #pragma warning( warning-specifier : warning-number-list @@ -1482,6 +1486,22 @@ struct PragmaWarningHandler : public PragmaHandler { } Ids.push_back(int(Value)); } + + // Only act on disable for now. + diag::Severity SV = diag::Severity(); + if (Specifier == PPCallbacks::PWS_Disable) + SV = diag::Severity::Ignored; + if (SV != diag::Severity()) + for (int Id : Ids) { + if (auto Group = diagGroupFromCLWarningID(Id)) { + bool unknownDiag = PP.getDiagnostics().setSeverityForGroup( + diag::Flavor::WarningOrError, *Group, SV, DiagLoc); + assert(!unknownDiag && + "wd table should only contain known diags"); + (void)unknownDiag; + } + } + if (Callbacks) Callbacks->PragmaWarning(DiagLoc, Specifier, Ids); diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index a5e1402c51d6e..74dd68753a1f0 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -353,7 +353,7 @@ // CHECK-C11: -std=c11 // For some warning ids, we can map from MSVC warning to Clang warning. -// RUN: %clang_cl -wd4005 -wd4100 -wd4910 -wd4996 -### -- %s 2>&1 | FileCheck -check-prefix=Wno %s +// RUN: %clang_cl -wd4005 -wd4100 -wd4910 -wd4996 -wd12345678 -### -- %s 2>&1 | FileCheck -check-prefix=Wno %s // Wno: "-cc1" // Wno: "-Wno-macro-redefined" // Wno: "-Wno-unused-parameter" diff --git a/clang/test/Sema/pragma-warning.cpp b/clang/test/Sema/pragma-warning.cpp new file mode 100644 index 0000000000000..a36ecbd3107a1 --- /dev/null +++ b/clang/test/Sema/pragma-warning.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fms-extensions -fsyntax-only -verify %s + +[[deprecated]] void f() {} // expected-note 2 {{marked deprecated here}} + +#define From__pragma() \ + __pragma(warning(push)) \ + __pragma(warning(disable:4996)) \ + f(); \ + __pragma(warning(pop)) + +void g() { + f(); // expected-warning {{deprecated}} + +#pragma warning(push) +#pragma warning(disable: 4996) + f(); // no diag + +#pragma warning(disable: 49960000) +#pragma warning(pop) + + f(); // expected-warning {{deprecated}} + + From__pragma(); // no diag +} diff --git a/clang/tools/diagtool/DiagnosticNames.cpp b/clang/tools/diagtool/DiagnosticNames.cpp index c54f81481a266..55b308e87e0e1 100644 --- a/clang/tools/diagtool/DiagnosticNames.cpp +++ b/clang/tools/diagtool/DiagnosticNames.cpp @@ -66,9 +66,10 @@ const DiagnosticRecord &diagtool::getDiagnosticForID(short DiagID) { // Second the table of options, sorted by name for fast binary lookup. static const GroupRecord OptionTable[] = { -#define GET_DIAG_TABLE +#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) \ + {FlagNameOffset, Members, SubGroups}, #include "clang/Basic/DiagnosticGroups.inc" -#undef GET_DIAG_TABLE +#undef DIAG_ENTRY }; llvm::StringRef GroupRecord::getName() const { diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index ad4bb8d78ced3..573bb5b4039bd 100644 --- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -129,6 +129,7 @@ namespace { }; struct GroupInfo { + llvm::StringRef GroupName; std::vector<const Record*> DiagsInGroup; std::vector<std::string> SubGroups; unsigned IDNo; @@ -174,6 +175,7 @@ static void groupDiagnostics(const std::vector<Record*> &Diags, Record *Group = DiagGroups[i]; GroupInfo &GI = DiagsInGroup[std::string(Group->getValueAsString("GroupName"))]; + GI.GroupName = Group->getName(); GI.Defs.push_back(Group); std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups"); @@ -1279,8 +1281,8 @@ void clang::EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS, OS << ", \""; OS.write_escaped(DiagTextBuilder.buildForDefinition(&R)) << '"'; - // Warning associated with the diagnostic. This is stored as an index into - // the alphabetically sorted warning table. + // Warning group associated with the diagnostic. This is stored as an index + // into the alphabetically sorted warning group table. if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) { std::map<std::string, GroupInfo>::iterator I = DiagsInGroup.find( std::string(DI->getDef()->getValueAsString("GroupName"))); @@ -1487,18 +1489,20 @@ static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup, for (auto const &I: DiagsInGroup) MaxLen = std::max(MaxLen, (unsigned)I.first.size()); - OS << "\n#ifdef GET_DIAG_TABLE\n"; + OS << "\n#ifdef DIAG_ENTRY\n"; unsigned SubGroupIndex = 1, DiagArrayIndex = 1; for (auto const &I: DiagsInGroup) { // Group option string. - OS << " { /* "; + OS << "DIAG_ENTRY("; + OS << I.second.GroupName << " /* "; + if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789!@#$%^*-+=:?") != std::string::npos) PrintFatalError("Invalid character in diagnostic group '" + I.first + "'"); - OS << I.first << " */ " << std::string(MaxLen - I.first.size(), ' '); + OS << I.first << " */, "; // Store a pascal-style length byte at the beginning of the string. std::string Name = char(I.first.size()) + I.first; OS << GroupNames.GetOrAddStringOffset(Name, false) << ", "; @@ -1517,7 +1521,7 @@ static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup, DiagArrayIndex += DiagsInPedantic.size(); DiagArrayIndex += V.size() + 1; } else { - OS << "/* Empty */ 0, "; + OS << "0, "; } // Subgroups. @@ -1530,12 +1534,12 @@ static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup, SubGroupIndex += GroupsInPedantic.size(); SubGroupIndex += SubGroups.size() + 1; } else { - OS << "/* Empty */ 0"; + OS << "0"; } - OS << " },\n"; + OS << " )\n"; } - OS << "#endif // GET_DIAG_TABLE\n\n"; + OS << "#endif // DIAG_ENTRY\n\n"; } /// Emit the table of diagnostic categories. diff --git a/llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn index 88c10d4e0fa6e..09afa57ab95fa 100644 --- a/llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/lib/Basic/BUILD.gn @@ -55,6 +55,7 @@ static_library("Basic") { sources = [ "Attributes.cpp", "Builtins.cpp", + "CLWarnings.cpp", "CharInfo.cpp", "CodeGenOptions.cpp", "Cuda.cpp", _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits