[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