aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-06-25 22:08:12 +0000
committerDouglas Gregor <dgregor@apple.com>2009-06-25 22:08:12 +0000
commite53060fa78ad7e98352049f72787bdb7543e2a48 (patch)
treed0c7858e55ac3c7d6f8fb15257c37385e952393e /lib/Sema/SemaLookup.cpp
parent6e4a86ddadea69e855603c1733d8b5bc99fc910d (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.cpp33
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