https://github.com/SihangZhu created https://github.com/llvm/llvm-project/pull/78837
Storage-class specifiers like static are not the first things in a declaration. According to the C Standard, this usage is obsolescent. This patch add a diagnose to warn it. This is a counterpart of gcc's Wswitch-default. >From 773b14c803b69073ef6a073b14b68fe8e5b628c3 Mon Sep 17 00:00:00 2001 From: SihangZhu <zhusih...@huawei.com> Date: Sat, 20 Jan 2024 17:11:31 +0800 Subject: [PATCH] [clang] support Wold-style-declaration as gcc --- .../clang/Basic/DiagnosticCommonKinds.td | 2 ++ clang/include/clang/Basic/DiagnosticGroups.td | 2 ++ clang/lib/Parse/ParseDecl.cpp | 11 +++++++ clang/test/Parser/old-style-declaration.c | 33 +++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 clang/test/Parser/old-style-declaration.c diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 5544dc88004d9a..0d29316767e950 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -84,6 +84,8 @@ def err_param_redefinition : Error<"redefinition of parameter %0">; def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">; def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">, InGroup<DuplicateArgDecl>, DefaultIgnore; +def warn_old_style_declaration: Warning <"'%0' is not at beginning of declaration">, + InGroup<OldStyleDeclaration>, DefaultIgnore; def err_invalid_storage_class_in_func_decl : Error< "invalid storage class specifier in function declarator">; def err_expected_namespace_name : Error<"expected namespace name">; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 6765721ae7002c..ebe751a9947971 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -578,6 +578,7 @@ def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">; def ObjCFlexibleArray : DiagGroup<"objc-flexible-array">; def ObjCBoxing : DiagGroup<"objc-boxing">; +def OldStyleDeclaration : DiagGroup<"old-style-declaration">; def CompletionHandler : DiagGroup<"completion-handler">; def CalledOnceParameter : DiagGroup<"called-once-parameter", [CompletionHandler]>; def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">; @@ -1026,6 +1027,7 @@ def Extra : DiagGroup<"extra", [ EmptyInitStatement, StringConcatation, FUseLdPath, + OldStyleDeclaration, ]>; def Most : DiagGroup<"most", [ diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 356e7851ec639c..ab1555ebc19088 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3348,6 +3348,7 @@ void Parser::ParseDeclarationSpecifiers( while (true) { bool isInvalid = false; bool isStorageClass = false; + bool isFunctionSpecifier = false; const char *PrevSpec = nullptr; unsigned DiagID = 0; @@ -4092,6 +4093,7 @@ void Parser::ParseDeclarationSpecifiers( // function-specifier case tok::kw_inline: isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID); + isFunctionSpecifier = true; break; case tok::kw_virtual: // C++ for OpenCL does not allow virtual function qualifier, to avoid @@ -4104,6 +4106,7 @@ void Parser::ParseDeclarationSpecifiers( isInvalid = true; } else { isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID); + isFunctionSpecifier = true; } break; case tok::kw_explicit: { @@ -4140,12 +4143,14 @@ void Parser::ParseDeclarationSpecifiers( } isInvalid = DS.setFunctionSpecExplicit(ExplicitLoc, PrevSpec, DiagID, ExplicitSpec, CloseParenLoc); + isFunctionSpecifier = true; break; } case tok::kw__Noreturn: if (!getLangOpts().C11) Diag(Tok, diag::ext_c11_feature) << Tok.getName(); isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID); + isFunctionSpecifier = true; break; // alignment-specifier @@ -4552,6 +4557,12 @@ void Parser::ParseDeclarationSpecifiers( continue; } + unsigned Specs = DS.getParsedSpecifiers(); + if (!getLangOpts().CPlusPlus && (isFunctionSpecifier || isStorageClass)) { + if (Specs & DeclSpec::PQ_TypeQualifier || DS.hasTypeSpecifier()) + Diag(Tok, diag::warn_old_style_declaration) << Tok.getName(); + } + DS.SetRangeEnd(ConsumedEnd.isValid() ? ConsumedEnd : Tok.getLocation()); // If the specifier wasn't legal, issue a diagnostic. diff --git a/clang/test/Parser/old-style-declaration.c b/clang/test/Parser/old-style-declaration.c new file mode 100644 index 00000000000000..e7ccea32bfa957 --- /dev/null +++ b/clang/test/Parser/old-style-declaration.c @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wold-style-declaration %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wextra %s + +static int x0; +int __attribute__ ((aligned (16))) static x1; // expected-warning {{'static' is not at beginning of declaration}} + +extern int x2; +int extern x3; // expected-warning {{'extern' is not at beginning of declaration}} + +typedef int x4; +int typedef x5; // expected-warning {{'typedef' is not at beginning of declaration}} + +void g (int); + +void +f (void) +{ + auto int x6 = 0; + int auto x7 = 0; // expected-warning {{'auto' is not at beginning of declaration}} + register int x8 = 0; + int register x9 = 0; // expected-warning {{'register' is not at beginning of declaration}} + g (x6 + x7 + x8 + x9); +} + +const static int x10; // expected-warning {{'static' is not at beginning of declaration}} + +/* Attributes are OK before storage class specifiers, since some + attributes are like such specifiers themselves. */ + +__attribute__((format(printf, 1, 2))) static void h (const char *, ...); +__attribute__((format(printf, 1, 2))) void static i (const char *, ...); // expected-warning {{'static' is not at beginning of declaration}} + +static __thread int var = 5; // not-expected-warning {{'__thread' is not at beginning of declaration}} \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits