]> granicus.if.org Git - clang/commitdiff
Improve support for overloaded operator templates.
authorDouglas Gregor <dgregor@apple.com>
Sat, 27 Jun 2009 21:05:07 +0000 (21:05 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 27 Jun 2009 21:05:07 +0000 (21:05 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74390 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclCXX.h
lib/AST/DeclCXX.cpp
lib/Sema/Sema.h
lib/Sema/SemaLookup.cpp
lib/Sema/SemaOverload.cpp
test/SemaTemplate/operator-template.cpp

index a2fe24e83105bb27ccaf2ae7df1b9ec31e8fc099..24c9d3e15dcd3919fbc1dec20a5767a2a4a8a671 100644 (file)
@@ -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<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
 
 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<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());
-  }
+  /// \brief Add a new overloaded function or function template to the set
+  /// of overloaded function templates.
+  void addOverload(AnyFunctionDecl F);
 
-  /// 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(); }
index 752218db042a1ba4454b4dc27d3be564171f80d1..bffa70f18eeb783166c547b91eecd60ace912b87 100644 (file)
@@ -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,
index 0dd68feb965812b4f730ca4c62e9a350f69fc60d..a53e420db34146ff2f110c731c1c7982a105ee4a 100644 (file)
@@ -679,7 +679,7 @@ public:
     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<CXXRecordDecl *, 16> AssociatedClassSet;
 
index cc9e783f61662af8d1504ab5429d0877ba1f834d..e99217ea573ef48b18790e4dc5aca5b0edbd191f 100644 (file)
@@ -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<FunctionDecl>(*Op))
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) {
       if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
         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).
     DeclContext::lookup_iterator I, E;
     for (llvm::tie(I, E) = (*NS)->lookup(Context, Name); I != E; ++I) {
-      FunctionDecl *Func = dyn_cast<FunctionDecl>(*I);
-      if (!Func)
-        break;
-
-      Functions.insert(Func);
+      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
+        Functions.insert(Func);
+      else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*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<FunctionDecl>(*I);
-      if (!Func)
-        break;
-      
-      Functions.insert(Func);
+      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
+        Functions.insert(Func);
+      else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))
+        Functions.insert(FunTmpl);
     }
   }
 }
index fcc155750cdc62fc5c5eb33be682bb6321ca8f76..e240c04e5dc7d82286bbc8f32f1897be8422ff26 100644 (file)
@@ -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<FunctionDecl>(*F))
+      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
@@ -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<FunctionDecl>(*Func))
+      AddOverloadCandidate(FD, Args, NumArgs, CandidateSet);
+    else
+      AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func), Args, 
+                                   NumArgs, CandidateSet);
+  }
 }
 
 /// isBetterOverloadCandidate - Determines whether the first overload
index 3d041ec13a329c69c43a186f0565d04f52667368..d65a2781c87f8dfea3139e71e1567cae4cb08823 100644 (file)
@@ -5,6 +5,8 @@ template<class X>struct A{typedef X Y;};
 template<class X>bool operator==(A<X>,typename A<X>::Y);
 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
 template<class X>struct B{typedef X Y;};
 template<class X>bool operator==(B<X>*,typename B<X>::Y); // \