aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c31
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/cp/pt.c13
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr60626.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/var-templ8.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/var-templ9.C15
7 files changed, 75 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 18a281b..d9bf905 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2014-08-25 Jason Merrill <jason@redhat.com>
+
+ * decl.c (start_decl): Look through member variable template.
+ * pt.c (tsubst_decl) [VAR_DECL]: Handle member variable templates.
+ * decl2.c (grokfield): Set DECL_CONTEXT earlier on
+ variables.
+
2014-08-25 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/34938
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e83192a..80696dd 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4650,13 +4650,37 @@ start_decl (const cp_declarator *declarator,
if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
{
+ bool this_tmpl = (processing_template_decl
+ > template_class_depth (context));
if (VAR_P (decl))
{
tree field = lookup_field (context, DECL_NAME (decl), 0, false);
- if (field == NULL_TREE || !VAR_P (field))
- error ("%q#D is not a static member of %q#T", decl, context);
+ if (field == NULL_TREE
+ || !(VAR_P (field) || variable_template_p (field)))
+ error ("%q+#D is not a static data member of %q#T", decl, context);
else
{
+ if (variable_template_p (field))
+ {
+ if (!this_tmpl)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "non-member-template declaration of %qD", decl);
+ inform (DECL_SOURCE_LOCATION (field), "does not match "
+ "member template declaration here");
+ return error_mark_node;
+ }
+ field = DECL_TEMPLATE_RESULT (field);
+ }
+ else if (this_tmpl)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "member template declaration of %qD", decl);
+ inform (DECL_SOURCE_LOCATION (field), "does not match "
+ "non-member-template declaration here");
+ return error_mark_node;
+ }
+
if (DECL_CONTEXT (field) != context)
{
if (!same_type_p (DECL_CONTEXT (field), context))
@@ -4683,8 +4707,7 @@ start_decl (const cp_declarator *declarator,
else
{
tree field = check_classfn (context, decl,
- (processing_template_decl
- > template_class_depth (context))
+ this_tmpl
? current_template_parms
: NULL_TREE);
if (field && field != error_mark_node
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 74a10fb..5b1313e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -994,6 +994,10 @@ grokfield (const cp_declarator *declarator,
&& DECL_CONTEXT (value) != current_class_type)
return value;
+ /* Need to set this before push_template_decl. */
+ if (TREE_CODE (value) == VAR_DECL)
+ DECL_CONTEXT (value) = current_class_type;
+
if (processing_template_decl && VAR_OR_FUNCTION_DECL_P (value))
{
value = push_template_decl (value);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a40f9d2..3e6d777 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11127,13 +11127,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
same_type_p, because DECL_CONTEXT is always
canonical... */
if (ctx == DECL_CONTEXT (t)
- && (TREE_CODE (t) != TYPE_DECL
- /* ... unless T is a member template; in which
- case our caller can be willing to create a
- specialization of that template represented
- by T. */
- || !(DECL_TI_TEMPLATE (t)
- && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t)))))
+ /* ... unless T is a member template; in which
+ case our caller can be willing to create a
+ specialization of that template represented
+ by T. */
+ && !(DECL_TI_TEMPLATE (t)
+ && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
spec = t;
}
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60626.C b/gcc/testsuite/g++.dg/cpp1y/pr60626.C
index 686db73..3114644 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr60626.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr60626.C
@@ -4,4 +4,4 @@
struct A {};
-void (*A::p)(auto) = 0; // { dg-error "static member|template" }
+void (*A::p)(auto) = 0; // { dg-error "static data member|template" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ8.C b/gcc/testsuite/g++.dg/cpp1y/var-templ8.C
new file mode 100644
index 0000000..8e3d34a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ8.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++14 } }
+// { dg-final { scan-assembler "_ZN1X1xIiEE" } }
+
+struct X
+{
+ template <class T> static T x;
+};
+
+template <class T>
+T X::x = T();
+
+int main()
+{
+ int x = X::x<int>;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ9.C b/gcc/testsuite/g++.dg/cpp1y/var-templ9.C
new file mode 100644
index 0000000..2ffb007
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ9.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++14 } }
+
+struct X
+{
+ template <class T> static int x;
+};
+
+int X::x = 42; // { dg-error "template" }
+
+struct Y
+{
+ static int y;
+};
+
+template <class T> int Y::y = 42; // { dg-error "template" }