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 @@ -611,7 +611,12 @@ def StaticLocalInInline : DiagGroup<"static-local-in-inline">; def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">; def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>; -def GNUStatementExpression : DiagGroup<"gnu-statement-expression">; +// Allow differentiation between GNU statement expressions in a macro versus +// written directly in source. +def GNUStatementExpressionFromMacroExpansion : + DiagGroup<"gnu-statement-expression-from-macro-expansion">; +def GNUStatementExpression : DiagGroup<"gnu-statement-expression", + [GNUStatementExpressionFromMacroExpansion]>; def StringConcatation : DiagGroup<"string-concatenation">; def StringCompare : DiagGroup<"string-compare">; def StringPlusInt : DiagGroup<"string-plus-int">; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -174,6 +174,9 @@ "statement expression not allowed at file scope">; def ext_gnu_statement_expr : Extension< "use of GNU statement expression extension">, InGroup; +def ext_gnu_statement_expr_macro : Extension< + "use of GNU statement expression extension from macro expansion">, + InGroup; def ext_gnu_conditional_expr : Extension< "use of GNU ?: conditional expression extension, omitting middle operand">, InGroup; def ext_gnu_empty_initializer : Extension< diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -2870,7 +2870,8 @@ // None of these cases should fall through with an invalid Result // unless they've already reported an error. if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) { - Diag(Tok, diag::ext_gnu_statement_expr); + Diag(Tok, OpenLoc.isMacroID() ? diag::ext_gnu_statement_expr_macro + : diag::ext_gnu_statement_expr); checkCompoundToken(OpenLoc, tok::l_paren, CompoundToken::StmtExprBegin); diff --git a/clang/test/Sema/gnu-flags.c b/clang/test/Sema/gnu-flags.c --- a/clang/test/Sema/gnu-flags.c +++ b/clang/test/Sema/gnu-flags.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wno-gnu -// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu +// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \ // RUN: -Wgnu-alignof-expression -Wgnu-case-range -Wgnu-complex-integer -Wgnu-conditional-omitted-operand \ // RUN: -Wgnu-empty-initializer -Wgnu-label-as-value -Wgnu-statement-expression \ @@ -20,6 +20,7 @@ // %clang_cc1 -fsyntax-only -verify %s -DEMPTYINIT -Wno-gnu -Wgnu-empty-initializer // %clang_cc1 -fsyntax-only -verify %s -DLABELVALUE -Wno-gnu -Wgnu-label-as-value // %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXP -Wno-gnu -Wgnu-statement-expression +// %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXPMACRO -Wno-gnu -Wgnu-statement-expression-from-macro-expansion // %clang_cc1 -fsyntax-only -verify %s -DCOMPOUNDLITERALINITIALIZER -Wno-gnu -Wgnu-compound-literal-initializer // %clang_cc1 -fsyntax-only -verify %s -DFLEXIBLEARRAYINITIALIZER -Wno-gnu -Wgnu-flexible-array-initializer // %clang_cc1 -fsyntax-only -verify %s -DREDECLAREDENUM -Wno-gnu -Wgnu-redeclared-enum @@ -95,6 +96,14 @@ int a = ({ 1; }); } +#if ALL || STATEMENTEXP || STATEMENTEXPMACRO +// expected-warning@+5 {{use of GNU statement expression extension from macro expansion}} +#endif + +#define STMT_EXPR_MACRO(a) ({ (a); }) +void statementexprmacro(void) { + int a = STMT_EXPR_MACRO(1); +} #if ALL || COMPOUNDLITERALINITIALIZER // expected-warning@+4 {{initialization of an array of type 'int[5]' from a compound literal of type 'int[5]' is a GNU extension}}