From b9ece24dfc0c600e495c7ff568654718be291cad Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 20 Apr 2015 20:00:49 +0000 Subject: [PATCH] Put statement expression decls in the enclosing code DeclContext We already check that statement expressions are in a function or block, but we didn't do anything with that information. Now we use that DeclContext for the duration of the statement expression. Otherwise, we'd treat statement expression locals as static data members and go into the weeds. llvm-svn: 235335 --- clang/lib/Parse/ParseExpr.cpp | 11 +++++++++++ clang/test/Sema/statements.c | 15 ++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 315c957..e889085 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/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(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/clang/test/Sema/statements.c b/clang/test/Sema/statements.c index 9ab5715..dbb4d56 100644 --- a/clang/test/Sema/statements.c +++ b/clang/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;})) + }; +} -- 2.7.4