[cfe-commits] r67092 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiate-enum.cpp

Douglas Gregor dgregor at apple.com
Tue Mar 17 12:06:02 PDT 2009


Author: dgregor
Date: Tue Mar 17 14:05:46 2009
New Revision: 67092

URL: http://llvm.org/viewvc/llvm-project?rev=67092&view=rev
Log:
Implement instantiation of enums within class templates. This isn't
quite as great as it sounds, because, while we can refer to the
enumerator values outside the template, e.g.,

  adder<long, 3, 4>::value

we can't yet refer to them with dependent names, so no Fibonacci
(yet). 

InstantiateClassTemplateSpecialization is getting messy; next commit
will put it into a less-ugly state.


Added:
    cfe/trunk/test/SemaTemplate/instantiate-enum.cpp
Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=67092&r1=67091&r2=67092&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 17 14:05:46 2009
@@ -399,6 +399,12 @@
   /// the definition of a tag (enumeration, class, struct, or union).
   virtual void ActOnTagFinishDefinition(Scope *S, DeclTy *TagDecl);
 
+  EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum,
+                                      EnumConstantDecl *LastEnumConst,
+                                      SourceLocation IdLoc,
+                                      IdentifierInfo *Id,
+                                      ExprArg val);
+
   virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl,
                                     DeclTy *LastEnumConstant,
                                     SourceLocation IdLoc, IdentifierInfo *Id,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar 17 14:05:46 2009
@@ -3755,6 +3755,57 @@
     ProcessDeclAttributeList(Record, Attr);
 }
 
+EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
+                                          EnumConstantDecl *LastEnumConst,
+                                          SourceLocation IdLoc,
+                                          IdentifierInfo *Id,
+                                          ExprArg val) {
+  Expr *Val = (Expr *)val.get();
+
+  llvm::APSInt EnumVal(32);
+  QualType EltTy;
+  if (Val && !Val->isTypeDependent()) {
+    // Make sure to promote the operand type to int.
+    UsualUnaryConversions(Val);
+    if (Val != val.get()) {
+      val.release();
+      val = Val;
+    }
+
+    // C99 6.7.2.2p2: Make sure we have an integer constant expression.
+    SourceLocation ExpLoc;
+    if (!Val->isValueDependent() &&
+        VerifyIntegerConstantExpression(Val, &EnumVal)) {
+      Val = 0;
+    } else {
+      EltTy = Val->getType();
+    }
+  }
+  
+  if (!Val) {
+    if (LastEnumConst) {
+      // Assign the last value + 1.
+      EnumVal = LastEnumConst->getInitVal();
+      ++EnumVal;
+
+      // Check for overflow on increment.
+      if (EnumVal < LastEnumConst->getInitVal())
+        Diag(IdLoc, diag::warn_enum_value_overflow);
+      
+      EltTy = LastEnumConst->getType();
+    } else {
+      // First value, set to zero.
+      EltTy = Context.IntTy;
+      EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy)));
+    }
+  }
+  
+  val.release();
+  return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
+                                  Val, EnumVal);  
+}
+
+
 Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
                                       DeclTy *lastEnumConst,
                                       SourceLocation IdLoc, IdentifierInfo *Id,
@@ -3794,46 +3845,12 @@
     }
   }
 
-  llvm::APSInt EnumVal(32);
-  QualType EltTy;
-  if (Val) {
-    // Make sure to promote the operand type to int.
-    UsualUnaryConversions(Val);
-    
-    // C99 6.7.2.2p2: Make sure we have an integer constant expression.
-    SourceLocation ExpLoc;
-    if (VerifyIntegerConstantExpression(Val, &EnumVal)) {
-      Val->Destroy(Context);
-      Val = 0;  // Just forget about it.
-    } else {
-      EltTy = Val->getType();
-    }
-  }
-  
-  if (!Val) {
-    if (LastEnumConst) {
-      // Assign the last value + 1.
-      EnumVal = LastEnumConst->getInitVal();
-      ++EnumVal;
+  EnumConstantDecl *New = CheckEnumConstant(TheEnumDecl, LastEnumConst,
+                                            IdLoc, Id, Owned(Val));
 
-      // Check for overflow on increment.
-      if (EnumVal < LastEnumConst->getInitVal())
-        Diag(IdLoc, diag::warn_enum_value_overflow);
-      
-      EltTy = LastEnumConst->getType();
-    } else {
-      // First value, set to zero.
-      EltTy = Context.IntTy;
-      EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy)));
-    }
-  }
-  
-  EnumConstantDecl *New = 
-    EnumConstantDecl::Create(Context, TheEnumDecl, IdLoc, Id, EltTy,
-                             Val, EnumVal);
-  
   // Register this decl in the current scope stack.
-  PushOnScopeChains(New, S);
+  if (New)
+    PushOnScopeChains(New, S);
 
   return New;
 }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Mar 17 14:05:46 2009
@@ -664,8 +664,7 @@
 
 Sema::OwningExprResult
 TemplateExprInstantiator::VisitParenExpr(ParenExpr *E) {
-  Sema::OwningExprResult SubExpr
-    = SemaRef.InstantiateExpr(E->getSubExpr(), TemplateArgs, NumTemplateArgs);
+  Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
   if (SubExpr.isInvalid())
     return SemaRef.ExprError();
 
@@ -733,6 +732,7 @@
     // expression.
     First.release();
     Second.release();
+    // FIXME: Don't reuse the callee here. We need to instantiate it.
     return SemaRef.Owned(new (SemaRef.Context) CXXOperatorCallExpr(
                                                        SemaRef.Context, 
                                                        E->getOperator(),
@@ -1147,6 +1147,57 @@
           
       } else
         Invalid = true;
+    } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(*Member)) {
+      // FIXME: Spaghetti, anyone?
+      EnumDecl *New = EnumDecl::Create(Context, ClassTemplateSpec, 
+                                       Enum->getLocation(),
+                                       Enum->getIdentifier(),
+                                       /*PrevDecl=*/0);
+      ClassTemplateSpec->addDecl(New);
+      New->startDefinition();
+
+      llvm::SmallVector<DeclTy *, 16> Enumerators;
+
+      EnumConstantDecl *LastEnumConst = 0;
+      for (EnumDecl::enumerator_iterator EC = Enum->enumerator_begin(),
+                                      ECEnd = Enum->enumerator_end();
+           EC != ECEnd; ++EC) {
+        // The specified value for the enumerator.
+        OwningExprResult Value = Owned((Expr *)0);
+        if (Expr *UninstValue = EC->getInitExpr()) 
+          Value = InstantiateExpr(UninstValue, 
+                                  ClassTemplateSpec->getTemplateArgs(),
+                                  ClassTemplateSpec->getNumTemplateArgs());
+
+        // Drop the initial value and continue.
+        bool isInvalid = false;
+        if (Value.isInvalid()) {
+          Value = Owned((Expr *)0);
+          isInvalid = true;
+        }
+
+        EnumConstantDecl *NewEnumConst 
+          = CheckEnumConstant(New, LastEnumConst,
+                              EC->getLocation(),
+                              EC->getIdentifier(),
+                              move(Value));
+
+        if (isInvalid) {
+          if (NewEnumConst)
+            NewEnumConst->setInvalidDecl();
+          New->setInvalidDecl();
+          Invalid = true;
+        }
+
+        if (NewEnumConst) {
+          New->addDecl(NewEnumConst);
+          Enumerators.push_back(NewEnumConst);
+          LastEnumConst = NewEnumConst;
+        }
+      }
+      
+      ActOnEnumBody(New->getLocation(), New,
+                    &Enumerators[0], Enumerators.size());
     }
   }
 

Added: cfe/trunk/test/SemaTemplate/instantiate-enum.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-enum.cpp?rev=67092&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-enum.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-enum.cpp Tue Mar 17 14:05:46 2009
@@ -0,0 +1,11 @@
+// RUN: clang -fsyntax-only %s
+
+template<typename T, T I, int J>
+struct adder {
+  enum {
+    value = I + J,
+    value2
+  };
+};
+
+int array1[adder<long, 3, 4>::value == 7? 1 : -1];





More information about the cfe-commits mailing list