[cfe-commits] r71814 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/instantiate-expr-2.cpp test/SemaTemplate/instantiate-function-1.cpp

Douglas Gregor dgregor at apple.com
Thu May 14 16:26:19 PDT 2009


Author: dgregor
Date: Thu May 14 18:26:13 2009
New Revision: 71814

URL: http://llvm.org/viewvc/llvm-project?rev=71814&view=rev
Log:
Introduce basic support for instantiating the definitions of member
functions of class templates. Only compound statements and expression
statements are currently implemented.

Added:
    cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp
Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
    cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu May 14 18:26:13 2009
@@ -1970,6 +1970,8 @@
   // C++ Template Instantiation
   //
 
+  const TemplateArgumentList &getTemplateInstantiationArgs(NamedDecl *D);
+
   /// \brief A template instantiation that is currently in progress.
   struct ActiveTemplateInstantiation {
     /// \brief The kind of template instantiation we are performing
@@ -2117,7 +2119,7 @@
     /// 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;
+    llvm::DenseMap<const VarDecl *, VarDecl *> LocalDecls;
 
     /// \brief The outer scope, in which contains local variable
     /// definitions from some other instantiation (that is not
@@ -2138,17 +2140,17 @@
       SemaRef.CurrentInstantiationScope = Outer;
     }
 
-    VarDecl *getInstantiationOf(VarDecl *Var) {
+    VarDecl *getInstantiationOf(const VarDecl *Var) {
       VarDecl *Result = LocalDecls[Var];
       assert(Result && "Variable was not instantiated in this scope!");
       return Result;
     }
 
-    ParmVarDecl *getInstantiationOf(ParmVarDecl *Var) {
+    ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) {
       return cast<ParmVarDecl>(getInstantiationOf(cast<VarDecl>(Var)));
     }
 
-    void InstantiatedLocal(VarDecl *Var, VarDecl *VarInst) {
+    void InstantiatedLocal(const VarDecl *Var, VarDecl *VarInst) {
       VarDecl *&Stored = LocalDecls[Var];
       assert(!Stored && "Already instantiated this local variable");
       Stored = VarInst;
@@ -2165,6 +2167,9 @@
   OwningExprResult InstantiateExpr(Expr *E, 
                                    const TemplateArgumentList &TemplateArgs);
 
+  OwningStmtResult InstantiateStmt(Stmt *S, 
+                                   const TemplateArgumentList &TemplateArgs);
+
   Decl *InstantiateDecl(Decl *D, DeclContext *Owner,
                         const TemplateArgumentList &TemplateArgs);
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu May 14 18:26:13 2009
@@ -2391,27 +2391,19 @@
     }
   }
 
-  // Find the enclosing template, because we need its template
-  // arguments to instantiate this class.
-  DeclContext *EnclosingTemplateCtx = Record->getDeclContext();
-  while (!isa<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx))
-    EnclosingTemplateCtx = EnclosingTemplateCtx->getParent();
-  ClassTemplateSpecializationDecl *EnclosingTemplate 
-    = cast<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx);
-  
   if (!Record->getDefinition(Context)) {
     // If the class has a definition, instantiate it (and all of its
     // members, recursively).
     Pattern = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
     if (Pattern && InstantiateClass(TemplateLoc, Record, Pattern, 
-                                    EnclosingTemplate->getTemplateArgs(),
+                                    getTemplateInstantiationArgs(Record),
                                     /*ExplicitInstantiation=*/true))
       return true;
   } else {
     // Instantiate all of the members of class.
     InstantiatingTemplate Inst(*this, TemplateLoc, Record);
     InstantiateClassMembers(TemplateLoc, Record, 
-                            EnclosingTemplate->getTemplateArgs());
+                            getTemplateInstantiationArgs(Record));
   }
 
   // FIXME: We don't have any representation for explicit

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu May 14 18:26:13 2009
@@ -24,6 +24,26 @@
 // Template Instantiation Support
 //===----------------------------------------------------------------------===/
 
+/// \brief Retrieve the template argument list that should be used to
+/// instantiate the given declaration.
+const TemplateArgumentList &
+Sema::getTemplateInstantiationArgs(NamedDecl *D) {
+  if (ClassTemplateSpecializationDecl *Spec 
+        = dyn_cast<ClassTemplateSpecializationDecl>(D))
+    return Spec->getTemplateArgs();
+
+  DeclContext *EnclosingTemplateCtx = D->getDeclContext();
+  while (!isa<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx)) {
+    assert(!EnclosingTemplateCtx->isFileContext() &&
+           "Tried to get the instantiation arguments of a non-template");
+    EnclosingTemplateCtx = EnclosingTemplateCtx->getParent();
+  }
+
+  ClassTemplateSpecializationDecl *EnclosingTemplate 
+    = cast<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx);
+  return EnclosingTemplate->getTemplateArgs();
+}
+
 Sema::InstantiatingTemplate::
 InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
                       CXXRecordDecl *Entity,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu May 14 18:26:13 2009
@@ -572,6 +572,9 @@
 void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) {
   // FIXME: make this work for function template specializations, too.
 
+  if (Function->isInvalidDecl())
+    return;
+
   // Find the function body that we'll be substituting.
   const FunctionDecl *PatternDecl 
     = Function->getInstantiatedFromMemberFunction();
@@ -582,7 +585,23 @@
   if (!Pattern)
     return;
 
-  // FIXME: instantiate the pattern  
+  // Introduce a new scope where local variable instantiations will be
+  // recorded.
+  LocalInstantiationScope Scope(*this);
+  
+  // Introduce the instantiated function parameters into the local
+  // instantiation scope.
+  for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I)
+    Scope.InstantiatedLocal(PatternDecl->getParamDecl(I),
+                            Function->getParamDecl(I));
+
+  // Instantiate the function body.
+  OwningStmtResult Body 
+    = InstantiateStmt(Pattern, getTemplateInstantiationArgs(Function));
+  if (Body.isInvalid())
+    Function->setInvalidDecl(true);
+  else
+    Function->setBody(Body.takeAs<Stmt>());
 }
 
 /// \brief Instantiate the definition of the given variable from its

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Thu May 14 18:26:13 2009
@@ -423,3 +423,73 @@
   TemplateExprInstantiator Instantiator(*this, TemplateArgs);
   return Instantiator.Visit(E);
 }
+
+namespace {
+  class VISIBILITY_HIDDEN TemplateStmtInstantiator 
+    : public StmtVisitor<TemplateStmtInstantiator, Sema::OwningStmtResult> {
+    Sema &SemaRef;
+    const TemplateArgumentList &TemplateArgs;
+
+  public:
+    typedef Sema::OwningExprResult OwningExprResult;
+    typedef Sema::OwningStmtResult OwningStmtResult;
+
+    TemplateStmtInstantiator(Sema &SemaRef, 
+                             const TemplateArgumentList &TemplateArgs)
+      : SemaRef(SemaRef), TemplateArgs(TemplateArgs) { }
+
+    // FIXME: Once we get closer to completion, replace these
+    // manually-written declarations with automatically-generated ones
+    // from clang/AST/StmtNodes.def.
+    OwningStmtResult VisitCompoundStmt(CompoundStmt *S);
+    OwningStmtResult VisitExpr(Expr *E);
+
+    // Base case. I'm supposed to ignore this.
+    OwningStmtResult VisitStmt(Stmt *S) { 
+      S->dump();
+      assert(false && "Cannot instantiate this kind of statement");
+      return SemaRef.StmtError(); 
+    }
+  };
+}
+
+Sema::OwningStmtResult 
+TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) {
+  // FIXME: We need an *easy* RAII way to delete these statements if
+  // something goes wrong.
+  llvm::SmallVector<Stmt *, 16> Statements;
+  
+  for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
+       B != BEnd; ++B) {
+    OwningStmtResult Result = Visit(*B);
+    if (Result.isInvalid()) {
+      // FIXME: This should be handled by an RAII destructor.
+      for (unsigned I = 0, N = Statements.size(); I != N; ++I)
+        Statements[I]->Destroy(SemaRef.Context);
+      return SemaRef.StmtError();
+    }
+
+    Statements.push_back(Result.takeAs<Stmt>());
+  }
+
+  return SemaRef.Owned(
+           new (SemaRef.Context) CompoundStmt(SemaRef.Context,
+                                              &Statements[0], 
+                                              Statements.size(),
+                                              S->getLBracLoc(),
+                                              S->getRBracLoc()));
+}
+
+Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) {
+  Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs);
+  if (Result.isInvalid())
+    return SemaRef.StmtError();
+  
+  return SemaRef.Owned(Result.takeAs<Stmt>());
+}
+
+Sema::OwningStmtResult 
+Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
+  TemplateStmtInstantiator Instantiator(*this, TemplateArgs);
+  return Instantiator.Visit(S);
+}

Modified: cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp?rev=71814&r1=71813&r2=71814&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp Thu May 14 18:26:13 2009
@@ -116,7 +116,7 @@
 
   //Cond<true, int*, double> C; // Errors
   //int V(C.foo()); // Errors
-  //typedef Cond<true, int*, double>::Type Type; // Errors + CRASHES!
+  //typedef Cond<true, int*, double>::Type Type; // Errors
   typedef Cond<true, int, double>::Type Type;
 }
 
@@ -128,5 +128,5 @@
 };
 
 void test_X0(X0<int> x, IntegralConstant<int, sizeof(int)> ic) {
-  x.f(5, ic);
+  x.f(5,ic);
 }

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

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp Thu May 14 18:26:13 2009
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, typename U>
+struct X0 {
+  void f(T x, U y) { 
+    x + y; // expected-error{{invalid operands}}
+  }
+};
+
+struct X1 { };
+
+template struct X0<int, float>;
+template struct X0<int*, int>;
+template struct X0<int X1::*, int>; // expected-note{{instantiation of}}





More information about the cfe-commits mailing list