OSDN Git Service

cp/
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index 385f8d9..a6187e2 100644 (file)
@@ -553,7 +553,8 @@ check_classfn (tree ctype, tree function, tree template_parms)
 {
   int ix;
   bool is_template;
-
+  tree pushed_scope;
+  
   if (DECL_USE_TEMPLATE (function)
       && !(TREE_CODE (function) == TEMPLATE_DECL
           && DECL_TEMPLATE_SPECIALIZATION (function))
@@ -583,16 +584,18 @@ check_classfn (tree ctype, tree function, tree template_parms)
   /* OK, is this a definition of a member template?  */
   is_template = (template_parms != NULL_TREE);
 
+  /* We must enter the scope here, because conversion operators are
+     named by target type, and type equivalence relies on typenames
+     resolving within the scope of CTYPE.  */
+  pushed_scope = push_scope (ctype);
   ix = class_method_index_for_fn (complete_type (ctype), function);
   if (ix >= 0)
     {
       VEC(tree,gc) *methods = CLASSTYPE_METHOD_VEC (ctype);
       tree fndecls, fndecl = 0;
       bool is_conv_op;
-      tree pushed_scope;
       const char *format = NULL;
 
-      pushed_scope = push_scope (ctype);
       for (fndecls = VEC_index (tree, methods, ix);
           fndecls; fndecls = OVL_NEXT (fndecls))
        {
@@ -631,10 +634,13 @@ check_classfn (tree ctype, tree function, tree template_parms)
                      == DECL_TI_TEMPLATE (fndecl))))
            break;
        }
-      if (pushed_scope)
-       pop_scope (pushed_scope);
       if (fndecls)
-       return OVL_CURRENT (fndecls);
+       {
+         if (pushed_scope)
+           pop_scope (pushed_scope);
+         return OVL_CURRENT (fndecls);
+       }
+      
       error ("prototype for %q#D does not match any in class %qT",
             function, ctype);
       is_conv_op = DECL_CONV_FN_P (fndecl);
@@ -673,11 +679,8 @@ check_classfn (tree ctype, tree function, tree template_parms)
   else if (!COMPLETE_TYPE_P (ctype))
     cxx_incomplete_type_error (function, ctype);
   else
-    {
-      error ("no %q#D member function declared in class %qT",
-            function, ctype);
-      return NULL_TREE;
-    }
+    error ("no %q#D member function declared in class %qT",
+          function, ctype);
 
   /* If we did not find the method in the class, add it to avoid
      spurious errors (unless the CTYPE is not yet defined, in which
@@ -685,6 +688,9 @@ check_classfn (tree ctype, tree function, tree template_parms)
      properly within the class.  */
   if (COMPLETE_TYPE_P (ctype))
     add_method (ctype, function, NULL_TREE);
+  
+  if (pushed_scope)
+    pop_scope (pushed_scope);
   return NULL_TREE;
 }
 
@@ -1536,7 +1542,7 @@ maybe_emit_vtables (tree ctype)
 /* A special return value from type_visibility meaning internal
    linkage.  */
 
-enum { VISIBILITY_STATIC = VISIBILITY_INTERNAL+1 };
+enum { VISIBILITY_ANON = VISIBILITY_INTERNAL+1 };
 
 /* walk_tree helper function for type_visibility.  */
 
@@ -1552,7 +1558,7 @@ min_vis_r (tree *tp, int *walk_subtrees, void *data)
     {
       if (!TREE_PUBLIC (TYPE_MAIN_DECL (*tp)))
        {
-         *vis_p = VISIBILITY_STATIC;
+         *vis_p = VISIBILITY_ANON;
          return *tp;
        }
       else if (CLASSTYPE_VISIBILITY (*tp) > *vis_p)
@@ -1572,29 +1578,28 @@ type_visibility (tree type)
   return vis;
 }
 
-/* Limit the visibility of DECL to VISIBILITY.  SPECIFIED is true if the
-   constraint comes from an attribute or pragma; REASON is the source of
-   the constraint.  */
+/* Limit the visibility of DECL to VISIBILITY, if not explicitly
+   specified (or if VISIBILITY is static).  */
 
 static bool
-constrain_visibility (tree decl, int visibility, bool specified,
-                     const char *reason)
+constrain_visibility (tree decl, int visibility)
 {
-  if (visibility == VISIBILITY_STATIC)
+  if (visibility == VISIBILITY_ANON)
     {
-      TREE_PUBLIC (decl) = 0;
-      DECL_INTERFACE_KNOWN (decl) = 1;
-      if (DECL_LANG_SPECIFIC (decl))
-       DECL_NOT_REALLY_EXTERN (decl) = 1;
+      /* extern "C" declarations aren't affected by the anonymous
+        namespace.  */
+      if (!DECL_EXTERN_C_P (decl))
+       {
+         TREE_PUBLIC (decl) = 0;
+         DECL_INTERFACE_KNOWN (decl) = 1;
+         if (DECL_LANG_SPECIFIC (decl))
+           DECL_NOT_REALLY_EXTERN (decl) = 1;
+       }
     }
-  else if (visibility > DECL_VISIBILITY (decl))
+  else if (visibility > DECL_VISIBILITY (decl)
+          && !DECL_VISIBILITY_SPECIFIED (decl))
     {
-      if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
-       warning (OPT_Wattributes, "%q+D: visibility attribute requests "
-                "greater visibility than its %s allows", decl, reason);
       DECL_VISIBILITY (decl) = visibility;
-      if (!DECL_VISIBILITY_SPECIFIED (decl))
-       DECL_VISIBILITY_SPECIFIED (decl) = specified;
       return true;
     }
   return false;
@@ -1627,13 +1632,13 @@ constrain_visibility_for_template (tree decl, tree targs)
              || TREE_CODE (arg) == FUNCTION_DECL)
            {
              if (! TREE_PUBLIC (arg))
-               vis = VISIBILITY_STATIC;
+               vis = VISIBILITY_ANON;
              else
                vis = DECL_VISIBILITY (arg);
            }
        }
       if (vis)
-       constrain_visibility (decl, vis, false, "template parameter");
+       constrain_visibility (decl, vis);
     }
 }
 
@@ -1735,8 +1740,7 @@ determine_visibility (tree decl)
        {
          /* tinfo visibility is based on the type it's for.  */
          constrain_visibility
-           (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))),
-            false, "type");
+           (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))));
        }
       else if (use_template)
        /* Template instantiations and specializations get visibility based
@@ -1752,43 +1756,46 @@ determine_visibility (tree decl)
 
   if (use_template)
     {
+      /* If the specialization doesn't specify visibility, use the
+        visibility from the template.  */
       tree tinfo = (TREE_CODE (decl) == TYPE_DECL
                    ? TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
                    : DECL_TEMPLATE_INFO (decl));
       tree args = TI_ARGS (tinfo);
-      int depth = TMPL_ARGS_DEPTH (args);
-
-      /* If the template has explicit visibility and the specialization
-        doesn't, use the visibility from the template.  */
-      if (!DECL_VISIBILITY_SPECIFIED (decl))
+      
+      if (args != error_mark_node)
        {
+         int depth = TMPL_ARGS_DEPTH (args);
          tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
-         DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
-       }
 
-      /* FIXME should TMPL_ARGS_DEPTH really return 1 for null input? */
-      if (args && depth > template_class_depth (class_type))
-       /* Don't let it have more visibility than its template type
-          arguments.  */
-       constrain_visibility_for_template (decl, args);
+         if (!DECL_VISIBILITY_SPECIFIED (decl))
+           {
+             DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
+             DECL_VISIBILITY_SPECIFIED (decl)
+               = DECL_VISIBILITY_SPECIFIED (pattern);
+           }
+
+         /* FIXME should TMPL_ARGS_DEPTH really return 1 for null input? */
+         if (args && depth > template_class_depth (class_type))
+           /* Limit visibility based on its template arguments.  */
+           constrain_visibility_for_template (decl, args);
+       }
     }
-  
+
   if (class_type)
     determine_visibility_from_class (decl, class_type);
 
-  /* Don't let it have more visibility than its type.  */
-  if (TREE_CODE (decl) != TYPE_DECL)
-    if (constrain_visibility (decl, type_visibility (TREE_TYPE (decl)),
-                             false, "type"))
-      warning (OPT_Wattributes, "\
-%q+D declared with greater visibility than its type",
-              decl);
-
   if (decl_anon_ns_mem_p (decl))
     /* Names in an anonymous namespace get internal linkage.
        This might change once we implement export.  */
-    constrain_visibility (decl, VISIBILITY_STATIC,
-                         false, "namespace");
+    constrain_visibility (decl, VISIBILITY_ANON);
+  else if (TREE_CODE (decl) != TYPE_DECL)
+    {
+      /* Propagate anonymity from type to decl.  */
+      int tvis = type_visibility (TREE_TYPE (decl));
+      if (tvis == VISIBILITY_ANON)
+       constrain_visibility (decl, tvis);
+    }
 }
 
 /* By default, static data members and function members receive
@@ -1804,13 +1811,17 @@ determine_visibility_from_class (tree decl, tree class_type)
       && !processing_template_decl
       && ! DECL_VISIBILITY_SPECIFIED (decl)
       && TREE_CODE (decl) == FUNCTION_DECL
-      && DECL_DECLARED_INLINE_P (decl))
+      && DECL_DECLARED_INLINE_P (decl)
+      && (! DECL_LANG_SPECIFIC (decl)
+         || ! DECL_EXPLICIT_INSTANTIATION (decl)))
     DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
-
-  /* The decl can't have more visibility than its class.  */
-  constrain_visibility (decl, CLASSTYPE_VISIBILITY (class_type),
-                       CLASSTYPE_VISIBILITY_SPECIFIED (class_type),
-                       "class");
+  else if (!DECL_VISIBILITY_SPECIFIED (decl))
+    {
+      /* Default to the class visibility.  */
+      DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
+      DECL_VISIBILITY_SPECIFIED (decl)
+       = CLASSTYPE_VISIBILITY_SPECIFIED (class_type);
+    }
 
   /* Give the target a chance to override the visibility associated
      with DECL.  */
@@ -1823,8 +1834,8 @@ determine_visibility_from_class (tree decl, tree class_type)
              && !DECL_CONSTRUCTION_VTABLE_P (decl)))
       && TREE_PUBLIC (decl)
       && !DECL_REALLY_EXTERN (decl)
-      && DECL_VISIBILITY_SPECIFIED (decl)
-      && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type)))
+      && !DECL_VISIBILITY_SPECIFIED (decl)
+      && !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
     targetm.cxx.determine_class_data_visibility (decl);
 }
 
@@ -1834,25 +1845,53 @@ determine_visibility_from_class (tree decl, tree class_type)
 void
 constrain_class_visibility (tree type)
 {
-  tree decl = TYPE_MAIN_DECL (type);
-  tree binfo = TYPE_BINFO (type);
+  tree binfo;
   tree t;
   int i;
 
+  int vis = type_visibility (type);
+
+  if (vis == VISIBILITY_ANON
+      || DECL_IN_SYSTEM_HEADER (TYPE_MAIN_DECL (type)))
+    return;
+
+  /* Don't warn about visibility if the class has explicit visibility.  */
+  if (CLASSTYPE_VISIBILITY_SPECIFIED (type))
+    vis = VISIBILITY_INTERNAL;
+
   for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
-    if (TREE_CODE (t) == FIELD_DECL)
-      if (constrain_visibility (decl, type_visibility (TREE_TYPE (t)),
-                               false, "field type"))
-       warning (OPT_Wattributes, "\
+    if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
+      {
+       tree ftype = strip_array_types (TREE_TYPE (t));
+       int subvis = type_visibility (ftype);
+
+       if (subvis == VISIBILITY_ANON)
+         warning (0, "\
+%qT has a field %qD whose type uses the anonymous namespace",
+                  type, t);
+       else if (IS_AGGR_TYPE (ftype)
+                && vis < VISIBILITY_HIDDEN
+                && subvis >= VISIBILITY_HIDDEN)
+         warning (OPT_Wattributes, "\
 %qT declared with greater visibility than the type of its field %qD",
-                type, t);
+                  type, t);
+      }
 
+  binfo = TYPE_BINFO (type);
   for (i = 0; BINFO_BASE_ITERATE (binfo, i, t); ++i)
-    if (constrain_visibility (decl, type_visibility (TREE_TYPE (t)),
-                             false, "base type"))
-      warning (OPT_Wattributes, "\
+    {
+      int subvis = type_visibility (TREE_TYPE (t));
+
+      if (subvis == VISIBILITY_ANON)
+       warning (0, "\
+%qT has a base %qT whose type uses the anonymous namespace",
+                type, TREE_TYPE (t));
+      else if (vis < VISIBILITY_HIDDEN
+              && subvis >= VISIBILITY_HIDDEN)
+       warning (OPT_Wattributes, "\
 %qT declared with greater visibility than its base %qT",
-              type, TREE_TYPE (t));
+                type, TREE_TYPE (t));
+    }
 }
 
 /* DECL is a FUNCTION_DECL or VAR_DECL.  If the object file linkage
@@ -3455,6 +3494,8 @@ mark_used (tree decl)
     }
 
   TREE_USED (decl) = 1;
+  if (DECL_CLONED_FUNCTION_P (decl))
+    TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
   /* If we don't need a value, then we don't need to synthesize DECL.  */
   if (skip_evaluation)
     return;