[cfe-commits] r124856 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.param/p9-0x.cpp

Douglas Gregor dgregor at apple.com
Thu Feb 3 20:20:44 PST 2011


Author: dgregor
Date: Thu Feb  3 22:20:44 2011
New Revision: 124856

URL: http://llvm.org/viewvc/llvm-project?rev=124856&view=rev
Log:
Tighten up the semantics of default template arguments, per C++0x
[temp.param]p9 and C++ DR226. Fixes PR8747.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/temp/temp.param/p9-0x.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=124856&r1=124855&r2=124856&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Feb  3 22:20:44 2011
@@ -2914,7 +2914,8 @@
     TPC_ClassTemplate,
     TPC_FunctionTemplate,
     TPC_ClassTemplateMember,
-    TPC_FriendFunctionTemplate
+    TPC_FriendFunctionTemplate,
+    TPC_FriendFunctionTemplateDefinition
   };
 
   bool CheckTemplateParameterList(TemplateParameterList *NewParams,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=124856&r1=124855&r2=124856&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Feb  3 22:20:44 2011
@@ -3967,8 +3967,14 @@
       FunctionTemplateDecl *PrevTemplate = FunctionTemplate->getPreviousDeclaration();
       CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(),
                                  PrevTemplate? PrevTemplate->getTemplateParameters() : 0,
-                                 D.getDeclSpec().isFriendSpecified()? TPC_FriendFunctionTemplate
-                                                  : TPC_FunctionTemplate);
+                            D.getDeclSpec().isFriendSpecified()
+                              ? (IsFunctionDefinition 
+                                   ? TPC_FriendFunctionTemplateDefinition
+                                   : TPC_FriendFunctionTemplate)
+                              : (D.getCXXScopeSpec().isSet() && 
+                                 DC && DC->isRecord())
+                                  ? TPC_ClassTemplateMember
+                                  : TPC_FunctionTemplate);
     }
 
     if (NewFD->isInvalidDecl()) {

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=124856&r1=124855&r2=124856&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Feb  3 22:20:44 2011
@@ -946,7 +946,10 @@
   // template declaration.
   if (CheckTemplateParameterList(TemplateParams,
             PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0,
-                                 TPC_ClassTemplate))
+                                 (SS.isSet() && SemanticContext &&
+                                  SemanticContext->isRecord())
+                                   ? TPC_ClassTemplateMember
+                                   : TPC_ClassTemplate))
     Invalid = true;
 
   if (SS.isSet()) {
@@ -1045,11 +1048,15 @@
     return false;
 
   case Sema::TPC_FunctionTemplate:
+  case Sema::TPC_FriendFunctionTemplateDefinition:
     // C++ [temp.param]p9:
     //   A default template-argument shall not be specified in a
     //   function template declaration or a function template
     //   definition [...]
-    // (This sentence is not in C++0x, per DR226).
+    //   If a friend function template declaration specifies a default 
+    //   template-argument, that declaration shall be a definition and shall be
+    //   the only declaration of the function template in the translation unit.
+    // (C++98/03 doesn't have this wording; see DR226).
     if (!S.getLangOptions().CPlusPlus0x)
       S.Diag(ParamLoc,
              diag::ext_template_parameter_default_in_function_template)

Modified: cfe/trunk/test/CXX/temp/temp.param/p9-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.param/p9-0x.cpp?rev=124856&r1=124855&r2=124856&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.param/p9-0x.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.param/p9-0x.cpp Thu Feb  3 22:20:44 2011
@@ -12,3 +12,41 @@
 
 template<template<class> class ...Templates = vector> // expected-error{{template parameter pack cannot have a default argument}}
 struct X2; 
+
+struct X3 {
+  template<typename T = int> // expected-error{{default template argument not permitted on a friend template}}
+  friend void f0(X3);
+
+  template<typename T = int>
+  friend void f1(X3) {
+  }
+};
+
+namespace PR8747 {
+  // Testcase 1
+  struct A0 { template<typename U> struct B; }; 
+  template<typename U = int> struct A0::B { }; // expected-error{{cannot add a default template argument to the definition of a member of a class template}}
+  
+  // Testcase 2
+  template<typename T> struct A1 { template<typename U> struct B; }; 
+  template<typename T> template<typename U = int> struct A1<T>::B { }; // expected-error{{cannot add a default template argument to the definition of a member of a class template}}
+
+  // Testcase 3
+  template<typename T>
+  struct X2 {
+    void f0();
+    template<typename U> void f1();
+  };
+  
+  template<typename T = int> void X2<T>::f0() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}} 
+  template<typename T> template<typename U = int> void X2<T>::f1() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}}
+
+  namespace Inner {
+    template<typename T> struct X3;
+    template<typename T> void f2();
+  }
+
+  // Okay; not class members.
+  template<typename T = int> struct Inner::X3 { };
+  template<typename T = int> void Inner::f2() {}
+}





More information about the cfe-commits mailing list