From 15448f8d238c591ce640da28aacc76311da576a6 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 27 Jun 2009 21:05:07 +0000 Subject: [PATCH] Improve support for overloaded operator templates. llvm-svn: 74390 --- clang/include/clang/AST/DeclCXX.h | 42 +++++++++++-------- clang/lib/AST/DeclCXX.cpp | 10 ++--- clang/lib/Sema/Sema.h | 2 +- clang/lib/Sema/SemaLookup.cpp | 28 ++++++++----- clang/lib/Sema/SemaOverload.cpp | 31 ++++++++++---- clang/test/SemaTemplate/operator-template.cpp | 2 + 6 files changed, 72 insertions(+), 43 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index a2fe24e83105..24c9d3e15dcd 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -32,6 +32,8 @@ class ClassTemplateSpecializationDecl; class AnyFunctionDecl { NamedDecl *Function; + AnyFunctionDecl(NamedDecl *ND) : Function(ND) { } + public: AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { } AnyFunctionDecl(FunctionTemplateDecl *FTD); @@ -42,6 +44,10 @@ public: /// \brief Retrieve the underlying function or function template. NamedDecl *get() const { return Function; } + + static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) { + return AnyFunctionDecl(ND); + } }; } // end namespace clang @@ -57,6 +63,22 @@ namespace llvm { }; template<> struct simplify_type< ::clang::AnyFunctionDecl> : public simplify_type {}; + + // 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 namespace clang { @@ -91,24 +113,10 @@ public: static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC, DeclarationName N); - /// addOverload - Add an overloaded function FD to this set of - /// overloaded functions. - void addOverload(FunctionDecl *FD) { - assert((FD->getDeclName() == getDeclName() || - isa(FD) || isa(FD)) && - "Overloaded functions must have the same name"); - Functions.push_back(FD); + /// \brief Add a new overloaded function or function template to the set + /// of overloaded function templates. + void addOverload(AnyFunctionDecl F); - // 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_end() { return Functions.end(); } function_const_iterator function_begin() const { return Functions.begin(); } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 752218db042a..bffa70f18eeb 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -420,13 +420,9 @@ OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC, return new (C) OverloadedFunctionDecl(DC, N); } -void OverloadedFunctionDecl::addOverload(FunctionTemplateDecl *FTD) { - Functions.push_back(FTD); - - // An overloaded function declaration always has the location of - // the most-recently-added function declaration. - if (FTD->getLocation().isValid()) - this->setLocation(FTD->getLocation()); +void OverloadedFunctionDecl::addOverload(AnyFunctionDecl F) { + Functions.push_back(F); + this->setLocation(F.get()->getLocation()); } LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 0dd68feb9658..a53e420db341 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -679,7 +679,7 @@ public: OR_Deleted ///< Overload resoltuion refers to a deleted function. }; - typedef llvm::SmallPtrSet FunctionSet; + typedef llvm::SmallPtrSet FunctionSet; typedef llvm::SmallPtrSet AssociatedNamespaceSet; typedef llvm::SmallPtrSet AssociatedClassSet; diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index cc9e783f6166..e99217ea573e 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1604,9 +1604,17 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end(); Op != OpEnd; ++Op) { - if (FunctionDecl *FD = dyn_cast(*Op)) + if (FunctionDecl *FD = dyn_cast(*Op)) { if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context)) Functions.insert(FD); // FIXME: canonical FD + } else if (FunctionTemplateDecl *FunTmpl + = dyn_cast(*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). DeclContext::lookup_iterator I, E; for (llvm::tie(I, E) = (*NS)->lookup(Context, Name); I != E; ++I) { - FunctionDecl *Func = dyn_cast(*I); - if (!Func) - break; - - Functions.insert(Func); + if (FunctionDecl *Func = dyn_cast(*I)) + Functions.insert(Func); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast(*I)) + Functions.insert(FunTmpl); } } @@ -1662,11 +1669,10 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, for (llvm::tie(I, E) = Context.getTranslationUnitDecl()->lookup(Context, Name); I != E; ++I) { - FunctionDecl *Func = dyn_cast(*I); - if (!Func) - break; - - Functions.insert(Func); + if (FunctionDecl *Func = dyn_cast(*I)) + Functions.insert(Func); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast(*I)) + Functions.insert(FunTmpl); } } } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index fcc155750cdc..e240c04e5dc7 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2161,9 +2161,15 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions, bool SuppressUserConversions) { for (FunctionSet::const_iterator F = Functions.begin(), FEnd = Functions.end(); - F != FEnd; ++F) - AddOverloadCandidate(*F, Args, NumArgs, CandidateSet, - SuppressUserConversions); + F != FEnd; ++F) { + if (FunctionDecl *FD = dyn_cast(*F)) + AddOverloadCandidate(FD, Args, NumArgs, CandidateSet, + SuppressUserConversions); + else + AddTemplateOverloadCandidate(cast(*F), Args, + NumArgs, CandidateSet, + SuppressUserConversions); + } } /// AddMethodCandidate - Adds the given C++ member function to the set @@ -3405,8 +3411,11 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), CandEnd = CandidateSet.end(); Cand != CandEnd; ++Cand) - if (Cand->Function) + if (Cand->Function) { Functions.insert(Cand->Function); + if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate()) + Functions.insert(FunTmpl); + } ArgumentDependentLookup(Name, Args, NumArgs, Functions); @@ -3415,15 +3424,23 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), CandEnd = CandidateSet.end(); Cand != CandEnd; ++Cand) - if (Cand->Function) + if (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 // set. for (FunctionSet::iterator Func = Functions.begin(), FuncEnd = Functions.end(); - Func != FuncEnd; ++Func) - AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet); + Func != FuncEnd; ++Func) { + if (FunctionDecl *FD = dyn_cast(*Func)) + AddOverloadCandidate(FD, Args, NumArgs, CandidateSet); + else + AddTemplateOverloadCandidate(cast(*Func), Args, + NumArgs, CandidateSet); + } } /// isBetterOverloadCandidate - Determines whether the first overload diff --git a/clang/test/SemaTemplate/operator-template.cpp b/clang/test/SemaTemplate/operator-template.cpp index 3d041ec13a32..d65a2781c87f 100644 --- a/clang/test/SemaTemplate/operator-template.cpp +++ b/clang/test/SemaTemplate/operator-template.cpp @@ -5,6 +5,8 @@ templatestruct A{typedef X Y;}; templatebool operator==(A,typename A::Y); int a(A x) { return operator==(x,1); } +int a0(A x) { return x == 1; } + // FIXME: The diagnostic here is a bit messed up templatestruct B{typedef X Y;}; templatebool operator==(B*,typename B::Y); // \