[cfe-commits] r85741 - in /cfe/trunk: lib/AST/Expr.cpp lib/AST/ExprConstant.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/instantiate-declref-ice.cpp

Douglas Gregor dgregor at apple.com
Sun Nov 1 12:32:49 PST 2009


Author: dgregor
Date: Sun Nov  1 14:32:48 2009
New Revision: 85741

URL: http://llvm.org/viewvc/llvm-project?rev=85741&view=rev
Log:
When determining whether a reference to a static data member is an
integral constant expression, make sure to find where the initializer
was provided---inside or outside the class definition---since that can
affect whether we have an integral constant expression (and, we need
to see the initializer itself).

Modified:
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaTemplate/instantiate-declref-ice.cpp

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=85741&r1=85740&r2=85741&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Sun Nov  1 14:32:48 2009
@@ -22,6 +22,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 using namespace clang;
@@ -1538,16 +1539,35 @@
       //   type initialized by an ICE can be used in ICEs.
       if (const VarDecl *Dcl =
               dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())) {
-        if (Dcl->isInitKnownICE()) {
-          // We have already checked whether this subexpression is an
-          // integral constant expression.
-          if (Dcl->isInitICE())
-            return NoDiag();
-          else
-            return ICEDiag(2, E->getLocStart());
-        }
+        Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers();
+        if (Quals.hasVolatile() || !Quals.hasConst())
+          return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+        
+        // Look for the definition of this variable, which will actually have
+        // an initializer.
+        const VarDecl *Def = 0;
+        const Expr *Init = Dcl->getDefinition(Def);
+        if (Init) {
+          if (Def->isInitKnownICE()) {
+            // We have already checked whether this subexpression is an
+            // integral constant expression.
+            if (Def->isInitICE())
+              return NoDiag();
+            else
+              return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+          }
 
-        if (const Expr *Init = Dcl->getInit()) {
+          // C++ [class.static.data]p4:
+          //   If a static data member is of const integral or const 
+          //   enumeration type, its declaration in the class definition can
+          //   specify a constant-initializer which shall be an integral 
+          //   constant expression (5.19). In that case, the member can appear
+          //   in integral constant expressions.
+          if (Def->isOutOfLine()) {
+            Dcl->setInitKnownICE(Ctx, false);
+            return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+          }
+          
           ICEDiag Result = CheckICE(Init, Ctx);
           // Cache the result of the ICE test.
           Dcl->setInitKnownICE(Ctx, Result.Val == 0);
@@ -1750,7 +1770,7 @@
   }
   EvalResult EvalResult;
   if (!Evaluate(EvalResult, Ctx))
-    assert(0 && "ICE cannot be evaluated!");
+    llvm::llvm_unreachable("ICE cannot be evaluated!");
   assert(!EvalResult.HasSideEffects && "ICE with side effects!");
   assert(EvalResult.Val.isInt() && "ICE that isn't integer!");
   Result = EvalResult.Val.getInt();

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=85741&r1=85740&r2=85741&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sun Nov  1 14:32:48 2009
@@ -270,8 +270,9 @@
     if (!VD->getType()->isReferenceType())
       return APValue(E, 0);
     // FIXME: Check whether VD might be overridden!
-    if (VD->getInit())
-      return Visit(VD->getInit());
+    const VarDecl *Def = 0;
+    if (const Expr *Init = VD->getDefinition(Def))
+      return Visit(const_cast<Expr *>(Init));
   }
 
   return APValue();
@@ -855,11 +856,14 @@
 
   // In C++, const, non-volatile integers initialized with ICEs are ICEs.
   // In C, they can also be folded, although they are not ICEs.
-  if (E->getType().getCVRQualifiers() == Qualifiers::Const) {
+  if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers() 
+                                                        == Qualifiers::Const) {
     if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
-      if (APValue *V = D->getEvaluatedValue())
-        return Success(V->getInt(), E);
-      if (const Expr *Init = D->getInit()) {
+      const VarDecl *Def = 0;
+      if (const Expr *Init = D->getDefinition(Def)) {
+        if (APValue *V = D->getEvaluatedValue())
+          return Success(V->getInt(), E);
+          
         if (Visit(const_cast<Expr*>(Init))) {
           // Cache the evaluated value in the variable declaration.
           D->setEvaluatedValue(Info.Ctx, Result);

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=85741&r1=85740&r2=85741&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Nov  1 14:32:48 2009
@@ -165,7 +165,7 @@
   // which they were instantiated.
   if (Var->isStaticDataMember())
     SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D, 
-                                                        TSK_ImplicitInstantiation);
+                                                     TSK_ImplicitInstantiation);
   
   if (D->getInit()) {
     OwningExprResult Init

Modified: cfe/trunk/test/SemaTemplate/instantiate-declref-ice.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-declref-ice.cpp?rev=85741&r1=85740&r2=85741&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-declref-ice.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-declref-ice.cpp Sun Nov  1 14:32:48 2009
@@ -5,3 +5,33 @@
   x<j>* y;
 };
 
+template<int i>
+const int x<i>::j;
+
+int array0[x<2>::j];
+
+
+template<typename T>
+struct X0 {
+  static const unsigned value = sizeof(T);
+};
+
+template<typename T>
+const unsigned X0<T>::value;
+
+int array1[X0<int>::value == sizeof(int)? 1 : -1];
+
+const unsigned& testX0() { return X0<int>::value; }
+
+int array2[X0<int>::value == sizeof(int)? 1 : -1];
+
+template<typename T>
+struct X1 {
+  static const unsigned value;
+};
+
+template<typename T>
+const unsigned X1<T>::value = sizeof(T);
+
+int array3[X1<int>::value == sizeof(int)? 1 : -1]; // expected-error{{variable length arrays are not permitted in C++}} \
+// expected-error{{variable length array declaration not allowed at file scope}}





More information about the cfe-commits mailing list