melver created this revision. melver added reviewers: aaron.ballman, dblaikie, rsmith. melver requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
GCC allows using -Wdeclaration-after-statement to warn when mixing code and declarations not just with C89, but also C99 and later. Because the warning may legitimately be used where a codebase's style forbids mixing declarations and code, Clang should match GCC behaviour. For example, the Linux kernel is one such codebase, and having this warning work is a requirement for moving to newer standards. Fix it by introducing a matching warning, and switching between the extension or warning depending on the C standard used. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D117232 Files: clang/include/clang/Basic/DiagnosticGroups.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaStmt.cpp clang/test/Sema/warn-mixed-decls-code.c Index: clang/test/Sema/warn-mixed-decls-code.c =================================================================== --- /dev/null +++ clang/test/Sema/warn-mixed-decls-code.c @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wall -Wno-comment -DSILENCE %s +// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify -Wall -pedantic -DSILENCE %s +// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wall -pedantic -DSILENCE %s +// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wno-comment -pedantic %s +// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wno-comment -Wdeclaration-after-statement %s +// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify -Wdeclaration-after-statement %s +// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wdeclaration-after-statement %s + +#ifdef SILENCE + // expected-no-diagnostics +#endif + +void foo(void); + +void test1(void) { + int a; + foo(); + int b; +#ifndef SILENCE + // expected-warning@-2 {{mixing declarations and code}} +#endif + (void)a; + (void)b; +} Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -410,9 +410,12 @@ ArrayRef<Stmt *> Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); - // If we're in C89 mode, check that we don't have any decls after stmts. If - // so, emit an extension diagnostic. - if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { + // If we're in C89 mode or have -Wdeclaration-after-statement, check that we + // don't have any decls after stmts. If so, emit an extension diagnostic. + const unsigned MixedDeclsCodeID = getLangOpts().C99 + ? diag::warn_mixed_decls_code + : diag::ext_mixed_decls_code; + if (!getLangOpts().CPlusPlus && !Diags.isIgnored(MixedDeclsCodeID, L)) { // Note that __extension__ can be around a decl. unsigned i = 0; // Skip over all declarations. @@ -425,7 +428,7 @@ if (i != NumElts) { Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin(); - Diag(D->getLocation(), diag::ext_mixed_decls_code); + Diag(D->getLocation(), MixedDeclsCodeID); } } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9862,7 +9862,9 @@ def ext_mixed_decls_code : Extension< "ISO C90 forbids mixing declarations and code">, - InGroup<DiagGroup<"declaration-after-statement">>; + InGroup<DeclarationAfterStatement>; +def warn_mixed_decls_code : Warning<"mixing declarations and code">, + InGroup<DeclarationAfterStatement>, DefaultIgnore; def err_non_local_variable_decl_in_for : Error< "declaration of non-local variable in 'for' loop">; Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -54,6 +54,7 @@ CompoundTokenSplitBySpace]>; def CoroutineMissingUnhandledException : DiagGroup<"coroutine-missing-unhandled-exception">; +def DeclarationAfterStatement : DiagGroup<"declaration-after-statement">; def DeprecatedExperimentalCoroutine : DiagGroup<"deprecated-experimental-coroutine">; def DeprecatedCoroutine :
Index: clang/test/Sema/warn-mixed-decls-code.c =================================================================== --- /dev/null +++ clang/test/Sema/warn-mixed-decls-code.c @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wall -Wno-comment -DSILENCE %s +// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify -Wall -pedantic -DSILENCE %s +// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wall -pedantic -DSILENCE %s +// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wno-comment -pedantic %s +// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wno-comment -Wdeclaration-after-statement %s +// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify -Wdeclaration-after-statement %s +// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wdeclaration-after-statement %s + +#ifdef SILENCE + // expected-no-diagnostics +#endif + +void foo(void); + +void test1(void) { + int a; + foo(); + int b; +#ifndef SILENCE + // expected-warning@-2 {{mixing declarations and code}} +#endif + (void)a; + (void)b; +} Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -410,9 +410,12 @@ ArrayRef<Stmt *> Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); - // If we're in C89 mode, check that we don't have any decls after stmts. If - // so, emit an extension diagnostic. - if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { + // If we're in C89 mode or have -Wdeclaration-after-statement, check that we + // don't have any decls after stmts. If so, emit an extension diagnostic. + const unsigned MixedDeclsCodeID = getLangOpts().C99 + ? diag::warn_mixed_decls_code + : diag::ext_mixed_decls_code; + if (!getLangOpts().CPlusPlus && !Diags.isIgnored(MixedDeclsCodeID, L)) { // Note that __extension__ can be around a decl. unsigned i = 0; // Skip over all declarations. @@ -425,7 +428,7 @@ if (i != NumElts) { Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin(); - Diag(D->getLocation(), diag::ext_mixed_decls_code); + Diag(D->getLocation(), MixedDeclsCodeID); } } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9862,7 +9862,9 @@ def ext_mixed_decls_code : Extension< "ISO C90 forbids mixing declarations and code">, - InGroup<DiagGroup<"declaration-after-statement">>; + InGroup<DeclarationAfterStatement>; +def warn_mixed_decls_code : Warning<"mixing declarations and code">, + InGroup<DeclarationAfterStatement>, DefaultIgnore; def err_non_local_variable_decl_in_for : Error< "declaration of non-local variable in 'for' loop">; Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -54,6 +54,7 @@ CompoundTokenSplitBySpace]>; def CoroutineMissingUnhandledException : DiagGroup<"coroutine-missing-unhandled-exception">; +def DeclarationAfterStatement : DiagGroup<"declaration-after-statement">; def DeprecatedExperimentalCoroutine : DiagGroup<"deprecated-experimental-coroutine">; def DeprecatedCoroutine :
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits