diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 315c9574e95b02281d7d2a18481a797e3da685b0..e889085b829e30b09afdc3f7092644c69629bc30 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -2106,6 +2106,17 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) { Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope)); } else { + // Find the nearest non-record decl context. Variables declared in a + // statement expression behave as if they were declared in the enclosing + // function, block, or other code construct. + DeclContext *CodeDC = Actions.CurContext; + while (CodeDC->isRecord() || isa<EnumDecl>(CodeDC)) { + CodeDC = CodeDC->getParent(); + assert(CodeDC && !CodeDC->isFileContext() && + "statement expr not in code context"); + } + Sema::ContextRAII SavedContext(Actions, CodeDC, /*NewThisContext=*/false); + Actions.ActOnStartStmtExpr(); StmtResult Stmt(ParseCompoundStatement(true)); diff --git a/test/Sema/statements.c b/test/Sema/statements.c index 9ab571521a3af80a49ca950ec8005c5685e5444e..dbb4d56ee1d17aed11ba083e0f20b20cff1c4248 100644 --- a/test/Sema/statements.c +++ b/test/Sema/statements.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -triple x86_64-pc-linux-gnu +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple x86_64-pc-linux-gnu -Wno-unevaluated-expression typedef unsigned __uint32_t; @@ -97,3 +97,16 @@ int test_pr8880() { return 1; } +// In PR22849, we considered __ptr to be a static data member of the anonymous +// union. Now we declare it in the parent DeclContext. +void test_pr22849() { + struct Bug { + typeof(({ unsigned long __ptr; (int *)(0); })) __val; + union Nested { + typeof(({ unsigned long __ptr; (int *)(0); })) __val; + } n; + }; + enum E { + SIZE = sizeof(({unsigned long __ptr; __ptr;})) + }; +}