re PR c++/19497 (Invalid declaration in template diagnosed too late)
authorNathan Sidwell <nathan@codesourcery.com>
Wed, 8 Jun 2005 11:49:23 +0000 (11:49 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 8 Jun 2005 11:49:23 +0000 (11:49 +0000)
cp:
PR c++/19497
* cp-tree.def (USING_DECL): Update documentation.
* cp-tree.h (DECL_DEPENDENT_P): New.
(USING_DECL_DECLS, USING_DECL_SCOPE): New.
* class.c (handle_using_decl): Move most of the processing to ...
* name-lookup.c (do_class_using_decl): ... here.  Make stricter.
(push_using_decl): Use USING_DECL_SCOPE.
(cp_emit_debug_info_for_using): Make extern.
* cxx-pretty-print.c (pp_cxx_statement) <USING_DECL case>: Adjust.
* name-lookup.h (cp_emit_debug_info_for_using): Declare.
* pt.c (tsubst_decl) <USING_DECL case>: Use do_class_using_decl
when tsubsting.
(tsubst_expr): Use USING_DECL_SCOPE.
* search.c (lookup_field_1): Use DECL_DEPENDENT_P.
* semantics.c (finish_member_declaration): Likewise.
testsuite:
PR c++/19497
* g++.dg/inherit/using5.C: New.
* g++.dg/inherit/using6.C: New.

From-SVN: r100757

13 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cxx-pretty-print.c
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/inherit/using5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/inherit/using6.C [new file with mode: 0644]

index c15f9b4043360555f26988a40c9ac90dda390f61..f08a2c65803f0b2a66d4bb30fe16e16119fec8af 100644 (file)
@@ -1,3 +1,21 @@
+2005-06-08  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/19497
+       * cp-tree.def (USING_DECL): Update documentation.
+       * cp-tree.h (DECL_DEPENDENT_P): New.
+       (USING_DECL_DECLS, USING_DECL_SCOPE): New.
+       * class.c (handle_using_decl): Move most of the processing to ...
+       * name-lookup.c (do_class_using_decl): ... here.  Make stricter.
+       (push_using_decl): Use USING_DECL_SCOPE.
+       (cp_emit_debug_info_for_using): Make extern.
+       * cxx-pretty-print.c (pp_cxx_statement) <USING_DECL case>: Adjust.
+       * name-lookup.h (cp_emit_debug_info_for_using): Declare.
+       * pt.c (tsubst_decl) <USING_DECL case>: Use do_class_using_decl
+       when tsubsting.
+       (tsubst_expr): Use USING_DECL_SCOPE.
+       * search.c (lookup_field_1): Use DECL_DEPENDENT_P.
+       * semantics.c (finish_member_declaration): Likewise.
+
 2005-06-08  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c++/19894
index 8661931ac781369518b32bac3c5a8bee38efa692..a790b561316505c18247bcbffc626be293902ef0 100644 (file)
@@ -1119,53 +1119,17 @@ alter_access (tree t, tree fdecl, tree access)
 static void
 handle_using_decl (tree using_decl, tree t)
 {
-  tree ctype = DECL_INITIAL (using_decl);
+  tree decl = USING_DECL_DECLS (using_decl);
   tree name = DECL_NAME (using_decl);
   tree access
     = TREE_PRIVATE (using_decl) ? access_private_node
     : TREE_PROTECTED (using_decl) ? access_protected_node
     : access_public_node;
-  tree fdecl, binfo;
   tree flist = NULL_TREE;
   tree old_value;
 
-  if (ctype == error_mark_node)
-    return;
-
-  binfo = lookup_base (t, ctype, ba_any, NULL);
-  if (! binfo)
-    {
-      location_t saved_loc = input_location;
-
-      input_location = DECL_SOURCE_LOCATION (using_decl);
-      error_not_base_type (ctype, t);
-      input_location = saved_loc;
-      return;
-    }
-  
-  if (constructor_name_p (name, ctype))
-    {
-      cp_error_at ("%qD names constructor", using_decl);
-      return;
-    }
-  if (constructor_name_p (name, t))
-    {
-      cp_error_at ("%qD invalid in %qT", using_decl, t);
-      return;
-    }
-
-  fdecl = lookup_member (binfo, name, 0, false);
+  gcc_assert (!processing_template_decl && decl);
   
-  if (!fdecl)
-    {
-      cp_error_at ("no members matching %qD in %q#T", using_decl, ctype);
-      return;
-    }
-
-  if (BASELINK_P (fdecl))
-    /* Ignore base type this came from.  */
-    fdecl = BASELINK_FUNCTIONS (fdecl);
-
   old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false);
   if (old_value)
     {
@@ -1177,9 +1141,11 @@ handle_using_decl (tree using_decl, tree t)
       else
        old_value = NULL_TREE;
     }
-
-  if (is_overloaded_fn (fdecl))
-    flist = fdecl;
+  
+  cp_emit_debug_info_for_using (decl, current_class_type);
+  
+  if (is_overloaded_fn (decl))
+    flist = decl;
 
   if (! old_value)
     ;
@@ -1211,7 +1177,7 @@ handle_using_decl (tree using_decl, tree t)
        alter_access (t, OVL_CURRENT (flist), access);
       }
   else
-    alter_access (t, fdecl, access);
+    alter_access (t, decl, access);
 }
 \f
 /* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P,
index aa0ea83b3230d60c27d306c3c3c1d96d2a69db6e..894b62db45c42ba06692525d141bbb091d458a1f 100644 (file)
@@ -197,10 +197,10 @@ DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm",
    TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template.  */
 DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", tcc_type, 0)
 
-/* A using declaration.  DECL_INITIAL contains the specified scope.  
-   This is not an alias, but is later expanded into multiple aliases.
-   The decl will have a NULL_TYPE iff the scope is a dependent scope,
-   otherwise it will have a void type.  */
+/* A using declaration.  USING_DECL_SCOPE contains the specified
+   scope.  In a member using decl, unless DECL_DEPENDENT_P is true,
+   USING_DECL_DECLS contains the _DECL or OVERLOAD so named.  This is
+   not an alias, but is later expanded into multiple aliases.  */
 DEFTREECODE (USING_DECL, "using_decl", tcc_declaration, 0)
 
 /* A using directive. The operand is USING_STMT_NAMESPACE.  */     
index 90de20c1e63230bdc7f0b9cbad3416e320169793..bb234bb5e135baf93dd5de91a2ba0986779a9c03 100644 (file)
@@ -93,6 +93,7 @@ struct diagnostic_context;
       DECL_TEMPLATE_PARM_P (in PARM_DECL, CONST_DECL, TYPE_DECL, or TEMPLATE_DECL)
       DECL_LOCAL_FUNCTION_P (in FUNCTION_DECL)
       DECL_MUTABLE_P (in FIELD_DECL)
+      DECL_DEPENDENT_P (in USING_DECL)
    1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
       DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
       DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
@@ -2039,6 +2040,15 @@ struct lang_decl GTY(())
    directives  */
 #define TREE_INDIRECT_USING(NODE) (TREE_LIST_CHECK (NODE)->common.lang_flag_0)
 
+/* Non zero if this is a using decl for a dependent scope. */
+#define DECL_DEPENDENT_P(NODE) DECL_LANG_FLAG_0 (USING_DECL_CHECK (NODE))
+
+/* The scope named in a using decl.  */
+#define USING_DECL_SCOPE(NODE) TREE_TYPE (USING_DECL_CHECK (NODE))
+
+/* The decls named by a using decl.  */
+#define USING_DECL_DECLS(NODE) DECL_INITIAL (USING_DECL_CHECK (NODE))
+
 /* In a VAR_DECL for a variable declared in a for statement,
    this is the shadowed (local) variable.  */
 #define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT_FLD(VAR_DECL_CHECK (NODE))
index afa969f9f710f4d4ef4e7737622ba14cfced958c..42435d026bcdc077951680aa51094ff038c1c4e0 100644 (file)
@@ -1519,7 +1519,7 @@ pp_cxx_statement (cxx_pretty_printer *pp, tree t)
 
     case USING_DECL:
       pp_cxx_identifier (pp, "using");
-      pp_cxx_nested_name_specifier (pp, DECL_INITIAL (t));
+      pp_cxx_nested_name_specifier (pp, USING_DECL_SCOPE (t));
       pp_cxx_unqualified_id (pp, DECL_NAME (t));
       break;
 
index 3197a41077d8169111983d7fc6fca3685309146c..7a878f68ec48f4ea3d21390b55c3986c07fa37e0 100644 (file)
@@ -51,7 +51,6 @@ static bool qualified_lookup_using_namespace (tree, tree,
                                              struct scope_binding *, int);
 static tree lookup_type_current_level (tree);
 static tree push_using_directive (tree);
-static void cp_emit_debug_info_for_using (tree, tree);
 
 /* The :: namespace.  */
 
@@ -1779,13 +1778,13 @@ push_using_decl (tree scope, tree name)
   gcc_assert (TREE_CODE (scope) == NAMESPACE_DECL);
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
   for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
-    if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
+    if (USING_DECL_SCOPE (decl) == scope && DECL_NAME (decl) == name)
       break;
   if (decl)
     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
                             namespace_bindings_p () ? decl : NULL_TREE);
-  decl = build_lang_decl (USING_DECL, name, void_type_node);
-  DECL_INITIAL (decl) = scope;
+  decl = build_lang_decl (USING_DECL, name, NULL_TREE);
+  USING_DECL_SCOPE (decl) = scope;
   TREE_CHAIN (decl) = current_binding_level->usings;
   current_binding_level->usings = decl;
   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
@@ -2691,35 +2690,80 @@ push_class_level_binding (tree name, tree x)
 tree
 do_class_using_decl (tree scope, tree name)
 {
-  tree value, type;
+  tree value, decl, binfo;
+  base_kind b_kind;
+  bool dependent_p;
   
   if (!scope || !TYPE_P (scope))
     {
       error ("using-declaration for non-member at class scope");
       return NULL_TREE;
     }
+
+  /* Make sure the scope is a base.  */
+  dependent_p = dependent_type_p (scope);
+  if (!dependent_p)
+    binfo = lookup_base (current_class_type, scope, ba_any, &b_kind);
+  else
+    {
+      binfo = NULL;
+      if (same_type_p (current_class_type, scope))
+       b_kind = bk_same_type;
+      else
+       b_kind = bk_proper_base;
+    }
+  
+  if (b_kind < bk_proper_base)
+    {
+      error_not_base_type (scope, current_class_type);
+      return NULL_TREE;
+    }
+  
+  /* Make sure the name is not invalid */
   if (TREE_CODE (name) == BIT_NOT_EXPR)
     {
-      error ("using-declaration cannot name destructor");
+      error ("%<%T::%D%> names destructor", scope, name);
+      return NULL_TREE;
+    }
+  if (constructor_name_p (name, scope))
+    {
+      error ("%<%T::%D%> names constructor", scope, name);
+      return NULL_TREE;
+    }
+  if (constructor_name_p (name, current_class_type))
+    {
+      error ("%<%T::%D%> names constructor in %qT",
+            scope, name, current_class_type);
       return NULL_TREE;
     }
 
-  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
-
-  /* Dependent using decls have a NULL type, non-dependent ones have a
-     void type.  */
-  type = dependent_type_p (scope) ? NULL_TREE : void_type_node;
-  value = build_lang_decl (USING_DECL, name, type);
-  DECL_INITIAL (value) = scope;
+  if (!dependent_p
+      && IDENTIFIER_OPNAME_P (name) && dependent_type_p (TREE_TYPE (name)))
+    dependent_p = 1;
 
-  if (scope && !processing_template_decl)
+  /* See if there are any members of the base. */
+  if (!dependent_p)
     {
-      tree r;
+      decl = lookup_member (binfo, name, 0, false);
+  
+      if (!decl)
+       {
+         error ("no members matching %<%T::%D%> in %q#T", scope, name, scope);
+         return NULL_TREE;
+       }
+
+      if (BASELINK_P (decl))
+       /* Ignore base type this came from.  */
+       decl = BASELINK_FUNCTIONS (decl);
+   }
+  else
+    decl = NULL_TREE;
+
+  value = build_lang_decl (USING_DECL, name, NULL_TREE);
+  USING_DECL_DECLS (value) = decl;
+  USING_DECL_SCOPE (value) = scope;
+  DECL_DEPENDENT_P (value) = dependent_p;
 
-      r = lookup_qualified_name (scope, name, false, false);
-      if (r && (DECL_P (r) || TREE_CODE (r) == OVERLOAD))
-       cp_emit_debug_info_for_using (r, scope);
-    }
   return value;
 }
 
@@ -4923,7 +4967,7 @@ pop_everything (void)
    If input tree is overloaded fn then emit debug info for all 
    candidates.  */
 
-static void
+void
 cp_emit_debug_info_for_using (tree t, tree context)
 {
   /* Ignore this FUNCTION_DECL if it refers to a builtin declaration 
@@ -4945,6 +4989,6 @@ cp_emit_debug_info_for_using (tree t, tree context)
   for (t = OVL_CURRENT (t); t; t = OVL_NEXT (t))
     if (TREE_CODE (t) != TEMPLATE_DECL)
       (*debug_hooks->imported_module_or_decl) (t, context);
-  }
+}
 
 #include "gt-cp-name-lookup.h"
index 19bcec0eba60d513b73d6ad61bbacf43ae989065..70c12a219f55ba4b75a7675d289051748483b3a0 100644 (file)
@@ -341,6 +341,7 @@ extern bool is_associated_namespace (tree, tree);
 extern void parse_using_directive (tree, tree);
 extern tree innermost_non_namespace_value (tree);
 extern cxx_binding *outer_binding (tree, cxx_binding *, bool);
+extern void cp_emit_debug_info_for_using (tree, tree);
 
 /* Set *DECL to the (non-hidden) declaration for ID at global scope,
    if present and return true; otherwise return false.  */
index 292dc0ae78b7b7a8e9df44bea26edf4522054dc5..8af0234f618294f6b21948d321d828ffc6c56623 100644 (file)
@@ -6557,16 +6557,20 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
       break;
 
     case USING_DECL:
-      {
-       r = copy_node (t);
-       /* It is not a dependent using decl any more.  */
-       TREE_TYPE (r) = void_type_node;
-       DECL_INITIAL (r)
-         = tsubst_copy (DECL_INITIAL (t), args, complain, in_decl);
-       DECL_NAME (r)
-         = tsubst_copy (DECL_NAME (t), args, complain, in_decl);
-       TREE_CHAIN (r) = NULL_TREE;
-      }
+      /* We reach here only for member using decls.  */
+      if (DECL_DEPENDENT_P (t))
+       {
+         r = do_class_using_decl
+           (tsubst_copy (USING_DECL_SCOPE (t), args, complain, in_decl),
+            tsubst_copy (DECL_NAME (t), args, complain, in_decl));
+         if (!r)
+           r = error_mark_node;
+       }
+      else
+       {
+         r = copy_node (t);
+         TREE_CHAIN (r) = NULL_TREE;
+       }
       break;
 
     case TYPE_DECL:
@@ -8085,7 +8089,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          finish_label_decl (DECL_NAME (decl));
        else if (TREE_CODE (decl) == USING_DECL)
          {
-           tree scope = DECL_INITIAL (decl);
+           tree scope = USING_DECL_SCOPE (decl);
            tree name = DECL_NAME (decl);
            tree decl;
            
index 45668a14a94a99acc947fb6b8ed6b8fb885eaa9f..8dec18e7743419dd9618f57daf35658be8354fdc 100644 (file)
@@ -471,9 +471,8 @@ lookup_field_1 (tree type, tree name, bool want_type)
             defined, USING_DECLs are purged from TYPE_FIELDS; see
             handle_using_decl.  However, we make special efforts to
             make using-declarations in class templates and class
-            template partial specializations work correctly noticing
-            that dependent USING_DECL's do not have TREE_TYPE set.  */
-         if (TREE_TYPE (field))
+            template partial specializations work correctly.  */
+         if (!DECL_DEPENDENT_P (field))
            continue;
        }
 
index 76464ad626adf98034ff7e0c267bc2ab2990cd93..298979b38e3148e9e1e100fb5a1b4cec0294700b 100644 (file)
@@ -2259,7 +2259,7 @@ finish_member_declaration (tree decl)
                                          /*friend_p=*/0);
     }
   /* Enter the DECL into the scope of the class.  */
-  else if ((TREE_CODE (decl) == USING_DECL && TREE_TYPE (decl))
+  else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
           || pushdecl_class_level (decl))
     {
       /* All TYPE_DECLs go at the end of TYPE_FIELDS.  Ordinary fields
index 05aa1b4f33cf1dfc587a88bf3671db1d727e6cda..8ac9bf504a23839cbc3ea505f4b2f9398ad1a1ea 100644 (file)
@@ -1,3 +1,9 @@
+2005-06-08  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/19497
+       * g++.dg/inherit/using5.C: New.
+       * g++.dg/inherit/using6.C: New.
+
 2005-06-08  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c++/19894
diff --git a/gcc/testsuite/g++.dg/inherit/using5.C b/gcc/testsuite/g++.dg/inherit/using5.C
new file mode 100644 (file)
index 0000000..896c2d4
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright (C) 2005 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 8 Jun 2005 <nathan@codesourcery.com>
+
+// PR 19496: Missing error during parsing.
+// Origin:  Volker Reichelt <reichelt@gcc.gnu.org>
+
+template<int> struct A
+{
+  A::A; // { dg-error "not a base" }
+};
+
+struct B
+{
+  void f ();
+  using B::f; // { dg-error "not a base" }
+};
+
diff --git a/gcc/testsuite/g++.dg/inherit/using6.C b/gcc/testsuite/g++.dg/inherit/using6.C
new file mode 100644 (file)
index 0000000..46c23ce
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright (C) 2005 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 8 Jun 2005 <nathan@codesourcery.com>
+
+struct A
+{
+  operator int ();
+};
+
+template <typename T> struct TPL : A
+{
+  using A::operator T; // { dg-error "operator float" }
+};
+
+TPL<int> i;
+TPL<float> j; // { dg-error "instantiated" }