]> granicus.if.org Git - clang/commitdiff
Introduce a stack of instantiation scopes that are used to store the mapping from...
authorDouglas Gregor <dgregor@apple.com>
Thu, 14 May 2009 21:44:34 +0000 (21:44 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 14 May 2009 21:44:34 +0000 (21:44 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71799 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.cpp
lib/Sema/Sema.h
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/SemaTemplateInstantiateExpr.cpp
test/SemaTemplate/instantiate-expr-2.cpp

index b931cf896728e2f18086c845f6f0c59d86fd8714..411d5a1677d140c6b7351c530bcf6eab4cdf3a54 100644 (file)
@@ -182,7 +182,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     ExternalSource(0), CurContext(0), PreDeclaratorDC(0),
     CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
     GlobalNewDeleteDeclared(false), 
-    CompleteTranslationUnit(CompleteTranslationUnit) {
+    CompleteTranslationUnit(CompleteTranslationUnit),
+    CurrentInstantiationScope(0) {
   
   StdNamespace = 0;
   TUScope = 0;
index 6cc8a99f8e642e7a8dacc4430d1191e045052ec0..d4c03a12a8edae90772bfe1f0398fd01315c0e0f 100644 (file)
@@ -2092,6 +2092,73 @@ public:
 
   void PrintInstantiationStack();
 
+  /// \brief A stack-allocated class that identifies which local
+  /// variable declaration instantiations are present in this scope.
+  ///
+  /// A new instance of this class type will be created whenever we
+  /// instantiate a new function declaration, which will have its own
+  /// set of parameter declarations.
+  class LocalInstantiationScope {
+    /// \brief Reference to the semantic analysis that is performing
+    /// this template instantiation.
+    Sema &SemaRef;
+
+    /// \brief A mapping from local variable declarations that occur
+    /// within a template to their instantiations.
+    ///
+    /// This mapping is used during instantiation to keep track of,
+    /// e.g., function parameter and variable declarations. For example,
+    /// given:
+    ///
+    /// \code
+    ///   template<typename T> T add(T x, T y) { return x + y; }
+    /// \endcode
+    ///
+    /// when we instantiate add<int>, we will introduce a mapping from
+    /// the ParmVarDecl for 'x' that occurs in the template to the
+    /// instantiated ParmVarDecl for 'x'.
+    llvm::DenseMap<VarDecl *, VarDecl *> LocalDecls;
+
+    /// \brief The outer scope, in which contains local variable
+    /// definitions from some other instantiation (that is not
+    /// relevant to this particular scope).
+    LocalInstantiationScope *Outer;
+
+    // This class is non-copyable
+    LocalInstantiationScope(const LocalInstantiationScope &);
+    LocalInstantiationScope &operator=(const LocalInstantiationScope &);
+
+  public:
+    LocalInstantiationScope(Sema &SemaRef)
+      : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope) { 
+      SemaRef.CurrentInstantiationScope = this;
+    }
+
+    ~LocalInstantiationScope() {
+      SemaRef.CurrentInstantiationScope = Outer;
+    }
+
+    VarDecl *getInstantiationOf(VarDecl *Var) {
+      VarDecl *Result = LocalDecls[Var];
+      assert(Result && "Variable was not instantiated in this scope!");
+      return Result;
+    }
+
+    ParmVarDecl *getInstantiationOf(ParmVarDecl *Var) {
+      return cast<ParmVarDecl>(getInstantiationOf(cast<VarDecl>(Var)));
+    }
+
+    void InstantiatedLocal(VarDecl *Var, VarDecl *VarInst) {
+      VarDecl *&Stored = LocalDecls[Var];
+      assert(!Stored && "Already instantiated this local variable");
+      Stored = VarInst;
+    }
+  };
+
+  /// \brief The current instantiation scope used to store local
+  /// variables.
+  LocalInstantiationScope *CurrentInstantiationScope;
+
   QualType InstantiateType(QualType T, const TemplateArgumentList &TemplateArgs,
                            SourceLocation Loc, DeclarationName Entity);
 
index 6ae6b2240b25afb04b3322217bcbddb9a7b04fba..19aaafbcc6b4a16c3a1735fdd155b6741a95a1e2 100644 (file)
@@ -279,6 +279,8 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
   if (D->getKind() != Decl::CXXMethod)
     return 0;
 
+  Sema::LocalInstantiationScope Scope(SemaRef);
+
   llvm::SmallVector<ParmVarDecl *, 16> Params;
   QualType T = InstantiateFunctionType(D, Params);
   if (T.isNull())
@@ -320,6 +322,8 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+  Sema::LocalInstantiationScope Scope(SemaRef);
+
   llvm::SmallVector<ParmVarDecl *, 16> Params;
   QualType T = InstantiateFunctionType(D, Params);
   if (T.isNull())
@@ -363,6 +367,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+  Sema::LocalInstantiationScope Scope(SemaRef);
+
   llvm::SmallVector<ParmVarDecl *, 16> Params;
   QualType T = InstantiateFunctionType(D, Params);
   if (T.isNull())
@@ -391,6 +397,8 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
+  Sema::LocalInstantiationScope Scope(SemaRef);
+
   llvm::SmallVector<ParmVarDecl *, 16> Params;
   QualType T = InstantiateFunctionType(D, Params);
   if (T.isNull())
@@ -452,6 +460,7 @@ ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
   // Note: we don't try to instantiate function parameters until after
   // we've instantiated the function's type. Therefore, we don't have
   // to check for 'void' parameter types here.
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
   return Param;
 }
 
index 89d88ff76ec7466a18245fbb9bfdfb370f52517a..d7b085499724f43cdda9891e653b48ba3663b52b 100644 (file)
@@ -85,6 +85,15 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
                                                  *Arg.getAsIntegral(),
                                                  T, 
                                        E->getSourceRange().getBegin()));
+  } else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
+    ParmVarDecl *ParmInst 
+      = SemaRef.CurrentInstantiationScope->getInstantiationOf(Parm);
+    QualType T = ParmInst->getType();
+    return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(ParmInst,
+                                                      T.getNonReferenceType(),
+                                                           E->getLocation(),
+                                                        T->isDependentType(),
+                                                        T->isDependentType()));
   } else
     assert(false && "Can't handle arbitrary declaration references");
 
index ea1e0af21a6d1c6f2d20d0ce032a39a0df38f035..1832fd4ab7067123521d6ce0dba28634ca4f4639 100644 (file)
@@ -120,8 +120,6 @@ namespace N7 {
   typedef Cond<true, int, double>::Type Type;
 }
 
-#if 0
-// FIXME: Unable to handle general declaration references at this point.
 template<typename T, unsigned long N> struct IntegralConstant { };
 
 template<typename T>
@@ -130,6 +128,5 @@ struct X0 {
 };
 
 void test_X0(X0<int> x, IntegralConstant<int, sizeof(int)> ic) {
-  x.f(ic);
+  x.f(5, ic);
 }
-#endif