OSDN Git Service

PR c++/57047
[pf3gnuchains/gcc-fork.git] / gcc / cp / search.c
index d6521fb..e48dcec 100644 (file)
@@ -1,7 +1,7 @@
 /* Breadth-first and depth-first routines for
    searching multiple-inheritance lattice for GNU C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -29,9 +29,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "tree.h"
 #include "cp-tree.h"
-#include "obstack.h"
+#include "intl.h"
 #include "flags.h"
-#include "rtl.h"
 #include "output.h"
 #include "toplev.h"
 #include "target.h"
@@ -63,7 +62,6 @@ static tree dfs_access_in_type (tree, void *);
 static access_kind access_in_type (tree, tree);
 static int protected_accessible_p (tree, tree, tree);
 static int friend_accessible_p (tree, tree, tree);
-static int template_self_reference_p (tree, tree);
 static tree dfs_get_pure_virtuals (tree, void *);
 
 \f
@@ -172,7 +170,7 @@ accessible_base_p (tree t, tree base, bool consider_local_p)
      public typedef created in the scope of every class.  */
   decl = TYPE_FIELDS (base);
   while (!DECL_SELF_REFERENCE_P (decl))
-    decl = TREE_CHAIN (decl);
+    decl = DECL_CHAIN (decl);
   while (ANON_AGGR_TYPE_P (t))
     t = TYPE_CONTEXT (t);
   return accessible_p (t, decl, consider_local_p);
@@ -214,9 +212,11 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
       t_binfo = TYPE_BINFO (t);
     }
 
-  base = complete_type (TYPE_MAIN_VARIANT (base));
+  base = TYPE_MAIN_VARIANT (base);
 
-  if (t_binfo)
+  /* If BASE is incomplete, it can't be a base of T--and instantiating it
+     might cause an error.  */
+  if (t_binfo && CLASS_TYPE_P (base) && COMPLETE_OR_OPEN_TYPE_P (base))
     {
       struct lookup_base_data_s data;
 
@@ -427,7 +427,7 @@ lookup_field_1 (tree type, tree name, bool want_type)
                    field = fields[i--];
                  while (i >= lo && DECL_NAME (fields[i]) == name);
                  if (TREE_CODE (field) != TYPE_DECL
-                     && !DECL_CLASS_TEMPLATE_P (field))
+                     && !DECL_TYPE_TEMPLATE_P (field))
                    field = NULL_TREE;
                }
              else
@@ -436,6 +436,14 @@ lookup_field_1 (tree type, tree name, bool want_type)
                    field = fields[i++];
                  while (i < hi && DECL_NAME (fields[i]) == name);
                }
+
+             if (field)
+               {
+                 field = strip_using_decl (field);
+                 if (is_overloaded_fn (field))
+                   field = NULL_TREE;
+               }
+
              return field;
            }
        }
@@ -447,8 +455,10 @@ lookup_field_1 (tree type, tree name, bool want_type)
 #ifdef GATHER_STATISTICS
   n_calls_lookup_field_1++;
 #endif /* GATHER_STATISTICS */
-  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+  for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     {
+      tree decl = field;
+
 #ifdef GATHER_STATISTICS
       n_fields_searched++;
 #endif /* GATHER_STATISTICS */
@@ -460,26 +470,20 @@ lookup_field_1 (tree type, tree name, bool want_type)
          if (temp)
            return temp;
        }
-      if (TREE_CODE (field) == USING_DECL)
+
+      if (TREE_CODE (decl) == USING_DECL
+         && DECL_NAME (decl) == name)
        {
-         /* We generally treat class-scope using-declarations as
-            ARM-style access specifications, because support for the
-            ISO semantics has not been implemented.  So, in general,
-            there's no reason to return a USING_DECL, and the rest of
-            the compiler cannot handle that.  Once the class is
-            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.  */
-         if (!DECL_DEPENDENT_P (field))
+         decl = strip_using_decl (decl);
+         if (is_overloaded_fn (decl))
            continue;
        }
 
-      if (DECL_NAME (field) == name
+      if (DECL_NAME (decl) == name
          && (!want_type
-             || TREE_CODE (field) == TYPE_DECL
-             || DECL_CLASS_TEMPLATE_P (field)))
-       return field;
+             || TREE_CODE (decl) == TYPE_DECL
+             || DECL_TYPE_TEMPLATE_P (decl)))
+       return decl;
     }
   /* Not found.  */
   if (name == vptr_identifier)
@@ -535,7 +539,11 @@ int
 at_function_scope_p (void)
 {
   tree cs = current_scope ();
-  return cs && TREE_CODE (cs) == FUNCTION_DECL;
+  /* Also check cfun to make sure that we're really compiling
+     this function (as opposed to having set current_function_decl
+     for access checking or some such).  */
+  return (cs && TREE_CODE (cs) == FUNCTION_DECL
+         && cfun && cfun->decl == current_function_decl);
 }
 
 /* Returns true if the innermost active scope is a class scope.  */
@@ -952,24 +960,6 @@ struct lookup_field_info {
   const char *errstr;
 };
 
-/* Within the scope of a template class, you can refer to the to the
-   current specialization with the name of the template itself.  For
-   example:
-
-     template <typename T> struct S { S* sp; }
-
-   Returns nonzero if DECL is such a declaration in a class TYPE.  */
-
-static int
-template_self_reference_p (tree type, tree decl)
-{
-  return  (CLASSTYPE_USE_TEMPLATE (type)
-          && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
-          && TREE_CODE (decl) == TYPE_DECL
-          && DECL_ARTIFICIAL (decl)
-          && DECL_NAME (decl) == constructor_name (type));
-}
-
 /* Nonzero for a class member means that it is shared between all objects
    of that class.
 
@@ -988,6 +978,7 @@ shared_member_p (tree t)
     return 1;
   if (is_overloaded_fn (t))
     {
+      t = get_fns (t);
       for (; t; t = OVL_NEXT (t))
        {
          tree fn = OVL_CURRENT (t);
@@ -1045,11 +1036,7 @@ lookup_field_r (tree binfo, void *data)
      member with the same name, and if there's a function and a type
      with the same name, the type is hidden by the function.  */
   if (!lfi->want_type)
-    {
-      int idx = lookup_fnfields_1 (type, lfi->name);
-      if (idx >= 0)
-       nval = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), idx);
-    }
+    nval = lookup_fnfields_slot (type, lfi->name);
 
   if (!nval)
     /* Look for a data member or type.  */
@@ -1063,7 +1050,7 @@ lookup_field_r (tree binfo, void *data)
   /* If we're looking up a type (as with an elaborated type specifier)
      we ignore all non-types we find.  */
   if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL
-      && !DECL_CLASS_TEMPLATE_P (nval))
+      && !DECL_TYPE_TEMPLATE_P (nval))
     {
       if (lfi->name == TYPE_IDENTIFIER (type))
        {
@@ -1089,11 +1076,6 @@ lookup_field_r (tree binfo, void *data)
        }
     }
 
-  /* You must name a template base class with a template-id.  */
-  if (!same_type_p (type, lfi->type)
-      && template_self_reference_p (type, nval))
-    goto done;
-
   /* If the lookup already found a match, and the new value doesn't
      hide the old one, we might have an ambiguity.  */
   if (lfi->rval_binfo
@@ -1122,7 +1104,7 @@ lookup_field_r (tree binfo, void *data)
          /* Add the new value.  */
          lfi->ambiguous = tree_cons (NULL_TREE, nval, lfi->ambiguous);
          TREE_TYPE (lfi->ambiguous) = error_mark_node;
-         lfi->errstr = "request for member %qD is ambiguous";
+         lfi->errstr = G_("request for member %qD is ambiguous");
        }
     }
   else
@@ -1177,7 +1159,8 @@ build_baselink (tree binfo, tree access_binfo, tree functions, tree optype)
    If nothing can be found return NULL_TREE and do not issue an error.  */
 
 tree
-lookup_member (tree xbasetype, tree name, int protect, bool want_type)
+lookup_member (tree xbasetype, tree name, int protect, bool want_type,
+              tsubst_flags_t complain)
 {
   tree rval, rval_binfo = NULL_TREE;
   tree type = NULL_TREE, basetype_path = NULL_TREE;
@@ -1192,7 +1175,9 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
 
   const char *errstr = 0;
 
-  if (name == error_mark_node)
+  if (name == error_mark_node
+      || xbasetype == NULL_TREE
+      || xbasetype == error_mark_node)
     return NULL_TREE;
 
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
@@ -1272,9 +1257,12 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
 
   if (errstr && protect)
     {
-      error (errstr, name, type);
-      if (lfi.ambiguous)
-       print_candidates (lfi.ambiguous);
+      if (complain & tf_error)
+       {
+         error (errstr, name, type);
+         if (lfi.ambiguous)
+           print_candidates (lfi.ambiguous);
+       }
       rval = error_mark_node;
     }
 
@@ -1291,7 +1279,8 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
 tree
 lookup_field (tree xbasetype, tree name, int protect, bool want_type)
 {
-  tree rval = lookup_member (xbasetype, name, protect, want_type);
+  tree rval = lookup_member (xbasetype, name, protect, want_type,
+                            tf_warning_or_error);
 
   /* Ignore functions, but propagate the ambiguity list.  */
   if (!error_operand_p (rval)
@@ -1307,7 +1296,8 @@ lookup_field (tree xbasetype, tree name, int protect, bool want_type)
 tree
 lookup_fnfields (tree xbasetype, tree name, int protect)
 {
-  tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false);
+  tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false,
+                            tf_warning_or_error);
 
   /* Ignore non-functions, but propagate the ambiguity list.  */
   if (!error_operand_p (rval)
@@ -1357,10 +1347,11 @@ lookup_conversion_operator (tree class_type, tree type)
 }
 
 /* TYPE is a class type. Return the index of the fields within
-   the method vector with name NAME, or -1 is no such field exists.  */
+   the method vector with name NAME, or -1 if no such field exists.
+   Does not lazily declare implicitly-declared member functions.  */
 
-int
-lookup_fnfields_1 (tree type, tree name)
+static int
+lookup_fnfields_idx_nolazy (tree type, tree name)
 {
   VEC(tree,gc) *method_vec;
   tree fn;
@@ -1370,30 +1361,6 @@ lookup_fnfields_1 (tree type, tree name)
   if (!CLASS_TYPE_P (type))
     return -1;
 
-  if (COMPLETE_TYPE_P (type))
-    {
-      if ((name == ctor_identifier
-          || name == base_ctor_identifier
-          || name == complete_ctor_identifier))
-       {
-         if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
-           lazily_declare_fn (sfk_constructor, type);
-         if (CLASSTYPE_LAZY_COPY_CTOR (type))
-           lazily_declare_fn (sfk_copy_constructor, type);
-         if (CLASSTYPE_LAZY_MOVE_CTOR (type))
-           lazily_declare_fn (sfk_move_constructor, type);
-       }
-      else if (name == ansi_assopname(NOP_EXPR)
-              && CLASSTYPE_LAZY_ASSIGNMENT_OP (type))
-       lazily_declare_fn (sfk_assignment_operator, type);
-      else if ((name == dtor_identifier
-               || name == base_dtor_identifier
-               || name == complete_dtor_identifier
-               || name == deleting_dtor_identifier)
-              && CLASSTYPE_LAZY_DESTRUCTOR (type))
-       lazily_declare_fn (sfk_destructor, type);
-    }
-
   method_vec = CLASSTYPE_METHOD_VEC (type);
   if (!method_vec)
     return -1;
@@ -1463,6 +1430,69 @@ lookup_fnfields_1 (tree type, tree name)
   return -1;
 }
 
+/* TYPE is a class type. Return the index of the fields within
+   the method vector with name NAME, or -1 if no such field exists.  */
+
+int
+lookup_fnfields_1 (tree type, tree name)
+{
+  if (!CLASS_TYPE_P (type))
+    return -1;
+
+  if (COMPLETE_TYPE_P (type))
+    {
+      if ((name == ctor_identifier
+          || name == base_ctor_identifier
+          || name == complete_ctor_identifier))
+       {
+         if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
+           lazily_declare_fn (sfk_constructor, type);
+         if (CLASSTYPE_LAZY_COPY_CTOR (type))
+           lazily_declare_fn (sfk_copy_constructor, type);
+         if (CLASSTYPE_LAZY_MOVE_CTOR (type))
+           lazily_declare_fn (sfk_move_constructor, type);
+       }
+      else if (name == ansi_assopname (NOP_EXPR))
+       {
+         if (CLASSTYPE_LAZY_COPY_ASSIGN (type))
+           lazily_declare_fn (sfk_copy_assignment, type);
+         if (CLASSTYPE_LAZY_MOVE_ASSIGN (type))
+           lazily_declare_fn (sfk_move_assignment, type);
+       }
+      else if ((name == dtor_identifier
+               || name == base_dtor_identifier
+               || name == complete_dtor_identifier
+               || name == deleting_dtor_identifier)
+              && CLASSTYPE_LAZY_DESTRUCTOR (type))
+       lazily_declare_fn (sfk_destructor, type);
+    }
+
+  return lookup_fnfields_idx_nolazy (type, name);
+}
+
+/* TYPE is a class type. Return the field within the method vector with
+   name NAME, or NULL_TREE if no such field exists.  */
+
+tree
+lookup_fnfields_slot (tree type, tree name)
+{
+  int ix = lookup_fnfields_1 (complete_type (type), name);
+  if (ix < 0)
+    return NULL_TREE;
+  return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
+}
+
+/* As above, but avoid lazily declaring functions.  */
+
+tree
+lookup_fnfields_slot_nolazy (tree type, tree name)
+{
+  int ix = lookup_fnfields_idx_nolazy (complete_type (type), name);
+  if (ix < 0)
+    return NULL_TREE;
+  return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
+}
+
 /* Like lookup_fnfields_1, except that the name is extracted from
    FUNCTION, which is a FUNCTION_DECL or a TEMPLATE_DECL.  */
 
@@ -1520,6 +1550,9 @@ adjust_result_of_qualified_name_lookup (tree decl,
        }
     }
 
+  if (BASELINK_P (decl))
+    BASELINK_QUALIFIED_P (decl) = true;
+
   return decl;
 }
 
@@ -1809,8 +1842,8 @@ check_final_overrider (tree overrider, tree basefn)
   tree base_type = TREE_TYPE (basefn);
   tree over_return = TREE_TYPE (over_type);
   tree base_return = TREE_TYPE (base_type);
-  tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
-  tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
+  tree over_throw, base_throw;
+
   int fail = 0;
 
   if (DECL_INVALID_OVERRIDER_P (overrider))
@@ -1841,11 +1874,17 @@ check_final_overrider (tree overrider, tree basefn)
 
       if (CLASS_TYPE_P (base_return) && CLASS_TYPE_P (over_return))
        {
-         tree binfo = lookup_base (over_return, base_return,
-                                   ba_check | ba_quiet, NULL);
+         /* Strictly speaking, the standard requires the return type to be
+            complete even if it only differs in cv-quals, but that seems
+            like a bug in the wording.  */
+         if (!same_type_ignoring_top_level_qualifiers_p (base_return, over_return))
+           {
+             tree binfo = lookup_base (over_return, base_return,
+                                       ba_check | ba_quiet, NULL);
 
-         if (!binfo)
-           fail = 1;
+             if (!binfo)
+               fail = 1;
+           }
        }
       else if (!pedantic
               && can_convert (TREE_TYPE (base_type), TREE_TYPE (over_type)))
@@ -1888,7 +1927,12 @@ check_final_overrider (tree overrider, tree basefn)
     }
 
   /* Check throw specifier is at least as strict.  */
-  if (!comp_except_specs (base_throw, over_throw, 0))
+  maybe_instantiate_noexcept (basefn);
+  maybe_instantiate_noexcept (overrider);
+  base_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (basefn));
+  over_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (overrider));
+
+  if (!comp_except_specs (base_throw, over_throw, ce_derived))
     {
       error ("looser throw specifier for %q+#F", overrider);
       error ("  overriding %q+#F", basefn);
@@ -1897,7 +1941,7 @@ check_final_overrider (tree overrider, tree basefn)
     }
 
   /* Check for conflicting type attributes.  */
-  if (!targetm.comp_type_attributes (over_type, base_type))
+  if (!comp_type_attributes (over_type, base_type))
     {
       error ("conflicting type attributes specified for %q+#D", overrider);
       error ("  overriding %q+#D", basefn);
@@ -1911,6 +1955,7 @@ check_final_overrider (tree overrider, tree basefn)
        {
          error ("deleted function %q+D", overrider);
          error ("overriding non-deleted function %q+D", basefn);
+         maybe_explain_implicit_delete (overrider);
        }
       else
        {
@@ -1919,6 +1964,12 @@ check_final_overrider (tree overrider, tree basefn)
        }
       return 0;
     }
+  if (DECL_FINAL_P (basefn))
+    {
+      error ("virtual function %q+D", overrider);
+      error ("overriding final function %q+D", basefn);
+      return 0;
+    }
   return 1;
 }
 
@@ -1940,6 +1991,11 @@ look_for_overrides (tree type, tree fndecl)
   int ix;
   int found = 0;
 
+  /* A constructor for a class T does not override a function T
+     in a base class.  */
+  if (DECL_CONSTRUCTOR_P (fndecl))
+    return 0;
+
   for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
     {
       tree basetype = BINFO_TYPE (base_binfo);