[clang] [clang] support Wold-style-declaration as gcc (PR #78837)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 20 01:25:23 PST 2024
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 <zhusihang at 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
More information about the cfe-commits
mailing list