Refactor instantiation of declarations within a template into a much
cleaner visitor framework.

Added a visitor for declarations, which is quite similar to the
visitor for statatements.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67104 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 4f0a992..cdb7f08 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1036,7 +1036,6 @@
   // Start the definition of this instantiation.
   ClassTemplateSpec->startDefinition();
 
-
   // Instantiate the base class specifiers.
   if (InstantiateBaseSpecifiers(ClassTemplateSpec, Template))
     Invalid = true;
@@ -1049,155 +1048,19 @@
   for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
                               MemberEnd = Pattern->decls_end();
        Member != MemberEnd; ++Member) {
-    if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(*Member)) {
-      // FIXME: Simplified instantiation of typedefs needs to be made
-      // "real".
-      QualType T = Typedef->getUnderlyingType();
-      if (T->isDependentType()) {
-        T = InstantiateType(T, ClassTemplateSpec->getTemplateArgs(),
-                            ClassTemplateSpec->getNumTemplateArgs(),
-                            Typedef->getLocation(),
-                            Typedef->getDeclName());
-        if (T.isNull()) {
-          Invalid = true;
-          T = Context.IntTy;
-        }
-      }
-       
-      // Create the new typedef
-      TypedefDecl *New 
-        = TypedefDecl::Create(Context, ClassTemplateSpec,
-                              Typedef->getLocation(),
-                              Typedef->getIdentifier(),
-                              T);
-      ClassTemplateSpec->addDecl(New);
-    } 
-    else if (FieldDecl *Field = dyn_cast<FieldDecl>(*Member)) {
-      // FIXME: Simplified instantiation of fields needs to be made
-      // "real".
-      bool InvalidDecl = false;
-      QualType T = Field->getType();
-      if (T->isDependentType())  {
-        T = InstantiateType(T, ClassTemplateSpec->getTemplateArgs(),
-                            ClassTemplateSpec->getNumTemplateArgs(),
-                            Field->getLocation(),
-                            Field->getDeclName());
-        if (!T.isNull() && T->isFunctionType()) {
-          // C++ [temp.arg.type]p3:
-          //   If a declaration acquires a function type through a type
-          //   dependent on a template-parameter and this causes a
-          //   declaration that does not use the syntactic form of a
-          //   function declarator to have function type, the program is
-          //   ill-formed.
-          Diag(Field->getLocation(), diag::err_field_instantiates_to_function) 
-            << T;
-          T = QualType();
-          InvalidDecl = true;
-        }
-      }
-
-      Expr *BitWidth = Field->getBitWidth();
-      if (InvalidDecl)
-        BitWidth = 0;
-      else if (BitWidth) {
-        OwningExprResult InstantiatedBitWidth
-          = InstantiateExpr(BitWidth, 
-                            ClassTemplateSpec->getTemplateArgs(),
-                            ClassTemplateSpec->getNumTemplateArgs());
-        if (InstantiatedBitWidth.isInvalid()) {
-          Invalid = InvalidDecl = true;
-          BitWidth = 0;
-        } else
-          BitWidth = (Expr *)InstantiatedBitWidth.release();
-      }
-
-      FieldDecl *New = CheckFieldDecl(Field->getDeclName(), T,
-                                      ClassTemplateSpec, 
-                                      Field->getLocation(),
-                                      Field->isMutable(),
-                                      BitWidth,
-                                      Field->getAccess(),
-                                      0);
-      if (New) {
-        ClassTemplateSpec->addDecl(New);
-        Fields.push_back(New);
-
-        if (InvalidDecl)
-          New->setInvalidDecl();
-
-        if (New->isInvalidDecl())
-          Invalid = true;
-      }
-    } else if (StaticAssertDecl *SA = dyn_cast<StaticAssertDecl>(*Member)) {
-      Expr *AssertExpr = SA->getAssertExpr();
-      
-      OwningExprResult InstantiatedAssertExpr
-        = InstantiateExpr(AssertExpr, 
-                          ClassTemplateSpec->getTemplateArgs(),
-                          ClassTemplateSpec->getNumTemplateArgs());
-      if (!InstantiatedAssertExpr.isInvalid()) {
-        OwningExprResult Message = Clone(SA->getMessage());
-
-        Decl *New = 
-          (Decl *)ActOnStaticAssertDeclaration(SA->getLocation(), 
-                                               move(InstantiatedAssertExpr),
-                                               move(Message));
-        if (New->isInvalidDecl())
-          Invalid = true;
-          
-      } else
+    Decl *NewMember = InstantiateDecl(*Member, ClassTemplateSpec,
+                                      ClassTemplateSpec->getTemplateArgs(),
+                                      ClassTemplateSpec->getNumTemplateArgs());
+    if (NewMember) {
+      if (NewMember->isInvalidDecl())
         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());
+      else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
+        Fields.push_back(Field);
+    } else {
+      // FIXME: Eventually, a NULL return will mean that one of the
+      // instantiations was a semantic disaster, and we'll want to set
+      // Invalid = true. For now, we expect to skip some members that
+      // we can't yet handle.
     }
   }