Skip to content

Commit

Permalink
[Parse] Allow 'constexpr' in condition declarations
Browse files Browse the repository at this point in the history
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
  • Loading branch information
meadori committed Jun 25, 2015
1 parent 9b921e5 commit f0af05c
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 8 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/Parse/Parser.h
Expand Up @@ -1705,6 +1705,7 @@ class Parser : public CodeCompletionHandler {
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
Expand All @@ -1715,6 +1716,7 @@ class Parser : public CodeCompletionHandler {
case DSC_class:
case DSC_top_level:
case DSC_objc_method_result:
case DSC_condition:
return false;

case DSC_template_type_arg:
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Parse/ParseDecl.cpp
Expand Up @@ -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();
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Parse/ParseExprCXX.cpp
Expand Up @@ -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);
Expand Down
13 changes: 7 additions & 6 deletions clang/lib/Sema/SemaStmt.cpp
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();
}
Expand Down
29 changes: 29 additions & 0 deletions clang/test/CXX/drs/dr9xx.cpp
Expand Up @@ -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
}

0 comments on commit f0af05c

Please sign in to comment.