re PR c++/26261 (Rejects template with const static data member used in return type)
authorJason Merrill <jason@redhat.com>
Thu, 18 Feb 2010 16:27:18 +0000 (11:27 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 18 Feb 2010 16:27:18 +0000 (11:27 -0500)
PR c++/26261
PR c++/43101
* pt.c (tsubst_qualified_id): Do normal lookup in non-dependent scope.
(maybe_update_decl_type): New fn.
* parser.c (cp_parser_init_declarator): Use it.

From-SVN: r156865

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/dependent-name6.C [new file with mode: 0644]

index 357b925390d1347fe939b076b70303bb08dd69a8..1fdeef498b3e0c0b3bcb1bf46d2265965f70d061 100644 (file)
@@ -1,5 +1,11 @@
 2010-02-18  Jason Merrill  <jason@redhat.com>
 
+       PR c++/26261
+       PR c++/43101
+       * pt.c (tsubst_qualified_id): Do normal lookup in non-dependent scope.
+       (maybe_update_decl_type): New fn.
+       * parser.c (cp_parser_init_declarator): Use it.
+
        PR c++/43109
        * semantics.c (begin_class_definition): Don't crash on unnamed ns.
 
index b5330a3ab8b6f9fedf954082e18c8a5eb1056453..8b5bb56d8d73ff198bd84a9ee8d387d2cc7b9bae 100644 (file)
@@ -4896,6 +4896,7 @@ extern tree process_template_parm         (tree, location_t, tree,
                                                 bool, bool);
 extern tree end_template_parm_list             (tree);
 extern void end_template_decl                  (void);
+extern tree maybe_update_decl_type             (tree, tree);
 extern bool check_default_tmpl_args             (tree, tree, int, int, int);
 extern tree push_template_decl                 (tree);
 extern tree push_template_decl_real            (tree, bool);
index 690f2c05eb0028c6c701da4697d960f08969d924..55d05174eee20bf8906f05fec6ac72acbaa7f12f 100644 (file)
@@ -13477,6 +13477,11 @@ cp_parser_init_declarator (cp_parser* parser,
      we compute it now.  */
   scope = get_scope_of_declarator (declarator);
 
+  /* Perform any lookups in the declared type which were thought to be
+     dependent, but are not in the scope of the declarator.  */
+  decl_specifiers->type
+    = maybe_update_decl_type (decl_specifiers->type, scope);
+
   /* If we're allowing GNU extensions, look for an asm-specification
      and attributes.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
index 0165a7d69fb6836e40e1a8782f5cfbf55fa1cfef..9e159a2a41488a0023d21e23b6a37cece2cf58e4 100644 (file)
@@ -3672,6 +3672,55 @@ current_template_args (void)
   return args;
 }
 
+/* Update the declared TYPE by doing any lookups which were thought to be
+   dependent, but are not now that we know the SCOPE of the declarator.  */
+
+tree
+maybe_update_decl_type (tree orig_type, tree scope)
+{
+  tree type = orig_type;
+
+  if (type == NULL_TREE)
+    return type;
+
+  if (TREE_CODE (orig_type) == TYPE_DECL)
+    type = TREE_TYPE (type);
+
+  if (scope && TYPE_P (scope) && dependent_type_p (scope)
+      && dependent_type_p (type)
+      /* Don't bother building up the args in this case.  */
+      && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
+    {
+      /* tsubst in the args corresponding to the template parameters,
+        including auto if present.  Most things will be unchanged, but
+        make_typename_type and tsubst_qualified_id will resolve
+        TYPENAME_TYPEs and SCOPE_REFs that were previously dependent.  */
+      tree args = current_template_args ();
+      tree auto_node = type_uses_auto (type);
+      if (auto_node)
+       {
+         tree auto_vec = make_tree_vec (1);
+         TREE_VEC_ELT (auto_vec, 0) = auto_node;
+         args = add_to_template_args (args, auto_vec);
+       }
+      push_scope (scope);
+      type = tsubst (type, args, tf_warning_or_error, NULL_TREE);
+      pop_scope (scope);
+    }
+
+  if (type == error_mark_node)
+    return orig_type;
+
+  if (TREE_CODE (orig_type) == TYPE_DECL)
+    {
+      if (same_type_p (type, TREE_TYPE (orig_type)))
+       type = orig_type;
+      else
+       type = TYPE_NAME (type);
+    }
+  return type;
+}
+
 /* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
    template PARMS.  If MEMBER_TEMPLATE_P is true, the new template is
    a member template.  Used by push_template_decl below.  */
@@ -10609,14 +10658,9 @@ tsubst_qualified_id (tree qualified_id, tree args,
   else
     expr = name;
 
-  if (dependent_type_p (scope))
-    {
-      tree type = NULL_TREE;
-      if (DECL_P (expr) && !dependent_scope_p (scope))
-       type = TREE_TYPE (expr);
-      return build_qualified_name (type, scope, expr,
-                                  QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
-    }
+  if (dependent_scope_p (scope))
+    return build_qualified_name (NULL_TREE, scope, expr,
+                                QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
 
   if (!BASELINK_P (name) && !DECL_P (expr))
     {
index dbc8226220b67fa458ed574cc3f2ddac42eccf83..4225d998ce0434031c2984047c413a1ac4768eca 100644 (file)
@@ -1,5 +1,8 @@
 2010-02-18  Jason Merrill  <jason@redhat.com>
 
+       PR c++/26261
+       * g++.dg/template/dependent-name6.C: New.
+
        PR c++/43109
        * g++.dg/parse/namespace12.C: New.
 
diff --git a/gcc/testsuite/g++.dg/template/dependent-name6.C b/gcc/testsuite/g++.dg/template/dependent-name6.C
new file mode 100644 (file)
index 0000000..e08bbe1
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/26261
+// { dg-final { scan-assembler "_ZN1YIiE1fIiEE1XILi1EEv" } }
+
+template <int dim> class X {};
+
+template <class T> struct Y {
+  static const unsigned int dim = 1;
+  template <class U> X<Y<T>::dim> f();
+};
+
+template <class T> template <class U>
+X<Y<T>::dim> Y<T>::f() { return X<dim>(); }
+
+int main()
+{
+  Y<int>().f<int>();
+}