OSDN Git Service

cp/
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index 9408c8a..a6187e2 100644 (file)
@@ -82,6 +82,7 @@ static tree prune_vars_needing_no_initialization (tree *);
 static void write_out_vars (tree);
 static void import_export_class (tree);
 static tree get_guard_bits (tree);
+static void determine_visibility_from_class (tree, tree);
 
 /* A list of static class variables.  This is needed, because a
    static class variable can be declared inside the class without
@@ -102,33 +103,31 @@ tree static_ctors;
 tree static_dtors;
 
 \f
-/* Incorporate `const' and `volatile' qualifiers for member functions.
-   FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
-   QUALS is a list of qualifiers.  Returns any explicit
-   top-level qualifiers of the method's this pointer, anything other than
-   TYPE_UNQUALIFIED will be an extension.  */
-
-int
-grok_method_quals (tree ctype, tree function, cp_cv_quals quals)
+
+/* Return a member function type (a METHOD_TYPE), given FNTYPE (a
+   FUNCTION_TYPE), CTYPE (class type), and QUALS (the cv-qualifiers
+   that apply to the function).  */
+
+tree
+build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals)
 {
-  tree fntype = TREE_TYPE (function);
-  tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
-  int type_quals = TYPE_UNQUALIFIED;
-  int this_quals = TYPE_UNQUALIFIED;
+  tree raises;
+  int type_quals;
 
-  type_quals = quals & ~TYPE_QUAL_RESTRICT;
-  this_quals = quals & TYPE_QUAL_RESTRICT;
+  if (fntype == error_mark_node || ctype == error_mark_node)
+    return error_mark_node;
 
+  type_quals = quals & ~TYPE_QUAL_RESTRICT;
   ctype = cp_build_qualified_type (ctype, type_quals);
   fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
                                       (TREE_CODE (fntype) == METHOD_TYPE
                                        ? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
                                        : TYPE_ARG_TYPES (fntype)));
+  raises = TYPE_RAISES_EXCEPTIONS (fntype);
   if (raises)
     fntype = build_exception_variant (fntype, raises);
 
-  TREE_TYPE (function) = fntype;
-  return this_quals;
+  return fntype;
 }
 
 /* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
@@ -148,7 +147,7 @@ cp_build_parm_decl (tree name, tree type)
 /* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
    indicated NAME.  */
 
-static tree
+tree
 build_artificial_parm (tree name, tree type)
 {
   tree parm = cp_build_parm_decl (name, type);
@@ -256,11 +255,9 @@ maybe_retrofit_in_chrg (tree fn)
    QUALS are the qualifiers for the this pointer.  */
 
 void
-grokclassfn (tree ctype, tree function, enum overload_flags flags,
-            cp_cv_quals quals)
+grokclassfn (tree ctype, tree function, enum overload_flags flags)
 {
   tree fn_name = DECL_NAME (function);
-  cp_cv_quals this_quals = TYPE_UNQUALIFIED;
 
   /* Even within an `extern "C"' block, members get C++ linkage.  See
      [dcl.link] for details.  */
@@ -273,28 +270,6 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags,
       DECL_NAME (function) = fn_name;
     }
 
-  if (quals)
-    this_quals = grok_method_quals (ctype, function, quals);
-
-  if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
-    {
-      /* Must add the class instance variable up front.  */
-      /* Right now we just make this a pointer.  But later
-        we may wish to make it special.  */
-      tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (function)));
-      tree qual_type;
-      tree parm;
-
-      /* The `this' parameter is implicitly `const'; it cannot be
-        assigned to.  */
-      this_quals |= TYPE_QUAL_CONST;
-      qual_type = cp_build_qualified_type (type, this_quals);
-      parm = build_artificial_parm (this_identifier, qual_type);
-      cp_apply_type_quals_to_decl (this_quals, parm);
-      TREE_CHAIN (parm) = DECL_ARGUMENTS (function);
-      DECL_ARGUMENTS (function) = parm;
-    }
-
   DECL_CONTEXT (function) = ctype;
 
   if (flags == DTOR_FLAG)
@@ -477,16 +452,9 @@ check_member_template (tree tmpl)
        error ("invalid declaration of member template %q#D in local class",
               decl);
 
-      if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
-       {
-         /* 14.5.2.3 [temp.mem]
-
-            A member function template shall not be virtual.  */
-         error
-           ("invalid use of %<virtual%> in template declaration of %q#D",
-            decl);
-         DECL_VIRTUAL_P (decl) = 0;
-       }
+      /* The parser rejects any use of virtual in a function template.  */
+      gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL
+                   && DECL_VIRTUAL_P (decl)));
 
       /* The debug-information generating code doesn't know what to do
         with member templates.  */
@@ -501,8 +469,11 @@ check_member_template (tree tmpl)
 static bool
 acceptable_java_type (tree type)
 {
+  if (type == error_mark_node)
+    return false;
+
   if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type))
-    return 1;
+    return true;
   if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
     {
       type = TREE_TYPE (type);
@@ -558,8 +529,9 @@ check_java_method (tree method)
       tree type = TREE_VALUE (arg_types);
       if (!acceptable_java_type (type))
        {
-         error ("Java method %qD has non-Java parameter type %qT",
-                method, type);
+          if (type != error_mark_node)
+           error ("Java method %qD has non-Java parameter type %qT",
+                  method, type);
          jerr = true;
        }
     }
@@ -581,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))
@@ -611,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))
        {
@@ -659,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);
@@ -710,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;
 }
 
@@ -728,36 +709,23 @@ note_vague_linkage_fn (tree decl)
     }
 }
 
-/* Like note_vague_linkage_fn but for variables.  */
-
-static void
-note_vague_linkage_var (tree var)
-{
-  VEC_safe_push (tree, gc, pending_statics, var);
-}
-
 /* We have just processed the DECL, which is a static data member.
-   Its initializer, if present, is INIT.  The ASMSPEC_TREE, if
-   present, is the assembly-language name for the data member.
-   FLAGS is as for cp_finish_decl.  */
+   The other parameters are as for cp_finish_decl.  */
 
 void
-finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree,
+finish_static_data_member_decl (tree decl,
+                               tree init, bool init_const_expr_p,
+                               tree asmspec_tree,
                                int flags)
 {
-  gcc_assert (TREE_PUBLIC (decl));
-
   DECL_CONTEXT (decl) = current_class_type;
 
   /* We cannot call pushdecl here, because that would fill in the
      TREE_CHAIN of our decl.  Instead, we modify cp_finish_decl to do
      the right thing, namely, to put this decl out straight away.  */
-  /* current_class_type can be NULL_TREE in case of error.  */
-  if (!asmspec_tree && current_class_type)
-    DECL_INITIAL (decl) = error_mark_node;
 
   if (! processing_template_decl)
-    note_vague_linkage_var (decl);
+    VEC_safe_push (tree, gc, pending_statics, decl);
 
   if (LOCAL_CLASS_P (current_class_type))
     pedwarn ("local class %q#T shall not have static data member %q#D",
@@ -783,31 +751,18 @@ finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree,
   DECL_INITIAL (decl) = init;
   DECL_IN_AGGR_P (decl) = 1;
 
-  cp_finish_decl (decl, init, asmspec_tree, flags);
+  cp_finish_decl (decl, init, init_const_expr_p, asmspec_tree, flags);
 }
 
-/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
-   of a structure component, returning a _DECL node.
-   QUALS is a list of type qualifiers for this decl (such as for declaring
-   const member functions).
-
-   This is done during the parsing of the struct declaration.
-   The _DECL nodes are chained together and the lot of them
-   are ultimately passed to `build_struct' to make the RECORD_TYPE node.
-
-   If class A defines that certain functions in class B are friends, then
-   the way I have set things up, it is B who is interested in permission
-   granted by A.  However, it is in A's context that these declarations
-   are parsed.  By returning a void_type_node, class A does not attempt
-   to incorporate the declarations of the friends within its structure.
-
-   DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
-   CHANGES TO CODE IN `start_method'.  */
+/* DECLARATOR and DECLSPECS correspond to a class member.  The other
+   parameters are as for cp_finish_decl.  Return the DECL for the
+   class member declared.  */
 
 tree
 grokfield (const cp_declarator *declarator,
           cp_decl_specifier_seq *declspecs,
-          tree init, tree asmspec_tree,
+          tree init, bool init_const_expr_p,
+          tree asmspec_tree,
           tree attrlist)
 {
   tree value;
@@ -817,6 +772,8 @@ grokfield (const cp_declarator *declarator,
   if (!declspecs->any_specifiers_p
       && declarator->kind == cdk_id
       && declarator->u.id.qualifying_scope
+      && TYPE_P (declarator->u.id.qualifying_scope)
+      && IS_AGGR_TYPE (declarator->u.id.qualifying_scope)
       && TREE_CODE (declarator->u.id.unqualified_name) == IDENTIFIER_NODE)
     /* Access declaration */
     return do_class_using_decl (declarator->u.id.qualifying_scope,
@@ -885,7 +842,7 @@ grokfield (const cp_declarator *declarator,
       return void_type_node;
     }
 
-  if (asmspec_tree)
+  if (asmspec_tree && asmspec_tree != error_mark_node)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
   if (init)
@@ -946,8 +903,8 @@ grokfield (const cp_declarator *declarator,
   switch (TREE_CODE (value))
     {
     case VAR_DECL:
-      finish_static_data_member_decl (value, init, asmspec_tree,
-                                     flags);
+      finish_static_data_member_decl (value, init, init_const_expr_p,
+                                     asmspec_tree, flags);
       return value;
 
     case FIELD_DECL:
@@ -955,7 +912,8 @@ grokfield (const cp_declarator *declarator,
        error ("%<asm%> specifiers are not permitted on non-static data members");
       if (DECL_INITIAL (value) == error_mark_node)
        init = error_mark_node;
-      cp_finish_decl (value, init, NULL_TREE, flags);
+      cp_finish_decl (value, init, /*init_const_expr_p=*/false,
+                     NULL_TREE, flags);
       DECL_INITIAL (value) = init;
       DECL_IN_AGGR_P (value) = 1;
       return value;
@@ -963,10 +921,11 @@ grokfield (const cp_declarator *declarator,
     case  FUNCTION_DECL:
       if (asmspec)
        set_user_assembler_name (value, asmspec);
-      if (!DECL_FRIEND_P (value))
-       grok_special_member_properties (value);
 
-      cp_finish_decl (value, init, asmspec_tree, flags);
+      cp_finish_decl (value,
+                     /*init=*/NULL_TREE,
+                     /*init_const_expr_p=*/false,
+                     asmspec_tree, flags);
 
       /* Pass friends back this way.  */
       if (DECL_FRIEND_P (value))
@@ -990,7 +949,8 @@ grokbitfield (const cp_declarator *declarator,
 {
   tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL);
 
-  if (! value) return NULL_TREE; /* friends went bad.  */
+  if (value == error_mark_node) 
+    return NULL_TREE; /* friends went bad.  */
 
   /* Pass friendly classes back.  */
   if (TREE_CODE (value) == VOID_TYPE)
@@ -1025,7 +985,7 @@ grokbitfield (const cp_declarator *declarator,
       error ("static member %qD cannot be a bit-field", value);
       return NULL_TREE;
     }
-  cp_finish_decl (value, NULL_TREE, NULL_TREE, 0);
+  finish_decl (value, NULL_TREE, NULL_TREE);
 
   if (width != error_mark_node)
     {
@@ -1042,7 +1002,8 @@ grokbitfield (const cp_declarator *declarator,
 void
 cplus_decl_attributes (tree *decl, tree attributes, int flags)
 {
-  if (*decl == NULL_TREE || *decl == void_type_node)
+  if (*decl == NULL_TREE || *decl == void_type_node
+      || *decl == error_mark_node)
     return;
 
   if (TREE_CODE (*decl) == TEMPLATE_DECL)
@@ -1155,6 +1116,8 @@ finish_anon_union (tree anon_union_decl)
     }
 
   main_decl = build_anon_union_vars (type, anon_union_decl);
+  if (main_decl == error_mark_node)
+    return;
   if (main_decl == NULL_TREE)
     {
       warning (0, "anonymous union with no members");
@@ -1576,22 +1539,166 @@ maybe_emit_vtables (tree ctype)
   return true;
 }
 
+/* A special return value from type_visibility meaning internal
+   linkage.  */
+
+enum { VISIBILITY_ANON = VISIBILITY_INTERNAL+1 };
+
+/* walk_tree helper function for type_visibility.  */
+
+static tree
+min_vis_r (tree *tp, int *walk_subtrees, void *data)
+{
+  int *vis_p = (int *)data;
+  if (! TYPE_P (*tp))
+    {
+      *walk_subtrees = 0;
+    }
+  else if (CLASS_TYPE_P (*tp))
+    {
+      if (!TREE_PUBLIC (TYPE_MAIN_DECL (*tp)))
+       {
+         *vis_p = VISIBILITY_ANON;
+         return *tp;
+       }
+      else if (CLASSTYPE_VISIBILITY (*tp) > *vis_p)
+       *vis_p = CLASSTYPE_VISIBILITY (*tp);
+    }
+  return NULL;
+}
+
+/* Returns the visibility of TYPE, which is the minimum visibility of its
+   component types.  */
+
+static int
+type_visibility (tree type)
+{
+  int vis = VISIBILITY_DEFAULT;
+  walk_tree_without_duplicates (&type, min_vis_r, &vis);
+  return vis;
+}
+
+/* Limit the visibility of DECL to VISIBILITY, if not explicitly
+   specified (or if VISIBILITY is static).  */
+
+static bool
+constrain_visibility (tree decl, int visibility)
+{
+  if (visibility == VISIBILITY_ANON)
+    {
+      /* 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)
+          && !DECL_VISIBILITY_SPECIFIED (decl))
+    {
+      DECL_VISIBILITY (decl) = visibility;
+      return true;
+    }
+  return false;
+}
+
+/* Constrain the visibility of DECL based on the visibility of its template
+   arguments.  */
+
+static void
+constrain_visibility_for_template (tree decl, tree targs)
+{
+  /* If this is a template instantiation, check the innermost
+     template args for visibility constraints.  The outer template
+     args are covered by the class check.  */
+  tree args = INNERMOST_TEMPLATE_ARGS (targs);
+  int i;
+  for (i = TREE_VEC_LENGTH (args); i > 0; --i)
+    {
+      int vis = 0;
+
+      tree arg = TREE_VEC_ELT (args, i-1);
+      if (TYPE_P (arg))
+       vis = type_visibility (arg);
+      else if (TREE_TYPE (arg) && POINTER_TYPE_P (TREE_TYPE (arg)))
+       {
+         STRIP_NOPS (arg);
+         if (TREE_CODE (arg) == ADDR_EXPR)
+           arg = TREE_OPERAND (arg, 0);
+         if (TREE_CODE (arg) == VAR_DECL
+             || TREE_CODE (arg) == FUNCTION_DECL)
+           {
+             if (! TREE_PUBLIC (arg))
+               vis = VISIBILITY_ANON;
+             else
+               vis = DECL_VISIBILITY (arg);
+           }
+       }
+      if (vis)
+       constrain_visibility (decl, vis);
+    }
+}
+
 /* Like c_determine_visibility, but with additional C++-specific
-   behavior.  */
+   behavior.
+
+   Function-scope entities can rely on the function's visibility because
+   it is set in start_preparsed_function.
+
+   Class-scope entities cannot rely on the class's visibility until the end
+   of the enclosing class definition.
+
+   Note that because namespaces have multiple independent definitions,
+   namespace visibility is handled elsewhere using the #pragma visibility
+   machinery rather than by decorating the namespace declaration.
+
+   The goal is for constraints from the type to give a diagnostic, and
+   other constraints to be applied silently.  */
 
 void
 determine_visibility (tree decl)
 {
-  tree class_type;
+  tree class_type = NULL_TREE;
+  bool use_template;
+
+  /* Remember that all decls get VISIBILITY_DEFAULT when built.  */
+
+  /* Only relevant for names with external linkage.  */
+  if (!TREE_PUBLIC (decl))
+    return;
 
   /* Cloned constructors and destructors get the same visibility as
      the underlying function.  That should be set up in
      maybe_clone_body.  */
   gcc_assert (!DECL_CLONED_FUNCTION_P (decl));
 
-  /* Give the common code a chance to make a determination.  */
-  if (c_determine_visibility (decl))
-    return;
+  if (TREE_CODE (decl) == TYPE_DECL)
+    {
+      if (CLASS_TYPE_P (TREE_TYPE (decl)))
+       use_template = CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl));
+      else if (TYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
+       use_template = 1;
+      else
+       use_template = 0;
+    }
+  else if (DECL_LANG_SPECIFIC (decl))
+    use_template = DECL_USE_TEMPLATE (decl);
+  else
+    use_template = 0;
+
+  /* Anything that is exported must have default visibility.  */
+  if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+      && lookup_attribute ("dllexport",
+                          TREE_CODE (decl) == TYPE_DECL
+                          ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
+                          : DECL_ATTRIBUTES (decl)))
+    {
+      DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+      DECL_VISIBILITY_SPECIFIED (decl) = 1;
+    }
 
   /* If DECL is a member of a class, visibility specifiers on the
      class can influence the visibility of the DECL.  */
@@ -1603,47 +1710,188 @@ determine_visibility (tree decl)
     class_type = TREE_TYPE (DECL_NAME (decl));
   else
     {
+      /* Not a class member.  */
+
       /* Virtual tables have DECL_CONTEXT set to their associated class,
         so they are automatically handled above.  */
       gcc_assert (TREE_CODE (decl) != VAR_DECL
                  || !DECL_VTABLE_OR_VTT_P (decl));
-      /* Entities not associated with any class just get the
-        visibility specified by their attributes.  */
-      return;
-    }
 
-  /* By default, static data members and function members receive
-     the visibility of their containing class.  */
-  if (class_type)
-    {
-      if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
-         && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class_type)))
-       {
-         DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
-         DECL_VISIBILITY_SPECIFIED (decl) = 1;
-       }
-      else if (TREE_CODE (decl) == FUNCTION_DECL
-              && DECL_DECLARED_INLINE_P (decl)
-              && visibility_options.inlines_hidden)
+      if (DECL_FUNCTION_SCOPE_P (decl) && ! DECL_VISIBILITY_SPECIFIED (decl))
        {
-         /* Don't change it if it has been set explicitly by user.  */
-         if (!DECL_VISIBILITY_SPECIFIED (decl))
+         /* Local statics and classes get the visibility of their
+            containing function by default, except that
+            -fvisibility-inlines-hidden doesn't affect them.  */
+         tree fn = DECL_CONTEXT (decl);
+         if (DECL_VISIBILITY_SPECIFIED (fn) || ! DECL_CLASS_SCOPE_P (fn))
            {
-             DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
-             DECL_VISIBILITY_SPECIFIED (decl) = 1;
+             DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
+             DECL_VISIBILITY_SPECIFIED (decl) = 
+               DECL_VISIBILITY_SPECIFIED (fn);
            }
+         else
+           determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+
+         /* Local classes in templates have CLASSTYPE_USE_TEMPLATE set,
+            but have no TEMPLATE_INFO, so don't try to check it.  */
+         use_template = 0;
        }
-      else if (CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
+      else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl))
        {
-         DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
-         DECL_VISIBILITY_SPECIFIED (decl) = 1;
+         /* tinfo visibility is based on the type it's for.  */
+         constrain_visibility
+           (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))));
        }
-      else if (!DECL_VISIBILITY_SPECIFIED (decl))
+      else if (use_template)
+       /* Template instantiations and specializations get visibility based
+          on their template unless they override it with an attribute.  */;
+      else if (! DECL_VISIBILITY_SPECIFIED (decl))
+       {
+         /* Set default visibility to whatever the user supplied with
+            #pragma GCC visibility or a namespace visibility attribute.  */
+         DECL_VISIBILITY (decl) = default_visibility;
+         DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+       }
+    }
+
+  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);
+      
+      if (args != error_mark_node)
        {
-         DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
-         DECL_VISIBILITY_SPECIFIED (decl) = 0;
+         int depth = TMPL_ARGS_DEPTH (args);
+         tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
+
+         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);
+
+  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_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
+   the visibility of their containing class.  */
+
+static void
+determine_visibility_from_class (tree decl, tree class_type)
+{
+  if (visibility_options.inlines_hidden
+      /* Don't do this for inline templates; specializations might not be
+        inline, and we don't want them to inherit the hidden
+        visibility.  We'll set it here for all inline instantiations.  */
+      && !processing_template_decl
+      && ! DECL_VISIBILITY_SPECIFIED (decl)
+      && TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_DECLARED_INLINE_P (decl)
+      && (! DECL_LANG_SPECIFIC (decl)
+         || ! DECL_EXPLICIT_INSTANTIATION (decl)))
+    DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+  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.  */
+  if (TREE_CODE (decl) == VAR_DECL
+      && (DECL_TINFO_P (decl)
+         || (DECL_VTABLE_OR_VTT_P (decl)
+             /* Construction virtual tables are not exported because
+                they cannot be referred to from other object files;
+                their name is not standardized by the ABI.  */
+             && !DECL_CONSTRUCTION_VTABLE_P (decl)))
+      && TREE_PUBLIC (decl)
+      && !DECL_REALLY_EXTERN (decl)
+      && !DECL_VISIBILITY_SPECIFIED (decl)
+      && !CLASSTYPE_VISIBILITY_SPECIFIED (class_type))
+    targetm.cxx.determine_class_data_visibility (decl);
+}
+
+/* Constrain the visibility of a class TYPE based on the visibility of its
+   field types.  Warn if any fields require lesser visibility.  */
+
+void
+constrain_class_visibility (tree 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 && 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);
+      }
+
+  binfo = TYPE_BINFO (type);
+  for (i = 0; BINFO_BASE_ITERATE (binfo, i, t); ++i)
+    {
+      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));
+    }
 }
 
 /* DECL is a FUNCTION_DECL or VAR_DECL.  If the object file linkage
@@ -1795,9 +2043,13 @@ import_export_decl (tree decl)
              /* The generic C++ ABI says that class data is always
                 COMDAT, even if there is a key function.  Some
                 variants (e.g., the ARM EABI) says that class data
-                only has COMDAT linkage if the class data might
-                be emitted in more than one translation unit.  */
+                only has COMDAT linkage if the class data might be
+                emitted in more than one translation unit.  When the
+                key method can be inline and is inline, we still have
+                to arrange for comdat even though
+                class_data_always_comdat is false.  */
              if (!CLASSTYPE_KEY_METHOD (class_type)
+                 || DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (class_type))
                  || targetm.cxx.class_data_always_comdat ())
                {
                  /* The ABI requires COMDAT linkage.  Normally, we
@@ -1836,7 +2088,9 @@ import_export_decl (tree decl)
              if (CLASSTYPE_INTERFACE_KNOWN (type)
                  && !CLASSTYPE_INTERFACE_ONLY (type))
                {
-                 comdat_p = targetm.cxx.class_data_always_comdat ();
+                 comdat_p = (targetm.cxx.class_data_always_comdat ()
+                             || (CLASSTYPE_KEY_METHOD (type)
+                                 && DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type))));
                  mark_needed (decl);
                  if (!flag_weak)
                    {
@@ -1910,21 +2164,6 @@ import_export_decl (tree decl)
       comdat_linkage (decl);
     }
 
-  /* Give the target a chance to override the visibility associated
-     with DECL.  */
-  if (TREE_CODE (decl) == VAR_DECL
-      && (DECL_TINFO_P (decl)
-         || (DECL_VTABLE_OR_VTT_P (decl)
-             /* Construction virtual tables are not exported because
-                they cannot be referred to from other object files;
-                their name is not standardized by the ABI.  */
-             && !DECL_CONSTRUCTION_VTABLE_P (decl)))
-      && TREE_PUBLIC (decl)
-      && !DECL_REALLY_EXTERN (decl)
-      && DECL_VISIBILITY_SPECIFIED (decl)
-      && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type)))
-    targetm.cxx.determine_class_data_visibility (decl);
-
   DECL_INTERFACE_KNOWN (decl) = 1;
 }
 
@@ -2110,7 +2349,7 @@ start_objects (int method_type, int initp)
 
   /* We cannot allow these functions to be elided, even if they do not
      have external linkage.  And, there's no point in deferring
-     compilation of thes functions; they're all going to have to be
+     compilation of these functions; they're all going to have to be
      out anyhow.  */
   DECL_INLINE (current_function_decl) = 0;
   DECL_UNINLINABLE (current_function_decl) = 1;
@@ -2424,12 +2663,12 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
   if (initp)
     {
       if (init)
-        finish_expr_stmt (init);
+       finish_expr_stmt (init);
 
       /* If we're using __cxa_atexit, register a function that calls the
-         destructor for the object.  */
+        destructor for the object.  */
       if (flag_use_cxa_atexit)
-        finish_expr_stmt (register_dtor_fn (decl));
+       finish_expr_stmt (register_dtor_fn (decl));
     }
   else
     finish_expr_stmt (build_cleanup (decl));
@@ -2502,7 +2741,7 @@ do_static_initialization_or_destruction (tree vars, bool initp)
         node = TREE_CHAIN (node))
       /* Do one initialization or destruction.  */
       one_static_initialization_or_destruction (TREE_VALUE (node),
-                                               TREE_PURPOSE (node), initp);
+                                               TREE_PURPOSE (node), initp);
 
     /* Finish up the priority if-stmt body.  */
     finish_then_clause (priority_if_stmt);
@@ -2683,7 +2922,7 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
 static int
 generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
 {
-  location_t *locus = data;
+  location_t *locus = (location_t *) data;
   int priority = (int) n->key;
   priority_info pi = (priority_info) n->value;
 
@@ -2998,7 +3237,7 @@ cp_finish_file (void)
             DECL_EXTERNAL appropriately, so there's no need to check
             again, and we do not want to clear DECL_EXTERNAL if a
             previous call to import_export_decl set it.
-            
+
             This is done in a separate for cycle, because if some
             deferred function is contained in another deferred
             function later in deferred_fns varray,
@@ -3091,7 +3330,7 @@ cp_finish_file (void)
   else
     {
       /* If we have a ctor or this is obj-c++ and we need a static init,
-         call generate_ctor_or_dtor_function.  */
+        call generate_ctor_or_dtor_function.  */
       if (static_ctors || (c_dialect_objc () && objc_static_init_needed_p ()))
        generate_ctor_or_dtor_function (/*constructor_p=*/true,
                                        DEFAULT_INIT_PRIORITY, &locus);
@@ -3120,7 +3359,7 @@ cp_finish_file (void)
   if (VEC_length (tree, pending_statics) != 0)
     {
       check_global_declarations (VEC_address (tree, pending_statics),
-                                VEC_length (tree, pending_statics));
+                                VEC_length (tree, pending_statics));
       emit_debug_global_declarations (VEC_address (tree, pending_statics),
                                      VEC_length (tree, pending_statics));
     }
@@ -3228,7 +3467,7 @@ check_default_args (tree x)
       else if (saw_def)
        {
          error ("default argument missing for parameter %P of %q+#D", i, x);
-         break;
+         TREE_PURPOSE (arg) = error_mark_node;
        }
     }
 }
@@ -3255,7 +3494,9 @@ mark_used (tree decl)
     }
 
   TREE_USED (decl) = 1;
-  /* If we don't need a value, then we don't need to synthesize DECL.  */ 
+  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;
   /* Normally, we can wait until instantiation-time to synthesize
@@ -3279,9 +3520,9 @@ mark_used (tree decl)
       saved_processing_template_decl = processing_template_decl;
       processing_template_decl = 0;
     }
-  
+
   if (processing_template_decl)
-    return;  
+    return;
 
   if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
       && !TREE_ASM_WRITTEN (decl))
@@ -3316,30 +3557,29 @@ mark_used (tree decl)
     {
       synthesize_method (decl);
       /* If we've already synthesized the method we don't need to
-        instantiate it, so we can return right away.  */
-      return;
-    }
-
-  /* If this is a function or variable that is an instance of some
-     template, we now know that we will need to actually do the
-     instantiation. We check that DECL is not an explicit
-     instantiation because that is not checked in instantiate_decl.  */
-  if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
-      && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
-      && (!DECL_EXPLICIT_INSTANTIATION (decl)
-         || (TREE_CODE (decl) == FUNCTION_DECL
-             && DECL_INLINE (DECL_TEMPLATE_RESULT
-                             (template_for_substitution (decl))))
-         /* We need to instantiate static data members so that there
-            initializers are available in integral constant
-            expressions.  */
-         || (TREE_CODE (decl) == VAR_DECL
-             && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))))
-    /* We put off instantiating functions in order to improve compile
+        do the instantiation test below.  */
+    }
+  else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
+          && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
+          && (!DECL_EXPLICIT_INSTANTIATION (decl)
+              || (TREE_CODE (decl) == FUNCTION_DECL
+                  && DECL_INLINE (DECL_TEMPLATE_RESULT
+                                  (template_for_substitution (decl))))
+              /* We need to instantiate static data members so that there
+                 initializers are available in integral constant
+                 expressions.  */
+              || (TREE_CODE (decl) == VAR_DECL
+                  && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))))
+    /* If this is a function or variable that is an instance of some
+       template, we now know that we will need to actually do the
+       instantiation. We check that DECL is not an explicit
+       instantiation because that is not checked in instantiate_decl.
+
+       We put off instantiating functions in order to improve compile
        times.  Maintaining a stack of active functions is expensive,
        and the inliner knows to instantiate any functions it might
-       need.  */
-    instantiate_decl (decl, /*defer_ok=*/true, 
+       need.  Therefore, we always try to defer instantiation.  */
+    instantiate_decl (decl, /*defer_ok=*/true,
                      /*expl_inst_class_mem_p=*/false);
 
   processing_template_decl = saved_processing_template_decl;