From f0af05c4a57475b8e3b9ba9920018ddd5bd00322 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Thu, 25 Jun 2015 22:06:40 +0000 Subject: [PATCH] [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 llvm-svn: 240707 --- clang/include/clang/Parse/Parser.h | 2 ++ clang/lib/Parse/ParseDecl.cpp | 2 +- clang/lib/Parse/ParseExprCXX.cpp | 2 +- clang/lib/Sema/SemaStmt.cpp | 13 +++++++------ 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 7b9f8af..adae627 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 e3294ec..f497c59 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 7fb4b5e..02176c4 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 50e4345..6fca974 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(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/clang/test/CXX/drs/dr9xx.cpp b/clang/test/CXX/drs/dr9xx.cpp index 4bcd656..b37e17d 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 +} -- 2.7.4