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.

llvm-svn: 225514
This commit is contained in:
David Majnemer 2015-01-09 09:38:14 +00:00
parent ed13fab4bc
commit 02e764487f
5 changed files with 20 additions and 16 deletions

View File

@ -131,6 +131,8 @@ def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">, InGroup<GNULabelsAsValue>;
def ext_gnu_address_of_label : Extension<
"use of GNU address-of-label extension">, InGroup<GNULabelsAsValue>;
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<GNUStatementExpression>;
def ext_gnu_conditional_expr : Extension<

View File

@ -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<SignCompare>, DefaultIgnore;

View File

@ -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();

View File

@ -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.

View File

@ -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}}
};