summaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5ce6e8af87f..4a3942715b8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2208,6 +2208,66 @@ copy_default_args_to_explicit_spec (tree decl)
TREE_TYPE (decl) = new_type;
}
+/* Return the number of template headers we expect to see for a definition
+ or specialization of CTYPE or one of its non-template members. */
+
+int
+num_template_headers_for_class (tree ctype)
+{
+ int template_count = 0;
+ tree t = ctype;
+ while (t != NULL_TREE && CLASS_TYPE_P (t))
+ {
+ /* You're supposed to have one `template <...>' for every
+ template class, but you don't need one for a full
+ specialization. For example:
+
+ template <class T> struct S{};
+ template <> struct S<int> { void f(); };
+ void S<int>::f () {}
+
+ is correct; there shouldn't be a `template <>' for the
+ definition of `S<int>::f'. */
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
+ && !any_dependent_template_arguments_p (CLASSTYPE_TI_ARGS (t)))
+ /* T is an explicit (not partial) specialization. All
+ containing classes must therefore also be explicitly
+ specialized. */
+ break;
+ if ((CLASSTYPE_USE_TEMPLATE (t) || CLASSTYPE_IS_TEMPLATE (t))
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
+ template_count += 1;
+
+ t = TYPE_MAIN_DECL (t);
+ t = DECL_CONTEXT (t);
+ }
+
+ return template_count;
+}
+
+/* Do a simple sanity check on the template headers that precede the
+ variable declaration DECL. */
+
+void
+check_template_variable (tree decl)
+{
+ tree ctx = CP_DECL_CONTEXT (decl);
+ int wanted = num_template_headers_for_class (ctx);
+ if (!TYPE_P (ctx) || !CLASSTYPE_TEMPLATE_INFO (ctx))
+ permerror (DECL_SOURCE_LOCATION (decl),
+ "%qD is not a static data member of a class template", decl);
+ else if (template_header_count > wanted)
+ {
+ pedwarn (DECL_SOURCE_LOCATION (decl), 0,
+ "too many template headers for %D (should be %d)",
+ decl, wanted);
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
+ inform (DECL_SOURCE_LOCATION (decl),
+ "members of an explicitly specialized class are defined "
+ "without a template header");
+ }
+}
+
/* Check to see if the function just declared, as indicated in
DECLARATOR, and in DECL, is a specialization of a function
template. We may also discover that the declaration is an explicit