[clang] [Clang] [NFC] Introduce a helper for emitting compatibility diagnostics (PR #132348)

via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 20 23:47:05 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (Sirraide)

<details>
<summary>Changes</summary>

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.

Another thing I noticed is that the `DiagnosticAST.h`, `DiagnosticAnalysis.h`, etc. headers are quite repetitive; I think we should be able to tablegen those as well; I’m planning to explore that in a separate pr after this because updating all of them every time I changed something while working on this pr has been rather tedious.

---

Patch is 41.25 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132348.diff


32 Files Affected:

- (modified) clang/include/clang/Basic/CMakeLists.txt (+10) 
- (modified) clang/include/clang/Basic/Diagnostic.td (+18) 
- (modified) clang/include/clang/Basic/DiagnosticAST.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticAnalysis.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticComment.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticCrossTU.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticDriver.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticFrontend.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticIDs.h (+18) 
- (modified) clang/include/clang/Basic/DiagnosticInstallAPI.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticLex.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticParse.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+6-6) 
- (modified) clang/include/clang/Basic/DiagnosticRefactoring.h (+12) 
- (modified) clang/include/clang/Basic/DiagnosticSema.h (+13) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+1-1) 
- (modified) clang/include/clang/Basic/DiagnosticSerialization.h (+12) 
- (modified) clang/include/clang/Parse/Parser.h (+6) 
- (modified) clang/include/clang/Sema/SemaBase.h (+4) 
- (modified) clang/lib/Basic/Diagnostic.cpp (+2) 
- (modified) clang/lib/Basic/DiagnosticIDs.cpp (+46) 
- (modified) clang/lib/Parse/ParseDecl.cpp (+2-5) 
- (modified) clang/lib/Parse/Parser.cpp (+9) 
- (modified) clang/lib/Sema/SemaBase.cpp (+6) 
- (modified) clang/lib/Sema/SemaDecl.cpp (+3-8) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+21-54) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+1-3) 
- (modified) clang/lib/Sema/SemaTemplate.cpp (+4-15) 
- (modified) clang/test/Misc/show-diag-options.c (+1-1) 
- (modified) clang/utils/TableGen/ClangDiagnosticsEmitter.cpp (+44) 
- (modified) clang/utils/TableGen/TableGen.cpp (+6) 
- (modified) clang/utils/TableGen/TableGenBackends.h (+3) 


``````````diff
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..c20bf4fcfccb1 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 getCompatDiagId(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 4dc956f7ae6f7..98d598f654cca 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 eed06657536f4..18a013b633816 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 fbe2865b1b7c1..928bc585cd811 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/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 9e2f134135647..6842e0ef3acb6 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/AllDiagnostics.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/DiagnosticDriver.h"
 #include "clang/Basic/DiagnosticError.h"
@@ -39,6 +40,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cassert>
+#include <clang/Basic/LangOptions.h>
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index ca5b8d2da769e..0ab3ac884a161 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::getCompatDiagId(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/DiagnosticAllComp...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/132348


More information about the cfe-commits mailing list