summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorppalka <ppalka@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-12 01:11:52 +0000
committerppalka <ppalka@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-12 01:11:52 +0000
commit9ddb20d61efab00d2e84255959e283aefd31f5e0 (patch)
tree67075b34dd1ed4122cb9745ae312a3b6d3897034
parent24f65e370db5e2266b9db55c41824d73a877e29b (diff)
downloadgcc-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/ChangeLog11
-rw-r--r--gcc/cp/pt.c36
-rw-r--r--gcc/cp/typeck.c10
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/69098-2.C37
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/69098.C43
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()
+{
+}