Store "sugared" decls in LookupResults (i.e. decl aliases like using declarations);

strip the sugar off in getFoundDecl() and getAsSingleDecl(), but leave it on for
clients like overload resolution who want to use the iterators.

Refactor a few pieces of overload resolution to strip off using declarations in
a single place.  Don't do anything useful with the extra context knowledge yet.

llvm-svn: 89061
This commit is contained in:
John McCall 2009-11-17 07:50:12 +00:00
parent f19f251523
commit f0f1cf087e
3 changed files with 53 additions and 48 deletions

View File

@ -873,6 +873,11 @@ public:
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false);
void AddMethodCandidate(NamedDecl *Decl,
Expr *Object, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversion = false,
bool ForceRValue = false);
void AddMethodCandidate(CXXMethodDecl *Method,
Expr *Object, Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@ -1282,20 +1287,7 @@ public:
/// \brief Add a declaration to these results.
void addDecl(NamedDecl *D) {
// "Flatten" overloaded function declarations to get the underlying
// functions.
// FIXME: This may not be necessary with the impending using-declarations
// rewrite (11/09).
if (OverloadedFunctionDecl *Ovl
= dyn_cast<OverloadedFunctionDecl>(D->getUnderlyingDecl())) {
for (OverloadedFunctionDecl::function_iterator
F = Ovl->function_begin(),
FEnd = Ovl->function_end();
F != FEnd; ++F) {
Decls.push_back(*F);
}
} else
Decls.push_back(D->getUnderlyingDecl());
Decls.push_back(D);
ResultKind = Found;
}
@ -1339,7 +1331,7 @@ public:
NamedDecl *getFoundDecl() const {
assert(getResultKind() == Found
&& "getFoundDecl called on non-unique result");
return *Decls.begin();
return Decls[0]->getUnderlyingDecl();
}
/// \brief Asks if the result is a single tag decl.

View File

@ -254,21 +254,21 @@ void Sema::LookupResult::resolveKind() {
bool Ambiguous = false;
bool HasTag = false, HasFunction = false, HasNonFunction = false;
bool HasUnresolved = false;
unsigned UniqueTagIndex = 0;
unsigned I = 0;
while (I < N) {
NamedDecl *D = Decls[I];
assert(D == D->getUnderlyingDecl());
NamedDecl *D = Decls[I]->getUnderlyingDecl();
D = cast<NamedDecl>(D->getCanonicalDecl());
NamedDecl *CanonD = cast<NamedDecl>(D->getCanonicalDecl());
if (!Unique.insert(CanonD)) {
if (!Unique.insert(D)) {
// If it's not unique, pull something off the back (and
// continue at this index).
Decls[I] = Decls[--N];
} else if (isa<UnresolvedUsingDecl>(D)) {
// FIXME: proper support for UnresolvedUsingDecls.
HasUnresolved = true;
Decls[I] = Decls[--N];
} else {
// Otherwise, do some decl type analysis and then continue.
@ -288,6 +288,13 @@ void Sema::LookupResult::resolveKind() {
}
}
// Postpone all other decisions if we have an unresolved decl, even
// if we can prove ambiguity. We can probably do better than this.
if (HasUnresolved) {
ResultKind = LookupResult::FoundOverloaded;
return;
}
// C++ [basic.scope.hiding]p2:
// A class name or enumeration name can be hidden by the name of
// an object, function, or enumerator declared in the same
@ -329,7 +336,7 @@ void Sema::LookupResult::resolveKind() {
NamedDecl *Sema::LookupResult::getAsSingleDecl(ASTContext &C) const {
size_t size = Decls.size();
if (size == 0) return 0;
if (size == 1) return *begin();
if (size == 1) return (*begin())->getUnderlyingDecl();
if (isAmbiguous()) return 0;
@ -339,9 +346,7 @@ NamedDecl *Sema::LookupResult::getAsSingleDecl(ASTContext &C) const {
= OverloadedFunctionDecl::Create(C, (*I)->getDeclContext(),
(*I)->getDeclName());
for (; I != E; ++I) {
NamedDecl *ND = *I;
assert(ND->getUnderlyingDecl() == ND
&& "decls in lookup result should have redirections stripped");
NamedDecl *ND = (*I)->getUnderlyingDecl();
assert(ND->isFunctionOrFunctionTemplate());
if (isa<FunctionDecl>(ND))
Ovl->addOverload(cast<FunctionDecl>(ND));

View File

@ -2367,6 +2367,33 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions,
}
}
/// AddMethodCandidate - Adds a named decl (which is some kind of
/// method) as a method candidate to the given overload set.
void Sema::AddMethodCandidate(NamedDecl *Decl, Expr *Object,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions, bool ForceRValue) {
// FIXME: use this
//DeclContext *ActingContext = Decl->getDeclContext();
if (isa<UsingShadowDecl>(Decl))
Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl();
if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
"Expected a member function template");
AddMethodTemplateCandidate(TD, false, 0, 0,
Object, Args, NumArgs,
CandidateSet,
SuppressUserConversions,
ForceRValue);
} else {
AddMethodCandidate(cast<CXXMethodDecl>(Decl), Object, Args, NumArgs,
CandidateSet, SuppressUserConversions, ForceRValue);
}
}
/// AddMethodCandidate - Adds the given C++ member function to the set
/// of candidate functions, using the given function call arguments
/// and the object argument (@c Object). For example, in a call
@ -2840,21 +2867,9 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
for (LookupResult::iterator Oper = Operators.begin(),
OperEnd = Operators.end();
Oper != OperEnd;
++Oper) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Oper)) {
AddMethodCandidate(Method, Args[0], Args+1, NumArgs - 1, CandidateSet,
/*SuppressUserConversions=*/false);
continue;
}
assert(isa<FunctionTemplateDecl>(*Oper) &&
isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(*Oper)
->getTemplatedDecl()) &&
"Expected a member function template");
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Oper), false, 0, 0,
Args[0], Args+1, NumArgs - 1, CandidateSet,
/*SuppressUserConversions=*/false);
}
++Oper)
AddMethodCandidate(*Oper, Args[0], Args + 1, NumArgs - 1, CandidateSet,
/* SuppressUserConversions = */ false);
}
}
@ -5267,15 +5282,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*Oper)) {
AddMethodTemplateCandidate(FunTmpl, false, 0, 0, Object, Args, NumArgs,
CandidateSet,
/*SuppressUserConversions=*/false);
continue;
}
AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs,
CandidateSet, /*SuppressUserConversions=*/false);
AddMethodCandidate(*Oper, Object, Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/ false);
}
// C++ [over.call.object]p2: