summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2015-01-09 09:38:14 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2015-01-09 09:38:14 +0000
commit57dec60f901f9ebc7ad488e9ea00f7886563e180 (patch)
tree54cf40aa52beddfec9359f8b89210f2ebaf7b9ec
parent83d12ae2646c6b9db6df794c9510bb1747c3f780 (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Parse/ParseExpr.cpp21
-rw-r--r--lib/Sema/SemaExpr.cpp5
-rw-r--r--test/Parser/namespaces.cpp6
5 files changed, 20 insertions, 16 deletions
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<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<
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<SignCompare>, 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}}
+};