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));
-// 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;
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;}))
+ };
+}