blob: d85123c85369db2adec485f2fda06c29bd633ce6 [file] [log] [blame]
//===--------------------- SemaLookup.cpp - Name Lookup ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements name lookup for C, C++, Objective-C, and
// Objective-C++.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "SemaInherit.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <set>
#include <vector>
#include <iterator>
#include <utility>
#include <algorithm>
using namespace clang;
typedef llvm::SmallVector<UsingDirectiveDecl*, 4> UsingDirectivesTy;
typedef llvm::DenseSet<NamespaceDecl*> NamespaceSet;
typedef llvm::SmallVector<Sema::LookupResult, 3> LookupResultsTy;
/// UsingDirAncestorCompare - Implements strict weak ordering of
/// UsingDirectives. It orders them by address of its common ancestor.
struct UsingDirAncestorCompare {
/// @brief Compares UsingDirectiveDecl common ancestor with DeclContext.
bool operator () (UsingDirectiveDecl *U, const DeclContext *Ctx) const {
return U->getCommonAncestor() < Ctx;
}
/// @brief Compares UsingDirectiveDecl common ancestor with DeclContext.
bool operator () (const DeclContext *Ctx, UsingDirectiveDecl *U) const {
return Ctx < U->getCommonAncestor();
}
/// @brief Compares UsingDirectiveDecl common ancestors.
bool operator () (UsingDirectiveDecl *U1, UsingDirectiveDecl *U2) const {
return U1->getCommonAncestor() < U2->getCommonAncestor();
}
};
/// AddNamespaceUsingDirectives - Adds all UsingDirectiveDecl's to heap UDirs
/// (ordered by common ancestors), found in namespace NS,
/// including all found (recursively) in their nominated namespaces.
void AddNamespaceUsingDirectives(DeclContext *NS,
UsingDirectivesTy &UDirs,
NamespaceSet &Visited) {
DeclContext::udir_iterator I, End;
for (llvm::tie(I, End) = NS->getUsingDirectives(); I !=End; ++I) {
UDirs.push_back(*I);
std::push_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare());
NamespaceDecl *Nominated = (*I)->getNominatedNamespace();
if (Visited.insert(Nominated).second)
AddNamespaceUsingDirectives(Nominated, UDirs, /*ref*/ Visited);
}
}
/// AddScopeUsingDirectives - Adds all UsingDirectiveDecl's found in Scope S,
/// including all found in the namespaces they nominate.
static void AddScopeUsingDirectives(Scope *S, UsingDirectivesTy &UDirs) {
NamespaceSet VisitedNS;
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(Ctx))
VisitedNS.insert(NS);
AddNamespaceUsingDirectives(Ctx, UDirs, /*ref*/ VisitedNS);
} else {
Scope::udir_iterator I = S->using_directives_begin(),
End = S->using_directives_end();
for (; I != End; ++I) {
UsingDirectiveDecl *UD = I->getAs<UsingDirectiveDecl>();
UDirs.push_back(UD);
std::push_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare());
NamespaceDecl *Nominated = UD->getNominatedNamespace();
if (!VisitedNS.count(Nominated)) {
VisitedNS.insert(Nominated);
AddNamespaceUsingDirectives(Nominated, UDirs, /*ref*/ VisitedNS);
}
}
}
}
/// MaybeConstructOverloadSet - Name lookup has determined that the
/// elements in [I, IEnd) have the name that we are looking for, and
/// *I is a match for the namespace. This routine returns an
/// appropriate Decl for name lookup, which may either be *I or an
/// OverloadedFunctionDecl that represents the overloaded functions in
/// [I, IEnd).
///
/// The existance of this routine is temporary; users of LookupResult
/// should be able to handle multiple results, to deal with cases of
/// ambiguity and overloaded functions without needing to create a
/// Decl node.
template<typename DeclIterator>
static NamedDecl *
MaybeConstructOverloadSet(ASTContext &Context,
DeclIterator I, DeclIterator IEnd) {
assert(I != IEnd && "Iterator range cannot be empty");
assert(!isa<OverloadedFunctionDecl>(*I) &&
"Cannot have an overloaded function");
if (isa<FunctionDecl>(*I)) {
// 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) {
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));
}
Ovl->addOverload(cast<FunctionDecl>(*Last));
}
// If we had more than one function, we built an overload
// set. Return it.
if (Ovl)
return Ovl;
}
return *I;
}
/// Merges together multiple LookupResults dealing with duplicated Decl's.
static Sema::LookupResult
MergeLookupResults(ASTContext &Context, LookupResultsTy &Results) {
typedef Sema::LookupResult LResult;
typedef llvm::SmallPtrSet<NamedDecl*, 4> DeclsSetTy;
// Remove duplicated Decl pointing at same Decl, by storing them in
// associative collection. This might be case for code like:
//
// namespace A { int i; }
// namespace B { using namespace A; }
// namespace C { using namespace A; }
//
// void foo() {
// using namespace B;
// using namespace C;
// ++i; // finds A::i, from both namespace B and C at global scope
// }
//
// C++ [namespace.qual].p3:
// The same declaration found more than once is not an ambiguity
// (because it is still a unique declaration).
DeclsSetTy FoundDecls;
// Counter of tag names, and functions for resolving ambiguity
// and name hiding.
std::size_t TagNames = 0, Functions = 0, OrdinaryNonFunc = 0;
LookupResultsTy::iterator I = Results.begin(), End = Results.end();
// No name lookup results, return early.
if (I == End) return LResult::CreateLookupResult(Context, 0);
// Keep track of the tag declaration we found. We only use this if
// we find a single tag declaration.
TagDecl *TagFound = 0;
for (; I != End; ++I) {
switch (I->getKind()) {
case LResult::NotFound:
assert(false &&
"Should be always successful name lookup result here.");
break;
case LResult::AmbiguousReference:
case LResult::AmbiguousBaseSubobjectTypes:
case LResult::AmbiguousBaseSubobjects:
assert(false && "Shouldn't get ambiguous lookup here.");
break;
case LResult::Found: {
NamedDecl *ND = I->getAsDecl();
if (TagDecl *TD = dyn_cast<TagDecl>(ND)) {
TagFound = Context.getCanonicalDecl(TD);
TagNames += FoundDecls.insert(TagFound)? 1 : 0;
} else if (isa<FunctionDecl>(ND))
Functions += FoundDecls.insert(ND)? 1 : 0;
else
FoundDecls.insert(ND);
break;
}
case LResult::FoundOverloaded:
for (LResult::iterator FI = I->begin(), FEnd = I->end(); FI != FEnd; ++FI)
Functions += FoundDecls.insert(*FI)? 1 : 0;
break;
}
}
OrdinaryNonFunc = FoundDecls.size() - TagNames - Functions;
bool Ambiguous = false, NameHidesTags = false;
if (FoundDecls.size() == 1) {
// 1) Exactly one result.
} else if (TagNames > 1) {
// 2) Multiple tag names (even though they may be hidden by an
// object name).
Ambiguous = true;
} else if (FoundDecls.size() - TagNames == 1) {
// 3) Ordinary name hides (optional) tag.
NameHidesTags = TagFound;
} else if (Functions) {
// C++ [basic.lookup].p1:
// ... Name lookup may associate more than one declaration with
// a name if it finds the name to be a function name; the declarations
// are said to form a set of overloaded functions (13.1).
// Overload resolution (13.3) takes place after name lookup has succeeded.
//
if (!OrdinaryNonFunc) {
// 4) Functions hide tag names.
NameHidesTags = TagFound;
} else {
// 5) Functions + ordinary names.
Ambiguous = true;
}
} else {
// 6) Multiple non-tag names
Ambiguous = true;
}
if (Ambiguous)
return LResult::CreateLookupResult(Context,
FoundDecls.begin(), FoundDecls.size());
if (NameHidesTags) {
// There's only one tag, TagFound. Remove it.
assert(TagFound && FoundDecls.count(TagFound) && "No tag name found?");
FoundDecls.erase(TagFound);
}
// Return successful name lookup result.
return LResult::CreateLookupResult(Context,
MaybeConstructOverloadSet(Context,
FoundDecls.begin(),
FoundDecls.end()));
}
// Retrieve the set of identifier namespaces that correspond to a
// specific kind of name lookup.
inline unsigned
getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
bool CPlusPlus) {
unsigned IDNS = 0;
switch (NameKind) {
case Sema::LookupOrdinaryName:
case Sema::LookupOperatorName:
case Sema::LookupRedeclarationWithLinkage:
IDNS = Decl::IDNS_Ordinary;
if (CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
break;
case Sema::LookupTagName:
IDNS = Decl::IDNS_Tag;
break;
case Sema::LookupMemberName:
IDNS = Decl::IDNS_Member;
if (CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary;
break;
case Sema::LookupNestedNameSpecifierName:
case Sema::LookupNamespaceName:
IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
break;
}
return IDNS;
}
Sema::LookupResult
Sema::LookupResult::CreateLookupResult(ASTContext &Context, NamedDecl *D) {
LookupResult Result;
Result.StoredKind = (D && isa<OverloadedFunctionDecl>(D))?
OverloadedDeclSingleDecl : SingleDecl;
Result.First = reinterpret_cast<uintptr_t>(D);
Result.Last = 0;
Result.Context = &Context;
return Result;
}
/// @brief Moves the name-lookup results from Other to this LookupResult.
Sema::LookupResult
Sema::LookupResult::CreateLookupResult(ASTContext &Context,
IdentifierResolver::iterator F,
IdentifierResolver::iterator L) {
LookupResult Result;
Result.Context = &Context;
if (F != L && isa<FunctionDecl>(*F)) {
IdentifierResolver::iterator Next = F;
++Next;
if (Next != L && isa<FunctionDecl>(*Next)) {
Result.StoredKind = OverloadedDeclFromIdResolver;
Result.First = F.getAsOpaqueValue();
Result.Last = L.getAsOpaqueValue();
return Result;
}
}
Result.StoredKind = SingleDecl;
Result.First = reinterpret_cast<uintptr_t>(*F);
Result.Last = 0;
return Result;
}
Sema::LookupResult
Sema::LookupResult::CreateLookupResult(ASTContext &Context,
DeclContext::lookup_iterator F,
DeclContext::lookup_iterator L) {
LookupResult Result;
Result.Context = &Context;
if (F != L && isa<FunctionDecl>(*F)) {
DeclContext::lookup_iterator Next = F;
++Next;
if (Next != L && isa<FunctionDecl>(*Next)) {
Result.StoredKind = OverloadedDeclFromDeclContext;
Result.First = reinterpret_cast<uintptr_t>(F);
Result.Last = reinterpret_cast<uintptr_t>(L);
return Result;
}
}
Result.StoredKind = SingleDecl;
Result.First = reinterpret_cast<uintptr_t>(*F);
Result.Last = 0;
return Result;
}
/// @brief Determine the result of name lookup.
Sema::LookupResult::LookupKind Sema::LookupResult::getKind() const {
switch (StoredKind) {
case SingleDecl:
return (reinterpret_cast<Decl *>(First) != 0)? Found : NotFound;
case OverloadedDeclSingleDecl:
case OverloadedDeclFromIdResolver:
case OverloadedDeclFromDeclContext:
return FoundOverloaded;
case AmbiguousLookupStoresBasePaths:
return Last? AmbiguousBaseSubobjectTypes : AmbiguousBaseSubobjects;
case AmbiguousLookupStoresDecls:
return AmbiguousReference;
}
// We can't ever get here.
return NotFound;
}
/// @brief Converts the result of name lookup into a single (possible
/// NULL) pointer to a declaration.
///
/// The resulting declaration will either be the declaration we found
/// (if only a single declaration was found), an
/// OverloadedFunctionDecl (if an overloaded function was found), or
/// NULL (if no declaration was found). This conversion must not be
/// used anywhere where name lookup could result in an ambiguity.
///
/// The OverloadedFunctionDecl conversion is meant as a stop-gap
/// solution, since it causes the OverloadedFunctionDecl to be
/// leaked. FIXME: Eventually, there will be a better way to iterate
/// over the set of overloaded functions returned by name lookup.
NamedDecl *Sema::LookupResult::getAsDecl() const {
switch (StoredKind) {
case SingleDecl:
return reinterpret_cast<NamedDecl *>(First);
case OverloadedDeclFromIdResolver:
return MaybeConstructOverloadSet(*Context,
IdentifierResolver::iterator::getFromOpaqueValue(First),
IdentifierResolver::iterator::getFromOpaqueValue(Last));
case OverloadedDeclFromDeclContext:
return MaybeConstructOverloadSet(*Context,
reinterpret_cast<DeclContext::lookup_iterator>(First),
reinterpret_cast<DeclContext::lookup_iterator>(Last));
case OverloadedDeclSingleDecl:
return reinterpret_cast<OverloadedFunctionDecl*>(First);
case AmbiguousLookupStoresDecls:
case AmbiguousLookupStoresBasePaths:
assert(false &&
"Name lookup returned an ambiguity that could not be handled");
break;
}
return 0;
}
/// @brief Retrieves the BasePaths structure describing an ambiguous
/// name lookup, or null.
BasePaths *Sema::LookupResult::getBasePaths() const {
if (StoredKind == AmbiguousLookupStoresBasePaths)
return reinterpret_cast<BasePaths *>(First);
return 0;
}
Sema::LookupResult::iterator::reference
Sema::LookupResult::iterator::operator*() const {
switch (Result->StoredKind) {
case SingleDecl:
return reinterpret_cast<NamedDecl*>(Current);
case OverloadedDeclSingleDecl:
return *reinterpret_cast<NamedDecl**>(Current);
case OverloadedDeclFromIdResolver:
return *IdentifierResolver::iterator::getFromOpaqueValue(Current);
case AmbiguousLookupStoresBasePaths:
if (Result->Last)
return *reinterpret_cast<NamedDecl**>(Current);
// Fall through to handle the DeclContext::lookup_iterator we're
// storing.
case OverloadedDeclFromDeclContext:
case AmbiguousLookupStoresDecls:
return *reinterpret_cast<DeclContext::lookup_iterator>(Current);
}
return 0;
}
Sema::LookupResult::iterator& Sema::LookupResult::iterator::operator++() {
switch (Result->StoredKind) {
case SingleDecl:
Current = reinterpret_cast<uintptr_t>((NamedDecl*)0);
break;
case OverloadedDeclSingleDecl: {
NamedDecl ** I = reinterpret_cast<NamedDecl**>(Current);
++I;
Current = reinterpret_cast<uintptr_t>(I);
break;
}
case OverloadedDeclFromIdResolver: {
IdentifierResolver::iterator I
= IdentifierResolver::iterator::getFromOpaqueValue(Current);
++I;
Current = I.getAsOpaqueValue();
break;
}
case AmbiguousLookupStoresBasePaths:
if (Result->Last) {
NamedDecl ** I = reinterpret_cast<NamedDecl**>(Current);
++I;
Current = reinterpret_cast<uintptr_t>(I);
break;
}
// Fall through to handle the DeclContext::lookup_iterator we're
// storing.
case OverloadedDeclFromDeclContext:
case AmbiguousLookupStoresDecls: {
DeclContext::lookup_iterator I
= reinterpret_cast<DeclContext::lookup_iterator>(Current);
++I;
Current = reinterpret_cast<uintptr_t>(I);
break;
}
}
return *this;
}
Sema::LookupResult::iterator Sema::LookupResult::begin() {
switch (StoredKind) {
case SingleDecl:
case OverloadedDeclFromIdResolver:
case OverloadedDeclFromDeclContext:
case AmbiguousLookupStoresDecls:
return iterator(this, First);
case OverloadedDeclSingleDecl: {
OverloadedFunctionDecl * Ovl =
reinterpret_cast<OverloadedFunctionDecl*>(First);
return iterator(this,
reinterpret_cast<uintptr_t>(&(*Ovl->function_begin())));
}
case AmbiguousLookupStoresBasePaths:
if (Last)
return iterator(this,
reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_begin()));
else
return iterator(this,
reinterpret_cast<uintptr_t>(getBasePaths()->front().Decls.first));
}
// Required to suppress GCC warning.
return iterator();
}
Sema::LookupResult::iterator Sema::LookupResult::end() {
switch (StoredKind) {
case SingleDecl:
case OverloadedDeclFromIdResolver:
case OverloadedDeclFromDeclContext:
case AmbiguousLookupStoresDecls:
return iterator(this, Last);
case OverloadedDeclSingleDecl: {
OverloadedFunctionDecl * Ovl =
reinterpret_cast<OverloadedFunctionDecl*>(First);
return iterator(this,
reinterpret_cast<uintptr_t>(&(*Ovl->function_end())));
}
case AmbiguousLookupStoresBasePaths:
if (Last)
return iterator(this,
reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_end()));
else
return iterator(this, reinterpret_cast<uintptr_t>(
getBasePaths()->front().Decls.second));
}
// Required to suppress GCC warning.
return iterator();
}
void Sema::LookupResult::Destroy() {
if (BasePaths *Paths = getBasePaths())
delete Paths;
else if (getKind() == AmbiguousReference)
delete[] reinterpret_cast<NamedDecl **>(First);
}
static void
CppNamespaceLookup(ASTContext &Context, DeclContext *NS,
DeclarationName Name, Sema::LookupNameKind NameKind,
unsigned IDNS, LookupResultsTy &Results,
UsingDirectivesTy *UDirs = 0) {
assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!");
// Perform qualified name lookup into the LookupCtx.
DeclContext::lookup_iterator I, E;
for (llvm::tie(I, E) = NS->lookup(Name); I != E; ++I)
if (Sema::isAcceptableLookupResult(*I, NameKind, IDNS)) {
Results.push_back(Sema::LookupResult::CreateLookupResult(Context, I, E));
break;
}
if (UDirs) {
// For each UsingDirectiveDecl, which common ancestor is equal
// to NS, we preform qualified name lookup into namespace nominated by it.
UsingDirectivesTy::const_iterator UI, UEnd;
llvm::tie(UI, UEnd) =
std::equal_range(UDirs->begin(), UDirs->end(), NS,
UsingDirAncestorCompare());
for (; UI != UEnd; ++UI)
CppNamespaceLookup(Context, (*UI)->getNominatedNamespace(),
Name, NameKind, IDNS, Results);
}
}
static bool isNamespaceOrTranslationUnitScope(Scope *S) {
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
return Ctx->isFileContext();
return false;
}
std::pair<bool, Sema::LookupResult>
Sema::CppLookupName(Scope *S, DeclarationName Name,
LookupNameKind NameKind, bool RedeclarationOnly) {
assert(getLangOptions().CPlusPlus &&
"Can perform only C++ lookup");
unsigned IDNS
= getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true);
Scope *Initial = S;
DeclContext *OutOfLineCtx = 0;
IdentifierResolver::iterator
I = IdResolver.begin(Name),
IEnd = IdResolver.end();
// First we lookup local scope.
// We don't consider using-directives, as per 7.3.4.p1 [namespace.udir]
// ...During unqualified name lookup (3.4.1), the names appear as if
// they were declared in the nearest enclosing namespace which contains
// both the using-directive and the nominated namespace.
// [Note: in this context, “contains” means “contains directly or
// indirectly”.
//
// For example:
// namespace A { int i; }
// void foo() {
// int i;
// {
// using namespace A;
// ++i; // finds local 'i', A::i appears at global scope
// }
// }
//
for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
// Check whether the IdResolver has anything in this scope.
for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
if (isAcceptableLookupResult(*I, NameKind, IDNS)) {
// We found something. Look for anything else in our scope
// with this same name and in an acceptable identifier
// namespace, so that we can construct an overload set if we
// need to.
IdentifierResolver::iterator LastI = I;
for (++LastI; LastI != IEnd; ++LastI) {
if (!S->isDeclScope(DeclPtrTy::make(*LastI)))
break;
}
LookupResult Result =
LookupResult::CreateLookupResult(Context, I, LastI);
return std::make_pair(true, Result);
}
}
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
LookupResult R;
// Perform member lookup into struct.
// FIXME: In some cases, we know that every name that could be
// found by this qualified name lookup will also be on the
// identifier chain. For example, inside a class without any
// base classes, we never need to perform qualified lookup
// because all of the members are on top of the identifier
// chain.
if (isa<RecordDecl>(Ctx)) {
R = LookupQualifiedName(Ctx, Name, NameKind, RedeclarationOnly);
if (R || RedeclarationOnly)
return std::make_pair(true, R);
}
if (Ctx->getParent() != Ctx->getLexicalParent()) {
// It is out of line defined C++ method or struct, we continue
// doing name lookup in parent context. Once we will find namespace
// or translation-unit we save it for possible checking
// using-directives later.
for (OutOfLineCtx = Ctx; OutOfLineCtx && !OutOfLineCtx->isFileContext();
OutOfLineCtx = OutOfLineCtx->getParent()) {
R = LookupQualifiedName(OutOfLineCtx, Name, NameKind, RedeclarationOnly);
if (R || RedeclarationOnly)
return std::make_pair(true, R);
}
}
}
}
// Collect UsingDirectiveDecls in all scopes, and recursively all
// nominated namespaces by those using-directives.
// UsingDirectives are pushed to heap, in common ancestor pointer
// value order.
// FIXME: Cache this sorted list in Scope structure, and DeclContext,
// so we don't build it for each lookup!
UsingDirectivesTy UDirs;
for (Scope *SC = Initial; SC; SC = SC->getParent())
if (SC->getFlags() & Scope::DeclScope)
AddScopeUsingDirectives(SC, UDirs);
// Sort heapified UsingDirectiveDecls.
std::sort_heap(UDirs.begin(), UDirs.end());
// Lookup namespace scope, and global scope.
// Unqualified name lookup in C++ requires looking into scopes
// that aren't strictly lexical, and therefore we walk through the
// context as well as walking through the scopes.
LookupResultsTy LookupResults;
assert((!OutOfLineCtx || OutOfLineCtx->isFileContext()) &&
"We should have been looking only at file context here already.");
bool LookedInCtx = false;
LookupResult Result;
while (OutOfLineCtx &&
OutOfLineCtx != S->getEntity() &&
OutOfLineCtx->isNamespace()) {
LookedInCtx = true;
// Look into context considering using-directives.
CppNamespaceLookup(Context, OutOfLineCtx, Name, NameKind, IDNS,
LookupResults, &UDirs);
if ((Result = MergeLookupResults(Context, LookupResults)) ||
(RedeclarationOnly && !OutOfLineCtx->isTransparentContext()))
return std::make_pair(true, Result);
OutOfLineCtx = OutOfLineCtx->getParent();
}
for (; S; S = S->getParent()) {
DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
assert(Ctx && Ctx->isFileContext() &&
"We should have been looking only at file context here already.");
// Check whether the IdResolver has anything in this scope.
for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
if (isAcceptableLookupResult(*I, NameKind, IDNS)) {
// We found something. Look for anything else in our scope
// with this same name and in an acceptable identifier
// namespace, so that we can construct an overload set if we
// need to.
IdentifierResolver::iterator LastI = I;
for (++LastI; LastI != IEnd; ++LastI) {
if (!S->isDeclScope(DeclPtrTy::make(*LastI)))
break;
}
// We store name lookup result, and continue trying to look into
// associated context, and maybe namespaces nominated by
// using-directives.
LookupResults.push_back(
LookupResult::CreateLookupResult(Context, I, LastI));
break;
}
}
LookedInCtx = true;
// Look into context considering using-directives.
CppNamespaceLookup(Context, Ctx, Name, NameKind, IDNS,
LookupResults, &UDirs);
if ((Result = MergeLookupResults(Context, LookupResults)) ||
(RedeclarationOnly && !Ctx->isTransparentContext()))
return std::make_pair(true, Result);
}
if (!(LookedInCtx || LookupResults.empty())) {
// We didn't Performed lookup in Scope entity, so we return
// result form IdentifierResolver.
assert((LookupResults.size() == 1) && "Wrong size!");
return std::make_pair(true, LookupResults.front());
}
return std::make_pair(false, LookupResult());
}
/// @brief Perform unqualified name lookup starting from a given
/// scope.
///
/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is
/// used to find names within the current scope. For example, 'x' in
/// @code
/// int x;
/// int f() {
/// return x; // unqualified name look finds 'x' in the global scope
/// }
/// @endcode
///
/// Different lookup criteria can find different names. For example, a
/// particular scope can have both a struct and a function of the same
/// name, and each can be found by certain lookup criteria. For more
/// information about lookup criteria, see the documentation for the
/// class LookupCriteria.
///
/// @param S The scope from which unqualified name lookup will
/// begin. If the lookup criteria permits, name lookup may also search
/// in the parent scopes.
///
/// @param Name The name of the entity that we are searching for.
///
/// @param Loc If provided, the source location where we're performing
/// name lookup. At present, this is only used to produce diagnostics when
/// C library functions (like "malloc") are implicitly declared.
///
/// @returns The result of name lookup, which includes zero or more
/// declarations and possibly additional information used to diagnose
/// ambiguities.
Sema::LookupResult
Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind,
bool RedeclarationOnly, bool AllowBuiltinCreation,
SourceLocation Loc) {
if (!Name) return LookupResult::CreateLookupResult(Context, 0);
if (!getLangOptions().CPlusPlus) {
// Unqualified name lookup in C/Objective-C is purely lexical, so
// search in the declarations attached to the name.
unsigned IDNS = 0;
switch (NameKind) {
case Sema::LookupOrdinaryName:
IDNS = Decl::IDNS_Ordinary;
break;
case Sema::LookupTagName:
IDNS = Decl::IDNS_Tag;
break;
case Sema::LookupMemberName:
IDNS = Decl::IDNS_Member;
break;
case Sema::LookupOperatorName:
case Sema::LookupNestedNameSpecifierName:
case Sema::LookupNamespaceName:
assert(false && "C does not perform these kinds of name lookup");
break;
case Sema::LookupRedeclarationWithLinkage:
// Find the nearest non-transparent declaration scope.
while (!(S->getFlags() & Scope::DeclScope) ||
(S->getEntity() &&
static_cast<DeclContext *>(S->getEntity())
->isTransparentContext()))
S = S->getParent();
IDNS = Decl::IDNS_Ordinary;
break;
}
// Scan up the scope chain looking for a decl that matches this
// identifier that is in the appropriate namespace. This search
// should not take long, as shadowing of names is uncommon, and
// deep shadowing is extremely uncommon.
bool LeftStartingScope = false;
for (IdentifierResolver::iterator I = IdResolver.begin(Name),
IEnd = IdResolver.end();
I != IEnd; ++I)
if ((*I)->isInIdentifierNamespace(IDNS)) {
if (NameKind == LookupRedeclarationWithLinkage) {
// Determine whether this (or a previous) declaration is
// out-of-scope.
if (!LeftStartingScope && !S->isDeclScope(DeclPtrTy::make(*I)))
LeftStartingScope = true;
// If we found something outside of our starting scope that
// does not have linkage, skip it.
if (LeftStartingScope && !((*I)->hasLinkage()))
continue;
}
if ((*I)->getAttr<OverloadableAttr>()) {
// If this declaration has the "overloadable" attribute, we
// might have a set of overloaded functions.
// Figure out what scope the identifier is in.
while (!(S->getFlags() & Scope::DeclScope) ||
!S->isDeclScope(DeclPtrTy::make(*I)))
S = S->getParent();
// Find the last declaration in this scope (with the same
// name, naturally).
IdentifierResolver::iterator LastI = I;
for (++LastI; LastI != IEnd; ++LastI) {
if (!S->isDeclScope(DeclPtrTy::make(*LastI)))
break;
}
return LookupResult::CreateLookupResult(Context, I, LastI);
}
// We have a single lookup result.
return LookupResult::CreateLookupResult(Context, *I);
}
} else {
// Perform C++ unqualified name lookup.
std::pair<bool, LookupResult> MaybeResult =
CppLookupName(S, Name, NameKind, RedeclarationOnly);
if (MaybeResult.first)
return MaybeResult.second;
}
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
// now, injecting it into translation unit scope, and return it.
if (NameKind == LookupOrdinaryName ||
NameKind == LookupRedeclarationWithLinkage) {
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (II && AllowBuiltinCreation) {
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID()) {
// In C++, we don't have any predefined library functions like
// 'malloc'. Instead, we'll just error.
if (getLangOptions().CPlusPlus &&
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return LookupResult::CreateLookupResult(Context, 0);
return LookupResult::CreateLookupResult(Context,
LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
S, RedeclarationOnly, Loc));
}
}
if (getLangOptions().ObjC1 && II) {
// @interface and @compatibility_alias introduce typedef-like names.
// Unlike typedef's, they can only be introduced at file-scope (and are
// therefore not scoped decls). They can, however, be shadowed by
// other names in IDNS_Ordinary.
ObjCInterfaceDeclsTy::iterator IDI = ObjCInterfaceDecls.find(II);
if (IDI != ObjCInterfaceDecls.end())
return LookupResult::CreateLookupResult(Context, IDI->second);
ObjCAliasTy::iterator I = ObjCAliasDecls.find(II);
if (I != ObjCAliasDecls.end())
return LookupResult::CreateLookupResult(Context,
I->second->getClassInterface());
}
}
return LookupResult::CreateLookupResult(Context, 0);
}
/// @brief Perform qualified name lookup into a given context.
///
/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
/// names when the context of those names is explicit specified, e.g.,
/// "std::vector" or "x->member".
///
/// Different lookup criteria can find different names. For example, a
/// particular scope can have both a struct and a function of the same
/// name, and each can be found by certain lookup criteria. For more
/// information about lookup criteria, see the documentation for the
/// class LookupCriteria.
///
/// @param LookupCtx The context in which qualified name lookup will
/// search. If the lookup criteria permits, name lookup may also search
/// in the parent contexts or (for C++ classes) base classes.
///
/// @param Name The name of the entity that we are searching for.
///
/// @param Criteria The criteria that this routine will use to
/// determine which names are visible and which names will be
/// found. Note that name lookup will find a name that is visible by
/// the given criteria, but the entity itself may not be semantically
/// correct or even the kind of entity expected based on the
/// lookup. For example, searching for a nested-name-specifier name
/// might result in an EnumDecl, which is visible but is not permitted
/// as a nested-name-specifier in C++03.
///
/// @returns The result of name lookup, which includes zero or more
/// declarations and possibly additional information used to diagnose
/// ambiguities.
Sema::LookupResult
Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
LookupNameKind NameKind, bool RedeclarationOnly) {
assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
if (!Name) return LookupResult::CreateLookupResult(Context, 0);
// If we're performing qualified name lookup (e.g., lookup into a
// struct), find fields as part of ordinary name lookup.
unsigned IDNS
= getIdentifierNamespacesFromLookupNameKind(NameKind,
getLangOptions().CPlusPlus);
if (NameKind == LookupOrdinaryName)
IDNS |= Decl::IDNS_Member;
// Perform qualified name lookup into the LookupCtx.
DeclContext::lookup_iterator I, E;
for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I)
if (isAcceptableLookupResult(*I, NameKind, IDNS))
return LookupResult::CreateLookupResult(Context, I, E);
// If this isn't a C++ class or we aren't allowed to look into base
// classes, we're done.
if (RedeclarationOnly || !isa<CXXRecordDecl>(LookupCtx))
return LookupResult::CreateLookupResult(Context, 0);
// Perform lookup into our base classes.
BasePaths Paths;
Paths.setOrigin(Context.getTypeDeclType(cast<RecordDecl>(LookupCtx)));
// Look for this member in our base classes
if (!LookupInBases(cast<CXXRecordDecl>(LookupCtx),
MemberLookupCriteria(Name, NameKind, IDNS), Paths))
return LookupResult::CreateLookupResult(Context, 0);
// C++ [class.member.lookup]p2:
// [...] If the resulting set of declarations are not all from
// sub-objects of the same type, or the set has a nonstatic member
// and includes members from distinct sub-objects, there is an
// ambiguity and the program is ill-formed. Otherwise that set is
// the result of the lookup.
// FIXME: support using declarations!
QualType SubobjectType;
int SubobjectNumber = 0;
for (BasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
Path != PathEnd; ++Path) {
const BasePathElement &PathElement = Path->back();
// Determine whether we're looking at a distinct sub-object or not.
if (SubobjectType.isNull()) {
// This is the first subobject we've looked at. Record it's type.
SubobjectType = Context.getCanonicalType(PathElement.Base->getType());
SubobjectNumber = PathElement.SubobjectNumber;
} else if (SubobjectType
!= Context.getCanonicalType(PathElement.Base->getType())) {
// We found members of the given name in two subobjects of
// different types. This lookup is ambiguous.
BasePaths *PathsOnHeap = new BasePaths;
PathsOnHeap->swap(Paths);
return LookupResult::CreateLookupResult(Context, PathsOnHeap, true);
} else if (SubobjectNumber != PathElement.SubobjectNumber) {
// We have a different subobject of the same type.
// C++ [class.member.lookup]p5:
// A static member, a nested type or an enumerator defined in
// a base class T can unambiguously be found even if an object
// has more than one base class subobject of type T.
Decl *FirstDecl = *Path->Decls.first;
if (isa<VarDecl>(FirstDecl) ||
isa<TypeDecl>(FirstDecl) ||
isa<EnumConstantDecl>(FirstDecl))
continue;
if (isa<CXXMethodDecl>(FirstDecl)) {
// Determine whether all of the methods are static.
bool AllMethodsAreStatic = true;
for (DeclContext::lookup_iterator Func = Path->Decls.first;
Func != Path->Decls.second; ++Func) {
if (!isa<CXXMethodDecl>(*Func)) {
assert(isa<TagDecl>(*Func) && "Non-function must be a tag decl");
break;
}
if (!cast<CXXMethodDecl>(*Func)->isStatic()) {
AllMethodsAreStatic = false;
break;
}
}
if (AllMethodsAreStatic)
continue;
}
// We have found a nonstatic member name in multiple, distinct
// subobjects. Name lookup is ambiguous.
BasePaths *PathsOnHeap = new BasePaths;
PathsOnHeap->swap(Paths);
return LookupResult::CreateLookupResult(Context, PathsOnHeap, false);
}
}
// 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))
return LookupResult::CreateLookupResult(Context,
Paths.front().Decls.first, Paths.front().Decls.second);
// We found a non-function declaration; return a single declaration.
return LookupResult::CreateLookupResult(Context, *Paths.front().Decls.first);
}
/// @brief Performs name lookup for a name that was parsed in the
/// source code, and may contain a C++ scope specifier.
///
/// This routine is a convenience routine meant to be called from
/// contexts that receive a name and an optional C++ scope specifier
/// (e.g., "N::M::x"). It will then perform either qualified or
/// unqualified name lookup (with LookupQualifiedName or LookupName,
/// respectively) on the given name and return those results.
///
/// @param S The scope from which unqualified name lookup will
/// begin.
///
/// @param SS An optional C++ scope-specified, e.g., "::N::M".
///
/// @param Name The name of the entity that name lookup will
/// search for.
///
/// @param Loc If provided, the source location where we're performing
/// name lookup. At present, this is only used to produce diagnostics when
/// C library functions (like "malloc") are implicitly declared.
///
/// @returns The result of qualified or unqualified name lookup.
Sema::LookupResult
Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS,
DeclarationName Name, LookupNameKind NameKind,
bool RedeclarationOnly, bool AllowBuiltinCreation,
SourceLocation Loc) {
if (SS) {
if (SS->isInvalid() || RequireCompleteDeclContext(*SS))
return LookupResult::CreateLookupResult(Context, 0);
if (SS->isSet()) {
return LookupQualifiedName(computeDeclContext(*SS),
Name, NameKind, RedeclarationOnly);
}
}
return LookupName(S, Name, NameKind, RedeclarationOnly,
AllowBuiltinCreation, Loc);
}
/// @brief Produce a diagnostic describing the ambiguity that resulted
/// from name lookup.
///
/// @param Result The ambiguous name lookup result.
///
/// @param Name The name of the entity that name lookup was
/// searching for.
///
/// @param NameLoc The location of the name within the source code.
///
/// @param LookupRange A source range that provides more
/// source-location information concerning the lookup itself. For
/// example, this range might highlight a nested-name-specifier that
/// precedes the name.
///
/// @returns true
bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
SourceLocation NameLoc,
SourceRange LookupRange) {
assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
if (BasePaths *Paths = Result.getBasePaths()) {
if (Result.getKind() == LookupResult::AmbiguousBaseSubobjects) {
QualType SubobjectType = Paths->front().back().Base->getType();
Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects)
<< Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
<< LookupRange;
DeclContext::lookup_iterator Found = Paths->front().Decls.first;
while (isa<CXXMethodDecl>(*Found) &&
cast<CXXMethodDecl>(*Found)->isStatic())
++Found;
Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
Result.Destroy();
return true;
}
assert(Result.getKind() == LookupResult::AmbiguousBaseSubobjectTypes &&
"Unhandled form of name lookup ambiguity");
Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types)
<< Name << LookupRange;
std::set<Decl *> DeclsPrinted;
for (BasePaths::paths_iterator Path = Paths->begin(), PathEnd = Paths->end();
Path != PathEnd; ++Path) {
Decl *D = *Path->Decls.first;
if (DeclsPrinted.insert(D).second)
Diag(D->getLocation(), diag::note_ambiguous_member_found);
}
Result.Destroy();
return true;
} else if (Result.getKind() == LookupResult::AmbiguousReference) {
Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
NamedDecl **DI = reinterpret_cast<NamedDecl **>(Result.First),
**DEnd = reinterpret_cast<NamedDecl **>(Result.Last);
for (; DI != DEnd; ++DI)
Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
Result.Destroy();
return true;
}
assert(false && "Unhandled form of name lookup ambiguity");
// We can't reach here.
return true;
}
// \brief Add the associated classes and namespaces for
// argument-dependent lookup with an argument of class type
// (C++ [basic.lookup.koenig]p2).
static void
addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
ASTContext &Context,
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
Sema::AssociatedClassSet &AssociatedClasses) {
// C++ [basic.lookup.koenig]p2:
// [...]
// -- If T is a class type (including unions), its associated
// classes are: the class itself; the class of which it is a
// member, if any; and its direct and indirect base
// classes. Its associated namespaces are the namespaces in
// which its associated classes are defined.
// Add the class of which it is a member, if any.
DeclContext *Ctx = Class->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
AssociatedClasses.insert(EnclosingClass);
// Add the associated namespace for this class.
while (Ctx->isRecord())
Ctx = Ctx->getParent();
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
AssociatedNamespaces.insert(EnclosingNamespace);
// Add the class itself. If we've already seen this class, we don't
// need to visit base classes.
if (!AssociatedClasses.insert(Class))
return;
// FIXME: Handle class template specializations
// Add direct and indirect base classes along with their associated
// namespaces.
llvm::SmallVector<CXXRecordDecl *, 32> Bases;
Bases.push_back(Class);
while (!Bases.empty()) {
// Pop this class off the stack.
Class = Bases.back();
Bases.pop_back();
// Visit the base classes.
for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(),
BaseEnd = Class->bases_end();
Base != BaseEnd; ++Base) {
const RecordType *BaseType = Base->getType()->getAsRecordType();
CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
if (AssociatedClasses.insert(BaseDecl)) {
// Find the associated namespace for this base class.
DeclContext *BaseCtx = BaseDecl->getDeclContext();
while (BaseCtx->isRecord())
BaseCtx = BaseCtx->getParent();
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(BaseCtx))
AssociatedNamespaces.insert(EnclosingNamespace);
// Make sure we visit the bases of this base class.
if (BaseDecl->bases_begin() != BaseDecl->bases_end())
Bases.push_back(BaseDecl);
}
}
}
}
// \brief Add the associated classes and namespaces for
// argument-dependent lookup with an argument of type T
// (C++ [basic.lookup.koenig]p2).
static void
addAssociatedClassesAndNamespaces(QualType T,
ASTContext &Context,
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
Sema::AssociatedClassSet &AssociatedClasses) {
// C++ [basic.lookup.koenig]p2:
//
// For each argument type T in the function call, there is a set
// of zero or more associated namespaces and a set of zero or more
// associated classes to be considered. The sets of namespaces and
// classes is determined entirely by the types of the function
// arguments (and the namespace of any template template
// argument). Typedef names and using-declarations used to specify
// the types do not contribute to this set. The sets of namespaces
// and classes are determined in the following way:
T = Context.getCanonicalType(T).getUnqualifiedType();
// -- If T is a pointer to U or an array of U, its associated
// namespaces and classes are those associated with U.
//
// We handle this by unwrapping pointer and array types immediately,
// to avoid unnecessary recursion.
while (true) {
if (const PointerType *Ptr = T->getAsPointerType())
T = Ptr->getPointeeType();
else if (const ArrayType *Ptr = Context.getAsArrayType(T))
T = Ptr->getElementType();
else
break;
}
// -- If T is a fundamental type, its associated sets of
// namespaces and classes are both empty.
if (T->getAsBuiltinType())
return;
// -- If T is a class type (including unions), its associated
// classes are: the class itself; the class of which it is a
// member, if any; and its direct and indirect base
// classes. Its associated namespaces are the namespaces in
// which its associated classes are defined.
if (const RecordType *ClassType = T->getAsRecordType())
if (CXXRecordDecl *ClassDecl
= dyn_cast<CXXRecordDecl>(ClassType->getDecl())) {
addAssociatedClassesAndNamespaces(ClassDecl, Context,
AssociatedNamespaces,
AssociatedClasses);
return;
}
// -- If T is an enumeration type, its associated namespace is
// the namespace in which it is defined. If it is class
// member, its associated class is the member’s class; else
// it has no associated class.
if (const EnumType *EnumT = T->getAsEnumType()) {
EnumDecl *Enum = EnumT->getDecl();
DeclContext *Ctx = Enum->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
AssociatedClasses.insert(EnclosingClass);
// Add the associated namespace for this class.
while (Ctx->isRecord())
Ctx = Ctx->getParent();
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
AssociatedNamespaces.insert(EnclosingNamespace);
return;
}
// -- If T is a function type, its associated namespaces and
// classes are those associated with the function parameter
// types and those associated with the return type.
if (const FunctionType *FunctionType = T->getAsFunctionType()) {
// Return type
addAssociatedClassesAndNamespaces(FunctionType->getResultType(),
Context,
AssociatedNamespaces, AssociatedClasses);
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FunctionType);
if (!Proto)
return;
// Argument types
for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
ArgEnd = Proto->arg_type_end();
Arg != ArgEnd; ++Arg)
addAssociatedClassesAndNamespaces(*Arg, Context,
AssociatedNamespaces, AssociatedClasses);
return;
}
// -- If T is a pointer to a member function of a class X, its
// associated namespaces and classes are those associated
// with the function parameter types and return type,
// together with those associated with X.
//
// -- If T is a pointer to a data member of class X, its
// associated namespaces and classes are those associated
// with the member type together with those associated with
// X.
if (const MemberPointerType *MemberPtr = T->getAsMemberPointerType()) {
// Handle the type that the pointer to member points to.
addAssociatedClassesAndNamespaces(MemberPtr->getPointeeType(),
Context,
AssociatedNamespaces, AssociatedClasses);
// Handle the class type into which this points.
if (const RecordType *Class = MemberPtr->getClass()->getAsRecordType())
addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()),
Context,
AssociatedNamespaces, AssociatedClasses);
return;
}
// FIXME: What about block pointers?
// FIXME: What about Objective-C message sends?
}
/// \brief Find the associated classes and namespaces for
/// argument-dependent lookup for a call with the given set of
/// arguments.
///
/// This routine computes the sets of associated classes and associated
/// namespaces searched by argument-dependent lookup
/// (C++ [basic.lookup.argdep]) for a given set of arguments.
void
Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
AssociatedNamespaceSet &AssociatedNamespaces,
AssociatedClassSet &AssociatedClasses) {
AssociatedNamespaces.clear();
AssociatedClasses.clear();
// C++ [basic.lookup.koenig]p2:
// For each argument type T in the function call, there is a set
// of zero or more associated namespaces and a set of zero or more
// associated classes to be considered. The sets of namespaces and
// classes is determined entirely by the types of the function
// arguments (and the namespace of any template template
// argument).
for (unsigned ArgIdx = 0; ArgIdx != NumArgs; ++ArgIdx) {
Expr *Arg = Args[ArgIdx];
if (Arg->getType() != Context.OverloadTy) {
addAssociatedClassesAndNamespaces(Arg->getType(), Context,
AssociatedNamespaces, AssociatedClasses);
continue;
}
// [...] In addition, if the argument is the name or address of a
// set of overloaded functions and/or function templates, its
// associated classes and namespaces are the union of those
// associated with each of the members of the set: the namespace
// in which the function or function template is defined and the
// classes and namespaces associated with its (non-dependent)
// parameter types and return type.
DeclRefExpr *DRE = 0;
if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg)) {
if (unaryOp->getOpcode() == UnaryOperator::AddrOf)
DRE = dyn_cast<DeclRefExpr>(unaryOp->getSubExpr());
} else
DRE = dyn_cast<DeclRefExpr>(Arg);
if (!DRE)
continue;
OverloadedFunctionDecl *Ovl
= dyn_cast<OverloadedFunctionDecl>(DRE->getDecl());
if (!Ovl)
continue;
for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(),
FuncEnd = Ovl->function_end();
Func != FuncEnd; ++Func) {
FunctionDecl *FDecl = cast<FunctionDecl>(*Func);
// Add the namespace in which this function was defined. Note
// that, if this is a member function, we do *not* consider the
// enclosing namespace of its class.
DeclContext *Ctx = FDecl->getDeclContext();
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
AssociatedNamespaces.insert(EnclosingNamespace);
// Add the classes and namespaces associated with the parameter
// types and return type of this function.
addAssociatedClassesAndNamespaces(FDecl->getType(), Context,
AssociatedNamespaces, AssociatedClasses);
}
}
}
/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is
/// an acceptable non-member overloaded operator for a call whose
/// arguments have types T1 (and, if non-empty, T2). This routine
/// implements the check in C++ [over.match.oper]p3b2 concerning
/// enumeration types.
static bool
IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
QualType T1, QualType T2,
ASTContext &Context) {
if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
return true;
if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
return true;
const FunctionProtoType *Proto = Fn->getType()->getAsFunctionProtoType();
if (Proto->getNumArgs() < 1)
return false;
if (T1->isEnumeralType()) {
QualType ArgType = Proto->getArgType(0).getNonReferenceType();
if (Context.getCanonicalType(T1).getUnqualifiedType()
== Context.getCanonicalType(ArgType).getUnqualifiedType())
return true;
}
if (Proto->getNumArgs() < 2)
return false;
if (!T2.isNull() && T2->isEnumeralType()) {
QualType ArgType = Proto->getArgType(1).getNonReferenceType();
if (Context.getCanonicalType(T2).getUnqualifiedType()
== Context.getCanonicalType(ArgType).getUnqualifiedType())
return true;
}
return false;
}
void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
FunctionSet &Functions) {
// C++ [over.match.oper]p3:
// -- The set of non-member candidates is the result of the
// unqualified lookup of operator@ in the context of the
// expression according to the usual rules for name lookup in
// unqualified function calls (3.4.2) except that all member
// functions are ignored. However, if no operand has a class
// type, only those non-member functions in the lookup set
// that have a first parameter of type T1 or “reference to
// (possibly cv-qualified) T1”, when T1 is an enumeration
// type, or (if there is a right operand) a second parameter
// of type T2 or “reference to (possibly cv-qualified) T2”,
// when T2 is an enumeration type, are candidate functions.
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
LookupResult Operators = LookupName(S, OpName, LookupOperatorName);
assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
if (!Operators)
return;
for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
Op != OpEnd; ++Op) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op))
if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
Functions.insert(FD); // FIXME: canonical FD
}
}
void Sema::ArgumentDependentLookup(DeclarationName Name,
Expr **Args, unsigned NumArgs,
FunctionSet &Functions) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
AssociatedClassSet AssociatedClasses;
FindAssociatedClassesAndNamespaces(Args, NumArgs,
AssociatedNamespaces, AssociatedClasses);
// C++ [basic.lookup.argdep]p3:
// Let X be the lookup set produced by unqualified lookup (3.4.1)
// and let Y be the lookup set produced by argument dependent
// lookup (defined as follows). If X contains [...] then Y is
// empty. Otherwise Y is the set of declarations found in the
// namespaces associated with the argument types as described
// below. The set of declarations found by the lookup of the name
// is the union of X and Y.
//
// Here, we compute Y and add its members to the overloaded
// candidate set.
for (AssociatedNamespaceSet::iterator NS = AssociatedNamespaces.begin(),
NSEnd = AssociatedNamespaces.end();
NS != NSEnd; ++NS) {
// When considering an associated namespace, the lookup is the
// same as the lookup performed when the associated namespace is
// used as a qualifier (3.4.3.2) except that:
//
// -- Any using-directives in the associated namespace are
// ignored.
//
// -- FIXME: Any namespace-scope friend functions declared in
// associated classes are visible within their respective
// namespaces even if they are not visible during an ordinary
// lookup (11.4).
DeclContext::lookup_iterator I, E;
for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
FunctionDecl *Func = dyn_cast<FunctionDecl>(*I);
if (!Func)
break;
Functions.insert(Func);
}
}
}