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-11-18 15:57:50 +08:00
|
|
|
|
#include "Lookup.h"
|
2009-01-15 08:26:24 +08:00
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2009-10-07 01:59:45 +08:00
|
|
|
|
#include "clang/AST/CXXInheritance.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-07-08 18:57:20 +08:00
|
|
|
|
#include "clang/AST/ExprCXX.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-10-10 13:48:19 +08:00
|
|
|
|
#include "llvm/Support/ErrorHandling.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-11-10 15:01:13 +08:00
|
|
|
|
namespace {
|
|
|
|
|
class UnqualUsingEntry {
|
|
|
|
|
const DeclContext *Nominated;
|
|
|
|
|
const DeclContext *CommonAncestor;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
UnqualUsingEntry(const DeclContext *Nominated,
|
|
|
|
|
const DeclContext *CommonAncestor)
|
|
|
|
|
: Nominated(Nominated), CommonAncestor(CommonAncestor) {
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
const DeclContext *getCommonAncestor() const {
|
|
|
|
|
return CommonAncestor;
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
const DeclContext *getNominatedNamespace() const {
|
|
|
|
|
return Nominated;
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
// Sort by the pointer value of the common ancestor.
|
|
|
|
|
struct Comparator {
|
|
|
|
|
bool operator()(const UnqualUsingEntry &L, const UnqualUsingEntry &R) {
|
|
|
|
|
return L.getCommonAncestor() < R.getCommonAncestor();
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
bool operator()(const UnqualUsingEntry &E, const DeclContext *DC) {
|
|
|
|
|
return E.getCommonAncestor() < DC;
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
bool operator()(const DeclContext *DC, const UnqualUsingEntry &E) {
|
|
|
|
|
return DC < E.getCommonAncestor();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// A collection of using directives, as used by C++ unqualified
|
|
|
|
|
/// lookup.
|
|
|
|
|
class UnqualUsingDirectiveSet {
|
|
|
|
|
typedef llvm::SmallVector<UnqualUsingEntry, 8> ListTy;
|
|
|
|
|
|
|
|
|
|
ListTy list;
|
|
|
|
|
llvm::SmallPtrSet<DeclContext*, 8> visited;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
UnqualUsingDirectiveSet() {}
|
|
|
|
|
|
|
|
|
|
void visitScopeChain(Scope *S, Scope *InnermostFileScope) {
|
|
|
|
|
// C++ [namespace.udir]p1:
|
|
|
|
|
// During unqualified name lookup, the names appear as if they
|
|
|
|
|
// were declared in the nearest enclosing namespace which contains
|
|
|
|
|
// both the using-directive and the nominated namespace.
|
|
|
|
|
DeclContext *InnermostFileDC
|
|
|
|
|
= static_cast<DeclContext*>(InnermostFileScope->getEntity());
|
|
|
|
|
assert(InnermostFileDC && InnermostFileDC->isFileContext());
|
|
|
|
|
|
|
|
|
|
for (; S; S = S->getParent()) {
|
|
|
|
|
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
|
|
|
|
|
DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC);
|
|
|
|
|
visit(Ctx, EffectiveDC);
|
|
|
|
|
} else {
|
|
|
|
|
Scope::udir_iterator I = S->using_directives_begin(),
|
|
|
|
|
End = S->using_directives_end();
|
|
|
|
|
|
|
|
|
|
for (; I != End; ++I)
|
|
|
|
|
visit(I->getAs<UsingDirectiveDecl>(), InnermostFileDC);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
// Visits a context and collect all of its using directives
|
|
|
|
|
// recursively. Treats all using directives as if they were
|
|
|
|
|
// declared in the context.
|
|
|
|
|
//
|
|
|
|
|
// A given context is only every visited once, so it is important
|
|
|
|
|
// that contexts be visited from the inside out in order to get
|
|
|
|
|
// the effective DCs right.
|
|
|
|
|
void visit(DeclContext *DC, DeclContext *EffectiveDC) {
|
|
|
|
|
if (!visited.insert(DC))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
addUsingDirectives(DC, EffectiveDC);
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
// Visits a using directive and collects all of its using
|
|
|
|
|
// directives recursively. Treats all using directives as if they
|
|
|
|
|
// were declared in the effective DC.
|
|
|
|
|
void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
|
|
|
|
|
DeclContext *NS = UD->getNominatedNamespace();
|
|
|
|
|
if (!visited.insert(NS))
|
|
|
|
|
return;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
addUsingDirective(UD, EffectiveDC);
|
|
|
|
|
addUsingDirectives(NS, EffectiveDC);
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
// Adds all the using directives in a context (and those nominated
|
|
|
|
|
// by its using directives, transitively) as if they appeared in
|
|
|
|
|
// the given effective context.
|
|
|
|
|
void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) {
|
|
|
|
|
llvm::SmallVector<DeclContext*,4> queue;
|
|
|
|
|
while (true) {
|
|
|
|
|
DeclContext::udir_iterator I, End;
|
|
|
|
|
for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) {
|
|
|
|
|
UsingDirectiveDecl *UD = *I;
|
|
|
|
|
DeclContext *NS = UD->getNominatedNamespace();
|
|
|
|
|
if (visited.insert(NS)) {
|
|
|
|
|
addUsingDirective(UD, EffectiveDC);
|
|
|
|
|
queue.push_back(NS);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (queue.empty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
DC = queue.back();
|
|
|
|
|
queue.pop_back();
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-11-10 15:01:13 +08:00
|
|
|
|
|
|
|
|
|
// Add a using directive as if it had been declared in the given
|
|
|
|
|
// context. This helps implement C++ [namespace.udir]p3:
|
|
|
|
|
// The using-directive is transitive: if a scope contains a
|
|
|
|
|
// using-directive that nominates a second namespace that itself
|
|
|
|
|
// contains using-directives, the effect is as if the
|
|
|
|
|
// using-directives from the second namespace also appeared in
|
|
|
|
|
// the first.
|
|
|
|
|
void addUsingDirective(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) {
|
|
|
|
|
// Find the common ancestor between the effective context and
|
|
|
|
|
// the nominated namespace.
|
|
|
|
|
DeclContext *Common = UD->getNominatedNamespace();
|
|
|
|
|
while (!Common->Encloses(EffectiveDC))
|
|
|
|
|
Common = Common->getParent();
|
2009-11-10 17:20:04 +08:00
|
|
|
|
Common = Common->getPrimaryContext();
|
2009-11-10 15:01:13 +08:00
|
|
|
|
|
|
|
|
|
list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void done() {
|
|
|
|
|
std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef ListTy::iterator iterator;
|
|
|
|
|
typedef ListTy::const_iterator const_iterator;
|
|
|
|
|
|
|
|
|
|
iterator begin() { return list.begin(); }
|
|
|
|
|
iterator end() { return list.end(); }
|
|
|
|
|
const_iterator begin() const { return list.begin(); }
|
|
|
|
|
const_iterator end() const { return list.end(); }
|
|
|
|
|
|
|
|
|
|
std::pair<const_iterator,const_iterator>
|
|
|
|
|
getNamespacesFor(DeclContext *DC) const {
|
2009-11-10 17:20:04 +08:00
|
|
|
|
return std::equal_range(begin(), end(), DC->getPrimaryContext(),
|
2009-11-10 15:01:13 +08:00
|
|
|
|
UnqualUsingEntry::Comparator());
|
|
|
|
|
}
|
|
|
|
|
};
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Retrieve the set of identifier namespaces that correspond to a
|
|
|
|
|
// specific kind of name lookup.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
inline unsigned
|
|
|
|
|
getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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)
|
2009-09-09 23:08:12 +08:00
|
|
|
|
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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-12-10 17:41:52 +08:00
|
|
|
|
case Sema::LookupUsingDeclName:
|
|
|
|
|
IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag
|
|
|
|
|
| Decl::IDNS_Member | Decl::IDNS_Using;
|
|
|
|
|
break;
|
|
|
|
|
|
2009-04-24 08:11:27 +08:00
|
|
|
|
case Sema::LookupObjCProtocolName:
|
|
|
|
|
IDNS = Decl::IDNS_ObjCProtocol;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Sema::LookupObjCImplementationName:
|
|
|
|
|
IDNS = Decl::IDNS_ObjCImplementation;
|
|
|
|
|
break;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
return IDNS;
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
// Necessary because CXXBasePaths is not complete in Sema.h
|
2009-11-18 15:57:50 +08:00
|
|
|
|
void LookupResult::deletePaths(CXXBasePaths *Paths) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
delete Paths;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-22 08:44:51 +08:00
|
|
|
|
/// Resolves the result kind of this lookup.
|
2009-11-18 15:57:50 +08:00
|
|
|
|
void LookupResult::resolveKind() {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
unsigned N = Decls.size();
|
2009-12-10 17:41:52 +08:00
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
// Fast case: no possible ambiguity.
|
2009-11-19 06:49:29 +08:00
|
|
|
|
if (N == 0) {
|
|
|
|
|
assert(ResultKind == NotFound);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-22 08:44:51 +08:00
|
|
|
|
// If there's a single decl, we need to examine it to decide what
|
|
|
|
|
// kind of lookup this is.
|
2009-11-18 10:36:19 +08:00
|
|
|
|
if (N == 1) {
|
2009-11-22 08:44:51 +08:00
|
|
|
|
if (isa<FunctionTemplateDecl>(Decls[0]))
|
|
|
|
|
ResultKind = FoundOverloaded;
|
|
|
|
|
else if (isa<UnresolvedUsingValueDecl>(Decls[0]))
|
2009-11-18 10:36:19 +08:00
|
|
|
|
ResultKind = FoundUnresolvedValue;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-06-26 11:37:05 +08:00
|
|
|
|
|
2009-10-10 13:48:19 +08:00
|
|
|
|
// Don't do any extra resolution if we've already resolved as ambiguous.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (ResultKind == Ambiguous) return;
|
2009-10-10 13:48:19 +08:00
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
llvm::SmallPtrSet<NamedDecl*, 16> Unique;
|
|
|
|
|
|
|
|
|
|
bool Ambiguous = false;
|
|
|
|
|
bool HasTag = false, HasFunction = false, HasNonFunction = false;
|
2009-11-22 08:44:51 +08:00
|
|
|
|
bool HasFunctionTemplate = false, HasUnresolved = false;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
unsigned UniqueTagIndex = 0;
|
|
|
|
|
|
|
|
|
|
unsigned I = 0;
|
|
|
|
|
while (I < N) {
|
2009-11-17 15:50:12 +08:00
|
|
|
|
NamedDecl *D = Decls[I]->getUnderlyingDecl();
|
|
|
|
|
D = cast<NamedDecl>(D->getCanonicalDecl());
|
2009-10-10 05:13:30 +08:00
|
|
|
|
|
2009-11-17 15:50:12 +08:00
|
|
|
|
if (!Unique.insert(D)) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
// If it's not unique, pull something off the back (and
|
|
|
|
|
// continue at this index).
|
|
|
|
|
Decls[I] = Decls[--N];
|
|
|
|
|
} else {
|
|
|
|
|
// Otherwise, do some decl type analysis and then continue.
|
2009-11-18 10:36:19 +08:00
|
|
|
|
|
|
|
|
|
if (isa<UnresolvedUsingValueDecl>(D)) {
|
|
|
|
|
HasUnresolved = true;
|
|
|
|
|
} else if (isa<TagDecl>(D)) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
if (HasTag)
|
|
|
|
|
Ambiguous = true;
|
|
|
|
|
UniqueTagIndex = I;
|
|
|
|
|
HasTag = true;
|
2009-11-22 08:44:51 +08:00
|
|
|
|
} else if (isa<FunctionTemplateDecl>(D)) {
|
|
|
|
|
HasFunction = true;
|
|
|
|
|
HasFunctionTemplate = true;
|
|
|
|
|
} else if (isa<FunctionDecl>(D)) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
HasFunction = true;
|
|
|
|
|
} else {
|
|
|
|
|
if (HasNonFunction)
|
|
|
|
|
Ambiguous = true;
|
|
|
|
|
HasNonFunction = true;
|
|
|
|
|
}
|
|
|
|
|
I++;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-04-24 10:57:34 +08:00
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
// C++ [basic.scope.hiding]p2:
|
|
|
|
|
// A class name or enumeration name can be hidden by the name of
|
|
|
|
|
// an object, function, or enumerator declared in the same
|
|
|
|
|
// scope. If a class or enumeration name and an object, function,
|
|
|
|
|
// or enumerator are declared in the same scope (in any order)
|
|
|
|
|
// with the same name, the class or enumeration name is hidden
|
|
|
|
|
// wherever the object, function, or enumerator name is visible.
|
|
|
|
|
// But it's still an error if there are distinct tag types found,
|
|
|
|
|
// even if they're not visible. (ref?)
|
2009-12-03 08:58:24 +08:00
|
|
|
|
if (HideTags && HasTag && !Ambiguous &&
|
|
|
|
|
(HasFunction || HasNonFunction || HasUnresolved))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
Decls[UniqueTagIndex] = Decls[--N];
|
|
|
|
|
|
|
|
|
|
Decls.set_size(N);
|
|
|
|
|
|
2009-12-03 08:58:24 +08:00
|
|
|
|
if (HasNonFunction && (HasFunction || HasUnresolved))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
Ambiguous = true;
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
if (Ambiguous)
|
2009-10-10 13:48:19 +08:00
|
|
|
|
setAmbiguous(LookupResult::AmbiguousReference);
|
2009-11-18 10:36:19 +08:00
|
|
|
|
else if (HasUnresolved)
|
|
|
|
|
ResultKind = LookupResult::FoundUnresolvedValue;
|
2009-11-22 08:44:51 +08:00
|
|
|
|
else if (N > 1 || HasFunctionTemplate)
|
2009-11-17 10:14:36 +08:00
|
|
|
|
ResultKind = LookupResult::FoundOverloaded;
|
2009-10-10 05:13:30 +08:00
|
|
|
|
else
|
2009-11-17 10:14:36 +08:00
|
|
|
|
ResultKind = LookupResult::Found;
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-18 15:57:50 +08:00
|
|
|
|
void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
CXXBasePaths::paths_iterator I, E;
|
|
|
|
|
DeclContext::lookup_iterator DI, DE;
|
|
|
|
|
for (I = P.begin(), E = P.end(); I != E; ++I)
|
|
|
|
|
for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI)
|
|
|
|
|
addDecl(*DI);
|
2009-01-15 08:26:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-18 15:57:50 +08:00
|
|
|
|
void LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
Paths = new CXXBasePaths;
|
|
|
|
|
Paths->swap(P);
|
|
|
|
|
addDeclsFromBasePaths(*Paths);
|
|
|
|
|
resolveKind();
|
2009-10-10 13:48:19 +08:00
|
|
|
|
setAmbiguous(AmbiguousBaseSubobjects);
|
2009-02-03 05:35:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-18 15:57:50 +08:00
|
|
|
|
void LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
Paths = new CXXBasePaths;
|
|
|
|
|
Paths->swap(P);
|
|
|
|
|
addDeclsFromBasePaths(*Paths);
|
|
|
|
|
resolveKind();
|
2009-10-10 13:48:19 +08:00
|
|
|
|
setAmbiguous(AmbiguousBaseSubobjectTypes);
|
2009-02-03 05:35:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-18 15:57:50 +08:00
|
|
|
|
void LookupResult::print(llvm::raw_ostream &Out) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
Out << Decls.size() << " result(s)";
|
|
|
|
|
if (isAmbiguous()) Out << ", ambiguous";
|
|
|
|
|
if (Paths) Out << ", base paths present";
|
|
|
|
|
|
|
|
|
|
for (iterator I = begin(), E = end(); I != E; ++I) {
|
|
|
|
|
Out << "\n";
|
|
|
|
|
(*I)->print(Out, 2);
|
2009-04-02 05:51:26 +08:00
|
|
|
|
}
|
2009-02-03 05:35:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
// Adds all qualifying matches for a name within a decl context to the
|
|
|
|
|
// given lookup result. Returns true if any matches were found.
|
2009-11-18 15:57:50 +08:00
|
|
|
|
static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
bool Found = false;
|
2009-04-02 05:51:26 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
DeclContext::lookup_const_iterator I, E;
|
2009-11-17 10:14:36 +08:00
|
|
|
|
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I)
|
|
|
|
|
if (Sema::isAcceptableLookupResult(*I, R.getLookupKind(),
|
|
|
|
|
R.getIdentifierNamespace()))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
R.addDecl(*I), Found = true;
|
2009-04-02 05:51:26 +08:00
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return Found;
|
2009-02-03 05:35:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
// Performs C++ unqualified lookup into the given file context.
|
2009-10-10 05:13:30 +08:00
|
|
|
|
static bool
|
2009-11-18 15:57:50 +08:00
|
|
|
|
CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS,
|
2009-11-17 10:14:36 +08:00
|
|
|
|
UnqualUsingDirectiveSet &UDirs) {
|
2009-02-06 03:25:20 +08:00
|
|
|
|
|
|
|
|
|
assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!");
|
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
// Perform direct name lookup into the LookupCtx.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
bool Found = LookupDirect(R, NS);
|
2009-02-06 03:25:20 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
// Perform direct name lookup into the namespaces nominated by the
|
|
|
|
|
// using directives whose common ancestor is this namespace.
|
|
|
|
|
UnqualUsingDirectiveSet::const_iterator UI, UEnd;
|
|
|
|
|
llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
for (; UI != UEnd; ++UI)
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (LookupDirect(R, UI->getNominatedNamespace()))
|
2009-11-10 15:01:13 +08:00
|
|
|
|
Found = true;
|
2009-10-10 05:13:30 +08:00
|
|
|
|
|
|
|
|
|
R.resolveKind();
|
|
|
|
|
|
|
|
|
|
return Found;
|
2009-02-06 03:25:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-09-11 00:57:35 +08:00
|
|
|
|
// Find the next outer declaration context corresponding to this scope.
|
|
|
|
|
static DeclContext *findOuterContext(Scope *S) {
|
|
|
|
|
for (S = S->getParent(); S; S = S->getParent())
|
|
|
|
|
if (S->getEntity())
|
|
|
|
|
return static_cast<DeclContext *>(S->getEntity())->getPrimaryContext();
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
bool Sema::CppLookupName(LookupResult &R, Scope *S) {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
assert(getLangOptions().CPlusPlus &&
|
|
|
|
|
"Can perform only C++ lookup");
|
2009-11-17 10:14:36 +08:00
|
|
|
|
LookupNameKind NameKind = R.getLookupKind();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
unsigned IDNS
|
2009-02-05 01:27:36 +08:00
|
|
|
|
= getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true);
|
2009-08-28 15:59:38 +08:00
|
|
|
|
|
|
|
|
|
// If we're testing for redeclarations, also look in the friend namespaces.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (R.isForRedeclaration()) {
|
2009-08-28 15:59:38 +08:00
|
|
|
|
if (IDNS & Decl::IDNS_Tag) IDNS |= Decl::IDNS_TagFriend;
|
|
|
|
|
if (IDNS & Decl::IDNS_Ordinary) IDNS |= Decl::IDNS_OrdinaryFriend;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
R.setIdentifierNamespace(IDNS);
|
|
|
|
|
|
|
|
|
|
DeclarationName Name = R.getLookupName();
|
|
|
|
|
|
2009-02-04 03:21:40 +08:00
|
|
|
|
Scope *Initial = S;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
IdentifierResolver::iterator
|
2009-02-04 03:21:40 +08:00
|
|
|
|
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.
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// [Note: in this context, "contains" means "contains directly or
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// indirectly".
|
2009-02-04 03:21:40 +08:00
|
|
|
|
//
|
|
|
|
|
// 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-10-10 05:13:30 +08:00
|
|
|
|
bool Found = false;
|
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)) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
Found = true;
|
|
|
|
|
R.addDecl(*I);
|
2009-02-04 03:21:40 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-10 05:13:30 +08:00
|
|
|
|
if (Found) {
|
|
|
|
|
R.resolveKind();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) {
|
2009-09-11 00:57:35 +08:00
|
|
|
|
DeclContext *OuterCtx = findOuterContext(S);
|
|
|
|
|
for (; Ctx && Ctx->getPrimaryContext() != OuterCtx;
|
|
|
|
|
Ctx = Ctx->getLookupParent()) {
|
2009-12-08 23:38:36 +08:00
|
|
|
|
// We do not directly look into function or method contexts
|
|
|
|
|
// (since all local variables are found via the identifier
|
|
|
|
|
// changes) or in transparent contexts (since those entities
|
|
|
|
|
// will be found in the nearest enclosing non-transparent
|
|
|
|
|
// context).
|
|
|
|
|
if (Ctx->isFunctionOrMethod() || Ctx->isTransparentContext())
|
2009-09-11 00:57:35 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Perform qualified name lookup into this context.
|
|
|
|
|
// 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-11-17 10:14:36 +08:00
|
|
|
|
if (LookupQualifiedName(R, Ctx))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return true;
|
2009-03-27 12:21:56 +08:00
|
|
|
|
}
|
2009-02-06 03:25:20 +08:00
|
|
|
|
}
|
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-11-10 15:01:13 +08:00
|
|
|
|
// Stop if we ran out of scopes.
|
|
|
|
|
// FIXME: This really, really shouldn't be happening.
|
|
|
|
|
if (!S) return false;
|
|
|
|
|
|
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-11-10 15:01:13 +08:00
|
|
|
|
//
|
2009-05-16 15:39:55 +08:00
|
|
|
|
// 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
|
|
|
|
|
2009-11-10 15:01:13 +08:00
|
|
|
|
UnqualUsingDirectiveSet UDirs;
|
|
|
|
|
UDirs.visitScopeChain(Initial, S);
|
|
|
|
|
UDirs.done();
|
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
|
|
|
|
|
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());
|
2009-08-25 02:55:03 +08:00
|
|
|
|
if (Ctx->isTransparentContext())
|
|
|
|
|
continue;
|
|
|
|
|
|
2009-02-06 03:25:20 +08:00
|
|
|
|
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-10-10 05:13:30 +08:00
|
|
|
|
bool Found = false;
|
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.
|
2009-10-10 05:13:30 +08:00
|
|
|
|
Found = true;
|
|
|
|
|
R.addDecl(*I);
|
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
|
|
|
|
// Look into context considering using-directives.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (CppNamespaceLookup(R, Context, Ctx, UDirs))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
Found = true;
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
if (Found) {
|
|
|
|
|
R.resolveKind();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (R.isForRedeclaration() && !Ctx->isTransparentContext())
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return 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
|
|
|
|
}
|
2009-10-10 05:13:30 +08:00
|
|
|
|
|
|
|
|
|
return !R.empty();
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
/// name lookup. At present, this is only used to produce diagnostics when
|
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
|
|
|
|
/// 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.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
|
|
|
|
|
DeclarationName Name = R.getLookupName();
|
2009-10-10 05:13:30 +08:00
|
|
|
|
if (!Name) return false;
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
LookupNameKind NameKind = R.getLookupKind();
|
|
|
|
|
|
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:
|
2009-12-10 17:41:52 +08:00
|
|
|
|
case Sema::LookupUsingDeclName:
|
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
|
|
|
|
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) ||
|
2009-09-09 23:08:12 +08:00
|
|
|
|
(S->getEntity() &&
|
2009-02-25 04:03:32 +08:00
|
|
|
|
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;
|
2009-09-09 23:08:12 +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-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),
|
2009-09-09 23:08:12 +08:00
|
|
|
|
IEnd = IdResolver.end();
|
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
|
|
|
|
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-10-10 05:13:30 +08:00
|
|
|
|
R.addDecl(*I);
|
|
|
|
|
|
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;
|
2009-10-10 05:13:30 +08:00
|
|
|
|
R.addDecl(*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
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
R.resolveKind();
|
|
|
|
|
|
|
|
|
|
return true;
|
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.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (CppLookupName(R, S))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return true;
|
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-09-09 23:08:12 +08:00
|
|
|
|
if (NameKind == LookupOrdinaryName ||
|
2009-02-25 04:03:32 +08:00
|
|
|
|
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.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (getLangOptions().CPlusPlus &&
|
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
|
|
|
|
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return false;
|
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
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
|
2009-11-17 10:14:36 +08:00
|
|
|
|
S, R.isForRedeclaration(),
|
|
|
|
|
R.getNameLoc());
|
2009-10-10 05:13:30 +08:00
|
|
|
|
if (D) R.addDecl(D);
|
|
|
|
|
return (D != NULL);
|
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
|
|
|
|
}
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return false;
|
2009-01-15 06:20:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-10-10 13:48:19 +08:00
|
|
|
|
/// @brief Perform qualified name lookup in the namespaces nominated by
|
|
|
|
|
/// using directives by the given context.
|
|
|
|
|
///
|
|
|
|
|
/// C++98 [namespace.qual]p2:
|
|
|
|
|
/// Given X::m (where X is a user-declared namespace), or given ::m
|
|
|
|
|
/// (where X is the global namespace), let S be the set of all
|
|
|
|
|
/// declarations of m in X and in the transitive closure of all
|
|
|
|
|
/// namespaces nominated by using-directives in X and its used
|
|
|
|
|
/// namespaces, except that using-directives are ignored in any
|
|
|
|
|
/// namespace, including X, directly containing one or more
|
|
|
|
|
/// declarations of m. No namespace is searched more than once in
|
|
|
|
|
/// the lookup of a name. If S is the empty set, the program is
|
|
|
|
|
/// ill-formed. Otherwise, if S has exactly one member, or if the
|
|
|
|
|
/// context of the reference is a using-declaration
|
|
|
|
|
/// (namespace.udecl), S is the required set of declarations of
|
|
|
|
|
/// m. Otherwise if the use of m is not one that allows a unique
|
|
|
|
|
/// declaration to be chosen from S, the program is ill-formed.
|
|
|
|
|
/// C++98 [namespace.qual]p5:
|
|
|
|
|
/// During the lookup of a qualified namespace member name, if the
|
|
|
|
|
/// lookup finds more than one declaration of the member, and if one
|
|
|
|
|
/// declaration introduces a class name or enumeration name and the
|
|
|
|
|
/// other declarations either introduce the same object, the same
|
|
|
|
|
/// enumerator or a set of functions, the non-type name hides the
|
|
|
|
|
/// class or enumeration name if and only if the declarations are
|
|
|
|
|
/// from the same namespace; otherwise (the declarations are from
|
|
|
|
|
/// different namespaces), the program is ill-formed.
|
2009-11-18 15:57:50 +08:00
|
|
|
|
static bool LookupQualifiedNameInUsingDirectives(LookupResult &R,
|
2009-11-17 10:14:36 +08:00
|
|
|
|
DeclContext *StartDC) {
|
2009-10-10 13:48:19 +08:00
|
|
|
|
assert(StartDC->isFileContext() && "start context is not a file context");
|
|
|
|
|
|
|
|
|
|
DeclContext::udir_iterator I = StartDC->using_directives_begin();
|
|
|
|
|
DeclContext::udir_iterator E = StartDC->using_directives_end();
|
|
|
|
|
|
|
|
|
|
if (I == E) return false;
|
|
|
|
|
|
|
|
|
|
// We have at least added all these contexts to the queue.
|
|
|
|
|
llvm::DenseSet<DeclContext*> Visited;
|
|
|
|
|
Visited.insert(StartDC);
|
|
|
|
|
|
|
|
|
|
// We have not yet looked into these namespaces, much less added
|
|
|
|
|
// their "using-children" to the queue.
|
|
|
|
|
llvm::SmallVector<NamespaceDecl*, 8> Queue;
|
|
|
|
|
|
|
|
|
|
// We have already looked into the initial namespace; seed the queue
|
|
|
|
|
// with its using-children.
|
|
|
|
|
for (; I != E; ++I) {
|
2009-11-10 17:25:37 +08:00
|
|
|
|
NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace();
|
2009-10-10 13:48:19 +08:00
|
|
|
|
if (Visited.insert(ND).second)
|
|
|
|
|
Queue.push_back(ND);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The easiest way to implement the restriction in [namespace.qual]p5
|
|
|
|
|
// is to check whether any of the individual results found a tag
|
|
|
|
|
// and, if so, to declare an ambiguity if the final result is not
|
|
|
|
|
// a tag.
|
|
|
|
|
bool FoundTag = false;
|
|
|
|
|
bool FoundNonTag = false;
|
|
|
|
|
|
2009-11-18 15:57:50 +08:00
|
|
|
|
LookupResult LocalR(LookupResult::Temporary, R);
|
2009-10-10 13:48:19 +08:00
|
|
|
|
|
|
|
|
|
bool Found = false;
|
|
|
|
|
while (!Queue.empty()) {
|
|
|
|
|
NamespaceDecl *ND = Queue.back();
|
|
|
|
|
Queue.pop_back();
|
|
|
|
|
|
|
|
|
|
// We go through some convolutions here to avoid copying results
|
|
|
|
|
// between LookupResults.
|
|
|
|
|
bool UseLocal = !R.empty();
|
2009-11-18 15:57:50 +08:00
|
|
|
|
LookupResult &DirectR = UseLocal ? LocalR : R;
|
2009-11-17 10:14:36 +08:00
|
|
|
|
bool FoundDirect = LookupDirect(DirectR, ND);
|
2009-10-10 13:48:19 +08:00
|
|
|
|
|
|
|
|
|
if (FoundDirect) {
|
|
|
|
|
// First do any local hiding.
|
|
|
|
|
DirectR.resolveKind();
|
|
|
|
|
|
|
|
|
|
// If the local result is a tag, remember that.
|
|
|
|
|
if (DirectR.isSingleTagDecl())
|
|
|
|
|
FoundTag = true;
|
|
|
|
|
else
|
|
|
|
|
FoundNonTag = true;
|
|
|
|
|
|
|
|
|
|
// Append the local results to the total results if necessary.
|
|
|
|
|
if (UseLocal) {
|
|
|
|
|
R.addAllDecls(LocalR);
|
|
|
|
|
LocalR.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we find names in this namespace, ignore its using directives.
|
|
|
|
|
if (FoundDirect) {
|
|
|
|
|
Found = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) {
|
|
|
|
|
NamespaceDecl *Nom = (*I)->getNominatedNamespace();
|
|
|
|
|
if (Visited.insert(Nom).second)
|
|
|
|
|
Queue.push_back(Nom);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Found) {
|
|
|
|
|
if (FoundTag && FoundNonTag)
|
|
|
|
|
R.setAmbiguousQualifiedTagHiding();
|
|
|
|
|
else
|
|
|
|
|
R.resolveKind();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Found;
|
|
|
|
|
}
|
|
|
|
|
|
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.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) {
|
2009-01-15 06:20:51 +08:00
|
|
|
|
assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (!R.getLookupName())
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
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.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
LookupNameKind NameKind = R.getLookupKind();
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
= getIdentifierNamespacesFromLookupNameKind(NameKind,
|
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
|
|
|
|
getLangOptions().CPlusPlus);
|
|
|
|
|
if (NameKind == LookupOrdinaryName)
|
|
|
|
|
IDNS |= Decl::IDNS_Member;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
R.setIdentifierNamespace(IDNS);
|
|
|
|
|
|
2009-09-03 06:59:36 +08:00
|
|
|
|
// Make sure that the declaration context is complete.
|
|
|
|
|
assert((!isa<TagDecl>(LookupCtx) ||
|
|
|
|
|
LookupCtx->isDependentContext() ||
|
|
|
|
|
cast<TagDecl>(LookupCtx)->isDefinition() ||
|
|
|
|
|
Context.getTypeDeclType(cast<TagDecl>(LookupCtx))->getAs<TagType>()
|
|
|
|
|
->isBeingDefined()) &&
|
|
|
|
|
"Declaration context must already be complete!");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-01-15 06:20:51 +08:00
|
|
|
|
// Perform qualified name lookup into the LookupCtx.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (LookupDirect(R, LookupCtx)) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
R.resolveKind();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
2009-10-10 13:48:19 +08:00
|
|
|
|
// Don't descend into implied contexts for redeclarations.
|
|
|
|
|
// C++98 [namespace.qual]p6:
|
|
|
|
|
// In a declaration for a namespace member in which the
|
|
|
|
|
// declarator-id is a qualified-id, given that the qualified-id
|
|
|
|
|
// for the namespace member has the form
|
|
|
|
|
// nested-name-specifier unqualified-id
|
|
|
|
|
// the unqualified-id shall name a member of the namespace
|
|
|
|
|
// designated by the nested-name-specifier.
|
|
|
|
|
// See also [class.mfct]p5 and [class.static.data]p2.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (R.isForRedeclaration())
|
2009-10-10 13:48:19 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
// If this is a namespace, look it up in the implied namespaces.
|
2009-10-10 13:48:19 +08:00
|
|
|
|
if (LookupCtx->isFileContext())
|
2009-11-17 10:14:36 +08:00
|
|
|
|
return LookupQualifiedNameInUsingDirectives(R, LookupCtx);
|
2009-10-10 13:48:19 +08:00
|
|
|
|
|
2009-09-03 06:59:36 +08:00
|
|
|
|
// If this isn't a C++ class, we aren't allowed to look into base
|
2009-09-12 06:57:37 +08:00
|
|
|
|
// classes, we're done.
|
2009-10-10 13:48:19 +08:00
|
|
|
|
if (!isa<CXXRecordDecl>(LookupCtx))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return false;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
|
|
|
|
|
// Perform lookup into our base classes.
|
2009-10-07 01:59:45 +08:00
|
|
|
|
CXXRecordDecl *LookupRec = cast<CXXRecordDecl>(LookupCtx);
|
|
|
|
|
CXXBasePaths Paths;
|
|
|
|
|
Paths.setOrigin(LookupRec);
|
2009-01-15 08:26:24 +08:00
|
|
|
|
|
|
|
|
|
// Look for this member in our base classes
|
2009-10-07 01:59:45 +08:00
|
|
|
|
CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0;
|
2009-11-17 10:14:36 +08:00
|
|
|
|
switch (R.getLookupKind()) {
|
2009-10-07 01:59:45 +08:00
|
|
|
|
case LookupOrdinaryName:
|
|
|
|
|
case LookupMemberName:
|
|
|
|
|
case LookupRedeclarationWithLinkage:
|
|
|
|
|
BaseCallback = &CXXRecordDecl::FindOrdinaryMember;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case LookupTagName:
|
|
|
|
|
BaseCallback = &CXXRecordDecl::FindTagMember;
|
|
|
|
|
break;
|
2009-12-10 17:41:52 +08:00
|
|
|
|
|
|
|
|
|
case LookupUsingDeclName:
|
|
|
|
|
// This lookup is for redeclarations only.
|
2009-10-07 01:59:45 +08:00
|
|
|
|
|
|
|
|
|
case LookupOperatorName:
|
|
|
|
|
case LookupNamespaceName:
|
|
|
|
|
case LookupObjCProtocolName:
|
|
|
|
|
case LookupObjCImplementationName:
|
|
|
|
|
// These lookups will never find a member in a C++ class (or base class).
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return false;
|
2009-10-07 01:59:45 +08:00
|
|
|
|
|
|
|
|
|
case LookupNestedNameSpecifierName:
|
|
|
|
|
BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
if (!LookupRec->lookupInBases(BaseCallback,
|
|
|
|
|
R.getLookupName().getAsOpaquePtr(), Paths))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return false;
|
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-10-07 01:59:45 +08:00
|
|
|
|
for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
|
2009-01-15 08:26:24 +08:00
|
|
|
|
Path != PathEnd; ++Path) {
|
2009-10-07 01:59:45 +08:00
|
|
|
|
const CXXBasePathElement &PathElement = Path->back();
|
2009-01-15 08:26:24 +08:00
|
|
|
|
|
|
|
|
|
// Determine whether we're looking at a distinct sub-object or not.
|
|
|
|
|
if (SubobjectType.isNull()) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
// This is the first subobject we've looked at. Record its type.
|
2009-01-15 08:26:24 +08:00
|
|
|
|
SubobjectType = Context.getCanonicalType(PathElement.Base->getType());
|
|
|
|
|
SubobjectNumber = PathElement.SubobjectNumber;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
} else if (SubobjectType
|
2009-01-15 08:26:24 +08:00
|
|
|
|
!= Context.getCanonicalType(PathElement.Base->getType())) {
|
|
|
|
|
// We found members of the given name in two subobjects of
|
|
|
|
|
// different types. This lookup is ambiguous.
|
2009-10-10 05:13:30 +08:00
|
|
|
|
R.setAmbiguousBaseSubobjectTypes(Paths);
|
|
|
|
|
return 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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// 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.
|
2009-10-10 05:13:30 +08:00
|
|
|
|
R.setAmbiguousBaseSubobjects(Paths);
|
|
|
|
|
return true;
|
2009-01-15 08:26:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Lookup in a base class succeeded; return these results.
|
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
DeclContext::lookup_iterator I, E;
|
|
|
|
|
for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I)
|
|
|
|
|
R.addDecl(*I);
|
|
|
|
|
R.resolveKind();
|
|
|
|
|
return true;
|
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.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
///
|
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
|
|
|
|
/// @param SS An optional C++ scope-specifier, e.g., "::N::M".
|
2009-01-15 06:20:51 +08:00
|
|
|
|
///
|
|
|
|
|
/// @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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
/// name lookup. At present, this is only used to produce diagnostics when
|
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
|
|
|
|
/// C library functions (like "malloc") are implicitly declared.
|
|
|
|
|
///
|
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
|
|
|
|
/// @param EnteringContext Indicates whether we are going to enter the
|
|
|
|
|
/// context of the scope-specifier SS (if present).
|
|
|
|
|
///
|
2009-10-10 05:13:30 +08:00
|
|
|
|
/// @returns True if any decls were found (but possibly ambiguous)
|
|
|
|
|
bool Sema::LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
|
2009-11-17 10:14:36 +08:00
|
|
|
|
bool AllowBuiltinCreation, bool EnteringContext) {
|
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
|
|
|
|
if (SS && SS->isInvalid()) {
|
|
|
|
|
// When the scope specifier is invalid, don't even look for
|
2009-05-12 03:58:34 +08:00
|
|
|
|
// anything.
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return false;
|
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
|
|
|
|
if (SS && SS->isSet()) {
|
|
|
|
|
if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// We have resolved the scope specifier to a particular declaration
|
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
|
|
|
|
// contex, and will perform name lookup in that context.
|
2009-09-03 06:59:36 +08:00
|
|
|
|
if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS))
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
R.setContextRange(SS->getRange());
|
|
|
|
|
|
|
|
|
|
return LookupQualifiedName(R, DC);
|
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
|
|
|
|
|
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
|
|
|
|
// We could not resolve the scope specified to a specific declaration
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// context, which means that SS refers to an unknown specialization.
|
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
|
|
|
|
// Name lookup can't find anything in this case.
|
2009-10-10 05:13:30 +08:00
|
|
|
|
return 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
|
|
|
|
}
|
2009-01-15 06:20:51 +08:00
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// Perform unqualified name lookup starting in the given scope.
|
2009-11-17 10:14:36 +08:00
|
|
|
|
return LookupName(R, S, AllowBuiltinCreation);
|
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.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
///
|
2009-01-15 08:26:24 +08:00
|
|
|
|
/// @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
|
2009-11-17 10:14:36 +08:00
|
|
|
|
bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
|
2009-01-15 08:26:24 +08:00
|
|
|
|
assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
|
|
|
|
|
|
2009-11-17 10:14:36 +08:00
|
|
|
|
DeclarationName Name = Result.getLookupName();
|
|
|
|
|
SourceLocation NameLoc = Result.getNameLoc();
|
|
|
|
|
SourceRange LookupRange = Result.getContextRange();
|
|
|
|
|
|
2009-10-10 13:48:19 +08:00
|
|
|
|
switch (Result.getAmbiguityKind()) {
|
|
|
|
|
case LookupResult::AmbiguousBaseSubobjects: {
|
|
|
|
|
CXXBasePaths *Paths = Result.getBasePaths();
|
|
|
|
|
QualType SubobjectType = Paths->front().back().Base->getType();
|
|
|
|
|
Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects)
|
|
|
|
|
<< Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
|
|
|
|
|
<< LookupRange;
|
|
|
|
|
|
|
|
|
|
DeclContext::lookup_iterator Found = Paths->front().Decls.first;
|
|
|
|
|
while (isa<CXXMethodDecl>(*Found) &&
|
|
|
|
|
cast<CXXMethodDecl>(*Found)->isStatic())
|
|
|
|
|
++Found;
|
|
|
|
|
|
|
|
|
|
Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2009-02-04 03:21:40 +08:00
|
|
|
|
|
2009-10-10 13:48:19 +08:00
|
|
|
|
case LookupResult::AmbiguousBaseSubobjectTypes: {
|
2009-02-04 03:21:40 +08:00
|
|
|
|
Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types)
|
|
|
|
|
<< Name << LookupRange;
|
2009-10-10 13:48:19 +08:00
|
|
|
|
|
|
|
|
|
CXXBasePaths *Paths = Result.getBasePaths();
|
2009-02-04 03:21:40 +08:00
|
|
|
|
std::set<Decl *> DeclsPrinted;
|
2009-10-10 13:48:19 +08:00
|
|
|
|
for (CXXBasePaths::paths_iterator Path = Paths->begin(),
|
|
|
|
|
PathEnd = Paths->end();
|
2009-02-04 03:21:40 +08:00
|
|
|
|
Path != PathEnd; ++Path) {
|
|
|
|
|
Decl *D = *Path->Decls.first;
|
|
|
|
|
if (DeclsPrinted.insert(D).second)
|
|
|
|
|
Diag(D->getLocation(), diag::note_ambiguous_member_found);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
2009-01-16 08:38:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-10-10 13:48:19 +08:00
|
|
|
|
case LookupResult::AmbiguousTagHiding: {
|
|
|
|
|
Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange;
|
2009-10-10 05:13:30 +08:00
|
|
|
|
|
2009-10-10 13:48:19 +08:00
|
|
|
|
llvm::SmallPtrSet<NamedDecl*,8> TagDecls;
|
|
|
|
|
|
|
|
|
|
LookupResult::iterator DI, DE = Result.end();
|
|
|
|
|
for (DI = Result.begin(); DI != DE; ++DI)
|
|
|
|
|
if (TagDecl *TD = dyn_cast<TagDecl>(*DI)) {
|
|
|
|
|
TagDecls.insert(TD);
|
|
|
|
|
Diag(TD->getLocation(), diag::note_hidden_tag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (DI = Result.begin(); DI != DE; ++DI)
|
|
|
|
|
if (!isa<TagDecl>(*DI))
|
|
|
|
|
Diag((*DI)->getLocation(), diag::note_hiding_object);
|
|
|
|
|
|
|
|
|
|
// For recovery purposes, go ahead and implement the hiding.
|
|
|
|
|
Result.hideDecls(TagDecls);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case LookupResult::AmbiguousReference: {
|
|
|
|
|
Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
|
2009-10-10 05:13:30 +08:00
|
|
|
|
|
2009-10-10 13:48:19 +08:00
|
|
|
|
LookupResult::iterator DI = Result.begin(), DE = Result.end();
|
|
|
|
|
for (; DI != DE; ++DI)
|
|
|
|
|
Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-01-17 09:13:24 +08:00
|
|
|
|
|
2009-10-10 13:48:19 +08:00
|
|
|
|
llvm::llvm_unreachable("unknown ambiguity kind");
|
2009-01-15 08:26:24 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
static void
|
|
|
|
|
addAssociatedClassesAndNamespaces(QualType T,
|
2009-07-08 15:51:57 +08:00
|
|
|
|
ASTContext &Context,
|
|
|
|
|
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
Sema::AssociatedClassSet &AssociatedClasses);
|
|
|
|
|
|
|
|
|
|
static void CollectNamespace(Sema::AssociatedNamespaceSet &Namespaces,
|
|
|
|
|
DeclContext *Ctx) {
|
|
|
|
|
if (Ctx->isFileContext())
|
|
|
|
|
Namespaces.insert(Ctx);
|
|
|
|
|
}
|
2009-07-08 15:51:57 +08:00
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// \brief Add the associated classes and namespaces for argument-dependent
|
2009-07-08 15:51:57 +08:00
|
|
|
|
// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
|
2009-09-09 23:08:12 +08:00
|
|
|
|
static void
|
|
|
|
|
addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
|
2009-07-08 15:51:57 +08:00
|
|
|
|
ASTContext &Context,
|
|
|
|
|
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
Sema::AssociatedClassSet &AssociatedClasses) {
|
2009-07-08 15:51:57 +08:00
|
|
|
|
// C++ [basic.lookup.koenig]p2, last bullet:
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// -- [...] ;
|
2009-07-08 15:51:57 +08:00
|
|
|
|
switch (Arg.getKind()) {
|
|
|
|
|
case TemplateArgument::Null:
|
|
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-07-08 15:51:57 +08:00
|
|
|
|
case TemplateArgument::Type:
|
|
|
|
|
// [...] the namespaces and classes associated with the types of the
|
|
|
|
|
// template arguments provided for template type parameters (excluding
|
|
|
|
|
// template template parameters)
|
|
|
|
|
addAssociatedClassesAndNamespaces(Arg.getAsType(), Context,
|
|
|
|
|
AssociatedNamespaces,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedClasses);
|
2009-07-08 15:51:57 +08:00
|
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-11-11 09:00:40 +08:00
|
|
|
|
case TemplateArgument::Template: {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// [...] the namespaces in which any template template arguments are
|
|
|
|
|
// defined; and the classes in which any member templates used as
|
2009-07-08 15:51:57 +08:00
|
|
|
|
// template template arguments are defined.
|
2009-11-11 09:00:40 +08:00
|
|
|
|
TemplateName Template = Arg.getAsTemplate();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (ClassTemplateDecl *ClassTemplate
|
2009-11-11 09:00:40 +08:00
|
|
|
|
= dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
|
2009-07-08 15:51:57 +08:00
|
|
|
|
DeclContext *Ctx = ClassTemplate->getDeclContext();
|
|
|
|
|
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
|
|
|
|
|
AssociatedClasses.insert(EnclosingClass);
|
|
|
|
|
// Add the associated namespace for this class.
|
|
|
|
|
while (Ctx->isRecord())
|
|
|
|
|
Ctx = Ctx->getParent();
|
2009-08-08 06:18:02 +08:00
|
|
|
|
CollectNamespace(AssociatedNamespaces, Ctx);
|
2009-07-08 15:51:57 +08:00
|
|
|
|
}
|
|
|
|
|
break;
|
2009-11-11 09:00:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TemplateArgument::Declaration:
|
2009-07-08 15:51:57 +08:00
|
|
|
|
case TemplateArgument::Integral:
|
|
|
|
|
case TemplateArgument::Expression:
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// [Note: non-type template arguments do not contribute to the set of
|
2009-07-08 15:51:57 +08:00
|
|
|
|
// associated namespaces. ]
|
|
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-07-08 15:51:57 +08:00
|
|
|
|
case TemplateArgument::Pack:
|
|
|
|
|
for (TemplateArgument::pack_iterator P = Arg.pack_begin(),
|
|
|
|
|
PEnd = Arg.pack_end();
|
|
|
|
|
P != PEnd; ++P)
|
|
|
|
|
addAssociatedClassesAndNamespaces(*P, Context,
|
|
|
|
|
AssociatedNamespaces,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedClasses);
|
2009-07-08 15:51:57 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-04 08:32:51 +08:00
|
|
|
|
// \brief Add the associated classes and namespaces for
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// argument-dependent lookup with an argument of class type
|
|
|
|
|
// (C++ [basic.lookup.koenig]p2).
|
|
|
|
|
static void
|
|
|
|
|
addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
|
2009-02-04 08:32:51 +08:00
|
|
|
|
ASTContext &Context,
|
|
|
|
|
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
Sema::AssociatedClassSet &AssociatedClasses) {
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// which its associated classes are defined.
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
// 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();
|
2009-08-08 06:18:02 +08:00
|
|
|
|
CollectNamespace(AssociatedNamespaces, Ctx);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
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;
|
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// -- If T is a template-id, its associated namespaces and classes are
|
|
|
|
|
// the namespace in which the template is defined; for member
|
2009-07-08 15:51:57 +08:00
|
|
|
|
// templates, the member template’s class; the namespaces and classes
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// associated with the types of the template arguments provided for
|
2009-07-08 15:51:57 +08:00
|
|
|
|
// template type parameters (excluding template template parameters); the
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// namespaces in which any template template arguments are defined; and
|
|
|
|
|
// the classes in which any member templates used as template template
|
|
|
|
|
// arguments are defined. [Note: non-type template arguments do not
|
2009-07-08 15:51:57 +08:00
|
|
|
|
// contribute to the set of associated namespaces. ]
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (ClassTemplateSpecializationDecl *Spec
|
2009-07-08 15:51:57 +08:00
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(Class)) {
|
|
|
|
|
DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext();
|
|
|
|
|
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
|
|
|
|
|
AssociatedClasses.insert(EnclosingClass);
|
|
|
|
|
// Add the associated namespace for this class.
|
|
|
|
|
while (Ctx->isRecord())
|
|
|
|
|
Ctx = Ctx->getParent();
|
2009-08-08 06:18:02 +08:00
|
|
|
|
CollectNamespace(AssociatedNamespaces, Ctx);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-07-08 15:51:57 +08:00
|
|
|
|
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
|
|
|
|
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
|
|
|
|
|
addAssociatedClassesAndNamespaces(TemplateArgs[I], Context,
|
|
|
|
|
AssociatedNamespaces,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedClasses);
|
2009-07-08 15:51:57 +08:00
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-02-04 08:32:51 +08:00
|
|
|
|
// 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) {
|
2009-07-30 05:53:49 +08:00
|
|
|
|
const RecordType *BaseType = Base->getType()->getAs<RecordType>();
|
2009-10-25 17:35:33 +08:00
|
|
|
|
// In dependent contexts, we do ADL twice, and the first time around,
|
|
|
|
|
// the base type might be a dependent TemplateSpecializationType, or a
|
|
|
|
|
// TemplateTypeParmType. If that happens, simply ignore it.
|
|
|
|
|
// FIXME: If we want to support export, we probably need to add the
|
|
|
|
|
// namespace of the template in a TemplateSpecializationType, or even
|
|
|
|
|
// the classes and namespaces of known non-dependent arguments.
|
|
|
|
|
if (!BaseType)
|
|
|
|
|
continue;
|
2009-02-04 08:32:51 +08:00
|
|
|
|
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();
|
2009-08-08 06:18:02 +08:00
|
|
|
|
CollectNamespace(AssociatedNamespaces, BaseCtx);
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// (C++ [basic.lookup.koenig]p2).
|
|
|
|
|
static void
|
|
|
|
|
addAssociatedClassesAndNamespaces(QualType T,
|
2009-02-04 08:32:51 +08:00
|
|
|
|
ASTContext &Context,
|
|
|
|
|
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
Sema::AssociatedClassSet &AssociatedClasses) {
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// namespaces and classes are those associated with U.
|
2009-02-04 08:32:51 +08:00
|
|
|
|
//
|
|
|
|
|
// We handle this by unwrapping pointer and array types immediately,
|
|
|
|
|
// to avoid unnecessary recursion.
|
|
|
|
|
while (true) {
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const PointerType *Ptr = T->getAs<PointerType>())
|
2009-02-04 08:32:51 +08:00
|
|
|
|
T = Ptr->getPointeeType();
|
|
|
|
|
else if (const ArrayType *Ptr = Context.getAsArrayType(T))
|
|
|
|
|
T = Ptr->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
else
|
2009-02-04 08:32:51 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -- If T is a fundamental type, its associated sets of
|
|
|
|
|
// namespaces and classes are both empty.
|
2009-09-22 07:43:11 +08:00
|
|
|
|
if (T->getAs<BuiltinType>())
|
2009-02-04 08:32:51 +08:00
|
|
|
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// which its associated classes are defined.
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *ClassType = T->getAs<RecordType>())
|
2009-09-09 23:08:12 +08:00
|
|
|
|
if (CXXRecordDecl *ClassDecl
|
2009-02-28 09:32:25 +08:00
|
|
|
|
= dyn_cast<CXXRecordDecl>(ClassType->getDecl())) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
addAssociatedClassesAndNamespaces(ClassDecl, Context,
|
|
|
|
|
AssociatedNamespaces,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedClasses);
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// it has no associated class.
|
2009-09-22 07:43:11 +08:00
|
|
|
|
if (const EnumType *EnumT = T->getAs<EnumType>()) {
|
2009-02-04 08:32:51 +08:00
|
|
|
|
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();
|
2009-08-08 06:18:02 +08:00
|
|
|
|
CollectNamespace(AssociatedNamespaces, Ctx);
|
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.
|
2009-09-22 07:43:11 +08:00
|
|
|
|
if (const FunctionType *FnType = T->getAs<FunctionType>()) {
|
2009-02-04 08:32:51 +08:00
|
|
|
|
// Return type
|
2009-09-22 07:43:11 +08:00
|
|
|
|
addAssociatedClassesAndNamespaces(FnType->getResultType(),
|
2009-02-04 08:32:51 +08:00
|
|
|
|
Context,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedNamespaces, AssociatedClasses);
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
2009-09-22 07:43:11 +08:00
|
|
|
|
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType);
|
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-09-09 23:08:12 +08:00
|
|
|
|
ArgEnd = Proto->arg_type_end();
|
2009-02-04 08:32:51 +08:00
|
|
|
|
Arg != ArgEnd; ++Arg)
|
|
|
|
|
addAssociatedClassesAndNamespaces(*Arg, Context,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedNamespaces, AssociatedClasses);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
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,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// together with those associated with X.
|
2009-02-04 08:32:51 +08:00
|
|
|
|
//
|
|
|
|
|
// -- 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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// X.
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const MemberPointerType *MemberPtr = T->getAs<MemberPointerType>()) {
|
2009-02-04 08:32:51 +08:00
|
|
|
|
// Handle the type that the pointer to member points to.
|
|
|
|
|
addAssociatedClassesAndNamespaces(MemberPtr->getPointeeType(),
|
|
|
|
|
Context,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedNamespaces,
|
|
|
|
|
AssociatedClasses);
|
2009-02-04 08:32:51 +08:00
|
|
|
|
|
|
|
|
|
// Handle the class type into which this points.
|
2009-07-30 05:53:49 +08:00
|
|
|
|
if (const RecordType *Class = MemberPtr->getClass()->getAs<RecordType>())
|
2009-02-04 08:32:51 +08:00
|
|
|
|
addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()),
|
|
|
|
|
Context,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedNamespaces,
|
|
|
|
|
AssociatedClasses);
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
/// namespaces searched by argument-dependent lookup
|
2009-02-04 08:32:51 +08:00
|
|
|
|
/// (C++ [basic.lookup.argdep]) for a given set of arguments.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
void
|
2009-02-04 08:32:51 +08:00
|
|
|
|
Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
|
|
|
|
|
AssociatedNamespaceSet &AssociatedNamespaces,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedClassSet &AssociatedClasses) {
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// argument).
|
2009-02-04 08:32:51 +08:00
|
|
|
|
for (unsigned ArgIdx = 0; ArgIdx != NumArgs; ++ArgIdx) {
|
|
|
|
|
Expr *Arg = Args[ArgIdx];
|
|
|
|
|
|
|
|
|
|
if (Arg->getType() != Context.OverloadTy) {
|
|
|
|
|
addAssociatedClassesAndNamespaces(Arg->getType(), Context,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedNamespaces,
|
|
|
|
|
AssociatedClasses);
|
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.
|
2009-07-08 18:57:20 +08:00
|
|
|
|
Arg = Arg->IgnoreParens();
|
2009-11-21 16:51:07 +08:00
|
|
|
|
if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg))
|
|
|
|
|
if (unaryOp->getOpcode() == UnaryOperator::AddrOf)
|
|
|
|
|
Arg = unaryOp->getSubExpr();
|
|
|
|
|
|
|
|
|
|
// TODO: avoid the copies. This should be easy when the cases
|
|
|
|
|
// share a storage implementation.
|
|
|
|
|
llvm::SmallVector<NamedDecl*, 8> Functions;
|
|
|
|
|
|
|
|
|
|
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg))
|
|
|
|
|
Functions.append(ULE->decls_begin(), ULE->decls_end());
|
2009-11-25 03:00:30 +08:00
|
|
|
|
else
|
2009-02-04 08:32:51 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
2009-11-21 16:51:07 +08:00
|
|
|
|
for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Functions.begin(),
|
|
|
|
|
E = Functions.end(); I != E; ++I) {
|
|
|
|
|
FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I);
|
2009-06-26 06:08:12 +08:00
|
|
|
|
if (!FDecl)
|
2009-11-21 16:51:07 +08:00
|
|
|
|
FDecl = cast<FunctionTemplateDecl>(*I)->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();
|
2009-08-08 06:18:02 +08:00
|
|
|
|
CollectNamespace(AssociatedNamespaces, Ctx);
|
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-08-08 06:18:02 +08:00
|
|
|
|
AssociatedNamespaces,
|
|
|
|
|
AssociatedClasses);
|
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.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
static bool
|
2009-03-13 08:33:25 +08:00
|
|
|
|
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;
|
|
|
|
|
|
2009-09-22 07:43:11 +08:00
|
|
|
|
const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>();
|
2009-03-13 08:33:25 +08:00
|
|
|
|
if (Proto->getNumArgs() < 1)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (T1->isEnumeralType()) {
|
|
|
|
|
QualType ArgType = Proto->getArgType(0).getNonReferenceType();
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
|
if (Context.hasSameUnqualifiedType(T1, ArgType))
|
2009-03-13 08:33:25 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Proto->getNumArgs() < 2)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (!T2.isNull() && T2->isEnumeralType()) {
|
|
|
|
|
QualType ArgType = Proto->getArgType(1).getNonReferenceType();
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
|
if (Context.hasSameUnqualifiedType(T2, ArgType))
|
2009-03-13 08:33:25 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-18 15:57:50 +08:00
|
|
|
|
NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name,
|
|
|
|
|
LookupNameKind NameKind,
|
|
|
|
|
RedeclarationKind Redecl) {
|
|
|
|
|
LookupResult R(*this, Name, SourceLocation(), NameKind, Redecl);
|
|
|
|
|
LookupName(R, S);
|
2009-12-02 16:25:40 +08:00
|
|
|
|
return R.getAsSingle<NamedDecl>();
|
2009-11-18 15:57:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-04-24 07:18:26 +08:00
|
|
|
|
/// \brief Find the protocol with the given name, if any.
|
|
|
|
|
ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) {
|
2009-10-10 05:13:30 +08:00
|
|
|
|
Decl *D = LookupSingleName(TUScope, II, LookupObjCProtocolName);
|
2009-04-24 07:18:26 +08:00
|
|
|
|
return cast_or_null<ObjCProtocolDecl>(D);
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-13 08:33:25 +08:00
|
|
|
|
void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
|
2009-09-09 23:08:12 +08:00
|
|
|
|
QualType T1, QualType T2,
|
2009-03-13 08:33:25 +08:00
|
|
|
|
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
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// that have a first parameter of type T1 or "reference to
|
|
|
|
|
// (possibly cv-qualified) T1", when T1 is an enumeration
|
2009-03-13 08:33:25 +08:00
|
|
|
|
// type, or (if there is a right operand) a second parameter
|
2009-08-06 03:21:58 +08:00
|
|
|
|
// of type T2 or "reference to (possibly cv-qualified) T2",
|
2009-03-13 08:33:25 +08:00
|
|
|
|
// when T2 is an enumeration type, are candidate functions.
|
|
|
|
|
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
|
2009-11-17 10:14:36 +08:00
|
|
|
|
LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName);
|
|
|
|
|
LookupName(Operators, S);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-03-13 08:33:25 +08:00
|
|
|
|
assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
|
|
|
|
|
|
2009-10-10 05:13:30 +08:00
|
|
|
|
if (Operators.empty())
|
2009-03-13 08:33:25 +08:00
|
|
|
|
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-09-09 23:08:12 +08:00
|
|
|
|
} else if (FunctionTemplateDecl *FunTmpl
|
2009-06-28 05:05:07 +08:00
|
|
|
|
= dyn_cast<FunctionTemplateDecl>(*Op)) {
|
|
|
|
|
// FIXME: friend operators?
|
2009-09-09 23:08:12 +08:00
|
|
|
|
// FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
|
2009-06-28 05:05:07 +08:00
|
|
|
|
// later?
|
|
|
|
|
if (!FunTmpl->getDeclContext()->isRecord())
|
|
|
|
|
Functions.insert(FunTmpl);
|
|
|
|
|
}
|
2009-03-13 08:33:25 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-08 06:18:02 +08:00
|
|
|
|
static void CollectFunctionDecl(Sema::FunctionSet &Functions,
|
|
|
|
|
Decl *D) {
|
|
|
|
|
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
|
|
|
|
|
Functions.insert(Func);
|
|
|
|
|
else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
|
|
|
|
|
Functions.insert(FunTmpl);
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-24 03:23:15 +08:00
|
|
|
|
void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
|
2009-03-13 08:33:25 +08:00
|
|
|
|
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-09-09 23:08:12 +08:00
|
|
|
|
FindAssociatedClassesAndNamespaces(Args, NumArgs,
|
2009-08-08 06:18:02 +08:00
|
|
|
|
AssociatedNamespaces,
|
|
|
|
|
AssociatedClasses);
|
2009-03-13 08:33:25 +08:00
|
|
|
|
|
2009-10-24 03:23:15 +08:00
|
|
|
|
QualType T1, T2;
|
|
|
|
|
if (Operator) {
|
|
|
|
|
T1 = Args[0]->getType();
|
|
|
|
|
if (NumArgs >= 2)
|
|
|
|
|
T2 = Args[1]->getType();
|
|
|
|
|
}
|
|
|
|
|
|
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(),
|
2009-09-09 23:08:12 +08:00
|
|
|
|
NSEnd = AssociatedNamespaces.end();
|
|
|
|
|
NS != NSEnd; ++NS) {
|
2009-03-13 08:33:25 +08:00
|
|
|
|
// 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.
|
|
|
|
|
//
|
2009-08-08 06:18:02 +08:00
|
|
|
|
// -- Any namespace-scope friend functions declared in
|
2009-03-13 08:33:25 +08:00
|
|
|
|
// associated classes are visible within their respective
|
|
|
|
|
// namespaces even if they are not visible during an ordinary
|
|
|
|
|
// lookup (11.4).
|
2009-06-24 04:14:09 +08:00
|
|
|
|
DeclContext::lookup_iterator I, E;
|
2009-08-11 14:59:38 +08:00
|
|
|
|
for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
|
2009-08-08 06:18:02 +08:00
|
|
|
|
Decl *D = *I;
|
2009-08-28 15:59:38 +08:00
|
|
|
|
// If the only declaration here is an ordinary friend, consider
|
|
|
|
|
// it only if it was declared in an associated classes.
|
|
|
|
|
if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
|
2009-08-11 14:59:38 +08:00
|
|
|
|
DeclContext *LexDC = D->getLexicalDeclContext();
|
|
|
|
|
if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
2009-10-24 03:23:15 +08:00
|
|
|
|
FunctionDecl *Fn;
|
|
|
|
|
if (!Operator || !(Fn = dyn_cast<FunctionDecl>(D)) ||
|
|
|
|
|
IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context))
|
|
|
|
|
CollectFunctionDecl(Functions, D);
|
2009-06-24 04:14:09 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-03-13 08:33:25 +08:00
|
|
|
|
}
|