OSDN Git Service

PR c++/50372
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 11 Nov 2011 04:29:04 +0000 (04:29 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 11 Nov 2011 04:29:04 +0000 (04:29 +0000)
* pt.c (convert_nontype_argument_function): Allow decls with
internal linkage in C++11.
(convert_nontype_argument): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181280 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/visibility/anon8.C
gcc/testsuite/g++.dg/parse/template21.C
gcc/testsuite/g++.dg/template/linkage1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/linkage4.C

index 11fa21d..9568030 100644 (file)
@@ -1,5 +1,10 @@
 2011-11-10  Jason Merrill  <jason@redhat.com>
 
+       PR c++/50372
+       * pt.c (convert_nontype_argument_function): Allow decls with
+       internal linkage in C++11.
+       (convert_nontype_argument): Likewise.
+
        PR c++/50973
        * decl2.c (mark_used): Defer synthesis of virtual functions.
        * method.c (use_thunk): Make sure the target function has
index da5497e..9738026 100644 (file)
@@ -5324,6 +5324,7 @@ convert_nontype_argument_function (tree type, tree expr)
 {
   tree fns = expr;
   tree fn, fn_no_ptr;
+  linkage_kind linkage;
 
   fn = instantiate_type (type, fns, tf_none);
   if (fn == error_mark_node)
@@ -5340,12 +5341,19 @@ convert_nontype_argument_function (tree type, tree expr)
      A template-argument for a non-type, non-template template-parameter
      shall be one of:
      [...]
-     -- the address of an object or function with external linkage.  */
-  if (!DECL_EXTERNAL_LINKAGE_P (fn_no_ptr))
+     -- the address of an object or function with external [C++11: or
+        internal] linkage.  */
+  linkage = decl_linkage (fn_no_ptr);
+  if (cxx_dialect >= cxx0x ? linkage == lk_none : linkage != lk_external)
     {
-      error ("%qE is not a valid template argument for type %qT "
-            "because function %qD has not external linkage",
-            expr, type, fn_no_ptr);
+      if (cxx_dialect >= cxx0x)
+       error ("%qE is not a valid template argument for type %qT "
+              "because %qD has no linkage",
+              expr, type, fn_no_ptr);
+      else
+       error ("%qE is not a valid template argument for type %qT "
+              "because %qD does not have external linkage",
+              expr, type, fn_no_ptr);
       return NULL_TREE;
     }
 
@@ -5838,13 +5846,20 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
                     expr, type, decl);
              return NULL_TREE;
            }
-         else if (!DECL_EXTERNAL_LINKAGE_P (decl))
+         else if (cxx_dialect < cxx0x && !DECL_EXTERNAL_LINKAGE_P (decl))
            {
              error ("%qE is not a valid template argument of type %qT "
                     "because %qD does not have external linkage",
                     expr, type, decl);
              return NULL_TREE;
            }
+         else if (cxx_dialect >= cxx0x && decl_linkage (decl) == lk_none)
+           {
+             error ("%qE is not a valid template argument of type %qT "
+                    "because %qD has no linkage",
+                    expr, type, decl);
+             return NULL_TREE;
+           }
        }
 
       expr = decay_conversion (expr);
index 85f77a9..0c9d088 100644 (file)
@@ -1,5 +1,9 @@
 2011-11-10  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/template/linkage1.C: New.
+       * g++.dg/ext/visibility/anon8.C: Adjust for C++11.
+       * g++.old-deja/g++.other/linkage4.C: Likewise.
+
        PR c++/50973
        * g++.dg/cpp0x/defaulted33.C: New.
 
index 8ef8d68..5e58b55 100644 (file)
@@ -26,10 +26,8 @@ int main ()
     static void fn2 () {}
   };
   call<&B1::fn1> ();
-  call<&B2::fn2> ();   // { dg-error "not external linkage|no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 29 }
+  call<&B2::fn2> ();   // { dg-error "linkage|no matching" }
   call<&fn3> ();
   call<&B1::fn4> ();
-  call<&fn5> ();       // { dg-error "not external linkage|no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 33 }
+  call<&fn5> ();       // { dg-error "linkage|no matching" "" { target c++98 } }
 }
index e1ac769..963d269 100644 (file)
@@ -2,4 +2,4 @@
 
 template <const int*> class Helper { };
 const int foo = 0;
-typedef Helper<&foo> HelperType; // { dg-error "linkage|type" }
+typedef Helper<&foo> HelperType; // { dg-error "linkage|type" "" { target c++98 } }
diff --git a/gcc/testsuite/g++.dg/template/linkage1.C b/gcc/testsuite/g++.dg/template/linkage1.C
new file mode 100644 (file)
index 0000000..02aa967
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/50372
+// Test that a template instantiation has the same linkage as its argument.
+// { dg-final { scan-assembler "(weak|glob)\[^\n\]*_Z3fooIXadL_Z13external_funcvEEEvv" } }
+// { dg-final { scan-assembler-not "(weak|glob)\[^\n\]*_Z3fooIXadL_ZL11static_funcvEEEvv" } }
+
+template<void (*fptr)(void)>
+void foo() { }
+
+static void static_func() {}
+void external_func() { }
+
+void test()
+{
+#if __cplusplus > 199711L
+  foo<&static_func>();
+#endif
+  foo<&external_func>();
+}
index 7531f45..450733f 100644 (file)
@@ -8,4 +8,4 @@ void f () {}
 
 // Check that the strlen declaration here is given internal linkage by
 // using it as a non-type template argument, and expecting an error.
-template void f<strlen>(); // { dg-error "" } no matching template
+template void f<strlen>(); // { dg-error "" "" { target c++98 } } no matching template