forked from OSchip/llvm-project
Improve support for overloaded operator templates.
llvm-svn: 74390
This commit is contained in:
parent
3a4be9df4a
commit
15448f8d23
|
@ -32,6 +32,8 @@ class ClassTemplateSpecializationDecl;
|
||||||
class AnyFunctionDecl {
|
class AnyFunctionDecl {
|
||||||
NamedDecl *Function;
|
NamedDecl *Function;
|
||||||
|
|
||||||
|
AnyFunctionDecl(NamedDecl *ND) : Function(ND) { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { }
|
AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { }
|
||||||
AnyFunctionDecl(FunctionTemplateDecl *FTD);
|
AnyFunctionDecl(FunctionTemplateDecl *FTD);
|
||||||
|
@ -42,6 +44,10 @@ public:
|
||||||
|
|
||||||
/// \brief Retrieve the underlying function or function template.
|
/// \brief Retrieve the underlying function or function template.
|
||||||
NamedDecl *get() const { return Function; }
|
NamedDecl *get() const { return Function; }
|
||||||
|
|
||||||
|
static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) {
|
||||||
|
return AnyFunctionDecl(ND);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace clang
|
} // end namespace clang
|
||||||
|
@ -57,6 +63,22 @@ namespace llvm {
|
||||||
};
|
};
|
||||||
template<> struct simplify_type< ::clang::AnyFunctionDecl>
|
template<> struct simplify_type< ::clang::AnyFunctionDecl>
|
||||||
: public simplify_type<const ::clang::AnyFunctionDecl> {};
|
: public simplify_type<const ::clang::AnyFunctionDecl> {};
|
||||||
|
|
||||||
|
// Provide PointerLikeTypeTraits for non-cvr pointers.
|
||||||
|
template<>
|
||||||
|
class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> {
|
||||||
|
public:
|
||||||
|
static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) {
|
||||||
|
return F.get();
|
||||||
|
}
|
||||||
|
static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) {
|
||||||
|
return ::clang::AnyFunctionDecl::getFromNamedDecl(
|
||||||
|
static_cast< ::clang::NamedDecl*>(P));
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { NumLowBitsAvailable = 2 };
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
@ -91,24 +113,10 @@ public:
|
||||||
static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC,
|
static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC,
|
||||||
DeclarationName N);
|
DeclarationName N);
|
||||||
|
|
||||||
/// addOverload - Add an overloaded function FD to this set of
|
/// \brief Add a new overloaded function or function template to the set
|
||||||
/// overloaded functions.
|
/// of overloaded function templates.
|
||||||
void addOverload(FunctionDecl *FD) {
|
void addOverload(AnyFunctionDecl F);
|
||||||
assert((FD->getDeclName() == getDeclName() ||
|
|
||||||
isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
|
|
||||||
"Overloaded functions must have the same name");
|
|
||||||
Functions.push_back(FD);
|
|
||||||
|
|
||||||
// An overloaded function declaration always has the location of
|
|
||||||
// the most-recently-added function declaration.
|
|
||||||
if (FD->getLocation().isValid())
|
|
||||||
this->setLocation(FD->getLocation());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// addOverload - Add an overloaded function template FTD to this set of
|
|
||||||
/// overloaded functions.
|
|
||||||
void addOverload(FunctionTemplateDecl *FTD);
|
|
||||||
|
|
||||||
function_iterator function_begin() { return Functions.begin(); }
|
function_iterator function_begin() { return Functions.begin(); }
|
||||||
function_iterator function_end() { return Functions.end(); }
|
function_iterator function_end() { return Functions.end(); }
|
||||||
function_const_iterator function_begin() const { return Functions.begin(); }
|
function_const_iterator function_begin() const { return Functions.begin(); }
|
||||||
|
|
|
@ -420,13 +420,9 @@ OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
||||||
return new (C) OverloadedFunctionDecl(DC, N);
|
return new (C) OverloadedFunctionDecl(DC, N);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverloadedFunctionDecl::addOverload(FunctionTemplateDecl *FTD) {
|
void OverloadedFunctionDecl::addOverload(AnyFunctionDecl F) {
|
||||||
Functions.push_back(FTD);
|
Functions.push_back(F);
|
||||||
|
this->setLocation(F.get()->getLocation());
|
||||||
// An overloaded function declaration always has the location of
|
|
||||||
// the most-recently-added function declaration.
|
|
||||||
if (FTD->getLocation().isValid())
|
|
||||||
this->setLocation(FTD->getLocation());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
|
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
|
||||||
|
|
|
@ -679,7 +679,7 @@ public:
|
||||||
OR_Deleted ///< Overload resoltuion refers to a deleted function.
|
OR_Deleted ///< Overload resoltuion refers to a deleted function.
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef llvm::SmallPtrSet<FunctionDecl *, 16> FunctionSet;
|
typedef llvm::SmallPtrSet<AnyFunctionDecl, 16> FunctionSet;
|
||||||
typedef llvm::SmallPtrSet<NamespaceDecl *, 16> AssociatedNamespaceSet;
|
typedef llvm::SmallPtrSet<NamespaceDecl *, 16> AssociatedNamespaceSet;
|
||||||
typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
|
typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
|
||||||
|
|
||||||
|
|
|
@ -1604,9 +1604,17 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
|
||||||
|
|
||||||
for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
|
for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
|
||||||
Op != OpEnd; ++Op) {
|
Op != OpEnd; ++Op) {
|
||||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op))
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) {
|
||||||
if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
|
if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
|
||||||
Functions.insert(FD); // FIXME: canonical FD
|
Functions.insert(FD); // FIXME: canonical FD
|
||||||
|
} else if (FunctionTemplateDecl *FunTmpl
|
||||||
|
= dyn_cast<FunctionTemplateDecl>(*Op)) {
|
||||||
|
// FIXME: friend operators?
|
||||||
|
// FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
|
||||||
|
// later?
|
||||||
|
if (!FunTmpl->getDeclContext()->isRecord())
|
||||||
|
Functions.insert(FunTmpl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1649,11 +1657,10 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
|
||||||
// lookup (11.4).
|
// lookup (11.4).
|
||||||
DeclContext::lookup_iterator I, E;
|
DeclContext::lookup_iterator I, E;
|
||||||
for (llvm::tie(I, E) = (*NS)->lookup(Context, Name); I != E; ++I) {
|
for (llvm::tie(I, E) = (*NS)->lookup(Context, Name); I != E; ++I) {
|
||||||
FunctionDecl *Func = dyn_cast<FunctionDecl>(*I);
|
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
|
||||||
if (!Func)
|
Functions.insert(Func);
|
||||||
break;
|
else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))
|
||||||
|
Functions.insert(FunTmpl);
|
||||||
Functions.insert(Func);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1662,11 +1669,10 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
|
||||||
for (llvm::tie(I, E)
|
for (llvm::tie(I, E)
|
||||||
= Context.getTranslationUnitDecl()->lookup(Context, Name);
|
= Context.getTranslationUnitDecl()->lookup(Context, Name);
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
FunctionDecl *Func = dyn_cast<FunctionDecl>(*I);
|
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
|
||||||
if (!Func)
|
Functions.insert(Func);
|
||||||
break;
|
else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))
|
||||||
|
Functions.insert(FunTmpl);
|
||||||
Functions.insert(Func);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2161,9 +2161,15 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions,
|
||||||
bool SuppressUserConversions) {
|
bool SuppressUserConversions) {
|
||||||
for (FunctionSet::const_iterator F = Functions.begin(),
|
for (FunctionSet::const_iterator F = Functions.begin(),
|
||||||
FEnd = Functions.end();
|
FEnd = Functions.end();
|
||||||
F != FEnd; ++F)
|
F != FEnd; ++F) {
|
||||||
AddOverloadCandidate(*F, Args, NumArgs, CandidateSet,
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F))
|
||||||
SuppressUserConversions);
|
AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
|
||||||
|
SuppressUserConversions);
|
||||||
|
else
|
||||||
|
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*F), Args,
|
||||||
|
NumArgs, CandidateSet,
|
||||||
|
SuppressUserConversions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AddMethodCandidate - Adds the given C++ member function to the set
|
/// AddMethodCandidate - Adds the given C++ member function to the set
|
||||||
|
@ -3405,8 +3411,11 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
|
||||||
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
|
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
|
||||||
CandEnd = CandidateSet.end();
|
CandEnd = CandidateSet.end();
|
||||||
Cand != CandEnd; ++Cand)
|
Cand != CandEnd; ++Cand)
|
||||||
if (Cand->Function)
|
if (Cand->Function) {
|
||||||
Functions.insert(Cand->Function);
|
Functions.insert(Cand->Function);
|
||||||
|
if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
|
||||||
|
Functions.insert(FunTmpl);
|
||||||
|
}
|
||||||
|
|
||||||
ArgumentDependentLookup(Name, Args, NumArgs, Functions);
|
ArgumentDependentLookup(Name, Args, NumArgs, Functions);
|
||||||
|
|
||||||
|
@ -3415,15 +3424,23 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
|
||||||
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
|
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
|
||||||
CandEnd = CandidateSet.end();
|
CandEnd = CandidateSet.end();
|
||||||
Cand != CandEnd; ++Cand)
|
Cand != CandEnd; ++Cand)
|
||||||
if (Cand->Function)
|
if (Cand->Function) {
|
||||||
Functions.erase(Cand->Function);
|
Functions.erase(Cand->Function);
|
||||||
|
if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
|
||||||
|
Functions.erase(FunTmpl);
|
||||||
|
}
|
||||||
|
|
||||||
// For each of the ADL candidates we found, add it to the overload
|
// For each of the ADL candidates we found, add it to the overload
|
||||||
// set.
|
// set.
|
||||||
for (FunctionSet::iterator Func = Functions.begin(),
|
for (FunctionSet::iterator Func = Functions.begin(),
|
||||||
FuncEnd = Functions.end();
|
FuncEnd = Functions.end();
|
||||||
Func != FuncEnd; ++Func)
|
Func != FuncEnd; ++Func) {
|
||||||
AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet);
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func))
|
||||||
|
AddOverloadCandidate(FD, Args, NumArgs, CandidateSet);
|
||||||
|
else
|
||||||
|
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func), Args,
|
||||||
|
NumArgs, CandidateSet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isBetterOverloadCandidate - Determines whether the first overload
|
/// isBetterOverloadCandidate - Determines whether the first overload
|
||||||
|
|
|
@ -5,6 +5,8 @@ template<class X>struct A{typedef X Y;};
|
||||||
template<class X>bool operator==(A<X>,typename A<X>::Y);
|
template<class X>bool operator==(A<X>,typename A<X>::Y);
|
||||||
int a(A<int> x) { return operator==(x,1); }
|
int a(A<int> x) { return operator==(x,1); }
|
||||||
|
|
||||||
|
int a0(A<int> x) { return x == 1; }
|
||||||
|
|
||||||
// FIXME: The diagnostic here is a bit messed up
|
// FIXME: The diagnostic here is a bit messed up
|
||||||
template<class X>struct B{typedef X Y;};
|
template<class X>struct B{typedef X Y;};
|
||||||
template<class X>bool operator==(B<X>*,typename B<X>::Y); // \
|
template<class X>bool operator==(B<X>*,typename B<X>::Y); // \
|
||||||
|
|
Loading…
Reference in New Issue