Author: Sirraide
Date: 2026-07-15T19:49:29Z
New Revision: 0b18869a684febeb4144cd0213cef3163b8cb37e

URL: 
https://github.com/llvm/llvm-project/commit/0b18869a684febeb4144cd0213cef3163b8cb37e
DIFF: 
https://github.com/llvm/llvm-project/commit/0b18869a684febeb4144cd0213cef3163b8cb37e.diff

LOG: [Clang] [Diagnostic] Extend DiagCompat() to C language modes (#209241)

This expands the compatibility warnings infrastructure added in #132348
to support C mode as well. Implementing this was actually fairly
straight-forward because we are only ever in C _or_ C++ mode, i.e.
during a single compilation we either emit only C compatibility warnings
or only C++ compatibility warnings. This means we can simply reuse the
existing code and just check for different LangOpts depending on whether
we're in C or C++ mode.

Concretely, this means that instead of e.g.

```
def ext_c2y_alignof_incomplete_array : Extension<
  "'alignof' on an incomplete array type is a C2y extension">,
  InGroup<C2y>;
def warn_c2y_compat_alignof_incomplete_array : Warning<
  "'alignof' on an incomplete array type is incompatible with C standards "
  "before C2y">, InGroup<CPre2yCompat>, DefaultIgnore;
```

you can now simply write

```
defm alignof_incomplete_array : C2yCompat<"'alignof' on an incomplete array 
type is">;
```

And when emitting the warning(s), code such as

```
Diag(OpLoc, getLangOpts().C2y
                ? diag::warn_c2y_compat_alignof_incomplete_array
                : diag::ext_c2y_alignof_incomplete_array);
```

can now be replaced with

```
DiagCompat(OpLoc, diag_compat::alignof_incomplete_array);
```

I've also migrated the C compatibility warnings in
DiagnosticSemaKinds.td to use the new system to make sure that
everything is working properly.

Added: 
    

Modified: 
    clang/bindings/python/tests/cindex/test_diagnostics.py
    clang/include/clang/Basic/Diagnostic.td
    clang/include/clang/Basic/DiagnosticIDs.h
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Basic/DiagnosticIDs.cpp
    clang/lib/Parse/Parser.cpp
    clang/lib/Sema/SemaBase.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaStmt.cpp
    clang/lib/Sema/SemaType.cpp

Removed: 
    


################################################################################
diff  --git a/clang/bindings/python/tests/cindex/test_diagnostics.py 
b/clang/bindings/python/tests/cindex/test_diagnostics.py
index 17c1a4e50a20c..6e5d8b525028a 100644
--- a/clang/bindings/python/tests/cindex/test_diagnostics.py
+++ b/clang/bindings/python/tests/cindex/test_diagnostics.py
@@ -75,7 +75,7 @@ def test_diagnostic_category(self):
         self.assertEqual(d.location.line, 1)
         self.assertEqual(d.location.column, 11)
 
-        self.assertEqual(d.category_number, 3)
+        self.assertEqual(d.category_number, 2)
         self.assertEqual(d.category_name, "Semantic Issue")
 
     def test_diagnostic_option(self):
@@ -119,7 +119,7 @@ def test_diagnostic_string_format(self):
         self.assertEqual(str(d), "t.c:1:26: error: expected ';' after struct")
         self.assertEqual(
             d.format(0b111111),
-            "t.c:1:26: error: expected ';' after struct [2, Parse Issue]",
+            "t.c:1:26: error: expected ';' after struct [3, Parse Issue]",
         )
         with self.assertRaises(ValueError):
             d.format(0b1000000)

diff  --git a/clang/include/clang/Basic/Diagnostic.td 
b/clang/include/clang/Basic/Diagnostic.td
index 693984d8241f0..4477828c05eda 100644
--- a/clang/include/clang/Basic/Diagnostic.td
+++ b/clang/include/clang/Basic/Diagnostic.td
@@ -191,60 +191,80 @@ class CompatWarningId<string name, int std, string diag, 
string diag_pre> {
   string CategoryName = ?;
 }
 
-// C++ compatibility warnings.
-multiclass CXXCompat<
+// Compatibility warnings.
+multiclass CompatWarning<
+    // Diagnostic message.
     string message,
+    // Version number.
     int std_ver,
+    // Is this C++?
+    bit cxx,
+    // ExtWarn if true, Extension if false.
     bit ext_warn = true,
-    string std_ver_override = ""#std_ver> {
-    // 'X is a C++YZ extension'.
-    def compat_pre_cxx#std_ver#_#NAME :
-        Diagnostic<!strconcat(message, " a C++", std_ver_override,  " 
extension"),
+    // Language mode name to use in the diagnostic text.
+    string std_ver_name = ""#std_ver,
+    // Version string used in diagnostic group names.
+    string diag_group_ver_str = ""#std_ver> {
+    defvar lang = !if(cxx, "C++", "C");
+    defvar prefix = !if(cxx, "CXX", "C");
+    defvar prefix_lower = !tolower(prefix#diag_group_ver_str);
+    defvar is_cxx_11 = !and(cxx, !eq(std_ver, 11));
+
+    // 'X is a C(++)YZ extension'.
+    def compat_pre_#prefix_lower#_#NAME :
+        Diagnostic<!strconcat(message, " a ", lang, std_ver_name,  " 
extension"),
                    CLASS_EXTENSION,
                    !if(ext_warn, SEV_Warning, SEV_Ignored)>,
-        InGroup<!cast<DiagGroup>("CXX"#std_ver)>;
+        InGroup<!cast<DiagGroup>(prefix#diag_group_ver_str)>;
 
-    // 'X is incompatible with C++98' (if std_ver == 11).
-    // 'X is incompatible with C++ standards before C++YZ' (otherwise).
-    def compat_cxx#std_ver#_#NAME :
-        Warning<!if(!eq(std_ver, 11),
+    // 'X is incompatible with C++98' (if is_cxx_11 is true).
+    // 'X is incompatible with C(++) standards before C(++)YZ' (otherwise).
+    def compat_#prefix_lower#_#NAME :
+        Warning<!if(is_cxx_11,
                     !strconcat(message, " incompatible with C++98"),
-                    !strconcat(message, " incompatible with C++ standards 
before C++", std_ver_override))>,
-        InGroup<!cast<DiagGroup>(!if(!eq(std_ver, 11),
-                                     "CXX98Compat",
-                                     "CXXPre"#std_ver#"Compat"))>,
+                    !strconcat(message, " incompatible with ", lang, " 
standards before ", lang, std_ver_name))>,
+        InGroup<!cast<DiagGroup>(!if(is_cxx_11,
+                                     prefix#"98Compat",
+                                     
prefix#"Pre"#diag_group_ver_str#"Compat"))>,
         DefaultIgnore;
 
     def : CompatWarningId<
         NAME, std_ver,
-        "compat_cxx"#std_ver#"_"#NAME,
-        "compat_pre_cxx"#std_ver#"_"#NAME>;
+        "compat_"#prefix_lower#"_"#NAME,
+        "compat_pre_"#prefix_lower#"_"#NAME>;
 }
 
-// These generate pairs of C++ compatibility warnings of the form:
+// These generate pairs of C(++) compatibility warnings of the form:
 //
-//    - compat_cxx<std>_<name>
-//    - compat_pre_cxx<std>_<name>
+//    - compat_c(xx)<std>_<name>
+//    - compat_pre_c(xx)<std>_<name>
 //
-// The 'compat_cxx...' warning is intended to be issued in C++<std> mode,
-// and the 'compat_pre_cxx...' warning in C++ modes before C++<std>.
+// The 'compat_c(xx)...' warning is intended to be issued in C(++)<std> mode,
+// and the 'compat_pre_c(xx)...' warning in C(++) modes before C(++)<std>.
 //
 // Example:
 //
-//   defm inline_variable : CXX17Compat<"inline variables are">;
+//   defm inline_variable : C(XX)11Compat<"inline variables are">;
 //
 // This generates two warnings:
 //
-//   - compat_cxx17_inline_variable:     'inline variables are incompatible 
with C++ standards before C++17'
-//   - compat_pre_cxx17_inline_variable: 'inline variables are a C++17 
extension'
+//   - compat_c(xx)11_inline_variable:     'inline variables are incompatible 
with C(++) standards before C(++)11'
+//   - compat_pre_c(xx)11_inline_variable: 'inline variables are a C(++)11 
extension'
 //
-multiclass CXX11Compat<string message, bit ext_warn = true> : 
CXXCompat<message, 11, ext_warn>;
-multiclass CXX14Compat<string message, bit ext_warn = true> : 
CXXCompat<message, 14, ext_warn>;
-multiclass CXX17Compat<string message, bit ext_warn = true> : 
CXXCompat<message, 17, ext_warn>;
-multiclass CXX20Compat<string message, bit ext_warn = true> : 
CXXCompat<message, 20, ext_warn>;
-multiclass CXX23Compat<string message, bit ext_warn = true> : 
CXXCompat<message, 23, ext_warn>;
-multiclass CXX26Compat<string message, bit ext_warn = true> : 
CXXCompat<message, 26, ext_warn, "2c">;
-multiclass CXX29Compat<string message, bit ext_warn = true> : 
CXXCompat<message, 29, ext_warn, "2d">;
+multiclass CXX11Compat<string message, bit ext_warn = true> : 
CompatWarning<message, 11, /*cxx=*/true, ext_warn>;
+multiclass CXX14Compat<string message, bit ext_warn = true> : 
CompatWarning<message, 14, /*cxx=*/true, ext_warn>;
+multiclass CXX17Compat<string message, bit ext_warn = true> : 
CompatWarning<message, 17, /*cxx=*/true, ext_warn>;
+multiclass CXX20Compat<string message, bit ext_warn = true> : 
CompatWarning<message, 20, /*cxx=*/true, ext_warn>;
+multiclass CXX23Compat<string message, bit ext_warn = true> : 
CompatWarning<message, 23, /*cxx=*/true, ext_warn>;
+multiclass CXX26Compat<string message, bit ext_warn = true> : 
CompatWarning<message, 26, /*cxx=*/true, ext_warn, "2c">;
+multiclass CXX29Compat<string message, bit ext_warn = true> : 
CompatWarning<message, 29, /*cxx=*/true, ext_warn, "2d">;
+
+// C compatibility warnings generally use Extension rather than ExtWarn.
+multiclass C99Compat<string message, bit ext_warn = false> : 
CompatWarning<message, 99, /*cxx=*/false, ext_warn>;
+multiclass C11Compat<string message, bit ext_warn = false> : 
CompatWarning<message, 11, /*cxx=*/false, ext_warn>;
+multiclass C17Compat<string message, bit ext_warn = false> : 
CompatWarning<message, 17, /*cxx=*/false, ext_warn>;
+multiclass C23Compat<string message, bit ext_warn = false> : 
CompatWarning<message, 23, /*cxx=*/false, ext_warn>;
+multiclass C2yCompat<string message, bit ext_warn = false> : 
CompatWarning<message, 29, /*cxx=*/false, ext_warn, "2y", "2y">;
 
 // Definitions for Diagnostics.
 include "DiagnosticASTKinds.td"

diff  --git a/clang/include/clang/Basic/DiagnosticIDs.h 
b/clang/include/clang/Basic/DiagnosticIDs.h
index 63b5e6a28aac0..f71e47b5cba70 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -485,8 +485,8 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
 
   /// 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);
+  static unsigned getCompatDiagId(const LangOptions &LangOpts,
+                                  unsigned CompatDiagId);
 
   /// Return true if either of the following two conditions hold:
   /// 1. \p Loc is in a system header and the diagnostic kind \p DiagID does

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b6a38b9e281dc..f14288dd2967d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12,6 +12,17 @@
 
 let Component = "Sema" in {
 let CategoryName = "Semantic Issue" in {
+// C23 compatibility with C17.
+defm restrict_on_array_of_pointers : C23Compat<"'restrict' qualifier on an 
array of pointers is">;
+defm non_local_variable_decl_in_for : C23Compat<"declaration of non-local 
variable in 'for' loop is">;
+defm non_variable_decl_in_for : C23Compat<"non-variable declaration in 'for' 
loop is">;
+
+// C2y compatibility with C23.
+defm imaginary_constant : C2yCompat<"imaginary constants are">;
+defm alignof_incomplete_array : C2yCompat<"'alignof' on an incomplete array 
type is">;
+defm increment_complex : C2yCompat<"'%select{--|++}0' on an object of complex 
type is">;
+defm assoc_type_incomplete : C2yCompat<"use of incomplete type %0 in a 
'_Generic' association is">;
+
 // C++11 compatibility with C++98.
 defm nonclass_type_friend : CXX11Compat<"non-class friend type %0 is">;
 defm static_data_member_in_union : CXX11Compat<"static data member %0 in union 
is">;
@@ -66,8 +77,9 @@ 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 cxx#std#_constexpr_body_invalid_stmt : CXXCompat<
-    "use of this statement in a constexpr %select{function|constructor}0 is", 
std>;
+  defm cxx#std#_constexpr_body_invalid_stmt : CompatWarning<
+    "use of this statement in a constexpr %select{function|constructor}0 is",
+    std, /*cxx=*/true>;
 }
 
 def note_previous_decl : Note<"%0 declared here">;
@@ -322,11 +334,6 @@ def ext_designated_init_brace_elision : ExtWarn<
 // Declarations.
 def ext_plain_complex : ExtWarn<
   "plain '_Complex' requires a type specifier; assuming '_Complex double'">;
-def warn_c23_compat_imaginary_constant : Warning<
-  "imaginary constants are incompatible with C standards before C2y">,
-  DefaultIgnore, InGroup<CPre2yCompat>;
-def ext_c2y_imaginary_constant : Extension<
-  "imaginary constants are a C2y extension">, InGroup<C2y>;
 def ext_gnu_imaginary_constant : Extension<
   "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;
 def ext_integer_complex : Extension<
@@ -3826,12 +3833,6 @@ def warn_alignment_not_power_of_two : Warning<
   InGroup<DiagGroup<"non-power-of-two-alignment">>;
 def err_alignment_dependent_typedef_name : Error<
   "requested alignment is dependent but declaration is not dependent">;
-def ext_c2y_alignof_incomplete_array : Extension<
-  "'alignof' on an incomplete array type is a C2y extension">,
-  InGroup<C2y>;
-def warn_c2y_compat_alignof_incomplete_array : Warning<
-  "'alignof' on an incomplete array type is incompatible with C standards "
-  "before C2y">, InGroup<CPre2yCompat>, DefaultIgnore;
 
 def warn_alignment_builtin_useless : Warning<
   "%select{aligning a value|the result of checking whether a value is 
aligned}0"
@@ -7912,11 +7913,6 @@ def warn_c23_compat_utf8_string : Warning<
 def note_cxx20_c23_compat_utf8_string_remove_u8 : Note<
   "remove 'u8' prefix to avoid a change of behavior; "
   "Clang encodes unprefixed narrow string literals as UTF-8">;
-def warn_c23_compat_restrict_on_array_of_pointers : Warning<
-  "'restrict' qualifier on an array of pointers is incompatible with C 
standards before C23">,
-  InGroup<CPre23Compat>, DefaultIgnore;
-def ext_restrict_on_array_of_pointers_c23 : Extension<
-  "'restrict' qualifier on an array of pointers is a C23 extension">, 
InGroup<C23>;
 def err_array_init_
diff erent_type : Error<
   "cannot initialize array %
diff {of type $ with array of type $|"
   "with 
diff erent type of array}0,1">;
@@ -8365,12 +8361,6 @@ def note_gnu_counted_by_void_ptr_use_sized_by
            "to suppress this warning">;
 def err_readonly_message_assignment : Error<
   "assigning to 'readonly' return result of an Objective-C message not 
allowed">;
-def ext_c2y_increment_complex : Extension<
-  "'%select{--|++}0' on an object of complex type is a C2y extension">,
-  InGroup<C2y>;
-def warn_c2y_compat_increment_complex : Warning<
-  "'%select{--|++}0' on an object of complex type is incompatible with C "
-  "standards before C2y">, InGroup<CPre2yCompat>, DefaultIgnore;
 def ext_integer_complement_complex : Extension<
   "ISO C does not support '~' for complex conjugation of %0">;
 def err_nosetter_property_assignment : Error<
@@ -11218,13 +11208,6 @@ def warn_type_safety_null_pointer_required : Warning<
   "specified %0 type tag requires a null pointer">, InGroup<TypeSafety>;
 
 // Generic selections.
-def ext_assoc_type_incomplete : Extension<
-  "incomplete type %0 in a '_Generic' association is a C2y extension">,
-  InGroup<C2y>;
-def warn_c2y_compat_assoc_type_incomplete : Warning<
-  "use of incomplete type %0 in a '_Generic' association is incompatible with "
-  "C standards before C2y">,
-  InGroup<CPre2yCompat>, DefaultIgnore;
 def err_assoc_type_nonobject : Error<
   "type %0 in generic association not an object type">;
 def err_assoc_type_variably_modified : Error<
@@ -11619,22 +11602,6 @@ def err_non_local_variable_decl_in_for : Error<
 def err_non_variable_decl_in_for : Error<
   "non-variable declaration in 'for' loop">;
 
-def ext_c23_non_local_variable_decl_in_for : Extension<
-  "declaration of non-local variable in 'for' loop is a C23 extension">,
-  InGroup<C23>;
-
-def warn_c17_non_local_variable_decl_in_for : Warning<
-  "declaration of non-local variable in 'for' loop is incompatible with C 
standards before C23">,
-  DefaultIgnore, InGroup<CPre23Compat>;
-
-def ext_c23_non_variable_decl_in_for : Extension<
-  "non-variable declaration in 'for' loop is a C23 extension">,
-  InGroup<C23>;
-
-def warn_c17_non_variable_decl_in_for : Warning<
-  "non-variable declaration in 'for' loop is incompatible with C standards 
before C23">,
-  DefaultIgnore, InGroup<CPre23Compat>;
-
 def err_toomany_element_decls : Error<
   "only one element declaration is allowed">;
 def err_selector_element_not_lvalue : Error<

diff  --git a/clang/lib/Basic/DiagnosticIDs.cpp 
b/clang/lib/Basic/DiagnosticIDs.cpp
index 6445aa6f4ecb1..92f96d1b9ad90 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -876,8 +876,8 @@ StringRef DiagnosticIDs::getNearestOption(diag::Flavor 
Flavor,
   return Best;
 }
 
-unsigned DiagnosticIDs::getCXXCompatDiagId(const LangOptions &LangOpts,
-                                           unsigned CompatDiagId) {
+unsigned DiagnosticIDs::getCompatDiagId(const LangOptions &LangOpts,
+                                        unsigned CompatDiagId) {
   struct CompatDiag {
     unsigned StdVer;
     unsigned DiagId;
@@ -888,10 +888,17 @@ unsigned DiagnosticIDs::getCXXCompatDiagId(const 
LangOptions &LangOpts,
   // 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.
+  //
+  // Likewise, for C, we have C99 < C11 < C17 < C23 < C29.
+  //
+  // We do end up with some overlap between C and C++ here, e.g. 2011 is used
+  // for both C11 and C++11, but this doesn't matter since we're never in e.g.
+  // C11 and C++11 mode at the same time (additionally, we should only ever
+  // be issuing C compatibility diagnostics in C mode and likewise for C++).
 #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},
+  {Std >= 98 ? 1900 + Std : 2000 + Std, diag::Diag, diag::DiagPre},
   static constexpr CompatDiag Diags[]{
 #include "clang/Basic/DiagnosticAllCompatIDs.inc"
   };
@@ -902,6 +909,20 @@ unsigned DiagnosticIDs::getCXXCompatDiagId(const 
LangOptions &LangOpts,
   assert(CompatDiagId < std::size(Diags) && "Invalid compat diag id");
 
   unsigned StdVer = [&] {
+    if (!LangOpts.CPlusPlus) {
+      if (LangOpts.C2y)
+        return 2029;
+      if (LangOpts.C23)
+        return 2023;
+      if (LangOpts.C17)
+        return 2017;
+      if (LangOpts.C11)
+        return 2011;
+      if (LangOpts.C99)
+        return 1999;
+      return 1989;
+    }
+
     if (LangOpts.CPlusPlus29)
       return 2029;
     if (LangOpts.CPlusPlus26)

diff  --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 5e1fd4df1a3f0..f30cd68bf1e6c 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -95,8 +95,7 @@ DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned 
DiagID) {
 
 DiagnosticBuilder Parser::DiagCompat(SourceLocation Loc,
                                      unsigned CompatDiagId) {
-  return Diag(Loc,
-              DiagnosticIDs::getCXXCompatDiagId(getLangOpts(), CompatDiagId));
+  return Diag(Loc, DiagnosticIDs::getCompatDiagId(getLangOpts(), 
CompatDiagId));
 }
 
 DiagnosticBuilder Parser::DiagCompat(const Token &Tok, unsigned CompatDiagId) {

diff  --git a/clang/lib/Sema/SemaBase.cpp b/clang/lib/Sema/SemaBase.cpp
index 5524ff50fce85..e16ec2883b89c 100644
--- a/clang/lib/Sema/SemaBase.cpp
+++ b/clang/lib/Sema/SemaBase.cpp
@@ -97,7 +97,6 @@ Sema::SemaDiagnosticBuilder SemaBase::Diag(SourceLocation Loc,
 
 SemaBase::SemaDiagnosticBuilder SemaBase::DiagCompat(SourceLocation Loc,
                                                      unsigned CompatDiagId) {
-  return Diag(Loc,
-              DiagnosticIDs::getCXXCompatDiagId(getLangOpts(), CompatDiagId));
+  return Diag(Loc, DiagnosticIDs::getCompatDiagId(getLangOpts(), 
CompatDiagId));
 }
 } // namespace clang

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6d7cdf9f60dea..b844670543a55 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1924,8 +1924,8 @@ ExprResult Sema::CreateGenericSelectionExpr(
         // earlier because GCC does so.
         unsigned D = 0;
         if (ControllingExpr && Types[i]->getType()->isIncompleteType())
-          D = LangOpts.C2y ? diag::warn_c2y_compat_assoc_type_incomplete
-                           : diag::ext_assoc_type_incomplete;
+          D = LangOpts.C2y ? diag::compat_c2y_assoc_type_incomplete
+                           : diag::compat_pre_c2y_assoc_type_incomplete;
         else if (ControllingExpr && !Types[i]->getType()->isObjectType())
           D = diag::err_assoc_type_nonobject;
         else if (Types[i]->getType()->isVariablyModifiedType())
@@ -4260,14 +4260,10 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, 
Scope *UDLScope) {
                                         
Context.getComplexType(Res->getType()));
 
     // In C++, this is a GNU extension. In C, it's a C2y extension.
-    unsigned DiagId;
     if (getLangOpts().CPlusPlus)
-      DiagId = diag::ext_gnu_imaginary_constant;
-    else if (getLangOpts().C2y)
-      DiagId = diag::warn_c23_compat_imaginary_constant;
+      Diag(Tok.getLocation(), diag::ext_gnu_imaginary_constant);
     else
-      DiagId = diag::ext_c2y_imaginary_constant;
-    Diag(Tok.getLocation(), DiagId);
+      DiagCompat(Tok.getLocation(), diag_compat::imaginary_constant);
   }
   return Res;
 }
@@ -4734,9 +4730,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType 
ExprType,
     // trait to an incomplete array is an extension.
     if (ExprKind == UETT_AlignOf && !getLangOpts().CPlusPlus &&
         ExprType->isIncompleteArrayType())
-      Diag(OpLoc, getLangOpts().C2y
-                      ? diag::warn_c2y_compat_alignof_incomplete_array
-                      : diag::ext_c2y_alignof_incomplete_array);
+      DiagCompat(OpLoc, diag_compat::alignof_incomplete_array);
     ExprType = Context.getBaseElementType(ExprType);
   }
 
@@ -14824,8 +14818,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, 
Expr *Op,
       return QualType();
   } else if (ResType->isAnyComplexType()) {
     // C99 does not support ++/-- on complex types, we allow as an extension.
-    S.Diag(OpLoc, S.getLangOpts().C2y ? diag::warn_c2y_compat_increment_complex
-                                      : diag::ext_c2y_increment_complex)
+    S.DiagCompat(OpLoc, diag_compat::increment_complex)
         << IsInc << Op->getSourceRange();
   } else if (ResType->isPlaceholderType()) {
     ExprResult PR = S.CheckPlaceholderExpr(Op);

diff  --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index e6afcd4404501..cc325620883f0 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2293,10 +2293,8 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, 
SourceLocation LParenLoc,
         if (VarDecl *VD = dyn_cast<VarDecl>(DI)) {
           VarDeclSeen = true;
           if (VD->isLocalVarDecl() && !VD->hasLocalStorage())
-            Diag(DI->getLocation(),
-                 getLangOpts().C23
-                     ? diag::warn_c17_non_local_variable_decl_in_for
-                     : diag::ext_c23_non_local_variable_decl_in_for);
+            DiagCompat(DI->getLocation(),
+                       diag_compat::non_local_variable_decl_in_for);
         } else if (!NonVarSeen) {
           // Keep track of the first non-variable declaration we saw so that
           // we can diagnose if we don't see any variable declarations. This
@@ -2312,9 +2310,8 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, 
SourceLocation LParenLoc,
       // Diagnose if we saw a non-variable declaration but no variable
       // declarations.
       if (NonVarSeen && !VarDeclSeen)
-        Diag(NonVarSeen->getLocation(),
-             getLangOpts().C23 ? diag::warn_c17_non_variable_decl_in_for
-                               : diag::ext_c23_non_variable_decl_in_for);
+        DiagCompat(NonVarSeen->getLocation(),
+                   diag_compat::non_variable_decl_in_for);
     }
   }
 

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 28ff271531a56..5161db6ac1a99 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1651,9 +1651,7 @@ QualType Sema::BuildQualifiedType(QualType T, 
SourceLocation Loc,
       Qs.removeRestrict();
     } else {
       if (T->isArrayType())
-        Diag(Loc, getLangOpts().C23
-                      ? diag::warn_c23_compat_restrict_on_array_of_pointers
-                      : diag::ext_restrict_on_array_of_pointers_c23);
+        DiagCompat(Loc, diag_compat::restrict_on_array_of_pointers);
     }
   }
 


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to