OSDN Git Service

PR c++/27951
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index 88d7e8e..49e320c 100644 (file)
@@ -103,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
@@ -149,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);
@@ -257,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.  */
@@ -274,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)
@@ -478,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.  */
@@ -741,7 +708,7 @@ note_vague_linkage_var (tree var)
    The other parameters are as for cp_finish_decl.  */
 
 void
-finish_static_data_member_decl (tree decl, 
+finish_static_data_member_decl (tree decl,
                                tree init, bool init_const_expr_p,
                                tree asmspec_tree,
                                int flags)
@@ -753,9 +720,6 @@ finish_static_data_member_decl (tree decl,
   /* 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);
@@ -787,9 +751,9 @@ finish_static_data_member_decl (tree decl,
   cp_finish_decl (decl, init, init_const_expr_p, asmspec_tree, flags);
 }
 
-/* DECLARATOR and DECLSPECS correspond to a class member.  The othe
+/* 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.  */ 
+   class member declared.  */
 
 tree
 grokfield (const cp_declarator *declarator,
@@ -943,7 +907,7 @@ 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, /*init_const_expr_p=*/false, 
+      cp_finish_decl (value, init, /*init_const_expr_p=*/false,
                      NULL_TREE, flags);
       DECL_INITIAL (value) = init;
       DECL_IN_AGGR_P (value) = 1;
@@ -952,10 +916,10 @@ 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, /*init_const_expr_p=*/false, 
+      cp_finish_decl (value,
+                     /*init=*/NULL_TREE,
+                     /*init_const_expr_p=*/false,
                      asmspec_tree, flags);
 
       /* Pass friends back this way.  */
@@ -1145,6 +1109,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");
@@ -1644,7 +1610,7 @@ determine_visibility (tree decl)
          && DECL_VISIBILITY_SPECIFIED (decl)
          && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type)))
        targetm.cxx.determine_class_data_visibility (decl);
-    }      
+    }
 }
 
 static void
@@ -2142,7 +2108,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;
@@ -2456,12 +2422,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));
@@ -2534,7 +2500,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);
@@ -3030,7 +2996,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,
@@ -3123,7 +3089,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);
@@ -3152,7 +3118,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));
     }
@@ -3287,7 +3253,7 @@ mark_used (tree decl)
     }
 
   TREE_USED (decl) = 1;
-  /* If we don't need a value, then we don't need to synthesize DECL.  */ 
+  /* 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
@@ -3311,9 +3277,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))
@@ -3348,30 +3314,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;