[cfe-commits] r75069 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaOverload.cpp test/CXX/over/over.over/p4.cpp www/cxx_status.html

Douglas Gregor dgregor at apple.com
Wed Jul 8 16:33:58 PDT 2009


Author: dgregor
Date: Wed Jul  8 18:33:52 2009
New Revision: 75069

URL: http://llvm.org/viewvc/llvm-project?rev=75069&view=rev
Log:
Implement the simple form of overload resolution used when taking the
address of an overloaded function (which may involve both functions
and function templates). 

Added:
    cfe/trunk/test/CXX/over/over.over/p4.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=75069&r1=75068&r2=75069&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jul  8 18:33:52 2009
@@ -666,6 +666,10 @@
 def err_member_call_without_object : Error<
   "call to non-static member function without an object argument">;
 
+// C++ Address of Overloaded Function
+def err_addr_ovl_ambiguous : Error<
+  "address of overloaded function %0 is ambiguous">;
+
 // C++ Template Declarations
 def err_template_param_shadow : Error<
   "declaration of %0 shadows template parameter">;

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=75069&r1=75068&r2=75069&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Jul  8 18:33:52 2009
@@ -3742,7 +3742,9 @@
   
   // Look through all of the overloaded functions, searching for one
   // whose type matches exactly.
-  // FIXME: We still need to cope with duplicates, partial ordering, etc.
+  llvm::SmallPtrSet<FunctionDecl *, 4> Matches;
+  
+  bool FoundNonTemplateFunction = false;
   for (OverloadIterator FunEnd; Fun != FunEnd; ++Fun) {
     // C++ [over.over]p3:
     //   Non-member functions and static member functions match
@@ -3753,12 +3755,21 @@
 
     if (FunctionTemplateDecl *FunctionTemplate 
           = dyn_cast<FunctionTemplateDecl>(*Fun)) {
-      // C++ [temp.deduct.funcaddr]p1:
-      //   Template arguments can be deduced from the type specified when 
-      //   taking the address of an overloaded function (13.4). The function 
-      //   template’s function type and the specified type are used as the 
-      //   types of P and A, and the deduction is done as described in 
-      //   14.8.2.4.
+      if (CXXMethodDecl *Method 
+            = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
+        // Skip non-static function templates when converting to pointer, and 
+        // static when converting to member pointer.
+        if (Method->isStatic() == IsMember)
+          continue;
+      } else if (IsMember)
+        continue;
+      
+      // C++ [over.over]p2:
+      //   If the name is a function template, template argument deduction is 
+      //   done (14.8.2.2), and if the argument deduction succeeds, the 
+      //   resulting template argument list is used to generate a single 
+      //   function template specialization, which is added to the set of 
+      //   overloaded functions considered.
       FunctionDecl *Specialization = 0;
       TemplateDeductionInfo Info(Context);
       if (TemplateDeductionResult Result
@@ -3770,7 +3781,8 @@
       } else {
         assert(FunctionType 
                  == Context.getCanonicalType(Specialization->getType()));
-        return Specialization;
+        Matches.insert(
+                cast<FunctionDecl>(Context.getCanonicalDecl(Specialization)));
       }
     }
     
@@ -3779,15 +3791,54 @@
       // when converting to member pointer.
       if (Method->isStatic() == IsMember)
         continue;
-    } else if (IsMember) // FIXME: member templates
+    } else if (IsMember)
       continue;
 
     if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Fun)) {
-      if (FunctionType == Context.getCanonicalType(FunDecl->getType()))
-        return FunDecl;
+      if (FunctionType == Context.getCanonicalType(FunDecl->getType())) {
+        Matches.insert(cast<FunctionDecl>(Context.getCanonicalDecl(*Fun)));
+        FoundNonTemplateFunction = true;
+      }
     } 
   }
 
+  // If there were 0 or 1 matches, we're done.
+  if (Matches.empty())
+    return 0;
+  else if (Matches.size() == 1)
+    return *Matches.begin();
+
+  // C++ [over.over]p4:
+  //   If more than one function is selected, [...]
+  llvm::SmallVector<FunctionDecl *, 4> RemainingMatches;
+  if (FoundNonTemplateFunction) {
+    // [...] any function template specializations in the set are eliminated 
+    // if the set also contains a non-template function, [...]
+    for (llvm::SmallPtrSet<FunctionDecl *, 4>::iterator M = Matches.begin(),
+                                                     MEnd = Matches.end();
+         M != MEnd; ++M)
+      if ((*M)->getPrimaryTemplate() == 0)
+        RemainingMatches.push_back(*M);
+  } else {
+    // [...] and any given function template specialization F1 is eliminated 
+    // if the set contains a second function template specialization whose 
+    // function template is more specialized than the function template of F1 
+    // according to the partial ordering rules of 14.5.5.2.
+    // FIXME: Implement this!
+    RemainingMatches.append(Matches.begin(), Matches.end());
+  }
+  
+  // [...] After such eliminations, if any, there shall remain exactly one 
+  // selected function.
+  if (RemainingMatches.size() == 1)
+    return RemainingMatches.front();
+  
+  // FIXME: We should probably return the same thing that BestViableFunction
+  // returns (even if we issue the diagnostics here).
+  Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
+    << RemainingMatches[0]->getDeclName();
+  for (unsigned I = 0, N = RemainingMatches.size(); I != N; ++I)
+    Diag(RemainingMatches[I]->getLocation(), diag::err_ovl_candidate);
   return 0;
 }
 

Added: cfe/trunk/test/CXX/over/over.over/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.over/p4.cpp?rev=75069&view=auto

==============================================================================
--- cfe/trunk/test/CXX/over/over.over/p4.cpp (added)
+++ cfe/trunk/test/CXX/over/over.over/p4.cpp Wed Jul  8 18:33:52 2009
@@ -0,0 +1,23 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> T f0(T);
+int f0(int); // expected-note{{candidate function}}
+
+void test_f0() {
+  int (*fp0)(int) = f0;
+  int (*fp1)(int) = &f0;
+  float (*fp2)(float) = &f0;
+}
+
+namespace N {
+  int f0(int); // expected-note{{candidate function}}
+}
+
+int f0(int);
+
+void test_f0_2() {
+  using namespace N;
+  int (*fp0)(int) = f0; // expected-error{{ambiguous}} \ 
+                        // expected-error{{initializing}}
+  float (*fp1)(float) = f0;
+}

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=75069&r1=75068&r2=75069&view=diff

==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Wed Jul  8 18:33:52 2009
@@ -1689,12 +1689,10 @@
 <tr>
   <td>  13.4 [over.over]</td>
   <td class="na" align="center">N/A</td>  
-  <td class="medium" align="center"></td>
-  <td class="basic" align="center"></td>
+  <td class="advanced" align="center"></td>
+  <td class="advanced" align="center"></td>
   <td class="na" align="center">N/A</td>  
-  <td>Error messages need some work. Without templates or using
-  declarations, we don't have any ambiguities, so the semantic
-  analysis is incomplete.</td>
+  <td>No partial ordering of function templates.</td>
 </tr>
 <tr>
   <td>  13.5 [over.oper]</td>
@@ -2102,10 +2100,10 @@
 </tr>
 <tr>
   <td>      14.8.2.2 [temp.deduct.funcaddr]</td>
-  <td class="broken" align="center"></td>
-  <td class="broken" align="center"></td>
-  <td class="broken" align="center"></td>
-  <td class="broken" align="center"></td>
+  <td class="na" align="center">N/A</td>
+  <td class="advanced" align="center"></td>
+  <td class="advanced" align="center"></td>
+  <td class="na" align="center">N/A</td>
   <td></td>
 </tr>
 <tr>





More information about the cfe-commits mailing list