Commit 38d795d2 by Patrick Palka

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.

From-SVN: r233365
parent 3ac29b0f
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
......
......@@ -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)
{
......
......@@ -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
{
......
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
......
// 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>();
}
// 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()
{
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment