diff options
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 13 | ||||
-rw-r--r-- | clang/test/CXX/drs/dr9xx.cpp | 29 |
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 +} |