llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Erich Keane (erichkeane) <details> <summary>Changes</summary> This causes us to generate an enum to go along with the select diagnostic, which allows for clearer diagnostic error emit lines. The syntax for this is: %enum_select<EnumerationName>{%OptionalEnumeratorName{Text}|{Text2}}0 Where the curley brackets around the select-text are only required if an Enumerator name is provided. The TableGen here emits this as a normal 'select' to the frontend, which permits us to reuse all of the existing 'select' infrastructure. Documentation is the same as well. --- Patch is 30.67 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/122505.diff 20 Files Affected: - (modified) clang/include/clang/Basic/CMakeLists.txt (+5) - (modified) clang/include/clang/Basic/DiagnosticAST.h (+13) - (modified) clang/include/clang/Basic/DiagnosticAnalysis.h (+12) - (modified) clang/include/clang/Basic/DiagnosticComment.h (+13) - (modified) clang/include/clang/Basic/DiagnosticCrossTU.h (+13) - (modified) clang/include/clang/Basic/DiagnosticDriver.h (+13) - (modified) clang/include/clang/Basic/DiagnosticFrontend.h (+13) - (modified) clang/include/clang/Basic/DiagnosticInstallAPI.h (+13) - (modified) clang/include/clang/Basic/DiagnosticLex.h (+12) - (modified) clang/include/clang/Basic/DiagnosticParse.h (+13) - (modified) clang/include/clang/Basic/DiagnosticRefactoring.h (+13) - (modified) clang/include/clang/Basic/DiagnosticSema.h (+13) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5-3) - (modified) clang/include/clang/Basic/DiagnosticSerialization.h (+13) - (modified) clang/lib/Sema/SemaDeclCXX.cpp (+13-12) - (added) clang/test/TableGen/select-enum-errors.td (+16) - (added) clang/test/TableGen/select-enum.td (+26) - (modified) clang/utils/TableGen/ClangDiagnosticsEmitter.cpp (+190-2) - (modified) clang/utils/TableGen/TableGen.cpp (+6) - (modified) clang/utils/TableGen/TableGenBackends.h (+2) ``````````diff diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index 897a610b7f9089..56c27bacdb20b8 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -3,6 +3,11 @@ macro(clang_diag_gen component) -gen-clang-diags-defs -clang-component=${component} SOURCE Diagnostic.td TARGET ClangDiagnostic${component}) + + clang_tablegen(Diagnostic${component}Enums.inc + -gen-clang-diags-enums -clang-component=${component} + SOURCE Diagnostic.td + TARGET ClangDiagnostic${component}Enums) endmacro(clang_diag_gen) clang_diag_gen(Analysis) diff --git a/clang/include/clang/Basic/DiagnosticAST.h b/clang/include/clang/Basic/DiagnosticAST.h index 24ef2689eac01e..4f82114b7406be 100644 --- a/clang/include/clang/Basic/DiagnosticAST.h +++ b/clang/include/clang/Basic/DiagnosticAST.h @@ -22,6 +22,19 @@ enum { #undef DIAG NUM_BUILTIN_AST_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticASTEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticAnalysis.h b/clang/include/clang/Basic/DiagnosticAnalysis.h index 676b58f7d6ef2c..1a49461bcd1738 100644 --- a/clang/include/clang/Basic/DiagnosticAnalysis.h +++ b/clang/include/clang/Basic/DiagnosticAnalysis.h @@ -22,6 +22,18 @@ enum { #undef DIAG NUM_BUILTIN_ANALYSIS_DIAGNOSTICS }; +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticAnalysisEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticComment.h b/clang/include/clang/Basic/DiagnosticComment.h index 17c0053e9a33da..53143ef132e4b4 100644 --- a/clang/include/clang/Basic/DiagnosticComment.h +++ b/clang/include/clang/Basic/DiagnosticComment.h @@ -22,6 +22,19 @@ enum { #undef DIAG NUM_BUILTIN_COMMENT_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticCommentEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticCrossTU.h b/clang/include/clang/Basic/DiagnosticCrossTU.h index 4341bf327b69c0..428da95011027e 100644 --- a/clang/include/clang/Basic/DiagnosticCrossTU.h +++ b/clang/include/clang/Basic/DiagnosticCrossTU.h @@ -22,6 +22,19 @@ enum { #undef DIAG NUM_BUILTIN_CROSSTU_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticCrossTUEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticDriver.h b/clang/include/clang/Basic/DiagnosticDriver.h index 6931bd46542e86..c472afa3f6e967 100644 --- a/clang/include/clang/Basic/DiagnosticDriver.h +++ b/clang/include/clang/Basic/DiagnosticDriver.h @@ -22,6 +22,19 @@ enum { #undef DIAG NUM_BUILTIN_DRIVER_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticDriverEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticFrontend.h b/clang/include/clang/Basic/DiagnosticFrontend.h index ab4e855f2de029..766cac3d655b3e 100644 --- a/clang/include/clang/Basic/DiagnosticFrontend.h +++ b/clang/include/clang/Basic/DiagnosticFrontend.h @@ -22,6 +22,19 @@ enum { #undef DIAG NUM_BUILTIN_FRONTEND_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticFrontendEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticInstallAPI.h b/clang/include/clang/Basic/DiagnosticInstallAPI.h index a76f6e087a2b0a..cbdb00362624b7 100644 --- a/clang/include/clang/Basic/DiagnosticInstallAPI.h +++ b/clang/include/clang/Basic/DiagnosticInstallAPI.h @@ -21,6 +21,19 @@ enum { #undef DIAG NUM_BUILTIN_INSTALLAPI_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticInstallAPIEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // namespace diag } // 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 5f237085ae03a1..d14bf97e8642ed 100644 --- a/clang/include/clang/Basic/DiagnosticLex.h +++ b/clang/include/clang/Basic/DiagnosticLex.h @@ -22,6 +22,18 @@ enum { #undef DIAG NUM_BUILTIN_LEX_DIAGNOSTICS }; +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticLexEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticParse.h b/clang/include/clang/Basic/DiagnosticParse.h index 81a8185d25fb70..275e1a4c39b3fa 100644 --- a/clang/include/clang/Basic/DiagnosticParse.h +++ b/clang/include/clang/Basic/DiagnosticParse.h @@ -22,6 +22,19 @@ enum { #undef DIAG NUM_BUILTIN_PARSE_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticParseEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticRefactoring.h b/clang/include/clang/Basic/DiagnosticRefactoring.h index 9b628dbeb7c268..59d4bc912733aa 100644 --- a/clang/include/clang/Basic/DiagnosticRefactoring.h +++ b/clang/include/clang/Basic/DiagnosticRefactoring.h @@ -22,6 +22,19 @@ enum { #undef DIAG NUM_BUILTIN_REFACTORING_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticRefactoringEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticSema.h b/clang/include/clang/Basic/DiagnosticSema.h index 45014fe21271d8..84986c7bccf71d 100644 --- a/clang/include/clang/Basic/DiagnosticSema.h +++ b/clang/include/clang/Basic/DiagnosticSema.h @@ -22,6 +22,19 @@ enum { #undef DIAG NUM_BUILTIN_SEMA_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticSemaEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d4e897868f1a9a..bbac4d3fe71a61 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -617,9 +617,11 @@ def err_ambiguous_inherited_constructor : Error< "constructor of %0 inherited from multiple base class subobjects">; def note_ambiguous_inherited_constructor_using : Note< "inherited from base class %0 here">; -def note_using_decl_class_member_workaround : Note< - "use %select{an alias declaration|a typedef declaration|a reference|" - "a const variable|a constexpr variable}0 instead">; +def note_using_decl_class_member_workaround + : Note<"use %enum_select<MemClassWorkaround>{%AliasDecl{an alias " + "declaration}|%TypedefDecl{a typedef declaration}|%ReferenceDecl{a " + "reference}|%ConstVar{a const variable}|%ConstexprVar{a constexpr " + "variable}}0 instead">; def err_using_decl_can_not_refer_to_namespace : Error< "using declaration cannot refer to a namespace">; def note_namespace_using_decl : Note< diff --git a/clang/include/clang/Basic/DiagnosticSerialization.h b/clang/include/clang/Basic/DiagnosticSerialization.h index 0c622a5657737b..6fb836dca1b040 100644 --- a/clang/include/clang/Basic/DiagnosticSerialization.h +++ b/clang/include/clang/Basic/DiagnosticSerialization.h @@ -22,6 +22,19 @@ enum { #undef DIAG NUM_BUILTIN_SERIALIZATION_DIAGNOSTICS }; + +#define DIAG_ENUM(ENUM_NAME) \ + namespace ENUM_NAME { \ + enum { +#define DIAG_ENUM_ITEM(IDX, NAME) NAME = IDX, +#define DIAG_ENUM_END() \ + } \ + ; \ + } +#include "clang/Basic/DiagnosticSerializationEnums.inc" +#undef DIAG_ENUM_END +#undef DIAG_ENUM_ITEM +#undef DIAG_ENUM } // end namespace diag } // end namespace clang diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c5a72cf812ebc9..eb8a9c85c8ebb9 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -13217,18 +13217,18 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename, if (getLangOpts().CPlusPlus11) { // Convert 'using X::Y;' to 'using Y = X::Y;'. Diag(SS.getBeginLoc(), diag::note_using_decl_class_member_workaround) - << 0 // alias declaration - << FixItHint::CreateInsertion(SS.getBeginLoc(), - NameInfo.getName().getAsString() + - " = "); + << diag::MemClassWorkaround::AliasDecl + << FixItHint::CreateInsertion(SS.getBeginLoc(), + NameInfo.getName().getAsString() + + " = "); } else { // Convert 'using X::Y;' to 'typedef X::Y Y;'. SourceLocation InsertLoc = getLocForEndOfToken(NameInfo.getEndLoc()); Diag(InsertLoc, diag::note_using_decl_class_member_workaround) - << 1 // typedef declaration - << FixItHint::CreateReplacement(UsingLoc, "typedef") - << FixItHint::CreateInsertion( - InsertLoc, " " + NameInfo.getName().getAsString()); + << diag::MemClassWorkaround::TypedefDecl + << FixItHint::CreateReplacement(UsingLoc, "typedef") + << FixItHint::CreateInsertion( + InsertLoc, " " + NameInfo.getName().getAsString()); } } else if (R->getAsSingle<VarDecl>()) { // Don't provide a fixit outside C++11 mode; we don't want to suggest @@ -13241,8 +13241,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename, } Diag(UsingLoc, diag::note_using_decl_class_member_workaround) - << 2 // reference declaration - << FixIt; + << diag::MemClassWorkaround::ReferenceDecl << FixIt; } else if (R->getAsSingle<EnumConstantDecl>()) { // Don't provide a fixit outside C++11 mode; we don't want to suggest // repeating the type of the enumeration here, and we can't do so if @@ -13256,8 +13255,10 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename, } Diag(UsingLoc, diag::note_using_decl_class_member_workaround) - << (getLangOpts().CPlusPlus11 ? 4 : 3) // const[expr] variable - << FixIt; + << (getLangOpts().CPlusPlus11 + ? diag::MemClassWorkaround::ConstexprVar + : diag::MemClassWorkaround::ConstVar) + << FixIt; } } diff --git a/clang/test/TableGen/select-enum-errors.td b/clang/test/TableGen/select-enum-errors.td new file mode 100644 index 00000000000000..a2e8c09361760f --- /dev/null +++ b/clang/test/TableGen/select-enum-errors.td @@ -0,0 +1,16 @@ +// RUN: clang-tblgen --gen-clang-diags-enums -I%S %s 2>&1 | FileCheck %s +include "DiagnosticBase.inc" + +def DupeNames1 : Error<"%enum_select<DupeName>{}0">; +def DupeNames2 : Error<"%enum_select<DupeName>{}0">; +// CHECK: error: Duplicate enumeration name 'DupeName' +// CHECK-NEXT: def DupeNames2 +// CHECK: note: Previous diagnostic is here +// CHECK-NEXT: def DupeNames1 + +def DupeValue : Error<"%enum_select<DupeValue>{%Name{V1}|%Name{V2}}0">; +// CHECK: error: Duplicate enumerator name 'Name' + +def EnumValNotExpected : Error<"%enum_select{V1|%Val2{V2}}0">; +// CHECK: expected '<' after enum_select + diff --git a/clang/test/TableGen/select-enum.td b/clang/test/TableGen/select-enum.td new file mode 100644 index 00000000000000..8a92acec62cfb0 --- /dev/null +++ b/clang/test/TableGen/select-enum.td @@ -0,0 +1,26 @@ +// RUN: clang-tblgen --gen-clang-diags-enums -I%S %s 2>&1 | FileCheck %s +include "DiagnosticBase.inc" + +def Diag : Error<"%enum_select<EnumName>{%Val1{V1}|%Val2{V2}|%Val3{V3}}0">; +// CHECK: DIAG_ENUM(EnumName) +// CHECK-NEXT: DIAG_ENUM_ITEM(0, Val1) +// CHECK-NEXT: DIAG_ENUM_ITEM(1, Val2) +// CHECK-NEXT: DIAG_ENUM_ITEM(2, Val3) +// CHECK-NEXT: DIAG_ENUM_END() + +// These are OK, we permit missing values since they might not be useful. +def Missing1 : Error<"%enum_select<DupeEnumName1>{V1|%Val2{V2}|%Val3{V3}}0">; +// CHECK: DIAG_ENUM(DupeEnumName1) +// CHECK-NEXT: DIAG_ENUM_ITEM(1, Val2) +// CHECK-NEXT: DIAG_ENUM_ITEM(2, Val3) +// CHECK-NEXT: DIAG_ENUM_END() +def Missing2 : Error<"%enum_select<DupeEnumName2>{%Val1{V1}|V2|%Val3{V3}}0">; +// CHECK: DIAG_ENUM(DupeEnumName2) +// CHECK-NEXT: DIAG_ENUM_ITEM(0, Val1) +// CHECK-NEXT: DIAG_ENUM_ITEM(2, Val3) +// CHECK-NEXT: DIAG_ENUM_END() +def Missing3 : Error<"%enum_select<DupeEnumName3>{%Val1{V1}|%Val2{V2}|V3}0">; +// CHECK: DIAG_ENUM(DupeEnumName3) +// CHECK-NEXT: DIAG_ENUM_ITEM(0, Val1) +// CHECK-NEXT: DIAG_ENUM_ITEM(1, Val2) +// CHECK-NEXT: DIAG_ENUM_END() diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index 72b3468dac486f..824f0682f5531d 100644 --- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -399,6 +399,7 @@ enum PieceKind { TextPieceClass, PlaceholderPieceClass, SelectPieceClass, + EnumSelectPieceClass, PluralPieceClass, DiffPieceClass, SubstitutionPieceClass, @@ -408,6 +409,7 @@ enum ModifierType { MT_Unknown, MT_Placeholder, MT_Select, + MT_EnumSelect, MT_Sub, MT_Plural, MT_Diff, @@ -421,6 +423,7 @@ enum ModifierType { static StringRef getModifierName(ModifierType MT) { switch (MT) { + case MT_EnumSelect: case MT_Select: return "select"; case MT_Sub: @@ -512,10 +515,26 @@ struct SelectPiece : Piece { static bool classof(const Piece *P) { return P->getPieceClass() == SelectPieceClass || + P->getPieceClass() == EnumSelectPieceClass || P->getPieceClass() == PluralPieceClass; } }; +struct EnumSelectPiece : SelectPiece { + EnumSelectPiece() : SelectPiece(EnumSelectPieceClass, MT_EnumSelect) {} + + StringRef EnumName; + std::vector<StringRef> OptionEnumNames; + + static bool classof(const Piece *P) { + return P->getPieceClass() == EnumSelectPieceClass; + } +}; + +struct EnumValuePiece : Piece { + ModifierType Kind; +}; + struct PluralPiece : SelectPiece { PluralPiece() : SelectPiece(PluralPieceClass, MT_Plural) {} @@ -579,6 +598,9 @@ struct DiagnosticTextBuilder { std::vector<std::string> buildForDocumentation(StringRef Role, const Record *R); std::string buildForDefinition(const Record *R); + llvm::SmallVector<std::pair< + std::string, llvm::SmallVector<std::pair<unsigned, std::string>>>> + buildForEnum(const Record *R); Piece *getSubstitution(SubstitutionPiece *S) const... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/122505 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits