From: ppalka Date: Fri, 12 Feb 2016 01:11:52 +0000 (+0000) Subject: Fix PR c++/69098 (bogus errors with static data member template) X-Git-Tag: upstream/6.1~1120 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9ddb20d61efab00d2e84255959e283aefd31f5e0;p=platform%2Fupstream%2Flinaro-gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9e03f18..3f2177f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2016-02-12 Patrick Palka + + 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 * error.c: Spelling fixes - behaviour -> behavior and diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6780172..a55dc10 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 1ffb135..acedab8 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 8d05fea..5fcd863 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-02-12 Patrick Palka + + PR c++/69098 + * g++.dg/cpp1y/69098.C: New test. + * g++.dg/cpp1y/69098-2.C: New test. + 2016-02-12 Jakub Jelinek * 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 0000000..2e968bb --- /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 + static void *pf; +}; + +template +bool foo1 () { + return A::pf; +} + +template +bool foo2 () { + return B::template pf; +} + +template +bool foo3 () { + return &A::pf; +} + +template +bool foo4 () { + return &B::template pf; +} + + +void bar () { + foo1(); + foo2(); + foo3(); + foo4(); +} + diff --git a/gcc/testsuite/g++.dg/cpp1y/69098.C b/gcc/testsuite/g++.dg/cpp1y/69098.C new file mode 100644 index 0000000..afc4294 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/69098.C @@ -0,0 +1,43 @@ +// PR c++/69098 +// { dg-do compile { target c++14 } } + +template struct SpecPerType; + +class Specializer +{ +public: + template void MbrFnTempl() //Must be a template + { + } + template struct InnerClassTempl + { //Had to be a template whenever I tested for it + static void InnerMemberFn(); + }; + + void Trigger() + { + InnerClassTempl<0u>::InnerMemberFn(); + } +}; + +template<> struct SpecPerType +{ + using FnType = void (Specializer::*)(); + template static constexpr FnType SpecMbrFnPtr = + &Specializer::template MbrFnTempl

; +}; + +template constexpr SpecPerType::FnType + SpecPerType::SpecMbrFnPtr; //Just a formalism + +template void Specializer::InnerClassTempl::InnerMemberFn() +{ + using Spec = SpecPerType; + typename Spec::FnType ErrorSite = Spec::template SpecMbrFnPtr; + //ErrorSite would get called next in the original code + //(this should result in a call to MbrFnTempl) +} + +int main() +{ +}