summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Parse/Parser.h2
-rw-r--r--clang/lib/Parse/ParseDecl.cpp2
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp2
-rw-r--r--clang/lib/Sema/SemaStmt.cpp13
-rw-r--r--clang/test/CXX/drs/dr9xx.cpp29
5 files changed, 40 insertions, 8 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 7b9f8afafb1..adae6272237 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1705,6 +1705,7 @@ private:
DSC_top_level, // top-level/namespace declaration context
DSC_template_type_arg, // template type argument context
DSC_objc_method_result, // ObjC method result context, enables 'instancetype'
+ DSC_condition // condition declaration context
};
/// Is this a context in which we are parsing just a type-specifier (or
@@ -1715,6 +1716,7 @@ private:
case DSC_class:
case DSC_top_level:
case DSC_objc_method_result:
+ case DSC_condition:
return false;
case DSC_template_type_arg:
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index e3294eca46f..f497c59cec1 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2173,7 +2173,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
}
// Issue diagnostic and remove constexpr specfier if present.
- if (DS.isConstexprSpecified()) {
+ if (DS.isConstexprSpecified() && DSC != DSC_condition) {
Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr);
DS.ClearConstexprSpec();
}
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 7fb4b5e5a07..02176c41059 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1686,7 +1686,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
// type-specifier-seq
DeclSpec DS(AttrFactory);
DS.takeAttributesFrom(attrs);
- ParseSpecifierQualifierList(DS);
+ ParseSpecifierQualifierList(DS, AS_none, DSC_condition);
// declarator
Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 50e4345216a..6fca974d5b3 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -495,6 +495,7 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
+ CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc);
if (CondResult.isInvalid())
return StmtError();
}
@@ -649,12 +650,10 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
if (CondResult.isInvalid()) return StmtError();
Cond = CondResult.get();
- if (!CondVar) {
- CondResult = ActOnFinishFullExpr(Cond, SwitchLoc);
- if (CondResult.isInvalid())
- return StmtError();
- Cond = CondResult.get();
- }
+ CondResult = ActOnFinishFullExpr(Cond, SwitchLoc);
+ if (CondResult.isInvalid())
+ return StmtError();
+ Cond = CondResult.get();
getCurFunction()->setHasBranchIntoScope();
@@ -1229,6 +1228,7 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond,
if (CondVar) {
ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true);
+ CondResult = ActOnFinishFullExpr(CondResult.get(), WhileLoc);
if (CondResult.isInvalid())
return StmtError();
}
@@ -1634,6 +1634,7 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
if (secondVar) {
ConditionVar = cast<VarDecl>(secondVar);
SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true);
+ SecondResult = ActOnFinishFullExpr(SecondResult.get(), ForLoc);
if (SecondResult.isInvalid())
return StmtError();
}
diff --git a/clang/test/CXX/drs/dr9xx.cpp b/clang/test/CXX/drs/dr9xx.cpp
index 4bcd6565e06..b37e17d6b09 100644
--- a/clang/test/CXX/drs/dr9xx.cpp
+++ b/clang/test/CXX/drs/dr9xx.cpp
@@ -44,3 +44,32 @@ namespace dr990 { // dr990: 3.5
D d{};
#endif
}
+
+namespace dr948 { // dr948: 3.7
+#if __cplusplus >= 201103L
+ class A {
+ public:
+ constexpr A(int v) : v(v) { }
+ constexpr operator int() const { return v; }
+ private:
+ int v;
+ };
+
+ constexpr int id(int x)
+ {
+ return x;
+ }
+
+ void f() {
+ if (constexpr int i = id(101)) { }
+ switch (constexpr int i = id(2)) { default: break; case 2: break; }
+ for (; constexpr int i = id(0); ) { }
+ while (constexpr int i = id(0)) { }
+
+ if (constexpr A i = 101) { }
+ switch (constexpr A i = 2) { default: break; case 2: break; }
+ for (; constexpr A i = 0; ) { }
+ while (constexpr A i = 0) { }
+ }
+#endif
+}
OpenPOWER on IntegriCloud