[cfe-commits] r74079 - in /cfe/trunk: lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp

Douglas Gregor dgregor at apple.com
Wed Jun 24 09:50:45 PDT 2009


Author: dgregor
Date: Wed Jun 24 11:50:40 2009
New Revision: 74079

URL: http://llvm.org/viewvc/llvm-project?rev=74079&view=rev
Log:
Implement matching of function templates, so that one can declare overloaded function templates. C++ [temp.over.link] paragraphs 4-8.


Added:
    cfe/trunk/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp
Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Jun 24 11:50:40 2009
@@ -301,6 +301,15 @@
     // This function overloads every function in the overload set.
     return true;
   } else if (FunctionDecl* Old = dyn_cast<FunctionDecl>(OldD)) {
+    FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
+    FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); 
+    
+    // C++ [temp.fct]p2:
+    //   A function template can be overloaded with other function templates
+    //   and with normal (non-template) functions.
+    if ((OldTemplate == 0) != (NewTemplate == 0))
+      return true;
+
     // Is the function New an overload of the function Old?
     QualType OldQType = Context.getCanonicalType(Old->getType());
     QualType NewQType = Context.getCanonicalType(New->getType());
@@ -315,8 +324,8 @@
         isa<FunctionNoProtoType>(NewQType.getTypePtr()))
       return false;
 
-    FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType.getTypePtr());
-    FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType.getTypePtr());
+    FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
+    FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
 
     // The signature of a function includes the types of its
     // parameters (C++ 1.3.10), which includes the presence or absence
@@ -328,6 +337,22 @@
                      NewType->arg_type_begin())))
       return true;
 
+    // C++ [temp.over.link]p4:
+    //   The signature of a function template consists of its function 
+    //   signature, its return type and its template parameter list. The names
+    //   of the template parameters are significant only for establishing the
+    //   relationship between the template parameters and the rest of the 
+    //   signature.
+    //
+    // We check the return type and template parameter lists for function
+    // templates first; the remaining checks follow.
+    if (NewTemplate &&
+        (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), 
+                                         OldTemplate->getTemplateParameters(), 
+                                         false, false, SourceLocation()) ||
+         OldType->getResultType() != NewType->getResultType()))
+      return true;
+    
     // If the function is a class member, its signature includes the
     // cv-qualifiers (if any) on the function itself.
     //

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jun 24 11:50:40 2009
@@ -1874,15 +1874,17 @@
          OldParmEnd = Old->end(), NewParm = New->begin();
        OldParm != OldParmEnd; ++OldParm, ++NewParm) {
     if ((*OldParm)->getKind() != (*NewParm)->getKind()) {
-      unsigned NextDiag = diag::err_template_param_different_kind;
-      if (TemplateArgLoc.isValid()) {
-        Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
-        NextDiag = diag::note_template_param_different_kind;
-      }
-      Diag((*NewParm)->getLocation(), NextDiag)
+      if (Complain) {
+        unsigned NextDiag = diag::err_template_param_different_kind;
+        if (TemplateArgLoc.isValid()) {
+          Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+          NextDiag = diag::note_template_param_different_kind;
+        }
+        Diag((*NewParm)->getLocation(), NextDiag)
         << IsTemplateTemplateParm;
-      Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
+        Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
         << IsTemplateTemplateParm;
+      }
       return false;
     }
 

Added: cfe/trunk/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp?rev=74079&view=auto

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp Wed Jun 24 11:50:40 2009
@@ -0,0 +1,27 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> void f0(T) { } // expected-note{{previous}}
+template<class U> void f0(U) { } // expected-error{{redefinition}}
+
+template<int I> void f0() { } // expected-note{{previous}}
+template<int> void f0() { } // expected-error{{redefinition}}
+
+typedef int INT;
+
+template<template<class T, T Value1, INT> class X> 
+  void f0() { } // expected-note{{previous}}
+template<template<typename T, T Value1, int> class> 
+  void f0() { } // expected-error{{redefinition}}
+
+template<typename T>
+struct MetaFun;
+
+template<typename T>
+  typename MetaFun<T*>::type f0(const T&) { } // expected-note{{previous}}
+template<class U>
+  typename MetaFun<U*>::type f0(const U&) { } // expected-error{{redefinition}}
+
+// FIXME: We need canonicalization of expressions for this to work
+// template<int> struct A { };
+// template<int I> void f0(A<I>) { } // Xpected-note{{previous}}
+// template<int J> void f0(A<J>) { } // Xpected-error{{redefinition}}
\ No newline at end of file

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

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp Wed Jun 24 11:50:40 2009
@@ -0,0 +1,13 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// All of these function templates are distinct.
+template<typename T> void f0(T) { }
+template<typename T, typename U> void f0(T) { }
+template<typename T, typename U> void f0(U) { }
+void f0();
+template<typename T> void f0(T*);
+void f0(int);
+template<int I> void f0();
+template<typename T> void f0();
+
+





More information about the cfe-commits mailing list