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.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67092 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 25553e5..4f0a992 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -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());
     }
   }