From: David Majnemer Date: Fri, 9 Jan 2015 09:38:14 +0000 (+0000) Subject: Parse: Don't crash when namespace is in GNU statement expr X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=57dec60f901f9ebc7ad488e9ea00f7886563e180;p=clang Parse: Don't crash when namespace is in GNU statement expr Parser::ParseNamespace can get a little confused when it found itself inside a compound statement inside of a non-static data member initializer. Try to determine that the statement expression's scope makes sense before trying to parse it's contents. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225514 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index f39c2b888e..239d4d20bb 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -131,6 +131,8 @@ def ext_gnu_indirect_goto : Extension< "use of GNU indirect-goto extension">, InGroup; def ext_gnu_address_of_label : Extension< "use of GNU address-of-label extension">, InGroup; +def err_stmtexpr_file_scope : Error< + "statement expression not allowed at file scope">; def ext_gnu_statement_expr : Extension< "use of GNU statement expression extension">, InGroup; def ext_gnu_conditional_expr : Extension< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d3129bd62e..cfe7b99b93 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4984,8 +4984,6 @@ def err_typecheck_op_on_nonoverlapping_address_space_pointers : Error< "|arithmetic operation with operands of type %diff{ ($ and $)|}0,1}2" " which are pointers to non-overlapping address spaces">; def err_typecheck_assign_const : Error<"read-only variable is not assignable">; -def err_stmtexpr_file_scope : Error< - "statement expression not allowed at file scope">; def warn_mixed_sign_comparison : Warning< "comparison of integers of different signs: %0 and %1">, InGroup, DefaultIgnore; diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index a89036a98c..d0d97de84c 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -2084,16 +2084,21 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // unless they've already reported an error. if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) { Diag(Tok, diag::ext_gnu_statement_expr); - Actions.ActOnStartStmtExpr(); - StmtResult Stmt(ParseCompoundStatement(true)); - ExprType = CompoundStmt; - - // If the substmt parsed correctly, build the AST node. - if (!Stmt.isInvalid()) { - Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation()); + if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) { + Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope)); } else { - Actions.ActOnStmtExprError(); + Actions.ActOnStartStmtExpr(); + + StmtResult Stmt(ParseCompoundStatement(true)); + ExprType = CompoundStmt; + + // If the substmt parsed correctly, build the AST node. + if (!Stmt.isInvalid()) { + Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation()); + } else { + Actions.ActOnStmtExprError(); + } } } else if (ExprType >= CompoundLiteral && BridgeCast) { tok::TokenKind tokenKind = Tok.getKind(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 623d18d04e..68bad16ff3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10275,11 +10275,6 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, assert(!ExprNeedsCleanups && "cleanups within StmtExpr not correctly bound!"); PopExpressionEvaluationContext(); - bool isFileScope - = (getCurFunctionOrMethodDecl() == nullptr) && (getCurBlock() == nullptr); - if (isFileScope) - return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope)); - // FIXME: there are a variety of strange constraints to enforce here, for // example, it is not possible to goto into a stmt expression apparently. // More semantic analysis is needed. diff --git a/test/Parser/namespaces.cpp b/test/Parser/namespaces.cpp index 6491cfd446..25ff73b8ec 100644 --- a/test/Parser/namespaces.cpp +++ b/test/Parser/namespaces.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s // PR6596 namespace g { enum { o = 0 }; } @@ -10,3 +10,7 @@ void foo() { // PR14085 namespace PR14085 {} namespace = PR14085; // expected-error {{expected identifier}} + +struct namespace_nested_in_record { + int k = ({namespace {}}); // expected-error {{statement expression not allowed at file scope}} +};