From: Meador Inge Date: Thu, 25 Jun 2015 22:06:40 +0000 (+0000) Subject: [Parse] Allow 'constexpr' in condition declarations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=61cc2c83957bdb59564cfca62a45fa49fa6c6c24;p=clang [Parse] Allow 'constexpr' in condition declarations This patch implements the functionality specified by DR948. The changes are two fold. First, the parser was modified to allow 'constexpr's to appear in condition declarations (which was a hard error before). Second, Sema was modified to cleanup maybe odr-used declarations by way of a call to 'ActOnFinishFullExpr'. As 'constexpr's were not allowed in condition declarations before the cleanup wasn't necessary (such declarations were always odr-used). This fixes PR22491. Differential Revision: http://reviews.llvm.org/D8978 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@240707 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 7b9f8afafb..adae627223 100644 --- a/include/clang/Parse/Parser.h +++ b/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/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index e3294eca46..f497c59cec 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/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/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 7fb4b5e5a0..02176c4105 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/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/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 50e4345216..6fca974d5b 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -495,6 +495,7 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, if (CondVar) { ConditionVar = cast(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(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(secondVar); SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true); + SecondResult = ActOnFinishFullExpr(SecondResult.get(), ForLoc); if (SecondResult.isInvalid()) return StmtError(); } diff --git a/test/CXX/drs/dr9xx.cpp b/test/CXX/drs/dr9xx.cpp index 4bcd6565e0..b37e17d6b0 100644 --- a/test/CXX/drs/dr9xx.cpp +++ b/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 +}