diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-06-25 22:08:12 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-06-25 22:08:12 +0000 |
commit | e53060fa78ad7e98352049f72787bdb7543e2a48 (patch) | |
tree | d0c7858e55ac3c7d6f8fb15257c37385e952393e /lib/Sema/SemaLookup.cpp | |
parent | 6e4a86ddadea69e855603c1733d8b5bc99fc910d (diff) |
Improved semantic analysis and AST respresentation for function
templates.
For example, this now type-checks (but does not instantiate the body
of deref<int>):
template<typename T> T& deref(T* t) { return *t; }
void test(int *ip) {
int &ir = deref(ip);
}
Specific changes/additions:
* Template argument deduction from a call to a function template.
* Instantiation of a function template specializations (just the
declarations) from the template arguments deduced from a call.
* FunctionTemplateDecls are stored directly in declaration contexts
and found via name lookup (all forms), rather than finding the
FunctionDecl and then realizing it is a template. This is
responsible for most of the churn, since some of the core
declaration matching and lookup code assumes that all functions are
FunctionDecls.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74213 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 9bcf320771..e6f3d9ec3b 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -125,21 +125,30 @@ MaybeConstructOverloadSet(ASTContext &Context, assert(!isa<OverloadedFunctionDecl>(*I) && "Cannot have an overloaded function"); - if (isa<FunctionDecl>(*I)) { + if ((*I)->isFunctionOrFunctionTemplate()) { // If we found a function, there might be more functions. If // so, collect them into an overload set. DeclIterator Last = I; OverloadedFunctionDecl *Ovl = 0; - for (++Last; Last != IEnd && isa<FunctionDecl>(*Last); ++Last) { + for (++Last; + Last != IEnd && (*Last)->isFunctionOrFunctionTemplate(); + ++Last) { if (!Ovl) { // FIXME: We leak this overload set. Eventually, we want to stop // building the declarations for these overload sets, so there will be // nothing to leak. Ovl = OverloadedFunctionDecl::Create(Context, (*I)->getDeclContext(), (*I)->getDeclName()); - Ovl->addOverload(cast<FunctionDecl>(*I)); + if (isa<FunctionDecl>(*I)) + Ovl->addOverload(cast<FunctionDecl>(*I)); + else + Ovl->addOverload(cast<FunctionTemplateDecl>(*I)); } - Ovl->addOverload(cast<FunctionDecl>(*Last)); + + if (isa<FunctionDecl>(*Last)) + Ovl->addOverload(cast<FunctionDecl>(*Last)); + else + Ovl->addOverload(cast<FunctionTemplateDecl>(*Last)); } // If we had more than one function, we built an overload @@ -206,7 +215,7 @@ MergeLookupResults(ASTContext &Context, LookupResultsTy &Results) { if (TagDecl *TD = dyn_cast<TagDecl>(ND)) { TagFound = Context.getCanonicalDecl(TD); TagNames += FoundDecls.insert(TagFound)? 1 : 0; - } else if (isa<FunctionDecl>(ND)) + } else if (ND->isFunctionOrFunctionTemplate()) Functions += FoundDecls.insert(ND)? 1 : 0; else FoundDecls.insert(ND); @@ -334,10 +343,10 @@ Sema::LookupResult::CreateLookupResult(ASTContext &Context, LookupResult Result; Result.Context = &Context; - if (F != L && isa<FunctionDecl>(*F)) { + if (F != L && (*F)->isFunctionOrFunctionTemplate()) { IdentifierResolver::iterator Next = F; ++Next; - if (Next != L && isa<FunctionDecl>(*Next)) { + if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) { Result.StoredKind = OverloadedDeclFromIdResolver; Result.First = F.getAsOpaqueValue(); Result.Last = L.getAsOpaqueValue(); @@ -363,10 +372,10 @@ Sema::LookupResult::CreateLookupResult(ASTContext &Context, LookupResult Result; Result.Context = &Context; - if (F != L && isa<FunctionDecl>(*F)) { + if (F != L && (*F)->isFunctionOrFunctionTemplate()) { DeclContext::lookup_iterator Next = F; ++Next; - if (Next != L && isa<FunctionDecl>(*Next)) { + if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) { Result.StoredKind = OverloadedDeclFromDeclContext; Result.First = reinterpret_cast<uintptr_t>(F); Result.Last = reinterpret_cast<uintptr_t>(L); @@ -1083,7 +1092,7 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, // Lookup in a base class succeeded; return these results. // If we found a function declaration, return an overload set. - if (isa<FunctionDecl>(*Paths.front().Decls.first)) + if ((*Paths.front().Decls.first)->isFunctionOrFunctionTemplate()) return LookupResult::CreateLookupResult(Context, Paths.front().Decls.first, Paths.front().Decls.second); @@ -1489,7 +1498,9 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(), FuncEnd = Ovl->function_end(); Func != FuncEnd; ++Func) { - FunctionDecl *FDecl = cast<FunctionDecl>(*Func); + FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*Func); + if (!FDecl) + FDecl = cast<FunctionTemplateDecl>(*Func)->getTemplatedDecl(); // Add the namespace in which this function was defined. Note // that, if this is a member function, we do *not* consider the |