[cfe-commits] r72461 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/example-dynarray.cpp
Douglas Gregor
dgregor at apple.com
Tue May 26 22:35:13 PDT 2009
Author: dgregor
Date: Wed May 27 00:35:12 2009
New Revision: 72461
URL: http://llvm.org/viewvc/llvm-project?rev=72461&view=rev
Log:
Initial stab at a generalized operation for determining the
instantiation of a declaration from the template version (or version
that lives in a template) and a given set of template arguments. This
needs much, much more testing, but it suffices for simple examples
like
typedef T* iterator;
iterator begin();
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
cfe/trunk/test/SemaTemplate/example-dynarray.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=72461&r1=72460&r2=72461&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed May 27 00:35:12 2009
@@ -2138,7 +2138,7 @@
/// this template instantiation.
Sema &SemaRef;
- /// \brief A mapping from local variable declarations that occur
+ /// \brief A mapping from local declarations that occur
/// within a template to their instantiations.
///
/// This mapping is used during instantiation to keep track of,
@@ -2152,7 +2152,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<const VarDecl *, VarDecl *> LocalDecls;
+ llvm::DenseMap<const Decl *, Decl *> LocalDecls;
/// \brief The outer scope, in which contains local variable
/// definitions from some other instantiation (that is not
@@ -2173,20 +2173,24 @@
SemaRef.CurrentInstantiationScope = Outer;
}
- VarDecl *getInstantiationOf(const VarDecl *Var) {
- VarDecl *Result = LocalDecls[Var];
- assert(Result && "Variable was not instantiated in this scope!");
+ Decl *getInstantiationOf(const Decl *D) {
+ Decl *Result = LocalDecls[D];
+ assert(Result && "declaration was not instantiated in this scope!");
return Result;
}
+ VarDecl *getInstantiationOf(const VarDecl *Var) {
+ return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) {
- return cast<ParmVarDecl>(getInstantiationOf(cast<VarDecl>(Var)));
+ return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
}
- void InstantiatedLocal(const VarDecl *Var, VarDecl *VarInst) {
- VarDecl *&Stored = LocalDecls[Var];
- assert(!Stored && "Already instantiated this local variable");
- Stored = VarInst;
+ void InstantiatedLocal(const Decl *D, Decl *Inst) {
+ Decl *&Stored = LocalDecls[D];
+ assert(!Stored && "Already instantiated this local");
+ Stored = Inst;
}
};
@@ -2246,6 +2250,9 @@
FunctionDecl *Function);
void InstantiateVariableDefinition(VarDecl *Var);
+ NamedDecl *
+ InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs);
+
// Simple function for cloning expressions.
template<typename T>
OwningExprResult Clone(T *E) {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=72461&r1=72460&r2=72461&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed May 27 00:35:12 2009
@@ -406,9 +406,13 @@
QualType
TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
unsigned Quals) const {
- // FIXME: Implement this
- assert(false && "Cannot instantiate TypedefType yet");
- return QualType();
+ TypedefDecl *Typedef
+ = cast_or_null<TypedefDecl>(SemaRef.InstantiateDeclRef(T->getDecl(),
+ TemplateArgs));
+ if (!Typedef)
+ return QualType();
+
+ return SemaRef.Context.getTypeDeclType(Typedef);
}
QualType
@@ -435,17 +439,25 @@
QualType
TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
unsigned Quals) const {
- // FIXME: Implement this
- assert(false && "Cannot instantiate RecordType yet");
- return QualType();
+ RecordDecl *Record
+ = cast_or_null<RecordDecl>(SemaRef.InstantiateDeclRef(T->getDecl(),
+ TemplateArgs));
+ if (!Record)
+ return QualType();
+
+ return SemaRef.Context.getTypeDeclType(Record);
}
QualType
TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T,
unsigned Quals) const {
- // FIXME: Implement this
- assert(false && "Cannot instantiate EnumType yet");
- return QualType();
+ EnumDecl *Enum
+ = cast_or_null<EnumDecl>(SemaRef.InstantiateDeclRef(T->getDecl(),
+ TemplateArgs));
+ if (!Enum)
+ return QualType();
+
+ return SemaRef.Context.getTypeDeclType(Enum);
}
QualType
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=72461&r1=72460&r2=72461&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed May 27 00:35:12 2009
@@ -635,3 +635,125 @@
void Sema::InstantiateVariableDefinition(VarDecl *Var) {
// FIXME: Implement this!
}
+
+static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
+ if (D->getKind() != Other->getKind())
+ return false;
+
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other))
+ return Ctx.getCanonicalDecl(Record->getInstantiatedFromMemberClass())
+ == Ctx.getCanonicalDecl(D);
+
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other))
+ return Ctx.getCanonicalDecl(Function->getInstantiatedFromMemberFunction())
+ == Ctx.getCanonicalDecl(D);
+
+ // FIXME: Need something similar to the above for EnumDecls.
+
+ // FIXME: How can we find instantiations of anonymous unions?
+
+ return D->getDeclName() && isa<NamedDecl>(Other) &&
+ D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
+}
+
+template<typename ForwardIterator>
+static NamedDecl *findInstantiationOf(ASTContext &Ctx,
+ NamedDecl *D,
+ ForwardIterator first,
+ ForwardIterator last) {
+ for (; first != last; ++first)
+ if (isInstantiationOf(Ctx, D, *first))
+ return cast<NamedDecl>(*first);
+
+ return 0;
+}
+
+/// \brief Find the instantiation of the given declaration with the
+/// given template arguments.
+///
+/// This routine is intended to be used when \p D is a declaration
+/// referenced from within a template, that needs to mapped into the
+/// corresponding declaration within an instantiation. For example,
+/// given:
+///
+/// \code
+/// template<typename T>
+/// struct X {
+/// enum Kind {
+/// KnownValue = sizeof(T)
+/// };
+///
+/// bool getKind() const { return KnownValue; }
+/// };
+///
+/// template struct X<int>;
+/// \endcode
+///
+/// In the instantiation of X<int>::getKind(), we need to map the
+/// EnumConstantDecl for KnownValue (which refers to
+/// X<T>::<Kind>::KnownValue) to its instantiation
+/// (X<int>::<Kind>::KnownValue). InstantiateDeclRef() performs this
+/// mapping, given the template arguments 'int'.
+NamedDecl *
+Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs) {
+ DeclContext *ParentDC = D->getDeclContext();
+
+ if (!ParentDC->isFileContext()) {
+ NamedDecl *ParentDecl = cast<NamedDecl>(ParentDC);
+ ParentDecl = InstantiateDeclRef(ParentDecl, TemplateArgs);
+ if (!ParentDecl)
+ return 0;
+
+ ParentDC = cast<DeclContext>(ParentDecl);
+ }
+
+ if (ParentDC->isFunctionOrMethod()) {
+ // D is a local of some kind. Look into the map of local
+ // variables to their instantiations.
+ return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
+ }
+
+ if (ParentDC != D->getDeclContext()) {
+ // We performed some kind of instantiation in the parent context,
+ // so now we need to look into the instantiated parent context to
+ // find the instantiation of the declaration D.
+ NamedDecl *Result = 0;
+ if (D->getDeclName()) {
+ DeclContext::lookup_result Found
+ = ParentDC->lookup(Context, D->getDeclName());
+ Result = findInstantiationOf(Context, D, Found.first, Found.second);
+ } else {
+ // Since we don't have a name for the entity we're looking for,
+ // our only option is to walk through all of the declarations to
+ // find that name. This will occur in a few cases:
+ //
+ // - anonymous struct/union within a template
+ // - unnamed class/struct/union/enum within a template
+ //
+ // FIXME: Find a better way to find these instantiations!
+ Result = findInstantiationOf(Context, D,
+ ParentDC->decls_begin(Context),
+ ParentDC->decls_end(Context));
+ }
+ assert(Result && "Unable to find instantiation of declaration!");
+ D = Result;
+ }
+
+ // D itself might be a class template that we need to instantiate
+ // with the given template arguments.
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
+ if (ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate()) {
+ QualType InjectedClassName
+ = ClassTemplate->getInjectedClassNameType(Context);
+ QualType InstantiatedType = InstantiateType(InjectedClassName,
+ TemplateArgs,
+ Record->getLocation(),
+ Record->getDeclName());
+ if (InstantiatedType.isNull())
+ return 0;
+ if (const RecordType *RT = InstantiatedType->getAsRecordType())
+ D = RT->getDecl();
+ }
+
+ return D;
+}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=72461&r1=72460&r2=72461&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Wed May 27 00:35:12 2009
@@ -108,6 +108,7 @@
Sema::OwningExprResult
TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
+ // FIXME: Recast this in terms of Sema::InstantiateDeclRef.
Decl *D = E->getDecl();
ValueDecl *NewD = 0;
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
Modified: cfe/trunk/test/SemaTemplate/example-dynarray.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/example-dynarray.cpp?rev=72461&r1=72460&r2=72461&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/example-dynarray.cpp (original)
+++ cfe/trunk/test/SemaTemplate/example-dynarray.cpp Wed May 27 00:35:12 2009
@@ -77,16 +77,14 @@
return Start[Idx];
}
- // FIXME: use these for begin/end when we can instantiate
- // TypedefType nodes.
typedef T* iterator;
typedef const T* const_iterator;
- T* begin() { return Start; }
- const T* begin() const { return Start; }
+ iterator begin() { return Start; }
+ const_iterator begin() const { return Start; }
- T* end() { return Last; }
- const T* end() const { return Last; }
+ iterator end() { return Last; }
+ const_iterator end() const { return Last; }
public:
T* Start, *Last, *End;
@@ -115,6 +113,9 @@
for (dynarray<int>::iterator I = di.begin(), IEnd = di.end(); I != IEnd; ++I)
assert(*I == I - di.begin());
+ for (int I = 0, N = di.size(); I != N; ++I)
+ assert(di[I] == I);
+
di.pop_back();
assert(di.size() == 4);
di.push_back(4);
More information about the cfe-commits
mailing list