[clang] 0b18869 - [Clang] [Diagnostic] Extend DiagCompat() to C language modes (#209241)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 15 12:49:35 PDT 2026
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);
}
}
More information about the cfe-commits
mailing list