]> granicus.if.org Git - clang/commitdiff
Fix overload resolution when calling a member template or taking the
authorDouglas Gregor <dgregor@apple.com>
Sat, 24 Oct 2009 04:59:53 +0000 (04:59 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 24 Oct 2009 04:59:53 +0000 (04:59 +0000)
address of a member template when explicit template arguments are
provided.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84991 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Expr.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaOverload.cpp
test/SemaTemplate/member-template-access-expr.cpp

index 47df95dc71beecba51ea8ebb5a90c41f634c29ee..ad9c9cbe1070329d1bc978746c758c3b3e584a2f 100644 (file)
@@ -1126,6 +1126,18 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
     return LV_Valid;
   }
 
+  case TemplateIdRefExprClass: {
+    const TemplateIdRefExpr *TID = cast<TemplateIdRefExpr>(this);
+    TemplateName Template = TID->getTemplateName();
+    NamedDecl *ND = Template.getAsTemplateDecl();
+    if (!ND)
+      ND = Template.getAsOverloadedFunctionDecl();
+    if (ND && DeclCanBeLvalue(ND, Ctx))
+      return LV_Valid;
+    
+    break;
+  } 
+    
   default:
     break;
   }
index 6f26ea1eeef92554bde94cd6138b6b8f70a321d9..3aac415c04cd3fc101c17cd2709e52e37b5ce2a1 100644 (file)
@@ -2337,6 +2337,7 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D,
       if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)))
         Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
       
+      // FIXME: Do we have to know if there are explicit template arguments?
       if (Method && !Method->isStatic()) {
         Ctx = Method->getParent();
         if (isa<CXXMethodDecl>(D) && !FunTmpl)
index 7ed79f307337f36f500e45ef5bd3628d6204a32a..fbb50aea872e67c9a46c0a2a538a34ad7c766897 100644 (file)
@@ -4287,10 +4287,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
   if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) {
     Ovl = dyn_cast<OverloadedFunctionDecl>(DR->getDecl());
     FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl());
+    HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList();
+    ExplicitTemplateArgs = DR->getTemplateArgs();
+    NumExplicitTemplateArgs = DR->getNumTemplateArgs();
   } else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) {
     Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());
     FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());
-    // FIXME: Explicit template arguments
+    HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList();
+    ExplicitTemplateArgs = ME->getTemplateArgs();
+    NumExplicitTemplateArgs = ME->getNumTemplateArgs();
   } else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) {
     TemplateName Name = TIRE->getTemplateName();
     Ovl = Name.getAsOverloadedFunctionDecl();
@@ -4367,6 +4372,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
       // when converting to member pointer.
       if (Method->isStatic() == IsMember)
         continue;
+      
+      // If we have explicit template arguments, skip non-templates.
+      if (HasExplicitTemplateArgs)
+        continue;
     } else if (IsMember)
       continue;
 
@@ -4967,10 +4976,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
 
     for (OverloadIterator Func(MemExpr->getMemberDecl()), FuncEnd;
          Func != FuncEnd; ++Func) {
-      if ((Method = dyn_cast<CXXMethodDecl>(*Func)))
+      if ((Method = dyn_cast<CXXMethodDecl>(*Func))) {
+        // If explicit template arguments were provided, we can't call a
+        // non-template member function.
+        if (MemExpr->hasExplicitTemplateArgumentList())
+          continue;
+        
         AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet,
                            /*SuppressUserConversions=*/false);
-      else
+      else
         AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
                                    MemExpr->hasExplicitTemplateArgumentList(),
                                    MemExpr->getTemplateArgs(),
index 0f9f21f339d1cd89cfd7d3184be74fdab653a25f..feef7926fb76b0105cbe39c1008a3c2efaf157d0 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: clang-cc -fsyntax-only -verify %s
-
 template<typename U, typename T>
 U f0(T t) {
   return t.template get<U>();
@@ -50,3 +49,29 @@ B<T>::destroy()
 void do_destroy_B(B<int> b) {
   b.destroy();
 }
+
+struct X1 {
+  int* f1(int);
+  template<typename T> float* f1(T);
+  
+  static int* f2(int);
+  template<typename T> static float* f2(T);
+};
+
+void test_X1(X1 x1) {
+  float *fp1 = x1.f1<>(17);
+  float *fp2 = x1.f1<int>(3.14);
+  int *ip1 = x1.f1(17);
+  float *ip2 = x1.f1(3.14);
+  
+  float* (X1::*mf1)(int) = &X1::f1;
+  float* (X1::*mf2)(int) = &X1::f1<>;
+  float* (X1::*mf3)(float) = &X1::f1<float>;
+  
+  float* (*fp3)(int) = &X1::f2;
+  float* (*fp4)(int) = &X1::f2<>;
+  float* (*fp5)(float) = &X1::f2<float>;  
+  float* (*fp6)(int) = X1::f2;
+  float* (*fp7)(int) = X1::f2<>;
+  float* (*fp8)(float) = X1::f2<float>;  
+}