]> granicus.if.org Git - clang/commitdiff
[Parse] Allow 'constexpr' in condition declarations
authorMeador Inge <meadori@codesourcery.com>
Thu, 25 Jun 2015 22:06:40 +0000 (22:06 +0000)
committerMeador Inge <meadori@codesourcery.com>
Thu, 25 Jun 2015 22:06:40 +0000 (22:06 +0000)
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

include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseExprCXX.cpp
lib/Sema/SemaStmt.cpp
test/CXX/drs/dr9xx.cpp

index 7b9f8afafb157ca33e2d5984526cb223a3a95e6f..adae6272237939f456af704916bb51238ffc37e1 100644 (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:
index e3294eca46f68e0759b473769df1b335244b8859..f497c59cec1a5964cec1a9d2c0098be490137260 100644 (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();
   }
index 7fb4b5e5a07f35e5800b21c1f533b12a355e7d2e..02176c410592fff5192bbaea884b3fe5290425e7 100644 (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);
index 50e4345216a6ceb2a1fa8f83c771232460094ef9..6fca974d5b36657784f27eb18e199048dedfff25 100644 (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();
   }
index 4bcd6565e06869d0a3cda8eb8a0a1ab1507472b4..b37e17d6b098ded4167918529b02c5d822485011 100644 (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
+}