[Clang] [Diagnostic] Extend DiagCompat() to C language modes#209241
[Clang] [Diagnostic] Extend DiagCompat() to C language modes#209241Sirraide wants to merge 1 commit into
Conversation
This expands the compatibility warnings infrastructure added in llvm#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); ```
|
@llvm/pr-subscribers-clang Author: Sirraide ChangesThis 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. you can now simply write And when emitting the warning(s), code such as can now be replaced with I've also migrated the C compatibility warnings in DiagnosticSemaKinds.td to use the new system to make sure that everything is working properly. Patch is 21.38 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/209241.diff 9 Files Affected:
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 86b765fdf1fab..ab3a2de281bb0 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">;
@@ -318,11 +330,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<
@@ -3801,12 +3808,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"
@@ -7882,11 +7883,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_different_type : Error<
"cannot initialize array %diff{of type $ with array of type $|"
"with different type of array}0,1">;
@@ -8335,12 +8331,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<
@@ -11188,13 +11178,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<
@@ -11589,22 +11572,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 592cb1d588370..3bfc228843ae6 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1922,8 +1922,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())
@@ -4258,14 +4258,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;
}
@@ -4732,9 +4728,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);
}
@@ -14822,8 +14816,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 27fee88d20c60..b6592656ca108 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2267,10 +2267,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(),
+ ...
[truncated]
|
|
CI failures look unrelated; it seems main is just broken atm |
yronglin
left a comment
There was a problem hiding this comment.
Thank you working on this! LGTM with a nit.
| 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>; |
There was a problem hiding this comment.
nit: Can we define a CCompat or something else, then we can avoid write a cxx= for every c compatibility warnings.
|
Just leaving a comment here to get notified when this gets merged! |
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.
you can now simply write
And when emitting the warning(s), code such as
can now be replaced with
I've also migrated the C compatibility warnings in DiagnosticSemaKinds.td to use the new system to make sure that everything is working properly.