forked from OSchip/llvm-project
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:
parent
f19f251523
commit
f0f1cf087e
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue