diff options
author | ppalka <ppalka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-12 01:11:52 +0000 |
---|---|---|
committer | ppalka <ppalka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-12 01:11:52 +0000 |
commit | 9ddb20d61efab00d2e84255959e283aefd31f5e0 (patch) | |
tree | 67075b34dd1ed4122cb9745ae312a3b6d3897034 | |
parent | 24f65e370db5e2266b9db55c41824d73a877e29b (diff) | |
download | gcc-9ddb20d61efab00d2e84255959e283aefd31f5e0.tar.gz |
Fix PR c++/69098 (bogus errors with static data member template)
gcc/cp/ChangeLog:
PR c++/69098
* pt.c (lookup_and_finish_template_variable): New function,
extracted from ...
(tsubst_copy_and_build) [TEMPLATE_ID_EXPR]: ... here.
(tsubst_qualified_id): Consider that EXPR might be a variable
template.
* typeck.c (check_template_keyword): Don't emit an error
if DECL is a variable template.
gcc/testsuite/ChangeLog:
PR c++/69098
* g++.dg/cpp1y/69098.C: New test.
* g++.dg/cpp1y/69098-2.C: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233365 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/pt.c | 36 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/69098-2.C | 37 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/69098.C | 43 |
6 files changed, 132 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9e03f188449..3f2177f87ec 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2016-02-12 Patrick Palka <ppalka@gcc.gnu.org> + + PR c++/69098 + * pt.c (lookup_and_finish_template_variable): New function, + extracted from ... + (tsubst_copy_and_build) [TEMPLATE_ID_EXPR]: ... here. Use it. + (tsubst_qualified_id): Consider that EXPR might be a variable + template. + * typeck.c (check_template_keyword): Don't emit an error + if DECL is a variable template. + 2016-02-12 Jakub Jelinek <jakub@redhat.com> * error.c: Spelling fixes - behaviour -> behavior and diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 678017223e0..a55dc10fdfc 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8696,6 +8696,24 @@ finish_template_variable (tree var, tsubst_flags_t complain) return instantiate_template (templ, arglist, complain); } + +/* Construct a TEMPLATE_ID_EXPR for the given variable template TEMPL having + TARGS template args, and instantiate it if it's not dependent. */ + +static tree +lookup_and_finish_template_variable (tree templ, tree targs, + tsubst_flags_t complain) +{ + templ = lookup_template_variable (templ, targs); + if (!any_dependent_template_arguments_p (targs)) + { + templ = finish_template_variable (templ, complain); + mark_used (templ); + } + + return convert_from_reference (templ); +} + struct pair_fn_data { @@ -13732,7 +13750,13 @@ tsubst_qualified_id (tree qualified_id, tree args, } if (is_template) - expr = lookup_template_function (expr, template_args); + { + if (variable_template_p (expr)) + expr = lookup_and_finish_template_variable (expr, template_args, + complain); + else + expr = lookup_template_function (expr, template_args); + } if (expr == error_mark_node && complain & tf_error) qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1), @@ -15912,15 +15936,7 @@ tsubst_copy_and_build (tree t, return error_mark_node; if (variable_template_p (templ)) - { - templ = lookup_template_variable (templ, targs); - if (!any_dependent_template_arguments_p (targs)) - { - templ = finish_template_variable (templ, complain); - mark_used (templ); - } - RETURN (convert_from_reference (templ)); - } + RETURN (lookup_and_finish_template_variable (templ, targs, complain)); if (TREE_CODE (templ) == COMPONENT_REF) { diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 1ffb1355f76..acedab80d5c 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2601,7 +2601,15 @@ check_template_keyword (tree decl) if (TREE_CODE (decl) != TEMPLATE_DECL && TREE_CODE (decl) != TEMPLATE_ID_EXPR) { - if (!is_overloaded_fn (decl)) + if (VAR_P (decl)) + { + if (DECL_USE_TEMPLATE (decl) + && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))) + ; + else + permerror (input_location, "%qD is not a template", decl); + } + else if (!is_overloaded_fn (decl)) permerror (input_location, "%qD is not a template", decl); else { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8d05fea69de..5fcd8639941 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-02-12 Patrick Palka <ppalka@gcc.gnu.org> + + PR c++/69098 + * g++.dg/cpp1y/69098.C: New test. + * g++.dg/cpp1y/69098-2.C: New test. + 2016-02-12 Jakub Jelinek <jakub@redhat.com> * objc.dg/gnu-api-2-method.m: Spelling fixes - behaviour -> behavior diff --git a/gcc/testsuite/g++.dg/cpp1y/69098-2.C b/gcc/testsuite/g++.dg/cpp1y/69098-2.C new file mode 100644 index 00000000000..2e968bb5c9e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/69098-2.C @@ -0,0 +1,37 @@ +// PR c++/69098 +// { dg-do compile { target c++14 } } + +struct A +{ + template <int> + static void *pf; +}; + +template <typename B> +bool foo1 () { + return A::pf<false>; +} + +template <typename B> +bool foo2 () { + return B::template pf<false>; +} + +template <typename B> +bool foo3 () { + return &A::pf<false>; +} + +template <typename B> +bool foo4 () { + return &B::template pf<false>; +} + + +void bar () { + foo1<A>(); + foo2<A>(); + foo3<A>(); + foo4<A>(); +} + diff --git a/gcc/testsuite/g++.dg/cpp1y/69098.C b/gcc/testsuite/g++.dg/cpp1y/69098.C new file mode 100644 index 00000000000..afc4294c4df --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/69098.C @@ -0,0 +1,43 @@ +// PR c++/69098 +// { dg-do compile { target c++14 } } + +template<typename> struct SpecPerType; + +class Specializer +{ +public: + template<bool> void MbrFnTempl() //Must be a template + { + } + template<unsigned> struct InnerClassTempl + { //Had to be a template whenever I tested for it + static void InnerMemberFn(); + }; + + void Trigger() + { + InnerClassTempl<0u>::InnerMemberFn(); + } +}; + +template<> struct SpecPerType<Specializer> +{ + using FnType = void (Specializer::*)(); + template<bool P> static constexpr FnType SpecMbrFnPtr = + &Specializer::template MbrFnTempl<P>; +}; + +template<bool> constexpr SpecPerType<Specializer>::FnType + SpecPerType<Specializer>::SpecMbrFnPtr; //Just a formalism + +template<unsigned X> void Specializer::InnerClassTempl<X>::InnerMemberFn() +{ + using Spec = SpecPerType<Specializer>; + typename Spec::FnType ErrorSite = Spec::template SpecMbrFnPtr<true>; + //ErrorSite would get called next in the original code + //(this should result in a call to MbrFnTempl) +} + +int main() +{ +} |