diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/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 : diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9862,7 +9862,9 @@ def ext_mixed_decls_code : Extension< "ISO C90 forbids mixing declarations and code">, - InGroup>; + InGroup; +def warn_mixed_decls_code : Warning<"mixing declarations and code">, + InGroup, DefaultIgnore; def err_non_local_variable_decl_in_for : Error< "declaration of non-local variable in 'for' loop">; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -410,9 +410,12 @@ ArrayRef 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(Elts[i])->decl_begin(); - Diag(D->getLocation(), diag::ext_mixed_decls_code); + Diag(D->getLocation(), MixedDeclsCodeID); } } diff --git a/clang/test/Sema/warn-mixed-decls-code.c b/clang/test/Sema/warn-mixed-decls-code.c new file mode 100644 --- /dev/null +++ b/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; +}