[cfe-commits] r67104 - in /cfe/trunk: include/clang/AST/DeclVisitor.h lib/Sema/CMakeLists.txt lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp

Douglas Gregor dgregor at apple.com
Tue Mar 17 14:15:41 PDT 2009


Author: dgregor
Date: Tue Mar 17 16:15:40 2009
New Revision: 67104

URL: http://llvm.org/viewvc/llvm-project?rev=67104&view=rev
Log:
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.


Added:
    cfe/trunk/include/clang/AST/DeclVisitor.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
Modified:
    cfe/trunk/lib/Sema/CMakeLists.txt
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp

Added: cfe/trunk/include/clang/AST/DeclVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclVisitor.h?rev=67104&view=auto

==============================================================================
--- cfe/trunk/include/clang/AST/DeclVisitor.h (added)
+++ cfe/trunk/include/clang/AST/DeclVisitor.h Tue Mar 17 16:15:40 2009
@@ -0,0 +1,49 @@
+//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the DeclVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DECLVISITOR_H
+#define LLVM_CLANG_AST_DECLVISITOR_H
+
+namespace clang {
+
+#define DISPATCH(NAME, CLASS) \
+  return static_cast<ImplClass*>(this)-> Visit##NAME(static_cast<CLASS*>(D))
+
+/// \brief A simple visitor class that helps create declaration visitors.
+template<typename ImplClass, typename RetTy=void>
+class DeclVisitor {
+public:
+  RetTy Visit(Decl *D) {
+    switch (D->getKind()) {
+      default: assert(false && "Decl that isn't part of DeclNodes.def!");
+#define DECL(Derived, Base) \
+      case Decl::Derived: DISPATCH(Derived##Decl, Derived##Decl);
+#define ABSTRACT_DECL(Derived, Base)
+#include "clang/AST/DeclNodes.def"
+    }
+  }
+
+  // If the implementation chooses not to implement a certain visit
+  // method, fall back to the parent.
+#define DECL(Derived, Base)                                             \
+  RetTy Visit##Derived##Decl(Derived##Decl *D) { DISPATCH(Base, Base); }
+#define ABSTRACT_DECL(Derived, Base) DECL(Derived, Base)
+#include "clang/AST/DeclNodes.def"
+
+  RetTy VisitDecl(Decl *D) { return RetTy(); }
+};
+
+#undef DISPATCH
+
+}  // end namespace clang
+
+#endif // LLVM_CLANG_AST_DECLVISITOR_H

Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=67104&r1=67103&r2=67104&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Tue Mar 17 16:15:40 2009
@@ -22,6 +22,7 @@
   SemaStmt.cpp
   SemaTemplate.cpp
   SemaTemplateInstantiate.cpp
+  SemaTemplateInstantiateDecl.cpp
   SemaType.cpp
   )
 

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 17 16:15:40 2009
@@ -1864,6 +1864,10 @@
                                    const TemplateArgument *TemplateArgs,
                                    unsigned NumTemplateArgs);
 
+  Decl *InstantiateDecl(Decl *D, DeclContext *Owner,
+                        const TemplateArgument *TemplateArgs,
+                        unsigned NumTemplateArgs);
+
   bool 
   InstantiateBaseSpecifiers(ClassTemplateSpecializationDecl *ClassTemplateSpec,
                             ClassTemplateDecl *ClassTemplate);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Mar 17 16:15:40 2009
@@ -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.
     }
   }
 

Added: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=67104&view=auto

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (added)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Mar 17 16:15:40 2009
@@ -0,0 +1,202 @@
+//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+//  This file implements C++ template instantiation for declarations.
+//
+//===----------------------------------------------------------------------===/
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace clang;
+
+namespace {
+  class VISIBILITY_HIDDEN TemplateDeclInstantiator 
+    : public DeclVisitor<TemplateDeclInstantiator, Decl *> 
+  {
+    Sema &SemaRef;
+    DeclContext *Owner;
+    const TemplateArgument *TemplateArgs;
+    unsigned NumTemplateArgs;
+    
+  public:
+    typedef Sema::OwningExprResult OwningExprResult;
+
+    TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
+                             const TemplateArgument *TemplateArgs,
+                             unsigned NumTemplateArgs)
+      : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs), 
+        NumTemplateArgs(NumTemplateArgs) { }
+    
+    // FIXME: Once we get closer to completion, replace these
+    // manually-written declarations with automatically-generated ones
+    // from clang/AST/DeclNodes.def.
+    Decl *VisitTypedefDecl(TypedefDecl *D);
+    Decl *VisitFieldDecl(FieldDecl *D);
+    Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
+    Decl *VisitEnumDecl(EnumDecl *D);
+
+    // Base case. FIXME: Remove once we can instantiate everything.
+    Decl *VisitDecl(Decl *) { 
+      return 0;
+    }
+  };
+}
+
+Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
+  bool Invalid = false;
+  QualType T = D->getUnderlyingType();
+  if (T->isDependentType()) {
+    T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
+                                D->getLocation(),
+                                D->getDeclName());
+    if (T.isNull()) {
+      Invalid = true;
+      T = SemaRef.Context.IntTy;
+    }
+  }
+       
+  // Create the new typedef
+  TypedefDecl *Typedef
+    = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+                          D->getIdentifier(), T);
+  if (Invalid)
+    Typedef->setInvalidDecl();
+
+  Owner->addDecl(Typedef);
+  return Typedef;
+}
+
+Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
+  bool Invalid = false;
+  QualType T = D->getType();
+  if (T->isDependentType())  {
+    T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
+                                D->getLocation(),
+                                D->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.
+      SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
+        << T;
+      T = QualType();
+      Invalid = true;
+    }
+  }
+
+  Expr *BitWidth = D->getBitWidth();
+  if (Invalid)
+    BitWidth = 0;
+  else if (BitWidth) {
+    OwningExprResult InstantiatedBitWidth
+      = SemaRef.InstantiateExpr(BitWidth, TemplateArgs, NumTemplateArgs);
+    if (InstantiatedBitWidth.isInvalid()) {
+      Invalid = true;
+      BitWidth = 0;
+    } else
+      BitWidth = (Expr *)InstantiatedBitWidth.release();
+  }
+
+  FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), T,
+                                            cast<RecordDecl>(Owner), 
+                                            D->getLocation(),
+                                            D->isMutable(),
+                                            BitWidth,
+                                            D->getAccess(),
+                                            0);
+  if (Field) {
+    if (Invalid)
+      Field->setInvalidDecl();
+    
+    Owner->addDecl(Field);
+  }
+
+  return Field;
+}
+
+Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
+  Expr *AssertExpr = D->getAssertExpr();
+      
+  OwningExprResult InstantiatedAssertExpr
+    = SemaRef.InstantiateExpr(AssertExpr, TemplateArgs, NumTemplateArgs);
+  if (InstantiatedAssertExpr.isInvalid())
+    return 0;
+
+  OwningExprResult Message = SemaRef.Clone(D->getMessage());
+  Decl *StaticAssert 
+    = (Decl *)SemaRef.ActOnStaticAssertDeclaration(D->getLocation(), 
+                                                move(InstantiatedAssertExpr),
+                                                   move(Message));
+  return StaticAssert;
+}
+
+Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
+  EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, 
+                                    D->getLocation(), D->getIdentifier(),
+                                    /*PrevDecl=*/0);
+  Owner->addDecl(Enum);
+  Enum->startDefinition();
+
+  llvm::SmallVector<Sema::DeclTy *, 16> Enumerators;
+
+  EnumConstantDecl *LastEnumConst = 0;
+  for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(),
+         ECEnd = D->enumerator_end();
+       EC != ECEnd; ++EC) {
+    // The specified value for the enumerator.
+    OwningExprResult Value = SemaRef.Owned((Expr *)0);
+    if (Expr *UninstValue = EC->getInitExpr())
+      Value = SemaRef.InstantiateExpr(UninstValue, 
+                                      TemplateArgs, NumTemplateArgs);
+
+    // Drop the initial value and continue.
+    bool isInvalid = false;
+    if (Value.isInvalid()) {
+      Value = SemaRef.Owned((Expr *)0);
+      isInvalid = true;
+    }
+
+    EnumConstantDecl *EnumConst 
+      = SemaRef.CheckEnumConstant(Enum, LastEnumConst,
+                                  EC->getLocation(), EC->getIdentifier(),
+                                  move(Value));
+
+    if (isInvalid) {
+      if (EnumConst)
+        EnumConst->setInvalidDecl();
+      Enum->setInvalidDecl();
+    }
+
+    if (EnumConst) {
+      Enum->addDecl(EnumConst);
+      Enumerators.push_back(EnumConst);
+      LastEnumConst = EnumConst;
+    }
+  }
+      
+  SemaRef.ActOnEnumBody(Enum->getLocation(), Enum,
+                        &Enumerators[0], Enumerators.size());
+
+  return Enum;
+}
+
+Decl *Sema::InstantiateDecl(Decl *D, DeclContext *Owner,
+                            const TemplateArgument *TemplateArgs,
+                            unsigned NumTemplateArgs) {
+  TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs,
+                                        NumTemplateArgs);
+  return Instantiator.Visit(D);
+}
+





More information about the cfe-commits mailing list