diff options
author | Jason Merrill <jason@redhat.com> | 2011-11-10 23:29:04 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-11-10 23:29:04 -0500 |
commit | 4774d267d36bad7261eb60d19502d4706b0d8f26 (patch) | |
tree | e60aadb9585cca2e203bbb68325d42160fb8bb4d | |
parent | 5e3929ed1b1b079f87d3bdc9342b9f05fa9cfd06 (diff) | |
download | gcc-4774d267d36bad7261eb60d19502d4706b0d8f26.zip gcc-4774d267d36bad7261eb60d19502d4706b0d8f26.tar.gz gcc-4774d267d36bad7261eb60d19502d4706b0d8f26.tar.bz2 |
re PR c++/50372 ([C++0x] pointers to static functions should be valid template parameters)
PR c++/50372
* pt.c (convert_nontype_argument_function): Allow decls with
internal linkage in C++11.
(convert_nontype_argument): Likewise.
From-SVN: r181280
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/visibility/anon8.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/template21.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/linkage1.C | 18 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/linkage4.C | 2 |
7 files changed, 52 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 11fa21d..9568030 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index da5497e..9738026 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 85f77a9..0c9d088 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon8.C b/gcc/testsuite/g++.dg/ext/visibility/anon8.C index 8ef8d68..5e58b55 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/anon8.C +++ b/gcc/testsuite/g++.dg/ext/visibility/anon8.C @@ -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 } } } diff --git a/gcc/testsuite/g++.dg/parse/template21.C b/gcc/testsuite/g++.dg/parse/template21.C index e1ac769..963d269 100644 --- a/gcc/testsuite/g++.dg/parse/template21.C +++ b/gcc/testsuite/g++.dg/parse/template21.C @@ -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 index 0000000..02aa967 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/linkage1.C @@ -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>(); +} diff --git a/gcc/testsuite/g++.old-deja/g++.other/linkage4.C b/gcc/testsuite/g++.old-deja/g++.other/linkage4.C index 7531f45..450733f 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/linkage4.C +++ b/gcc/testsuite/g++.old-deja/g++.other/linkage4.C @@ -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 |