Author: Sirraide Date: 2025-04-02T08:06:29+02:00 New Revision: 9d06e0879b5600b19cd8cebd98e4f92b5e62400f
URL: https://github.com/llvm/llvm-project/commit/9d06e0879b5600b19cd8cebd98e4f92b5e62400f DIFF: https://github.com/llvm/llvm-project/commit/9d06e0879b5600b19cd8cebd98e4f92b5e62400f.diff LOG: [Clang] [NFC] Introduce a helper for emitting compatibility diagnostics (#132348) This is a follow-up to #132129. Currently, only `Parser` and `SemaBase` get a `DiagCompat()` helper; I’m planning to keep refactoring compatibility warnings and add more helpers to other classes as needed. I also refactored a single parser compat warning just to make sure everything works properly when diagnostics across multiple components (i.e. Sema and Parser in this case) are involved. Added: Modified: clang/include/clang/Basic/CMakeLists.txt clang/include/clang/Basic/Diagnostic.td clang/include/clang/Basic/DiagnosticAST.h clang/include/clang/Basic/DiagnosticAnalysis.h clang/include/clang/Basic/DiagnosticComment.h clang/include/clang/Basic/DiagnosticCrossTU.h clang/include/clang/Basic/DiagnosticDriver.h clang/include/clang/Basic/DiagnosticFrontend.h clang/include/clang/Basic/DiagnosticIDs.h clang/include/clang/Basic/DiagnosticInstallAPI.h clang/include/clang/Basic/DiagnosticLex.h clang/include/clang/Basic/DiagnosticParse.h clang/include/clang/Basic/DiagnosticParseKinds.td clang/include/clang/Basic/DiagnosticRefactoring.h clang/include/clang/Basic/DiagnosticSema.h clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Basic/DiagnosticSerialization.h clang/include/clang/Parse/Parser.h clang/include/clang/Sema/SemaBase.h clang/lib/Basic/DiagnosticIDs.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/SemaBase.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaTemplate.cpp clang/test/Misc/show-diag-options.c clang/utils/TableGen/ClangDiagnosticsEmitter.cpp clang/utils/TableGen/TableGen.cpp clang/utils/TableGen/TableGenBackends.h Removed: ################################################################################ diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index a671d5c764c22..6be6d063c20b4 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -8,6 +8,11 @@ macro(clang_diag_gen component) -gen-clang-diags-enums -clang-component=${component} SOURCE Diagnostic.td TARGET ClangDiagnostic${component}Enums) + + clang_tablegen(Diagnostic${component}CompatIDs.inc + -gen-clang-diags-compat-ids -clang-component=${component} + SOURCE Diagnostic.td + TARGET ClangDiagnostic${component}CompatIDs) endmacro(clang_diag_gen) clang_diag_gen(Analysis) @@ -31,6 +36,11 @@ clang_tablegen(DiagnosticIndexName.inc -gen-clang-diags-index-name SOURCE Diagnostic.td TARGET ClangDiagnosticIndexName) +clang_tablegen(DiagnosticAllCompatIDs.inc + -gen-clang-diags-compat-ids + SOURCE Diagnostic.td + TARGET ClangDiagnosticAllCompatIDs) + clang_tablegen(AttrList.inc -gen-clang-attr-list -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE Attr.td diff --git a/clang/include/clang/Basic/Diagnostic.td b/clang/include/clang/Basic/Diagnostic.td index b31d846210a8e..65b19f3feea4f 100644 --- a/clang/include/clang/Basic/Diagnostic.td +++ b/clang/include/clang/Basic/Diagnostic.td @@ -155,6 +155,19 @@ class DefaultWarnNoWerror { } class DefaultRemark { Severity DefaultSeverity = SEV_Remark; } +class CompatWarningId<string name, int std, string diag, string diag_pre> { + string Component = ?; + string Name = name; + string Diag = diag; + string DiagPre = diag_pre; + int Std = std; + + // This is unused, but Tablegen will complain if it's missing because we define + // the compatibility ids in the same place as the other diagnostics (which means + // that we'll be inside a 'let CategoryName = "" in { ... }' block). + string CategoryName = ?; +} + // C++ compatibility warnings. multiclass CXXCompat< string message, @@ -178,6 +191,11 @@ multiclass CXXCompat< "CXX98Compat", "CXXPre"#std_ver#"Compat"))>, DefaultIgnore; + + def : CompatWarningId< + NAME, std_ver, + "compat_cxx"#std_ver#"_"#NAME, + "compat_pre_cxx"#std_ver#"_"#NAME>; } // These generate pairs of C++ compatibility warnings of the form: diff --git a/clang/include/clang/Basic/DiagnosticAST.h b/clang/include/clang/Basic/DiagnosticAST.h index 4f82114b7406b..41e2598f7cc3b 100644 --- a/clang/include/clang/Basic/DiagnosticAST.h +++ b/clang/include/clang/Basic/DiagnosticAST.h @@ -36,6 +36,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticASTCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICAST_H diff --git a/clang/include/clang/Basic/DiagnosticAnalysis.h b/clang/include/clang/Basic/DiagnosticAnalysis.h index 1a49461bcd173..5ead092b946c5 100644 --- a/clang/include/clang/Basic/DiagnosticAnalysis.h +++ b/clang/include/clang/Basic/DiagnosticAnalysis.h @@ -35,6 +35,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticAnalysisCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICANALYSIS_H diff --git a/clang/include/clang/Basic/DiagnosticComment.h b/clang/include/clang/Basic/DiagnosticComment.h index 53143ef132e4b..08e66e8051834 100644 --- a/clang/include/clang/Basic/DiagnosticComment.h +++ b/clang/include/clang/Basic/DiagnosticComment.h @@ -36,6 +36,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticCommentCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICCOMMENT_H diff --git a/clang/include/clang/Basic/DiagnosticCrossTU.h b/clang/include/clang/Basic/DiagnosticCrossTU.h index 428da95011027..761716d781446 100644 --- a/clang/include/clang/Basic/DiagnosticCrossTU.h +++ b/clang/include/clang/Basic/DiagnosticCrossTU.h @@ -36,6 +36,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticCrossTUCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICCROSSTU_H diff --git a/clang/include/clang/Basic/DiagnosticDriver.h b/clang/include/clang/Basic/DiagnosticDriver.h index c472afa3f6e96..864a23a49e4cd 100644 --- a/clang/include/clang/Basic/DiagnosticDriver.h +++ b/clang/include/clang/Basic/DiagnosticDriver.h @@ -36,6 +36,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticDriverCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICDRIVER_H diff --git a/clang/include/clang/Basic/DiagnosticFrontend.h b/clang/include/clang/Basic/DiagnosticFrontend.h index 766cac3d655b3..3506f05daae54 100644 --- a/clang/include/clang/Basic/DiagnosticFrontend.h +++ b/clang/include/clang/Basic/DiagnosticFrontend.h @@ -36,6 +36,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticFrontendCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICFRONTEND_H diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h index 017ef7065610f..f2bd19f9b6e8a 100644 --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/Basic/DiagnosticIDs.h @@ -25,6 +25,7 @@ namespace clang { class DiagnosticsEngine; class DiagnosticBuilder; + class LangOptions; class SourceLocation; // Import the diagnostic enums themselves. @@ -104,6 +105,18 @@ namespace clang { }; } + namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticCommonCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END + } // end namespace diag_compat + class DiagnosticMapping { LLVM_PREFERRED_TYPE(diag::Severity) unsigned Severity : 3; @@ -464,6 +477,11 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> { /// given group name. static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group); + /// Get the appropriate diagnostic Id to use for issuing a compatibility + /// diagnostic. For use by the various DiagCompat() helpers. + static unsigned getCXXCompatDiagId(const LangOptions &LangOpts, + unsigned CompatDiagId); + private: /// Classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticClient. diff --git a/clang/include/clang/Basic/DiagnosticInstallAPI.h b/clang/include/clang/Basic/DiagnosticInstallAPI.h index cbdb00362624b..4619bfeea05a2 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPI.h +++ b/clang/include/clang/Basic/DiagnosticInstallAPI.h @@ -35,5 +35,17 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticInstallAPICompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICINSTALLAPI_H diff --git a/clang/include/clang/Basic/DiagnosticLex.h b/clang/include/clang/Basic/DiagnosticLex.h index d14bf97e8642e..6fa90f785bbf8 100644 --- a/clang/include/clang/Basic/DiagnosticLex.h +++ b/clang/include/clang/Basic/DiagnosticLex.h @@ -35,6 +35,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticLexCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICLEX_H diff --git a/clang/include/clang/Basic/DiagnosticParse.h b/clang/include/clang/Basic/DiagnosticParse.h index 275e1a4c39b3f..e2a4368a59c4b 100644 --- a/clang/include/clang/Basic/DiagnosticParse.h +++ b/clang/include/clang/Basic/DiagnosticParse.h @@ -36,6 +36,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticParseCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICPARSE_H diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 2582e1e5ef0f6..954f538e15026 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -11,6 +11,12 @@ //===----------------------------------------------------------------------===// let Component = "Parse" in { +let CategoryName = "Parse Issue" in { +// C++11 compatibility with C++98. +defm enum_fixed_underlying_type : CXX11Compat< + "enumeration types with a fixed underlying type are", + /*ext_warn=*/false>; +} def err_asm_qualifier_ignored : Error< "expected 'volatile', 'inline', 'goto', or '('">, CatInlineAsm; @@ -107,9 +113,6 @@ def err_enumerator_list_missing_comma : Error< "missing ',' between enumerators">; def err_enumerator_unnamed_no_def : Error< "unnamed enumeration must be a definition">; -def ext_cxx11_enum_fixed_underlying_type : Extension< - "enumeration types with a fixed underlying type are a C++11 extension">, - InGroup<CXX11>; def ext_ms_c_enum_fixed_underlying_type : Extension< "enumeration types with a fixed underlying type are a Microsoft extension">, InGroup<MicrosoftFixedEnum>; @@ -119,9 +122,6 @@ def ext_c23_enum_fixed_underlying_type : Extension< def warn_c17_compat_enum_fixed_underlying_type : Warning< "enumeration types with a fixed underlying type are incompatible with C standards before C23">, DefaultIgnore, InGroup<CPre23Compat>; -def warn_cxx98_compat_enum_fixed_underlying_type : Warning< - "enumeration types with a fixed underlying type are incompatible with C++98">, - InGroup<CXX98Compat>, DefaultIgnore; def ext_enum_base_in_type_specifier : ExtWarn< "non-defining declaration of enumeration with a fixed underlying type is " "only permitted as a standalone declaration" diff --git a/clang/include/clang/Basic/DiagnosticRefactoring.h b/clang/include/clang/Basic/DiagnosticRefactoring.h index 59d4bc912733a..b3f3a10925f09 100644 --- a/clang/include/clang/Basic/DiagnosticRefactoring.h +++ b/clang/include/clang/Basic/DiagnosticRefactoring.h @@ -36,6 +36,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticRefactoringCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICREFACTORING_H diff --git a/clang/include/clang/Basic/DiagnosticSema.h b/clang/include/clang/Basic/DiagnosticSema.h index 84986c7bccf71..943b2f64f427e 100644 --- a/clang/include/clang/Basic/DiagnosticSema.h +++ b/clang/include/clang/Basic/DiagnosticSema.h @@ -35,7 +35,20 @@ enum { #undef DIAG_ENUM_END #undef DIAG_ENUM_ITEM #undef DIAG_ENUM + } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticSemaCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICSEMA_H diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5e45482584946..265bed2df43cf 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -61,7 +61,7 @@ defm decomp_decl_cond : CXX26Compat<"structured binding declaration in a conditi // Compatibility warnings duplicated across multiple language versions. foreach std = [14, 20, 23] in { - defm constexpr_body_invalid_stmt : CXXCompat< + defm cxx#std#_constexpr_body_invalid_stmt : CXXCompat< "use of this statement in a constexpr %select{function|constructor}0 is", std>; } diff --git a/clang/include/clang/Basic/DiagnosticSerialization.h b/clang/include/clang/Basic/DiagnosticSerialization.h index 6fb836dca1b04..c8fb034e9bd4a 100644 --- a/clang/include/clang/Basic/DiagnosticSerialization.h +++ b/clang/include/clang/Basic/DiagnosticSerialization.h @@ -36,6 +36,18 @@ enum { #undef DIAG_ENUM_ITEM #undef DIAG_ENUM } // end namespace diag + +namespace diag_compat { +#define DIAG_COMPAT_IDS_BEGIN() enum { +#define DIAG_COMPAT_IDS_END() \ + } \ + ; +#define DIAG_COMPAT_ID(IDX, NAME, ...) NAME = IDX, +#include "clang/Basic/DiagnosticSerializationCompatIDs.inc" +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END +} // end namespace diag_compat } // end namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTICSERIALIZATION_H diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index c8ceef8f8987d..5770692c42f13 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1263,6 +1263,12 @@ class Parser : public CodeCompletionHandler { return Diag(Tok, DiagID); } + DiagnosticBuilder DiagCompat(SourceLocation Loc, unsigned CompatDiagId); + DiagnosticBuilder DiagCompat(const Token &Tok, unsigned CompatDiagId); + DiagnosticBuilder DiagCompat(unsigned CompatDiagId) { + return DiagCompat(Tok, CompatDiagId); + } + private: void SuggestParentheses(SourceLocation Loc, unsigned DK, SourceRange ParenRange); diff --git a/clang/include/clang/Sema/SemaBase.h b/clang/include/clang/Sema/SemaBase.h index 463cae83c7e81..550f530af72f5 100644 --- a/clang/include/clang/Sema/SemaBase.h +++ b/clang/include/clang/Sema/SemaBase.h @@ -219,6 +219,10 @@ class SemaBase { SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD, bool DeferHint = false); + /// Emit a compatibility diagnostic. + SemaDiagnosticBuilder DiagCompat(SourceLocation Loc, unsigned CompatDiagId, + bool DeferHint = false); + /// Build a partial diagnostic. PartialDiagnostic PDiag(unsigned DiagID = 0); }; diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index ca5b8d2da769e..d5928431f41a2 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/AllDiagnostics.h" #include "clang/Basic/DiagnosticCategories.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -769,6 +770,51 @@ StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, return Best; } +unsigned DiagnosticIDs::getCXXCompatDiagId(const LangOptions &LangOpts, + unsigned CompatDiagId) { + struct CompatDiag { + unsigned StdVer; + unsigned DiagId; + unsigned PreDiagId; + }; + + // We encode the standard version such that C++98 < C++11 < C++14 etc. The + // actual numbers don't really matter for this, but the definitions of the + // compat diags in the Tablegen file use the standard version number (i.e. + // 98, 11, 14, etc.), so we base the encoding here on that. +#define DIAG_COMPAT_IDS_BEGIN() +#define DIAG_COMPAT_IDS_END() +#define DIAG_COMPAT_ID(Value, Name, Std, Diag, DiagPre) \ + {Std == 98 ? 1998 : 2000 + Std, diag::Diag, diag::DiagPre}, + static constexpr CompatDiag Diags[]{ +#include "clang/Basic/DiagnosticAllCompatIDs.inc" + }; +#undef DIAG_COMPAT_ID +#undef DIAG_COMPAT_IDS_BEGIN +#undef DIAG_COMPAT_IDS_END + + assert(CompatDiagId < std::size(Diags) && "Invalid compat diag id"); + + unsigned StdVer = [&] { + if (LangOpts.CPlusPlus26) + return 2026; + if (LangOpts.CPlusPlus23) + return 2023; + if (LangOpts.CPlusPlus20) + return 2020; + if (LangOpts.CPlusPlus17) + return 2017; + if (LangOpts.CPlusPlus14) + return 2014; + if (LangOpts.CPlusPlus11) + return 2011; + return 1998; + }(); + + const CompatDiag &D = Diags[CompatDiagId]; + return StdVer >= D.StdVer ? D.DiagId : D.PreDiagId; +} + /// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 3f156407edc99..d77400e0f8272 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5452,11 +5452,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd()); if (!getLangOpts().ObjC) { - if (getLangOpts().CPlusPlus11) - Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type) - << BaseRange; - else if (getLangOpts().CPlusPlus) - Diag(ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type) + if (getLangOpts().CPlusPlus) + DiagCompat(ColonLoc, diag_compat::enum_fixed_underlying_type) << BaseRange; else if (getLangOpts().MicrosoftExt && !getLangOpts().C23) Diag(ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type) diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 2eca89179453b..1227514121973 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -89,6 +89,16 @@ DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) { return Diag(Tok.getLocation(), DiagID); } +DiagnosticBuilder Parser::DiagCompat(SourceLocation Loc, + unsigned CompatDiagId) { + return Diag(Loc, + DiagnosticIDs::getCXXCompatDiagId(getLangOpts(), CompatDiagId)); +} + +DiagnosticBuilder Parser::DiagCompat(const Token &Tok, unsigned CompatDiagId) { + return DiagCompat(Tok.getLocation(), CompatDiagId); +} + /// Emits a diagnostic suggesting parentheses surrounding a /// given range. /// diff --git a/clang/lib/Sema/SemaBase.cpp b/clang/lib/Sema/SemaBase.cpp index 85c4a0ab40fed..9b677f446f3e6 100644 --- a/clang/lib/Sema/SemaBase.cpp +++ b/clang/lib/Sema/SemaBase.cpp @@ -88,4 +88,11 @@ Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc, return Diag(Loc, PD.getDiagID(), DeferHint) << PD; } +SemaBase::SemaDiagnosticBuilder SemaBase::DiagCompat(SourceLocation Loc, + unsigned CompatDiagId, + bool DeferHint) { + return Diag(Loc, + DiagnosticIDs::getCXXCompatDiagId(getLangOpts(), CompatDiagId), + DeferHint); +} } // namespace clang diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index bbefbbf294dd1..9b7b3f856cc55 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7649,10 +7649,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( IsVariableTemplate = true; // Only C++1y supports variable templates (N3651). - Diag(D.getIdentifierLoc(), - getLangOpts().CPlusPlus14 - ? diag::compat_cxx14_variable_template - : diag::compat_pre_cxx14_variable_template); + DiagCompat(D.getIdentifierLoc(), diag_compat::variable_template); } } } else { @@ -7718,10 +7715,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( } else if (RD->isUnion()) { // C++98 [class.union]p1: If a union contains a static data member, // the program is ill-formed. C++11 drops this restriction. - Diag(D.getIdentifierLoc(), - getLangOpts().CPlusPlus11 - ? diag::compat_cxx11_static_data_member_in_union - : diag::compat_pre_cxx11_static_data_member_in_union) + DiagCompat(D.getIdentifierLoc(), + diag_compat::static_data_member_in_union) << Name; } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 43bf9b7cd0f95..b6ba7231d9a26 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -807,10 +807,8 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, for (auto Loc : BadSpecifierLocs) Err << SourceRange(Loc, Loc); } else if (!CPlusPlus20Specifiers.empty()) { - auto &&Warn = Diag(CPlusPlus20SpecifierLocs.front(), - getLangOpts().CPlusPlus20 - ? diag::compat_cxx20_decomp_decl_spec - : diag::compat_pre_cxx20_decomp_decl_spec); + auto &&Warn = DiagCompat(CPlusPlus20SpecifierLocs.front(), + diag_compat::decomp_decl_spec); Warn << (int)CPlusPlus20Specifiers.size() << llvm::join(CPlusPlus20Specifiers.begin(), CPlusPlus20Specifiers.end(), " "); @@ -2040,10 +2038,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, // C++1y allows types to be defined, not just declared. if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition()) { if (Kind == Sema::CheckConstexprKind::Diagnose) { - SemaRef.Diag(DS->getBeginLoc(), - SemaRef.getLangOpts().CPlusPlus14 - ? diag::compat_cxx14_constexpr_type_definition - : diag::compat_pre_cxx14_constexpr_type_definition) + SemaRef.DiagCompat(DS->getBeginLoc(), + diag_compat::constexpr_type_definition) << isa<CXXConstructorDecl>(Dcl); } else if (!SemaRef.getLangOpts().CPlusPlus14) { return false; @@ -2068,10 +2064,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, if (VD->isThisDeclarationADefinition()) { if (VD->isStaticLocal()) { if (Kind == Sema::CheckConstexprKind::Diagnose) { - SemaRef.Diag(VD->getLocation(), - SemaRef.getLangOpts().CPlusPlus23 - ? diag::compat_cxx23_constexpr_static_var - : diag::compat_pre_cxx23_constexpr_static_var) + SemaRef.DiagCompat(VD->getLocation(), + diag_compat::constexpr_static_var) << isa<CXXConstructorDecl>(Dcl) << (VD->getTLSKind() == VarDecl::TLS_Dynamic); } else if (!SemaRef.getLangOpts().CPlusPlus23) { @@ -2091,11 +2085,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, if (!VD->getType()->isDependentType() && !VD->hasInit() && !VD->isCXXForRangeDecl()) { if (Kind == Sema::CheckConstexprKind::Diagnose) { - SemaRef.Diag( - VD->getLocation(), - SemaRef.getLangOpts().CPlusPlus20 - ? diag::compat_cxx20_constexpr_local_var_no_init - : diag::compat_pre_cxx20_constexpr_local_var_no_init) + SemaRef.DiagCompat(VD->getLocation(), + diag_compat::constexpr_local_var_no_init) << isa<CXXConstructorDecl>(Dcl); } else if (!SemaRef.getLangOpts().CPlusPlus20) { return false; @@ -2104,10 +2095,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, } } if (Kind == Sema::CheckConstexprKind::Diagnose) { - SemaRef.Diag(VD->getLocation(), - SemaRef.getLangOpts().CPlusPlus14 - ? diag::compat_cxx14_constexpr_local_var - : diag::compat_pre_cxx14_constexpr_local_var) + SemaRef.DiagCompat(VD->getLocation(), diag_compat::constexpr_local_var) << isa<CXXConstructorDecl>(Dcl); } else if (!SemaRef.getLangOpts().CPlusPlus14) { return false; @@ -2177,10 +2165,8 @@ static bool CheckConstexprCtorInitializer(Sema &SemaRef, if (!Inits.count(Field)) { if (Kind == Sema::CheckConstexprKind::Diagnose) { if (!Diagnosed) { - SemaRef.Diag(Dcl->getLocation(), - SemaRef.getLangOpts().CPlusPlus20 - ? diag::compat_cxx20_constexpr_ctor_missing_init - : diag::compat_pre_cxx20_constexpr_ctor_missing_init); + SemaRef.DiagCompat(Dcl->getLocation(), + diag_compat::constexpr_ctor_missing_init); Diagnosed = true; } SemaRef.Diag(Field->getLocation(), @@ -2391,10 +2377,8 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, break; case Sema::CheckConstexprKind::Diagnose: - SemaRef.Diag(Body->getBeginLoc(), - SemaRef.getLangOpts().CPlusPlus20 - ? diag::compat_cxx20_constexpr_function_try_block - : diag::compat_pre_cxx20_constexpr_function_try_block) + SemaRef.DiagCompat(Body->getBeginLoc(), + diag_compat::constexpr_function_try_block) << isa<CXXConstructorDecl>(Dcl); break; } @@ -2421,22 +2405,13 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, (Cxx1yLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus17)) return false; } else if (Cxx2bLoc.isValid()) { - SemaRef.Diag(Cxx2bLoc, - SemaRef.getLangOpts().CPlusPlus23 - ? diag::compat_cxx23_constexpr_body_invalid_stmt - : diag::compat_pre_cxx23_constexpr_body_invalid_stmt) + SemaRef.DiagCompat(Cxx2bLoc, diag_compat::cxx23_constexpr_body_invalid_stmt) << isa<CXXConstructorDecl>(Dcl); } else if (Cxx2aLoc.isValid()) { - SemaRef.Diag(Cxx2aLoc, - SemaRef.getLangOpts().CPlusPlus20 - ? diag::compat_cxx20_constexpr_body_invalid_stmt - : diag::compat_pre_cxx20_constexpr_body_invalid_stmt) + SemaRef.DiagCompat(Cxx2aLoc, diag_compat::cxx20_constexpr_body_invalid_stmt) << isa<CXXConstructorDecl>(Dcl); } else if (Cxx1yLoc.isValid()) { - SemaRef.Diag(Cxx1yLoc, - SemaRef.getLangOpts().CPlusPlus14 - ? diag::compat_cxx14_constexpr_body_invalid_stmt - : diag::compat_pre_cxx14_constexpr_body_invalid_stmt) + SemaRef.DiagCompat(Cxx1yLoc, diag_compat::cxx14_constexpr_body_invalid_stmt) << isa<CXXConstructorDecl>(Dcl); } @@ -2453,11 +2428,8 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, if (Constructor->getNumCtorInitializers() == 0 && RD->hasVariantMembers()) { if (Kind == Sema::CheckConstexprKind::Diagnose) { - SemaRef.Diag( - Dcl->getLocation(), - SemaRef.getLangOpts().CPlusPlus20 - ? diag::compat_cxx20_constexpr_union_ctor_no_init - : diag::compat_pre_cxx20_constexpr_union_ctor_no_init); + SemaRef.DiagCompat(Dcl->getLocation(), + diag_compat::constexpr_union_ctor_no_init); } else if (!SemaRef.getLangOpts().CPlusPlus20) { return false; } @@ -2520,11 +2492,8 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, } else if (ReturnStmts.size() > 1) { switch (Kind) { case Sema::CheckConstexprKind::Diagnose: - SemaRef.Diag( - ReturnStmts.back(), - SemaRef.getLangOpts().CPlusPlus14 - ? diag::compat_cxx14_constexpr_body_multiple_return - : diag::compat_pre_cxx14_constexpr_body_multiple_return); + SemaRef.DiagCompat(ReturnStmts.back(), + diag_compat::constexpr_body_multiple_return); for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I) SemaRef.Diag(ReturnStmts[I], diag::note_constexpr_body_previous_return); @@ -17825,9 +17794,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, << FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc), InsertionText); } else { - Diag(FriendLoc, getLangOpts().CPlusPlus11 - ? diag::compat_cxx11_nonclass_type_friend - : diag::compat_pre_cxx11_nonclass_type_friend) + DiagCompat(FriendLoc, diag_compat::nonclass_type_friend) << T << DS.getSourceRange(); } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7cc8374e69d73..e7f418ae6802e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6508,9 +6508,7 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (const auto *ULE = dyn_cast<UnresolvedLookupExpr>(Fn); ULE && ULE->hasExplicitTemplateArgs() && ULE->decls_begin() == ULE->decls_end()) { - Diag(Fn->getExprLoc(), getLangOpts().CPlusPlus20 - ? diag::compat_cxx20_adl_only_template_id - : diag::compat_pre_cxx20_adl_only_template_id) + DiagCompat(Fn->getExprLoc(), diag_compat::adl_only_template_id) << ULE->getName(); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index eace9b87a5bfe..1f87ef4b27bab 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2234,10 +2234,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, // template-argument, that declaration shall be a definition and shall be // the only declaration of the function template in the translation unit. // (C++98/03 doesn't have this wording; see DR226). - S.Diag(ParamLoc, - S.getLangOpts().CPlusPlus11 - ? diag::compat_cxx11_templ_default_in_function_templ - : diag::compat_pre_cxx11_templ_default_in_function_templ) + S.DiagCompat(ParamLoc, diag_compat::templ_default_in_function_templ) << DefArgRange; return false; @@ -6432,10 +6429,7 @@ static bool CheckTemplateArgumentAddressOfObjectOrFunction( bool ExtraParens = false; while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { if (!Invalid && !ExtraParens) { - S.Diag(Arg->getBeginLoc(), - S.getLangOpts().CPlusPlus11 - ? diag::compat_cxx11_template_arg_extra_parens - : diag::compat_pre_cxx11_template_arg_extra_parens) + S.DiagCompat(Arg->getBeginLoc(), diag_compat::template_arg_extra_parens) << Arg->getSourceRange(); ExtraParens = true; } @@ -6655,10 +6649,7 @@ CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param, bool ExtraParens = false; while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { if (!Invalid && !ExtraParens) { - S.Diag(Arg->getBeginLoc(), - S.getLangOpts().CPlusPlus11 - ? diag::compat_cxx11_template_arg_extra_parens - : diag::compat_pre_cxx11_template_arg_extra_parens) + S.DiagCompat(Arg->getBeginLoc(), diag_compat::template_arg_extra_parens) << Arg->getSourceRange(); ExtraParens = true; } @@ -10639,9 +10630,7 @@ TypeResult Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, return true; if (TypenameLoc.isValid() && S && !S->getTemplateParamParent()) - Diag(TypenameLoc, getLangOpts().CPlusPlus11 - ? diag::compat_cxx11_typename_outside_of_template - : diag::compat_pre_cxx11_typename_outside_of_template) + DiagCompat(TypenameLoc, diag_compat::typename_outside_of_template) << FixItHint::CreateRemoval(TypenameLoc); NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); diff --git a/clang/test/Misc/show-diag-options.c b/clang/test/Misc/show-diag-options.c index 4e98d63195f10..b09820379da36 100644 --- a/clang/test/Misc/show-diag-options.c +++ b/clang/test/Misc/show-diag-options.c @@ -18,7 +18,7 @@ void test(int x, int y) { // BASE: {{.*}}: warning: {{[a-z ]+$}} // OPTION: {{.*}}: warning: {{[a-z ]+}} [-Wparentheses] // OPTION_ERROR: {{.*}}: error: {{[a-z ]+}} [-Werror,-Wparentheses] - // CATEGORY_ID: {{.*}}: warning: {{[a-z ]+}} [2] + // CATEGORY_ID: {{.*}}: warning: {{[a-z ]+}} [{{[0-9]+}}] // CATEGORY_NAME: {{.*}}: warning: {{[a-z ]+}} [Semantic Issue] // OPTION_ERROR_CATEGORY: {{.*}}: error: {{[a-z ]+}} [-Werror,-Wparentheses,Semantic Issue] diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index 8f846a4744bbf..73facbc916714 100644 --- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -1518,6 +1518,50 @@ static void verifyDiagnosticWording(const Record &Diag) { // runs into odd situations like [[clang::warn_unused_result]], // #pragma clang, or --unwindlib=libgcc. } + +/// ClangDiagsCompatIDsEmitter - Emit a set of 'compatibility diagnostic ids' +/// that map to a set of 2 regular diagnostic ids each and which are used to +/// simplify emitting compatibility warnings. +void clang::EmitClangDiagsCompatIDs(const llvm::RecordKeeper &Records, + llvm::raw_ostream &OS, + const std::string &Component) { + ArrayRef<const Record *> Ids = + Records.getAllDerivedDefinitions("CompatWarningId"); + + StringRef PrevComponent = ""; + for (auto [I, R] : enumerate(make_pointee_range(Ids))) { + StringRef DiagComponent = R.getValueAsString("Component"); + if (!Component.empty() && Component != DiagComponent) + continue; + + StringRef CompatDiagName = R.getValueAsString("Name"); + StringRef Diag = R.getValueAsString("Diag"); + StringRef DiagPre = R.getValueAsString("DiagPre"); + int64_t CXXStdVer = R.getValueAsInt("Std"); + + // We don't want to create empty enums since some compilers (including + // Clang) warn about that, so these macros are used to avoid having to + // unconditionally write 'enum {' and '};' in the headers. + if (PrevComponent != DiagComponent) { + if (!PrevComponent.empty()) + OS << "DIAG_COMPAT_IDS_END()\n"; + OS << "DIAG_COMPAT_IDS_BEGIN()\n"; + PrevComponent = DiagComponent; + } + + // FIXME: We sometimes define multiple compat diagnostics with the same + // name, e.g. 'constexpr_body_invalid_stmt' exists for C++14/20/23. It would + // be nice if we could combine all of them into a single compatibility diag + // id. + OS << "DIAG_COMPAT_ID(" << I << ","; + OS << CompatDiagName << "," << CXXStdVer << "," << Diag << "," << DiagPre; + OS << ")\n"; + } + + if (!PrevComponent.empty()) + OS << "DIAG_COMPAT_IDS_END()\n"; +} + /// ClangDiagsEnumsEmitter - The top-level class emits .def files containing /// declarations of Clang diagnostic enums for selects. void clang::EmitClangDiagsEnums(const RecordKeeper &Records, raw_ostream &OS, diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp index 7ffe6d2a913a9..4d3d56ed4b9d7 100644 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -48,6 +48,7 @@ enum ActionType { GenClangBasicWriter, GenClangBuiltins, GenClangBuiltinTemplates, + GenClangDiagsCompatIDs, GenClangDiagsDefs, GenClangDiagsEnums, GenClangDiagGroups, @@ -176,6 +177,8 @@ cl::opt<ActionType> Action( "Generate clang builtins list"), clEnumValN(GenClangBuiltinTemplates, "gen-clang-builtin-templates", "Generate clang builtins list"), + clEnumValN(GenClangDiagsCompatIDs, "gen-clang-diags-compat-ids", + "Generate Clang diagnostic compatibility ids"), clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", "Generate Clang diagnostics definitions"), clEnumValN(GenClangDiagsEnums, "gen-clang-diags-enums", @@ -399,6 +402,9 @@ bool ClangTableGenMain(raw_ostream &OS, const RecordKeeper &Records) { case GenClangBuiltinTemplates: EmitClangBuiltinTemplates(Records, OS); break; + case GenClangDiagsCompatIDs: + EmitClangDiagsCompatIDs(Records, OS, ClangComponent); + break; case GenClangDiagsDefs: EmitClangDiagsDefs(Records, OS, ClangComponent); break; diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h index ae8ea3ad34aa5..c26ce2825ea99 100644 --- a/clang/utils/TableGen/TableGenBackends.h +++ b/clang/utils/TableGen/TableGenBackends.h @@ -91,6 +91,9 @@ void EmitClangBuiltins(const llvm::RecordKeeper &Records, void EmitClangBuiltinTemplates(const llvm::RecordKeeper &Records, llvm::raw_ostream &OS); +void EmitClangDiagsCompatIDs(const llvm::RecordKeeper &Records, + llvm::raw_ostream &OS, + const std::string &Component); void EmitClangDiagsDefs(const llvm::RecordKeeper &Records, llvm::raw_ostream &OS, const std::string &Component); void EmitClangDiagsEnums(const llvm::RecordKeeper &Records, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits