[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
This commit is contained in:
Meador Inge 2015-06-25 22:06:40 +00:00
parent 9b921e5dc9
commit f0af05c4a5
5 changed files with 40 additions and 8 deletions

View File

@ -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:

View File

@ -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();
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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
}