2009-01-15 06:20:51 +08:00
|
|
|
|
//===--------------------- 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"
|
2009-01-15 08:26:24 +08:00
|
|
|
|
#include "SemaInherit.h"
|
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2009-01-15 06:20:51 +08:00
|
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
|
#include "clang/AST/DeclObjC.h"
|
2009-05-12 03:58:34 +08:00
|
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2009-02-04 08:32:51 +08:00
|
|
|
|
#include "clang/AST/Expr.h"
|
2009-01-15 06:20:51 +08:00
|
|
|
|
#include "clang/Parse/DeclSpec.h"
|
2009-06-14 09:54:56 +08:00
|
|
|
|
#include "clang/Basic/Builtins.h"
|
2009-01-15 06:20:51 +08:00
|
|
|
|
#include "clang/Basic/LangOptions.h"
|
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2009-02-04 08:32:51 +08:00
|
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2009-01-16 08:38:09 +08:00
|
|
|
|
#include <set>
|
2009-02-04 03:21:40 +08:00
|
|
|
|
#include <vector>
|
|
|
|
|
#include <iterator>
|
|
|
|
|
#include <utility>
|
|
|
|
|
#include <algorithm>
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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.
|
2009-04-10 05:40:53 +08:00
|
|
|
|
void AddNamespaceUsingDirectives(ASTContext &Context,
|
|
|
|
|
DeclContext *NS,
|
2009-02-04 03:21:40 +08:00
|
|
|
|
UsingDirectivesTy &UDirs,
|
|
|
|
|
NamespaceSet &Visited) {
|
|
|
|
|
DeclContext::udir_iterator I, End;
|
|
|
|
|
|
2009-04-10 05:40:53 +08:00
|
|
|
|
for (llvm::tie(I, End) = NS->getUsingDirectives(Context); I !=End; ++I) {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
UDirs.push_back(*I);
|
|
|
|
|
std::push_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare());
|
|
|
|
|
NamespaceDecl *Nominated = (*I)->getNominatedNamespace();
|
|
|
|
|
if (Visited.insert(Nominated).second)
|
2009-04-10 05:40:53 +08:00
|
|
|
|
AddNamespaceUsingDirectives(Context, Nominated, UDirs, /*ref*/ Visited);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// AddScopeUsingDirectives - Adds all UsingDirectiveDecl's found in Scope S,
|
|
|
|
|
/// including all found in the namespaces they nominate.
|
2009-04-10 05:40:53 +08:00
|
|
|
|
static void AddScopeUsingDirectives(ASTContext &Context, Scope *S,
|
|
|
|
|
UsingDirectivesTy &UDirs) {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
NamespaceSet VisitedNS;
|
|
|
|
|
|
|
|
|
|
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
|
|
|
|
|
|
|
|
|
|
if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(Ctx))
|
|
|
|
|
VisitedNS.insert(NS);
|
|
|
|
|
|
2009-04-10 05:40:53 +08:00
|
|
|
|
AddNamespaceUsingDirectives(Context, Ctx, UDirs, /*ref*/ VisitedNS);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
|
|
|
|
} else {
|
2009-03-29 03:18:32 +08:00
|
|
|
|
Scope::udir_iterator I = S->using_directives_begin(),
|
|
|
|
|
End = S->using_directives_end();
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
|
|
|
|
for (; I != End; ++I) {
|
2009-03-29 03:18:32 +08:00
|
|
|
|
UsingDirectiveDecl *UD = I->getAs<UsingDirectiveDecl>();
|
2009-02-04 03:21:40 +08:00
|
|
|
|
UDirs.push_back(UD);
|
|
|
|
|
std::push_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare());
|
|
|
|
|
|
|
|
|
|
NamespaceDecl *Nominated = UD->getNominatedNamespace();
|
|
|
|
|
if (!VisitedNS.count(Nominated)) {
|
|
|
|
|
VisitedNS.insert(Nominated);
|
2009-04-10 05:40:53 +08:00
|
|
|
|
AddNamespaceUsingDirectives(Context, Nominated, UDirs,
|
|
|
|
|
/*ref*/ VisitedNS);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-15 06:20:51 +08:00
|
|
|
|
/// 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
|
2009-02-04 03:21:40 +08:00
|
|
|
|
/// OverloadedFunctionDecl that represents the overloaded functions in
|
2009-01-15 06:20:51 +08:00
|
|
|
|
/// [I, IEnd).
|
|
|
|
|
///
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
/// The existance of this routine is temporary; users of LookupResult
|
|
|
|
|
/// should be able to handle multiple results, to deal with cases of
|
2009-01-15 06:20:51 +08:00
|
|
|
|
/// ambiguity and overloaded functions without needing to create a
|
|
|
|
|
/// Decl node.
|
|
|
|
|
template<typename DeclIterator>
|
2009-02-05 01:27:36 +08:00
|
|
|
|
static NamedDecl *
|
2009-01-15 06:20:51 +08:00
|
|
|
|
MaybeConstructOverloadSet(ASTContext &Context,
|
|
|
|
|
DeclIterator I, DeclIterator IEnd) {
|
|
|
|
|
assert(I != IEnd && "Iterator range cannot be empty");
|
|
|
|
|
assert(!isa<OverloadedFunctionDecl>(*I) &&
|
|
|
|
|
"Cannot have an overloaded function");
|
|
|
|
|
|
2009-06-26 06:08:12 +08:00
|
|
|
|
if ((*I)->isFunctionOrFunctionTemplate()) {
|
2009-01-15 06:20:51 +08:00
|
|
|
|
// If we found a function, there might be more functions. If
|
|
|
|
|
// so, collect them into an overload set.
|
|
|
|
|
DeclIterator Last = I;
|
|
|
|
|
OverloadedFunctionDecl *Ovl = 0;
|
2009-06-26 06:08:12 +08:00
|
|
|
|
for (++Last;
|
|
|
|
|
Last != IEnd && (*Last)->isFunctionOrFunctionTemplate();
|
|
|
|
|
++Last) {
|
2009-01-15 06:20:51 +08:00
|
|
|
|
if (!Ovl) {
|
2009-05-16 15:39:55 +08:00
|
|
|
|
// 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.
|
2009-01-20 09:17:11 +08:00
|
|
|
|
Ovl = OverloadedFunctionDecl::Create(Context, (*I)->getDeclContext(),
|
2009-01-15 06:20:51 +08:00
|
|
|
|
(*I)->getDeclName());
|
2009-06-26 14:29:23 +08:00
|
|
|
|
NamedDecl *ND = (*I)->getUnderlyingDecl();
|
2009-06-26 13:26:50 +08:00
|
|
|
|
if (isa<FunctionDecl>(ND))
|
|
|
|
|
Ovl->addOverload(cast<FunctionDecl>(ND));
|
2009-06-26 06:08:12 +08:00
|
|
|
|
else
|
2009-06-26 13:26:50 +08:00
|
|
|
|
Ovl->addOverload(cast<FunctionTemplateDecl>(ND));
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
2009-06-26 06:08:12 +08:00
|
|
|
|
|
2009-06-26 14:29:23 +08:00
|
|
|
|
NamedDecl *ND = (*Last)->getUnderlyingDecl();
|
2009-06-26 13:26:50 +08:00
|
|
|
|
if (isa<FunctionDecl>(ND))
|
|
|
|
|
Ovl->addOverload(cast<FunctionDecl>(ND));
|
2009-06-26 06:08:12 +08:00
|
|
|
|
else
|
2009-06-26 13:26:50 +08:00
|
|
|
|
Ovl->addOverload(cast<FunctionTemplateDecl>(ND));
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we had more than one function, we built an overload
|
|
|
|
|
// set. Return it.
|
|
|
|
|
if (Ovl)
|
|
|
|
|
return Ovl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return *I;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
/// Merges together multiple LookupResults dealing with duplicated Decl's.
|
|
|
|
|
static Sema::LookupResult
|
|
|
|
|
MergeLookupResults(ASTContext &Context, LookupResultsTy &Results) {
|
|
|
|
|
typedef Sema::LookupResult LResult;
|
2009-02-05 01:27:36 +08:00
|
|
|
|
typedef llvm::SmallPtrSet<NamedDecl*, 4> DeclsSetTy;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
// 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).
|
2009-02-05 01:27:36 +08:00
|
|
|
|
DeclsSetTy FoundDecls;
|
2009-02-06 03:25:20 +08:00
|
|
|
|
|
|
|
|
|
// Counter of tag names, and functions for resolving ambiguity
|
|
|
|
|
// and name hiding.
|
|
|
|
|
std::size_t TagNames = 0, Functions = 0, OrdinaryNonFunc = 0;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
|
|
|
|
LookupResultsTy::iterator I = Results.begin(), End = Results.end();
|
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
// 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) {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
switch (I->getKind()) {
|
|
|
|
|
case LResult::NotFound:
|
|
|
|
|
assert(false &&
|
|
|
|
|
"Should be always successful name lookup result here.");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case LResult::AmbiguousReference:
|
2009-02-06 03:25:20 +08:00
|
|
|
|
case LResult::AmbiguousBaseSubobjectTypes:
|
|
|
|
|
case LResult::AmbiguousBaseSubobjects:
|
|
|
|
|
assert(false && "Shouldn't get ambiguous lookup here.");
|
2009-02-04 03:21:40 +08:00
|
|
|
|
break;
|
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
case LResult::Found: {
|
2009-06-26 14:29:23 +08:00
|
|
|
|
NamedDecl *ND = I->getAsDecl()->getUnderlyingDecl();
|
2009-06-26 11:54:13 +08:00
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
if (TagDecl *TD = dyn_cast<TagDecl>(ND)) {
|
|
|
|
|
TagFound = Context.getCanonicalDecl(TD);
|
|
|
|
|
TagNames += FoundDecls.insert(TagFound)? 1 : 0;
|
2009-06-26 06:08:12 +08:00
|
|
|
|
} else if (ND->isFunctionOrFunctionTemplate())
|
2009-02-06 03:25:20 +08:00
|
|
|
|
Functions += FoundDecls.insert(ND)? 1 : 0;
|
|
|
|
|
else
|
|
|
|
|
FoundDecls.insert(ND);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case LResult::FoundOverloaded:
|
2009-02-06 03:25:20 +08:00
|
|
|
|
for (LResult::iterator FI = I->begin(), FEnd = I->end(); FI != FEnd; ++FI)
|
|
|
|
|
Functions += FoundDecls.insert(*FI)? 1 : 0;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-02-06 03:25:20 +08:00
|
|
|
|
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) {
|
2009-02-05 01:27:36 +08:00
|
|
|
|
// C++ [basic.lookup].p1:
|
|
|
|
|
// ... Name lookup may associate more than one declaration with
|
2009-02-04 03:21:40 +08:00
|
|
|
|
// 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.
|
2009-02-05 01:27:36 +08:00
|
|
|
|
//
|
2009-02-06 03:25:20 +08:00
|
|
|
|
if (!OrdinaryNonFunc) {
|
|
|
|
|
// 4) Functions hide tag names.
|
|
|
|
|
NameHidesTags = TagFound;
|
|
|
|
|
} else {
|
|
|
|
|
// 5) Functions + ordinary names.
|
|
|
|
|
Ambiguous = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 6) Multiple non-tag names
|
|
|
|
|
Ambiguous = true;
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
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);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
// Return successful name lookup result.
|
|
|
|
|
return LResult::CreateLookupResult(Context,
|
|
|
|
|
MaybeConstructOverloadSet(Context,
|
|
|
|
|
FoundDecls.begin(),
|
|
|
|
|
FoundDecls.end()));
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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:
|
2009-02-05 00:44:47 +08:00
|
|
|
|
case Sema::LookupOperatorName:
|
2009-02-25 04:03:32 +08:00
|
|
|
|
case Sema::LookupRedeclarationWithLinkage:
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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;
|
2009-04-24 07:18:26 +08:00
|
|
|
|
|
2009-04-24 08:11:27 +08:00
|
|
|
|
case Sema::LookupObjCProtocolName:
|
|
|
|
|
IDNS = Decl::IDNS_ObjCProtocol;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Sema::LookupObjCImplementationName:
|
|
|
|
|
IDNS = Decl::IDNS_ObjCImplementation;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Sema::LookupObjCCategoryImplName:
|
|
|
|
|
IDNS = Decl::IDNS_ObjCCategoryImpl;
|
2009-04-24 07:18:26 +08:00
|
|
|
|
break;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
return IDNS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Sema::LookupResult
|
2009-02-05 01:27:36 +08:00
|
|
|
|
Sema::LookupResult::CreateLookupResult(ASTContext &Context, NamedDecl *D) {
|
2009-06-26 14:29:23 +08:00
|
|
|
|
if (D)
|
|
|
|
|
D = D->getUnderlyingDecl();
|
2009-06-26 11:37:05 +08:00
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-15 10:19:31 +08:00
|
|
|
|
/// @brief Moves the name-lookup results from Other to this LookupResult.
|
2009-01-17 09:13:24 +08:00
|
|
|
|
Sema::LookupResult
|
|
|
|
|
Sema::LookupResult::CreateLookupResult(ASTContext &Context,
|
|
|
|
|
IdentifierResolver::iterator F,
|
|
|
|
|
IdentifierResolver::iterator L) {
|
|
|
|
|
LookupResult Result;
|
|
|
|
|
Result.Context = &Context;
|
|
|
|
|
|
2009-06-26 06:08:12 +08:00
|
|
|
|
if (F != L && (*F)->isFunctionOrFunctionTemplate()) {
|
2009-01-15 08:26:24 +08:00
|
|
|
|
IdentifierResolver::iterator Next = F;
|
|
|
|
|
++Next;
|
2009-06-26 06:08:12 +08:00
|
|
|
|
if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) {
|
2009-01-17 09:13:24 +08:00
|
|
|
|
Result.StoredKind = OverloadedDeclFromIdResolver;
|
|
|
|
|
Result.First = F.getAsOpaqueValue();
|
|
|
|
|
Result.Last = L.getAsOpaqueValue();
|
|
|
|
|
return Result;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-04-24 10:57:34 +08:00
|
|
|
|
|
2009-06-26 14:29:23 +08:00
|
|
|
|
NamedDecl *D = *F;
|
|
|
|
|
if (D)
|
|
|
|
|
D = D->getUnderlyingDecl();
|
2009-06-26 11:37:05 +08:00
|
|
|
|
|
2009-01-17 09:13:24 +08:00
|
|
|
|
Result.StoredKind = SingleDecl;
|
2009-04-24 10:57:34 +08:00
|
|
|
|
Result.First = reinterpret_cast<uintptr_t>(D);
|
2009-01-17 09:13:24 +08:00
|
|
|
|
Result.Last = 0;
|
|
|
|
|
return Result;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-01-17 09:13:24 +08:00
|
|
|
|
Sema::LookupResult
|
|
|
|
|
Sema::LookupResult::CreateLookupResult(ASTContext &Context,
|
|
|
|
|
DeclContext::lookup_iterator F,
|
|
|
|
|
DeclContext::lookup_iterator L) {
|
|
|
|
|
LookupResult Result;
|
|
|
|
|
Result.Context = &Context;
|
|
|
|
|
|
2009-06-26 06:08:12 +08:00
|
|
|
|
if (F != L && (*F)->isFunctionOrFunctionTemplate()) {
|
2009-01-15 08:26:24 +08:00
|
|
|
|
DeclContext::lookup_iterator Next = F;
|
|
|
|
|
++Next;
|
2009-06-26 06:08:12 +08:00
|
|
|
|
if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) {
|
2009-01-17 09:13:24 +08:00
|
|
|
|
Result.StoredKind = OverloadedDeclFromDeclContext;
|
|
|
|
|
Result.First = reinterpret_cast<uintptr_t>(F);
|
|
|
|
|
Result.Last = reinterpret_cast<uintptr_t>(L);
|
|
|
|
|
return Result;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-04-24 10:57:34 +08:00
|
|
|
|
|
2009-06-26 14:29:23 +08:00
|
|
|
|
NamedDecl *D = *F;
|
|
|
|
|
if (D)
|
|
|
|
|
D = D->getUnderlyingDecl();
|
|
|
|
|
|
2009-01-17 09:13:24 +08:00
|
|
|
|
Result.StoredKind = SingleDecl;
|
2009-04-24 10:57:34 +08:00
|
|
|
|
Result.First = reinterpret_cast<uintptr_t>(D);
|
2009-01-17 09:13:24 +08:00
|
|
|
|
Result.Last = 0;
|
|
|
|
|
return Result;
|
2009-01-15 10:19:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-01-15 06:20:51 +08:00
|
|
|
|
/// @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;
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
case OverloadedDeclSingleDecl:
|
2009-01-15 06:20:51 +08:00
|
|
|
|
case OverloadedDeclFromIdResolver:
|
|
|
|
|
case OverloadedDeclFromDeclContext:
|
|
|
|
|
return FoundOverloaded;
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
case AmbiguousLookupStoresBasePaths:
|
2009-01-15 08:26:24 +08:00
|
|
|
|
return Last? AmbiguousBaseSubobjectTypes : AmbiguousBaseSubobjects;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
|
|
|
|
case AmbiguousLookupStoresDecls:
|
|
|
|
|
return AmbiguousReference;
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-01-15 08:26:24 +08:00
|
|
|
|
// We can't ever get here.
|
|
|
|
|
return NotFound;
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @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.
|
2009-02-05 01:27:36 +08:00
|
|
|
|
NamedDecl *Sema::LookupResult::getAsDecl() const {
|
2009-01-15 06:20:51 +08:00
|
|
|
|
switch (StoredKind) {
|
|
|
|
|
case SingleDecl:
|
2009-02-05 01:27:36 +08:00
|
|
|
|
return reinterpret_cast<NamedDecl *>(First);
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
case OverloadedDeclSingleDecl:
|
|
|
|
|
return reinterpret_cast<OverloadedFunctionDecl*>(First);
|
|
|
|
|
|
|
|
|
|
case AmbiguousLookupStoresDecls:
|
|
|
|
|
case AmbiguousLookupStoresBasePaths:
|
2009-01-15 06:20:51 +08:00
|
|
|
|
assert(false &&
|
|
|
|
|
"Name lookup returned an ambiguity that could not be handled");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-15 08:26:24 +08:00
|
|
|
|
/// @brief Retrieves the BasePaths structure describing an ambiguous
|
2009-02-04 03:21:40 +08:00
|
|
|
|
/// name lookup, or null.
|
2009-01-15 08:26:24 +08:00
|
|
|
|
BasePaths *Sema::LookupResult::getBasePaths() const {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
if (StoredKind == AmbiguousLookupStoresBasePaths)
|
|
|
|
|
return reinterpret_cast<BasePaths *>(First);
|
|
|
|
|
return 0;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-03 05:35:47 +08:00
|
|
|
|
Sema::LookupResult::iterator::reference
|
|
|
|
|
Sema::LookupResult::iterator::operator*() const {
|
|
|
|
|
switch (Result->StoredKind) {
|
|
|
|
|
case SingleDecl:
|
2009-02-05 01:27:36 +08:00
|
|
|
|
return reinterpret_cast<NamedDecl*>(Current);
|
2009-02-03 05:35:47 +08:00
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
case OverloadedDeclSingleDecl:
|
2009-02-05 01:27:36 +08:00
|
|
|
|
return *reinterpret_cast<NamedDecl**>(Current);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-02-03 05:35:47 +08:00
|
|
|
|
case OverloadedDeclFromIdResolver:
|
|
|
|
|
return *IdentifierResolver::iterator::getFromOpaqueValue(Current);
|
|
|
|
|
|
2009-04-02 05:51:26 +08:00
|
|
|
|
case AmbiguousLookupStoresBasePaths:
|
|
|
|
|
if (Result->Last)
|
|
|
|
|
return *reinterpret_cast<NamedDecl**>(Current);
|
|
|
|
|
|
|
|
|
|
// Fall through to handle the DeclContext::lookup_iterator we're
|
|
|
|
|
// storing.
|
|
|
|
|
|
2009-02-03 05:35:47 +08:00
|
|
|
|
case OverloadedDeclFromDeclContext:
|
2009-02-04 03:21:40 +08:00
|
|
|
|
case AmbiguousLookupStoresDecls:
|
2009-04-02 05:51:26 +08:00
|
|
|
|
return *reinterpret_cast<DeclContext::lookup_iterator>(Current);
|
2009-02-03 05:35:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Sema::LookupResult::iterator& Sema::LookupResult::iterator::operator++() {
|
|
|
|
|
switch (Result->StoredKind) {
|
|
|
|
|
case SingleDecl:
|
2009-02-05 01:27:36 +08:00
|
|
|
|
Current = reinterpret_cast<uintptr_t>((NamedDecl*)0);
|
2009-02-03 05:35:47 +08:00
|
|
|
|
break;
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
case OverloadedDeclSingleDecl: {
|
2009-02-05 01:27:36 +08:00
|
|
|
|
NamedDecl ** I = reinterpret_cast<NamedDecl**>(Current);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
++I;
|
|
|
|
|
Current = reinterpret_cast<uintptr_t>(I);
|
2009-02-05 00:44:47 +08:00
|
|
|
|
break;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-03 05:35:47 +08:00
|
|
|
|
case OverloadedDeclFromIdResolver: {
|
|
|
|
|
IdentifierResolver::iterator I
|
|
|
|
|
= IdentifierResolver::iterator::getFromOpaqueValue(Current);
|
|
|
|
|
++I;
|
|
|
|
|
Current = I.getAsOpaqueValue();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-02 05:51:26 +08:00
|
|
|
|
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: {
|
2009-02-03 05:35:47 +08:00
|
|
|
|
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() {
|
2009-04-02 05:51:26 +08:00
|
|
|
|
switch (StoredKind) {
|
|
|
|
|
case SingleDecl:
|
|
|
|
|
case OverloadedDeclFromIdResolver:
|
|
|
|
|
case OverloadedDeclFromDeclContext:
|
|
|
|
|
case AmbiguousLookupStoresDecls:
|
2009-02-04 03:21:40 +08:00
|
|
|
|
return iterator(this, First);
|
2009-04-02 05:51:26 +08:00
|
|
|
|
|
|
|
|
|
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();
|
2009-02-03 05:35:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Sema::LookupResult::iterator Sema::LookupResult::end() {
|
2009-04-02 05:51:26 +08:00
|
|
|
|
switch (StoredKind) {
|
|
|
|
|
case SingleDecl:
|
|
|
|
|
case OverloadedDeclFromIdResolver:
|
|
|
|
|
case OverloadedDeclFromDeclContext:
|
|
|
|
|
case AmbiguousLookupStoresDecls:
|
2009-02-04 03:21:40 +08:00
|
|
|
|
return iterator(this, Last);
|
2009-04-02 05:51:26 +08:00
|
|
|
|
|
|
|
|
|
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);
|
2009-02-03 05:35:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
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;
|
2009-04-10 05:40:53 +08:00
|
|
|
|
for (llvm::tie(I, E) = NS->lookup(Context, Name); I != E; ++I)
|
2009-02-06 03:25:20 +08:00
|
|
|
|
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) {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
|
2009-02-06 03:25:20 +08:00
|
|
|
|
return Ctx->isFileContext();
|
|
|
|
|
return false;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
std::pair<bool, Sema::LookupResult>
|
|
|
|
|
Sema::CppLookupName(Scope *S, DeclarationName Name,
|
|
|
|
|
LookupNameKind NameKind, bool RedeclarationOnly) {
|
|
|
|
|
assert(getLangOptions().CPlusPlus &&
|
|
|
|
|
"Can perform only C++ lookup");
|
2009-02-05 00:44:47 +08:00
|
|
|
|
unsigned IDNS
|
2009-02-05 01:27:36 +08:00
|
|
|
|
= getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
Scope *Initial = S;
|
2009-02-06 03:25:20 +08:00
|
|
|
|
DeclContext *OutOfLineCtx = 0;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
IdentifierResolver::iterator
|
|
|
|
|
I = IdResolver.begin(Name),
|
|
|
|
|
IEnd = IdResolver.end();
|
|
|
|
|
|
|
|
|
|
// First we lookup local scope.
|
2009-02-05 03:02:06 +08:00
|
|
|
|
// We don't consider using-directives, as per 7.3.4.p1 [namespace.udir]
|
2009-02-04 03:21:40 +08:00
|
|
|
|
// ...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
|
|
|
|
|
// }
|
|
|
|
|
// }
|
2009-02-05 01:27:36 +08:00
|
|
|
|
//
|
2009-02-06 03:25:20 +08:00
|
|
|
|
for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
// Check whether the IdResolver has anything in this scope.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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) {
|
2009-03-29 03:18:32 +08:00
|
|
|
|
if (!S->isDeclScope(DeclPtrTy::make(*LastI)))
|
2009-02-04 03:21:40 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
LookupResult Result =
|
|
|
|
|
LookupResult::CreateLookupResult(Context, I, LastI);
|
|
|
|
|
return std::make_pair(true, Result);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-02-06 03:25:20 +08:00
|
|
|
|
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
|
|
|
|
|
LookupResult R;
|
|
|
|
|
// Perform member lookup into struct.
|
2009-05-16 15:39:55 +08:00
|
|
|
|
// 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.
|
2009-03-27 12:21:56 +08:00
|
|
|
|
if (isa<RecordDecl>(Ctx)) {
|
|
|
|
|
R = LookupQualifiedName(Ctx, Name, NameKind, RedeclarationOnly);
|
2009-06-18 07:37:01 +08:00
|
|
|
|
if (R)
|
2009-03-27 12:21:56 +08:00
|
|
|
|
return std::make_pair(true, R);
|
|
|
|
|
}
|
2009-05-28 01:07:49 +08:00
|
|
|
|
if (Ctx->getParent() != Ctx->getLexicalParent()
|
|
|
|
|
|| isa<CXXMethodDecl>(Ctx)) {
|
2009-02-06 03:25:20 +08:00
|
|
|
|
// 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()) {
|
2009-03-27 12:21:56 +08:00
|
|
|
|
R = LookupQualifiedName(OutOfLineCtx, Name, NameKind, RedeclarationOnly);
|
2009-06-18 07:37:01 +08:00
|
|
|
|
if (R)
|
2009-02-06 03:25:20 +08:00
|
|
|
|
return std::make_pair(true, R);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
// Collect UsingDirectiveDecls in all scopes, and recursively all
|
2009-02-04 03:21:40 +08:00
|
|
|
|
// nominated namespaces by those using-directives.
|
2009-05-16 15:39:55 +08:00
|
|
|
|
// 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!
|
2009-02-04 03:21:40 +08:00
|
|
|
|
UsingDirectivesTy UDirs;
|
|
|
|
|
for (Scope *SC = Initial; SC; SC = SC->getParent())
|
2009-02-05 01:27:36 +08:00
|
|
|
|
if (SC->getFlags() & Scope::DeclScope)
|
2009-04-10 05:40:53 +08:00
|
|
|
|
AddScopeUsingDirectives(Context, SC, UDirs);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
|
|
|
|
// Sort heapified UsingDirectiveDecls.
|
2009-05-19 06:06:54 +08:00
|
|
|
|
std::sort_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare());
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
// Lookup namespace scope, and global scope.
|
2009-02-04 03:21:40 +08:00
|
|
|
|
// 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.
|
2009-02-06 03:25:20 +08:00
|
|
|
|
|
|
|
|
|
LookupResultsTy LookupResults;
|
2009-02-07 08:15:38 +08:00
|
|
|
|
assert((!OutOfLineCtx || OutOfLineCtx->isFileContext()) &&
|
2009-02-06 03:25:20 +08:00
|
|
|
|
"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();
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
for (; S; S = S->getParent()) {
|
2009-02-06 03:25:20 +08:00
|
|
|
|
DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
|
|
|
|
|
assert(Ctx && Ctx->isFileContext() &&
|
|
|
|
|
"We should have been looking only at file context here already.");
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
|
|
|
|
// Check whether the IdResolver has anything in this scope.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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) {
|
2009-03-29 03:18:32 +08:00
|
|
|
|
if (!S->isDeclScope(DeclPtrTy::make(*LastI)))
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
LookedInCtx = true;
|
|
|
|
|
// Look into context considering using-directives.
|
|
|
|
|
CppNamespaceLookup(Context, Ctx, Name, NameKind, IDNS,
|
|
|
|
|
LookupResults, &UDirs);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
if ((Result = MergeLookupResults(Context, LookupResults)) ||
|
|
|
|
|
(RedeclarationOnly && !Ctx->isTransparentContext()))
|
|
|
|
|
return std::make_pair(true, Result);
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
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());
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
return std::make_pair(false, LookupResult());
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-01-15 06:20:51 +08:00
|
|
|
|
/// @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.
|
|
|
|
|
///
|
Implicitly declare certain C library functions (malloc, strcpy, memmove,
etc.) when we perform name lookup on them. This ensures that we
produce the correct signature for these functions, which has two
practical impacts:
1) When we're supporting the "implicit function declaration" feature
of C99, these functions will be implicitly declared with the right
signature rather than as a function returning "int" with no
prototype. See PR3541 for the reason why this is important (hint:
GCC always predeclares these functions).
2) If users attempt to redeclare one of these library functions with
an incompatible signature, we produce a hard error.
This patch does a little bit of work to give reasonable error
messages. For example, when we hit case #1 we complain that we're
implicitly declaring this function with a specific signature, and then
we give a note that asks the user to include the appropriate header
(e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In
case #2, we show the type of the implicit builtin that was incorrectly
declared, so the user can see the problem. We could do better here:
for example, when displaying this latter error message we say
something like:
'strcpy' was implicitly declared here with type 'char *(char *, char
const *)'
but we should really print out a fake code line showing the
declaration, like this:
'strcpy' was implicitly declared here as:
char *strcpy(char *, char const *)
This would also be good for printing built-in candidates with C++
operator overloading.
The set of C library functions supported by this patch includes all
functions from the C99 specification's <stdlib.h> and <string.h> that
(a) are predefined by GCC and (b) have signatures that could cause
codegen issues if they are treated as functions with no prototype
returning and int. Future work could extend this set of functions to
other C library functions that we know about.
llvm-svn: 64504
2009-02-14 07:20:09 +08:00
|
|
|
|
/// @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.
|
2009-01-15 06:20:51 +08:00
|
|
|
|
///
|
|
|
|
|
/// @returns The result of name lookup, which includes zero or more
|
|
|
|
|
/// declarations and possibly additional information used to diagnose
|
|
|
|
|
/// ambiguities.
|
|
|
|
|
Sema::LookupResult
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind,
|
Implicitly declare certain C library functions (malloc, strcpy, memmove,
etc.) when we perform name lookup on them. This ensures that we
produce the correct signature for these functions, which has two
practical impacts:
1) When we're supporting the "implicit function declaration" feature
of C99, these functions will be implicitly declared with the right
signature rather than as a function returning "int" with no
prototype. See PR3541 for the reason why this is important (hint:
GCC always predeclares these functions).
2) If users attempt to redeclare one of these library functions with
an incompatible signature, we produce a hard error.
This patch does a little bit of work to give reasonable error
messages. For example, when we hit case #1 we complain that we're
implicitly declaring this function with a specific signature, and then
we give a note that asks the user to include the appropriate header
(e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In
case #2, we show the type of the implicit builtin that was incorrectly
declared, so the user can see the problem. We could do better here:
for example, when displaying this latter error message we say
something like:
'strcpy' was implicitly declared here with type 'char *(char *, char
const *)'
but we should really print out a fake code line showing the
declaration, like this:
'strcpy' was implicitly declared here as:
char *strcpy(char *, char const *)
This would also be good for printing built-in candidates with C++
operator overloading.
The set of C library functions supported by this patch includes all
functions from the C99 specification's <stdlib.h> and <string.h> that
(a) are predefined by GCC and (b) have signatures that could cause
codegen issues if they are treated as functions with no prototype
returning and int. Future work could extend this set of functions to
other C library functions that we know about.
llvm-svn: 64504
2009-02-14 07:20:09 +08:00
|
|
|
|
bool RedeclarationOnly, bool AllowBuiltinCreation,
|
|
|
|
|
SourceLocation Loc) {
|
2009-01-17 09:13:24 +08:00
|
|
|
|
if (!Name) return LookupResult::CreateLookupResult(Context, 0);
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
|
|
|
|
if (!getLangOptions().CPlusPlus) {
|
|
|
|
|
// Unqualified name lookup in C/Objective-C is purely lexical, so
|
|
|
|
|
// search in the declarations attached to the name.
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
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;
|
|
|
|
|
|
2009-02-05 00:44:47 +08:00
|
|
|
|
case Sema::LookupOperatorName:
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
case Sema::LookupNestedNameSpecifierName:
|
|
|
|
|
case Sema::LookupNamespaceName:
|
|
|
|
|
assert(false && "C does not perform these kinds of name lookup");
|
|
|
|
|
break;
|
2009-02-25 04:03:32 +08:00
|
|
|
|
|
|
|
|
|
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;
|
2009-04-24 07:18:26 +08:00
|
|
|
|
|
2009-04-24 08:11:27 +08:00
|
|
|
|
case Sema::LookupObjCProtocolName:
|
|
|
|
|
IDNS = Decl::IDNS_ObjCProtocol;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Sema::LookupObjCImplementationName:
|
|
|
|
|
IDNS = Decl::IDNS_ObjCImplementation;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Sema::LookupObjCCategoryImplName:
|
|
|
|
|
IDNS = Decl::IDNS_ObjCCategoryImpl;
|
2009-04-24 07:18:26 +08:00
|
|
|
|
break;
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
}
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
|
|
|
|
// 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.
|
2009-02-25 04:03:32 +08:00
|
|
|
|
bool LeftStartingScope = false;
|
|
|
|
|
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
for (IdentifierResolver::iterator I = IdResolver.begin(Name),
|
|
|
|
|
IEnd = IdResolver.end();
|
|
|
|
|
I != IEnd; ++I)
|
Initial implementation of function overloading in C.
This commit adds a new attribute, "overloadable", that enables C++
function overloading in C. The attribute can only be added to function
declarations, e.g.,
int *f(int) __attribute__((overloadable));
If the "overloadable" attribute exists on a function with a given
name, *all* functions with that name (and in that scope) must have the
"overloadable" attribute. Sets of overloaded functions with the
"overloadable" attribute then follow the normal C++ rules for
overloaded functions, e.g., overloads must have different
parameter-type-lists from each other.
When calling an overloaded function in C, we follow the same
overloading rules as C++, with three extensions to the set of standard
conversions:
- A value of a given struct or union type T can be converted to the
type T. This is just the identity conversion. (In C++, this would
go through a copy constructor).
- A value of pointer type T* can be converted to a value of type U*
if T and U are compatible types. This conversion has Conversion
rank (it's considered a pointer conversion in C).
- A value of type T can be converted to a value of type U if T and U
are compatible (and are not both pointer types). This conversion
has Conversion rank (it's considered to be a new kind of
conversion unique to C, a "compatible" conversion).
Known defects (and, therefore, next steps):
1) The standard-conversion handling does not understand conversions
involving _Complex or vector extensions, so it is likely to get
these wrong. We need to add these conversions.
2) All overloadable functions with the same name will have the same
linkage name, which means we'll get a collision in the linker (if
not sooner). We'll need to mangle the names of these functions.
llvm-svn: 64336
2009-02-12 07:02:49 +08:00
|
|
|
|
if ((*I)->isInIdentifierNamespace(IDNS)) {
|
2009-02-25 04:03:32 +08:00
|
|
|
|
if (NameKind == LookupRedeclarationWithLinkage) {
|
|
|
|
|
// Determine whether this (or a previous) declaration is
|
|
|
|
|
// out-of-scope.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
if (!LeftStartingScope && !S->isDeclScope(DeclPtrTy::make(*I)))
|
2009-02-25 04:03:32 +08:00
|
|
|
|
LeftStartingScope = true;
|
|
|
|
|
|
|
|
|
|
// If we found something outside of our starting scope that
|
|
|
|
|
// does not have linkage, skip it.
|
|
|
|
|
if (LeftStartingScope && !((*I)->hasLinkage()))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-30 10:34:44 +08:00
|
|
|
|
if ((*I)->getAttr<OverloadableAttr>()) {
|
Initial implementation of function overloading in C.
This commit adds a new attribute, "overloadable", that enables C++
function overloading in C. The attribute can only be added to function
declarations, e.g.,
int *f(int) __attribute__((overloadable));
If the "overloadable" attribute exists on a function with a given
name, *all* functions with that name (and in that scope) must have the
"overloadable" attribute. Sets of overloaded functions with the
"overloadable" attribute then follow the normal C++ rules for
overloaded functions, e.g., overloads must have different
parameter-type-lists from each other.
When calling an overloaded function in C, we follow the same
overloading rules as C++, with three extensions to the set of standard
conversions:
- A value of a given struct or union type T can be converted to the
type T. This is just the identity conversion. (In C++, this would
go through a copy constructor).
- A value of pointer type T* can be converted to a value of type U*
if T and U are compatible types. This conversion has Conversion
rank (it's considered a pointer conversion in C).
- A value of type T can be converted to a value of type U if T and U
are compatible (and are not both pointer types). This conversion
has Conversion rank (it's considered to be a new kind of
conversion unique to C, a "compatible" conversion).
Known defects (and, therefore, next steps):
1) The standard-conversion handling does not understand conversions
involving _Complex or vector extensions, so it is likely to get
these wrong. We need to add these conversions.
2) All overloadable functions with the same name will have the same
linkage name, which means we'll get a collision in the linker (if
not sooner). We'll need to mangle the names of these functions.
llvm-svn: 64336
2009-02-12 07:02:49 +08:00
|
|
|
|
// If this declaration has the "overloadable" attribute, we
|
|
|
|
|
// might have a set of overloaded functions.
|
|
|
|
|
|
|
|
|
|
// Figure out what scope the identifier is in.
|
2009-03-29 03:18:32 +08:00
|
|
|
|
while (!(S->getFlags() & Scope::DeclScope) ||
|
|
|
|
|
!S->isDeclScope(DeclPtrTy::make(*I)))
|
Initial implementation of function overloading in C.
This commit adds a new attribute, "overloadable", that enables C++
function overloading in C. The attribute can only be added to function
declarations, e.g.,
int *f(int) __attribute__((overloadable));
If the "overloadable" attribute exists on a function with a given
name, *all* functions with that name (and in that scope) must have the
"overloadable" attribute. Sets of overloaded functions with the
"overloadable" attribute then follow the normal C++ rules for
overloaded functions, e.g., overloads must have different
parameter-type-lists from each other.
When calling an overloaded function in C, we follow the same
overloading rules as C++, with three extensions to the set of standard
conversions:
- A value of a given struct or union type T can be converted to the
type T. This is just the identity conversion. (In C++, this would
go through a copy constructor).
- A value of pointer type T* can be converted to a value of type U*
if T and U are compatible types. This conversion has Conversion
rank (it's considered a pointer conversion in C).
- A value of type T can be converted to a value of type U if T and U
are compatible (and are not both pointer types). This conversion
has Conversion rank (it's considered to be a new kind of
conversion unique to C, a "compatible" conversion).
Known defects (and, therefore, next steps):
1) The standard-conversion handling does not understand conversions
involving _Complex or vector extensions, so it is likely to get
these wrong. We need to add these conversions.
2) All overloadable functions with the same name will have the same
linkage name, which means we'll get a collision in the linker (if
not sooner). We'll need to mangle the names of these functions.
llvm-svn: 64336
2009-02-12 07:02:49 +08:00
|
|
|
|
S = S->getParent();
|
|
|
|
|
|
|
|
|
|
// Find the last declaration in this scope (with the same
|
|
|
|
|
// name, naturally).
|
|
|
|
|
IdentifierResolver::iterator LastI = I;
|
|
|
|
|
for (++LastI; LastI != IEnd; ++LastI) {
|
2009-03-29 03:18:32 +08:00
|
|
|
|
if (!S->isDeclScope(DeclPtrTy::make(*LastI)))
|
Initial implementation of function overloading in C.
This commit adds a new attribute, "overloadable", that enables C++
function overloading in C. The attribute can only be added to function
declarations, e.g.,
int *f(int) __attribute__((overloadable));
If the "overloadable" attribute exists on a function with a given
name, *all* functions with that name (and in that scope) must have the
"overloadable" attribute. Sets of overloaded functions with the
"overloadable" attribute then follow the normal C++ rules for
overloaded functions, e.g., overloads must have different
parameter-type-lists from each other.
When calling an overloaded function in C, we follow the same
overloading rules as C++, with three extensions to the set of standard
conversions:
- A value of a given struct or union type T can be converted to the
type T. This is just the identity conversion. (In C++, this would
go through a copy constructor).
- A value of pointer type T* can be converted to a value of type U*
if T and U are compatible types. This conversion has Conversion
rank (it's considered a pointer conversion in C).
- A value of type T can be converted to a value of type U if T and U
are compatible (and are not both pointer types). This conversion
has Conversion rank (it's considered to be a new kind of
conversion unique to C, a "compatible" conversion).
Known defects (and, therefore, next steps):
1) The standard-conversion handling does not understand conversions
involving _Complex or vector extensions, so it is likely to get
these wrong. We need to add these conversions.
2) All overloadable functions with the same name will have the same
linkage name, which means we'll get a collision in the linker (if
not sooner). We'll need to mangle the names of these functions.
llvm-svn: 64336
2009-02-12 07:02:49 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LookupResult::CreateLookupResult(Context, I, LastI);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We have a single lookup result.
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context, *I);
|
Initial implementation of function overloading in C.
This commit adds a new attribute, "overloadable", that enables C++
function overloading in C. The attribute can only be added to function
declarations, e.g.,
int *f(int) __attribute__((overloadable));
If the "overloadable" attribute exists on a function with a given
name, *all* functions with that name (and in that scope) must have the
"overloadable" attribute. Sets of overloaded functions with the
"overloadable" attribute then follow the normal C++ rules for
overloaded functions, e.g., overloads must have different
parameter-type-lists from each other.
When calling an overloaded function in C, we follow the same
overloading rules as C++, with three extensions to the set of standard
conversions:
- A value of a given struct or union type T can be converted to the
type T. This is just the identity conversion. (In C++, this would
go through a copy constructor).
- A value of pointer type T* can be converted to a value of type U*
if T and U are compatible types. This conversion has Conversion
rank (it's considered a pointer conversion in C).
- A value of type T can be converted to a value of type U if T and U
are compatible (and are not both pointer types). This conversion
has Conversion rank (it's considered to be a new kind of
conversion unique to C, a "compatible" conversion).
Known defects (and, therefore, next steps):
1) The standard-conversion handling does not understand conversions
involving _Complex or vector extensions, so it is likely to get
these wrong. We need to add these conversions.
2) All overloadable functions with the same name will have the same
linkage name, which means we'll get a collision in the linker (if
not sooner). We'll need to mangle the names of these functions.
llvm-svn: 64336
2009-02-12 07:02:49 +08:00
|
|
|
|
}
|
2009-01-15 06:20:51 +08:00
|
|
|
|
} else {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
// Perform C++ unqualified name lookup.
|
|
|
|
|
std::pair<bool, LookupResult> MaybeResult =
|
|
|
|
|
CppLookupName(S, Name, NameKind, RedeclarationOnly);
|
|
|
|
|
if (MaybeResult.first)
|
|
|
|
|
return MaybeResult.second;
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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.
|
2009-02-25 04:03:32 +08:00
|
|
|
|
if (NameKind == LookupOrdinaryName ||
|
|
|
|
|
NameKind == LookupRedeclarationWithLinkage) {
|
2009-01-15 06:20:51 +08:00
|
|
|
|
IdentifierInfo *II = Name.getAsIdentifierInfo();
|
Implicitly declare certain C library functions (malloc, strcpy, memmove,
etc.) when we perform name lookup on them. This ensures that we
produce the correct signature for these functions, which has two
practical impacts:
1) When we're supporting the "implicit function declaration" feature
of C99, these functions will be implicitly declared with the right
signature rather than as a function returning "int" with no
prototype. See PR3541 for the reason why this is important (hint:
GCC always predeclares these functions).
2) If users attempt to redeclare one of these library functions with
an incompatible signature, we produce a hard error.
This patch does a little bit of work to give reasonable error
messages. For example, when we hit case #1 we complain that we're
implicitly declaring this function with a specific signature, and then
we give a note that asks the user to include the appropriate header
(e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In
case #2, we show the type of the implicit builtin that was incorrectly
declared, so the user can see the problem. We could do better here:
for example, when displaying this latter error message we say
something like:
'strcpy' was implicitly declared here with type 'char *(char *, char
const *)'
but we should really print out a fake code line showing the
declaration, like this:
'strcpy' was implicitly declared here as:
char *strcpy(char *, char const *)
This would also be good for printing built-in candidates with C++
operator overloading.
The set of C library functions supported by this patch includes all
functions from the C99 specification's <stdlib.h> and <string.h> that
(a) are predefined by GCC and (b) have signatures that could cause
codegen issues if they are treated as functions with no prototype
returning and int. Future work could extend this set of functions to
other C library functions that we know about.
llvm-svn: 64504
2009-02-14 07:20:09 +08:00
|
|
|
|
if (II && AllowBuiltinCreation) {
|
2009-01-15 06:20:51 +08:00
|
|
|
|
// If this is a builtin on this (or all) targets, create the decl.
|
Implicitly declare certain C library functions (malloc, strcpy, memmove,
etc.) when we perform name lookup on them. This ensures that we
produce the correct signature for these functions, which has two
practical impacts:
1) When we're supporting the "implicit function declaration" feature
of C99, these functions will be implicitly declared with the right
signature rather than as a function returning "int" with no
prototype. See PR3541 for the reason why this is important (hint:
GCC always predeclares these functions).
2) If users attempt to redeclare one of these library functions with
an incompatible signature, we produce a hard error.
This patch does a little bit of work to give reasonable error
messages. For example, when we hit case #1 we complain that we're
implicitly declaring this function with a specific signature, and then
we give a note that asks the user to include the appropriate header
(e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In
case #2, we show the type of the implicit builtin that was incorrectly
declared, so the user can see the problem. We could do better here:
for example, when displaying this latter error message we say
something like:
'strcpy' was implicitly declared here with type 'char *(char *, char
const *)'
but we should really print out a fake code line showing the
declaration, like this:
'strcpy' was implicitly declared here as:
char *strcpy(char *, char const *)
This would also be good for printing built-in candidates with C++
operator overloading.
The set of C library functions supported by this patch includes all
functions from the C99 specification's <stdlib.h> and <string.h> that
(a) are predefined by GCC and (b) have signatures that could cause
codegen issues if they are treated as functions with no prototype
returning and int. Future work could extend this set of functions to
other C library functions that we know about.
llvm-svn: 64504
2009-02-14 07:20:09 +08:00
|
|
|
|
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);
|
|
|
|
|
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context,
|
2009-01-15 06:20:51 +08:00
|
|
|
|
LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
|
Implicitly declare certain C library functions (malloc, strcpy, memmove,
etc.) when we perform name lookup on them. This ensures that we
produce the correct signature for these functions, which has two
practical impacts:
1) When we're supporting the "implicit function declaration" feature
of C99, these functions will be implicitly declared with the right
signature rather than as a function returning "int" with no
prototype. See PR3541 for the reason why this is important (hint:
GCC always predeclares these functions).
2) If users attempt to redeclare one of these library functions with
an incompatible signature, we produce a hard error.
This patch does a little bit of work to give reasonable error
messages. For example, when we hit case #1 we complain that we're
implicitly declaring this function with a specific signature, and then
we give a note that asks the user to include the appropriate header
(e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In
case #2, we show the type of the implicit builtin that was incorrectly
declared, so the user can see the problem. We could do better here:
for example, when displaying this latter error message we say
something like:
'strcpy' was implicitly declared here with type 'char *(char *, char
const *)'
but we should really print out a fake code line showing the
declaration, like this:
'strcpy' was implicitly declared here as:
char *strcpy(char *, char const *)
This would also be good for printing built-in candidates with C++
operator overloading.
The set of C library functions supported by this patch includes all
functions from the C99 specification's <stdlib.h> and <string.h> that
(a) are predefined by GCC and (b) have signatures that could cause
codegen issues if they are treated as functions with no prototype
returning and int. Future work could extend this set of functions to
other C library functions that we know about.
llvm-svn: 64504
2009-02-14 07:20:09 +08:00
|
|
|
|
S, RedeclarationOnly, Loc));
|
|
|
|
|
}
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context, 0);
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @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,
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
LookupNameKind NameKind, bool RedeclarationOnly) {
|
2009-01-15 06:20:51 +08:00
|
|
|
|
assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
|
|
|
|
|
|
2009-01-17 09:13:24 +08:00
|
|
|
|
if (!Name) return LookupResult::CreateLookupResult(Context, 0);
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
|
|
|
|
// If we're performing qualified name lookup (e.g., lookup into a
|
|
|
|
|
// struct), find fields as part of ordinary name lookup.
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
unsigned IDNS
|
|
|
|
|
= getIdentifierNamespacesFromLookupNameKind(NameKind,
|
|
|
|
|
getLangOptions().CPlusPlus);
|
|
|
|
|
if (NameKind == LookupOrdinaryName)
|
|
|
|
|
IDNS |= Decl::IDNS_Member;
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
|
|
|
|
// Perform qualified name lookup into the LookupCtx.
|
|
|
|
|
DeclContext::lookup_iterator I, E;
|
2009-04-10 05:40:53 +08:00
|
|
|
|
for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I)
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
if (isAcceptableLookupResult(*I, NameKind, IDNS))
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context, I, E);
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
2009-01-15 08:26:24 +08:00
|
|
|
|
// If this isn't a C++ class or we aren't allowed to look into base
|
|
|
|
|
// classes, we're done.
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
if (RedeclarationOnly || !isa<CXXRecordDecl>(LookupCtx))
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context, 0);
|
2009-01-15 08:26:24 +08:00
|
|
|
|
|
|
|
|
|
// Perform lookup into our base classes.
|
|
|
|
|
BasePaths Paths;
|
2009-01-16 08:38:09 +08:00
|
|
|
|
Paths.setOrigin(Context.getTypeDeclType(cast<RecordDecl>(LookupCtx)));
|
2009-01-15 08:26:24 +08:00
|
|
|
|
|
|
|
|
|
// Look for this member in our base classes
|
|
|
|
|
if (!LookupInBases(cast<CXXRecordDecl>(LookupCtx),
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
MemberLookupCriteria(Name, NameKind, IDNS), Paths))
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context, 0);
|
2009-01-15 08:26:24 +08:00
|
|
|
|
|
|
|
|
|
// 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;
|
2009-01-16 02:32:35 +08:00
|
|
|
|
int SubobjectNumber = 0;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
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);
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context, PathsOnHeap, true);
|
2009-01-15 08:26:24 +08:00
|
|
|
|
} 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.
|
2009-01-20 09:17:11 +08:00
|
|
|
|
Decl *FirstDecl = *Path->Decls.first;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
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);
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context, PathsOnHeap, false);
|
2009-01-15 08:26:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lookup in a base class succeeded; return these results.
|
|
|
|
|
|
|
|
|
|
// If we found a function declaration, return an overload set.
|
2009-06-26 06:08:12 +08:00
|
|
|
|
if ((*Paths.front().Decls.first)->isFunctionOrFunctionTemplate())
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context,
|
2009-01-15 08:26:24 +08:00
|
|
|
|
Paths.front().Decls.first, Paths.front().Decls.second);
|
|
|
|
|
|
|
|
|
|
// We found a non-function declaration; return a single declaration.
|
2009-01-17 09:13:24 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context, *Paths.front().Decls.first);
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @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.
|
|
|
|
|
///
|
Implicitly declare certain C library functions (malloc, strcpy, memmove,
etc.) when we perform name lookup on them. This ensures that we
produce the correct signature for these functions, which has two
practical impacts:
1) When we're supporting the "implicit function declaration" feature
of C99, these functions will be implicitly declared with the right
signature rather than as a function returning "int" with no
prototype. See PR3541 for the reason why this is important (hint:
GCC always predeclares these functions).
2) If users attempt to redeclare one of these library functions with
an incompatible signature, we produce a hard error.
This patch does a little bit of work to give reasonable error
messages. For example, when we hit case #1 we complain that we're
implicitly declaring this function with a specific signature, and then
we give a note that asks the user to include the appropriate header
(e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In
case #2, we show the type of the implicit builtin that was incorrectly
declared, so the user can see the problem. We could do better here:
for example, when displaying this latter error message we say
something like:
'strcpy' was implicitly declared here with type 'char *(char *, char
const *)'
but we should really print out a fake code line showing the
declaration, like this:
'strcpy' was implicitly declared here as:
char *strcpy(char *, char const *)
This would also be good for printing built-in candidates with C++
operator overloading.
The set of C library functions supported by this patch includes all
functions from the C99 specification's <stdlib.h> and <string.h> that
(a) are predefined by GCC and (b) have signatures that could cause
codegen issues if they are treated as functions with no prototype
returning and int. Future work could extend this set of functions to
other C library functions that we know about.
llvm-svn: 64504
2009-02-14 07:20:09 +08:00
|
|
|
|
/// @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.
|
|
|
|
|
///
|
2009-01-15 06:20:51 +08:00
|
|
|
|
/// @returns The result of qualified or unqualified name lookup.
|
|
|
|
|
Sema::LookupResult
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS,
|
|
|
|
|
DeclarationName Name, LookupNameKind NameKind,
|
Implicitly declare certain C library functions (malloc, strcpy, memmove,
etc.) when we perform name lookup on them. This ensures that we
produce the correct signature for these functions, which has two
practical impacts:
1) When we're supporting the "implicit function declaration" feature
of C99, these functions will be implicitly declared with the right
signature rather than as a function returning "int" with no
prototype. See PR3541 for the reason why this is important (hint:
GCC always predeclares these functions).
2) If users attempt to redeclare one of these library functions with
an incompatible signature, we produce a hard error.
This patch does a little bit of work to give reasonable error
messages. For example, when we hit case #1 we complain that we're
implicitly declaring this function with a specific signature, and then
we give a note that asks the user to include the appropriate header
(e.g., "please include <stdlib.h> or explicitly declare 'malloc'"). In
case #2, we show the type of the implicit builtin that was incorrectly
declared, so the user can see the problem. We could do better here:
for example, when displaying this latter error message we say
something like:
'strcpy' was implicitly declared here with type 'char *(char *, char
const *)'
but we should really print out a fake code line showing the
declaration, like this:
'strcpy' was implicitly declared here as:
char *strcpy(char *, char const *)
This would also be good for printing built-in candidates with C++
operator overloading.
The set of C library functions supported by this patch includes all
functions from the C99 specification's <stdlib.h> and <string.h> that
(a) are predefined by GCC and (b) have signatures that could cause
codegen issues if they are treated as functions with no prototype
returning and int. Future work could extend this set of functions to
other C library functions that we know about.
llvm-svn: 64504
2009-02-14 07:20:09 +08:00
|
|
|
|
bool RedeclarationOnly, bool AllowBuiltinCreation,
|
|
|
|
|
SourceLocation Loc) {
|
2009-05-12 03:58:34 +08:00
|
|
|
|
if (SS && (SS->isSet() || SS->isInvalid())) {
|
|
|
|
|
// If the scope specifier is invalid, don't even look for
|
|
|
|
|
// anything.
|
|
|
|
|
if (SS->isInvalid())
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
return LookupResult::CreateLookupResult(Context, 0);
|
|
|
|
|
|
2009-05-12 03:58:34 +08:00
|
|
|
|
assert(!isUnknownSpecialization(*SS) && "Can't lookup dependent types");
|
|
|
|
|
|
|
|
|
|
if (isDependentScopeSpecifier(*SS)) {
|
|
|
|
|
// Determine whether we are looking into the current
|
|
|
|
|
// instantiation.
|
|
|
|
|
NestedNameSpecifier *NNS
|
|
|
|
|
= static_cast<NestedNameSpecifier *>(SS->getScopeRep());
|
|
|
|
|
CXXRecordDecl *Current = getCurrentInstantiationOf(NNS);
|
|
|
|
|
assert(Current && "Bad dependent scope specifier");
|
|
|
|
|
|
|
|
|
|
// We nested name specifier refers to the current instantiation,
|
|
|
|
|
// so now we will look for a member of the current instantiation
|
|
|
|
|
// (C++0x [temp.dep.type]).
|
|
|
|
|
unsigned IDNS = getIdentifierNamespacesFromLookupNameKind(NameKind, true);
|
|
|
|
|
DeclContext::lookup_iterator I, E;
|
|
|
|
|
for (llvm::tie(I, E) = Current->lookup(Context, Name); I != E; ++I)
|
|
|
|
|
if (isAcceptableLookupResult(*I, NameKind, IDNS))
|
|
|
|
|
return LookupResult::CreateLookupResult(Context, I, E);
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
|
}
|
2009-05-12 03:58:34 +08:00
|
|
|
|
|
|
|
|
|
if (RequireCompleteDeclContext(*SS))
|
|
|
|
|
return LookupResult::CreateLookupResult(Context, 0);
|
|
|
|
|
|
|
|
|
|
return LookupQualifiedName(computeDeclContext(*SS),
|
|
|
|
|
Name, NameKind, RedeclarationOnly);
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
llvm-svn: 63354
2009-01-30 09:04:22 +08:00
|
|
|
|
}
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
2009-06-20 08:51:54 +08:00
|
|
|
|
LookupResult result(LookupName(S, Name, NameKind, RedeclarationOnly,
|
|
|
|
|
AllowBuiltinCreation, Loc));
|
|
|
|
|
|
|
|
|
|
return(result);
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-01-15 08:26:24 +08:00
|
|
|
|
/// @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");
|
|
|
|
|
|
2009-04-02 05:51:26 +08:00
|
|
|
|
if (BasePaths *Paths = Result.getBasePaths()) {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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;
|
2009-01-16 08:38:09 +08:00
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
DeclContext::lookup_iterator Found = Paths->front().Decls.first;
|
2009-04-02 05:51:26 +08:00
|
|
|
|
while (isa<CXXMethodDecl>(*Found) &&
|
|
|
|
|
cast<CXXMethodDecl>(*Found)->isStatic())
|
2009-02-04 03:21:40 +08:00
|
|
|
|
++Found;
|
2009-01-16 08:38:09 +08:00
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
|
2009-01-17 08:42:38 +08:00
|
|
|
|
|
2009-04-02 05:51:26 +08:00
|
|
|
|
Result.Destroy();
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-02 05:51:26 +08:00
|
|
|
|
Result.Destroy();
|
2009-01-16 08:38:09 +08:00
|
|
|
|
return true;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
} else if (Result.getKind() == LookupResult::AmbiguousReference) {
|
|
|
|
|
Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
|
2009-02-05 01:27:36 +08:00
|
|
|
|
NamedDecl **DI = reinterpret_cast<NamedDecl **>(Result.First),
|
2009-04-02 05:51:26 +08:00
|
|
|
|
**DEnd = reinterpret_cast<NamedDecl **>(Result.Last);
|
2009-01-15 08:26:24 +08:00
|
|
|
|
|
2009-02-04 05:29:32 +08:00
|
|
|
|
for (; DI != DEnd; ++DI)
|
2009-02-05 01:27:36 +08:00
|
|
|
|
Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-04-02 05:51:26 +08:00
|
|
|
|
Result.Destroy();
|
2009-02-04 03:21:40 +08:00
|
|
|
|
return true;
|
2009-01-16 08:38:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
assert(false && "Unhandled form of name lookup ambiguity");
|
2009-01-17 09:13:24 +08:00
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
// We can't reach here.
|
2009-01-15 08:26:24 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
// \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,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
Sema::AssociatedClassSet &AssociatedClasses,
|
|
|
|
|
bool &GlobalScope) {
|
2009-02-04 08:32:51 +08:00
|
|
|
|
// 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);
|
2009-06-24 04:14:09 +08:00
|
|
|
|
else if (Ctx->isTranslationUnit())
|
|
|
|
|
GlobalScope = true;
|
|
|
|
|
|
2009-02-04 08:32:51 +08:00
|
|
|
|
// 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);
|
2009-06-24 04:14:09 +08:00
|
|
|
|
else if (BaseCtx->isTranslationUnit())
|
|
|
|
|
GlobalScope = true;
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
// 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,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
Sema::AssociatedClassSet &AssociatedClasses,
|
|
|
|
|
bool &GlobalScope) {
|
2009-02-04 08:32:51 +08:00
|
|
|
|
// 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.
|
2009-02-28 09:32:25 +08:00
|
|
|
|
if (const RecordType *ClassType = T->getAsRecordType())
|
|
|
|
|
if (CXXRecordDecl *ClassDecl
|
|
|
|
|
= dyn_cast<CXXRecordDecl>(ClassType->getDecl())) {
|
|
|
|
|
addAssociatedClassesAndNamespaces(ClassDecl, Context,
|
|
|
|
|
AssociatedNamespaces,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
AssociatedClasses,
|
|
|
|
|
GlobalScope);
|
2009-02-28 09:32:25 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
// -- 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);
|
2009-06-24 04:14:09 +08:00
|
|
|
|
else if (Ctx->isTranslationUnit())
|
|
|
|
|
GlobalScope = true;
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
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,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
AssociatedNamespaces, AssociatedClasses,
|
|
|
|
|
GlobalScope);
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
2009-02-27 07:50:07 +08:00
|
|
|
|
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FunctionType);
|
2009-02-04 08:32:51 +08:00
|
|
|
|
if (!Proto)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Argument types
|
2009-02-27 07:50:07 +08:00
|
|
|
|
for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
|
2009-02-04 08:32:51 +08:00
|
|
|
|
ArgEnd = Proto->arg_type_end();
|
|
|
|
|
Arg != ArgEnd; ++Arg)
|
|
|
|
|
addAssociatedClassesAndNamespaces(*Arg, Context,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
AssociatedNamespaces, AssociatedClasses,
|
|
|
|
|
GlobalScope);
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
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,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
AssociatedNamespaces, AssociatedClasses,
|
|
|
|
|
GlobalScope);
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
// Handle the class type into which this points.
|
|
|
|
|
if (const RecordType *Class = MemberPtr->getClass()->getAsRecordType())
|
|
|
|
|
addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()),
|
|
|
|
|
Context,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
AssociatedNamespaces, AssociatedClasses,
|
|
|
|
|
GlobalScope);
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
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,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
AssociatedClassSet &AssociatedClasses,
|
|
|
|
|
bool &GlobalScope) {
|
2009-02-04 08:32:51 +08:00
|
|
|
|
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,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
AssociatedNamespaces, AssociatedClasses,
|
|
|
|
|
GlobalScope);
|
2009-02-04 08:32:51 +08:00
|
|
|
|
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) {
|
2009-06-26 06:08:12 +08:00
|
|
|
|
FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*Func);
|
|
|
|
|
if (!FDecl)
|
|
|
|
|
FDecl = cast<FunctionTemplateDecl>(*Func)->getTemplatedDecl();
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
// 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);
|
2009-06-24 04:14:09 +08:00
|
|
|
|
else if (Ctx->isTranslationUnit())
|
|
|
|
|
GlobalScope = true;
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
// Add the classes and namespaces associated with the parameter
|
|
|
|
|
// types and return type of this function.
|
|
|
|
|
addAssociatedClassesAndNamespaces(FDecl->getType(), Context,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
AssociatedNamespaces, AssociatedClasses,
|
|
|
|
|
GlobalScope);
|
2009-02-04 08:32:51 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-03-13 08:33:25 +08:00
|
|
|
|
|
|
|
|
|
/// 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) {
|
2009-03-14 05:01:28 +08:00
|
|
|
|
if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
|
|
|
|
|
return true;
|
|
|
|
|
|
2009-03-13 08:33:25 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-24 07:18:26 +08:00
|
|
|
|
/// \brief Find the protocol with the given name, if any.
|
|
|
|
|
ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) {
|
2009-04-24 08:11:27 +08:00
|
|
|
|
Decl *D = LookupName(TUScope, II, LookupObjCProtocolName).getAsDecl();
|
2009-04-24 07:18:26 +08:00
|
|
|
|
return cast_or_null<ObjCProtocolDecl>(D);
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-24 08:11:27 +08:00
|
|
|
|
/// \brief Find the Objective-C implementation with the given name, if
|
|
|
|
|
/// any.
|
|
|
|
|
ObjCImplementationDecl *Sema::LookupObjCImplementation(IdentifierInfo *II) {
|
|
|
|
|
Decl *D = LookupName(TUScope, II, LookupObjCImplementationName).getAsDecl();
|
|
|
|
|
return cast_or_null<ObjCImplementationDecl>(D);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// \brief Find the Objective-C category implementation with the given
|
|
|
|
|
/// name, if any.
|
|
|
|
|
ObjCCategoryImplDecl *Sema::LookupObjCCategoryImpl(IdentifierInfo *II) {
|
|
|
|
|
Decl *D = LookupName(TUScope, II, LookupObjCCategoryImplName).getAsDecl();
|
|
|
|
|
return cast_or_null<ObjCCategoryImplDecl>(D);
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-13 08:33:25 +08:00
|
|
|
|
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) {
|
2009-06-28 05:05:07 +08:00
|
|
|
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) {
|
2009-03-13 08:33:25 +08:00
|
|
|
|
if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
|
|
|
|
|
Functions.insert(FD); // FIXME: canonical FD
|
2009-06-28 05:05:07 +08:00
|
|
|
|
} else if (FunctionTemplateDecl *FunTmpl
|
|
|
|
|
= dyn_cast<FunctionTemplateDecl>(*Op)) {
|
|
|
|
|
// FIXME: friend operators?
|
|
|
|
|
// FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
|
|
|
|
|
// later?
|
|
|
|
|
if (!FunTmpl->getDeclContext()->isRecord())
|
|
|
|
|
Functions.insert(FunTmpl);
|
|
|
|
|
}
|
2009-03-13 08:33:25 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2009-06-24 04:14:09 +08:00
|
|
|
|
bool GlobalScope = false;
|
2009-03-13 08:33:25 +08:00
|
|
|
|
FindAssociatedClassesAndNamespaces(Args, NumArgs,
|
2009-06-24 04:14:09 +08:00
|
|
|
|
AssociatedNamespaces, AssociatedClasses,
|
|
|
|
|
GlobalScope);
|
2009-03-13 08:33:25 +08:00
|
|
|
|
|
|
|
|
|
// 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;
|
2009-04-10 05:40:53 +08:00
|
|
|
|
for (llvm::tie(I, E) = (*NS)->lookup(Context, Name); I != E; ++I) {
|
2009-06-28 05:05:07 +08:00
|
|
|
|
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
|
|
|
|
|
Functions.insert(Func);
|
|
|
|
|
else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))
|
|
|
|
|
Functions.insert(FunTmpl);
|
2009-03-13 08:33:25 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-06-24 04:14:09 +08:00
|
|
|
|
|
|
|
|
|
if (GlobalScope) {
|
|
|
|
|
DeclContext::lookup_iterator I, E;
|
|
|
|
|
for (llvm::tie(I, E)
|
|
|
|
|
= Context.getTranslationUnitDecl()->lookup(Context, Name);
|
|
|
|
|
I != E; ++I) {
|
2009-06-28 05:05:07 +08:00
|
|
|
|
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
|
|
|
|
|
Functions.insert(Func);
|
|
|
|
|
else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))
|
|
|
|
|
Functions.insert(FunTmpl);
|
2009-06-24 04:14:09 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-03-13 08:33:25 +08:00
|
|
|
|
}
|