]> granicus.if.org Git - clang/commitdiff
Put statement expression decls in the enclosing code DeclContext
authorReid Kleckner <reid@kleckner.net>
Mon, 20 Apr 2015 20:00:49 +0000 (20:00 +0000)
committerReid Kleckner <reid@kleckner.net>
Mon, 20 Apr 2015 20:00:49 +0000 (20:00 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@235335 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Parse/ParseExpr.cpp
test/Sema/statements.c

index 315c9574e95b02281d7d2a18481a797e3da685b0..e889085b829e30b09afdc3f7092644c69629bc30 100644 (file)
@@ -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));
index 9ab571521a3af80a49ca950ec8005c5685e5444e..dbb4d56ee1d17aed11ba083e0f20b20cff1c4248 100644 (file)
@@ -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;}))
+  };
+}