OSDN Git Service

PR c++/57047
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index 8c976eb..e0c1c1f 100644 (file)
@@ -33,7 +33,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-common.h"
 #include "c-family/c-objc.h"
 #include "tree-inline.h"
-#include "tree-mudflap.h"
 #include "intl.h"
 #include "toplev.h"
 #include "flags.h"
@@ -1571,9 +1570,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
       else
        {
          /* Set the cv qualifiers.  */
-         int quals = (current_class_ref
-                      ? cp_type_quals (TREE_TYPE (current_class_ref))
-                      : TYPE_UNQUALIFIED);
+         int quals = cp_type_quals (TREE_TYPE (object));
 
          if (DECL_MUTABLE_P (decl))
            quals &= ~TYPE_QUAL_CONST;
@@ -2516,7 +2513,7 @@ check_template_template_default_arg (tree argument)
 /* Begin a class definition, as indicated by T.  */
 
 tree
-begin_class_definition (tree t, tree attributes)
+begin_class_definition (tree t)
 {
   if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t)))
     return error_mark_node;
@@ -2573,9 +2570,6 @@ begin_class_definition (tree t, tree attributes)
   pushclass (t);
   TYPE_BEING_DEFINED (t) = 1;
 
-  cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
-  fixup_attribute_variants (t);
-
   if (flag_pack_struct)
     {
       tree v;
@@ -2672,20 +2666,6 @@ finish_member_declaration (tree decl)
     {
       if (TREE_CODE (decl) == USING_DECL)
        {
-         /* We need to add the target functions to the
-            CLASSTYPE_METHOD_VEC if an enclosing scope is a template
-            class, so that this function be found by lookup_fnfields_1
-            when the using declaration is not instantiated yet.  */
-
-         tree target_decl = strip_using_decl (decl);
-         if (dependent_type_p (current_class_type)
-             && is_overloaded_fn (target_decl))
-           {
-             tree t = target_decl;
-             for (; t; t = OVL_NEXT (t))
-               add_method (current_class_type, OVL_CURRENT (t), decl);
-           }
-
          /* For now, ignore class-scope USING_DECLS, so that
             debugging backends do not see them. */
          DECL_IGNORED_P (decl) = 1;
@@ -2822,39 +2802,44 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
 tree
 baselink_for_fns (tree fns)
 {
-  tree fn;
+  tree scope;
   tree cl;
 
   if (BASELINK_P (fns) 
       || error_operand_p (fns))
     return fns;
-  
-  fn = fns;
-  if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
-    fn = TREE_OPERAND (fn, 0);
-  fn = get_first_fn (fn);
-  if (!DECL_FUNCTION_MEMBER_P (fn))
+
+  scope = ovl_scope (fns);
+  if (!CLASS_TYPE_P (scope))
     return fns;
 
-  cl = currently_open_derived_class (DECL_CONTEXT (fn));
+  cl = currently_open_derived_class (scope);
   if (!cl)
-    cl = DECL_CONTEXT (fn);
+    cl = scope;
   cl = TYPE_BINFO (cl);
   return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE);
 }
 
-/* Returns true iff DECL is an automatic variable from a function outside
+/* Returns true iff DECL is a variable from a function outside
    the current one.  */
 
 static bool
-outer_automatic_var_p (tree decl)
+outer_var_p (tree decl)
 {
   return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
          && DECL_FUNCTION_SCOPE_P (decl)
-         && !TREE_STATIC (decl)
          && DECL_CONTEXT (decl) != current_function_decl);
 }
 
+/* As above, but also checks that DECL is automatic.  */
+
+static bool
+outer_automatic_var_p (tree decl)
+{
+  return (outer_var_p (decl)
+         && !TREE_STATIC (decl));
+}
+
 /* ID_EXPRESSION is a representation of parsed, but unprocessed,
    id-expression.  (See cp_parser_id_expression for details.)  SCOPE,
    if non-NULL, is the type or namespace used to explicitly qualify
@@ -2961,9 +2946,18 @@ finish_id_expression (tree id_expression,
 
       /* Disallow uses of local variables from containing functions, except
         within lambda-expressions.  */
-      if (outer_automatic_var_p (decl)
+      if (!outer_var_p (decl)
          /* It's not a use (3.2) if we're in an unevaluated context.  */
-         && !cp_unevaluated_operand)
+         || cp_unevaluated_operand)
+       /* OK.  */;
+      else if (TREE_STATIC (decl))
+       {
+         if (processing_template_decl)
+           /* For a use of an outer static var, return the identifier so
+              that we'll look it up again in the instantiation.  */
+           return id_expression;
+       }
+      else
        {
          tree context = DECL_CONTEXT (decl);
          tree containing_function = current_function_decl;
@@ -2982,7 +2976,14 @@ finish_id_expression (tree id_expression,
 
             FIXME update for final resolution of core issue 696.  */
          if (decl_constant_var_p (decl))
-           return integral_constant_value (decl);
+           {
+             if (processing_template_decl)
+               /* In a template, the constant value may not be in a usable
+                  form, so look it up again at instantiation time.  */
+               return id_expression;
+             else
+               return integral_constant_value (decl);
+           }
 
          /* If we are in a lambda function, we can move out until we hit
             1. the context,
@@ -5372,6 +5373,7 @@ classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p)
       else if (copy_fn_p (fn) <= 0)
        continue;
 
+      maybe_instantiate_noexcept (fn);
       if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
        return false;
     }
@@ -5413,7 +5415,8 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
       return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2) 
              || (CLASS_TYPE_P (type1)
                  && (t = locate_ctor (type1))
-                 && TYPE_NOTHROW_P (TREE_TYPE (t))));
+                 && (maybe_instantiate_noexcept (t),
+                     TYPE_NOTHROW_P (TREE_TYPE (t)))));
 
     case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
       type1 = strip_array_types (type1);
@@ -5806,15 +5809,19 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec)
       member = TREE_OPERAND (t, 0);
       init = unshare_expr (TREE_OPERAND (t, 1));
     }
-  else
+  else if (TREE_CODE (t) == CALL_EXPR)
     {
-      gcc_assert (TREE_CODE (t) == CALL_EXPR);
       member = CALL_EXPR_ARG (t, 0);
       /* We don't use build_cplus_new here because it complains about
         abstract bases.  Leaving the call unwrapped means that it has the
         wrong type, but cxx_eval_constant_expression doesn't care.  */
       init = unshare_expr (t);
     }
+  else if (TREE_CODE (t) == DECL_EXPR)
+    /* Declaring a temporary, don't add it to the CONSTRUCTOR.  */
+    return true;
+  else
+    gcc_unreachable ();
   if (TREE_CODE (member) == INDIRECT_REF)
     member = TREE_OPERAND (member, 0);
   if (TREE_CODE (member) == NOP_EXPR)
@@ -5838,12 +5845,9 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec)
        member = op;
       else
        {
-         /* We don't put out anything for an empty base.  */
+         /* This is an initializer for an empty base; keep it for now so
+            we can check it in cxx_eval_bare_aggregate.  */
          gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member))));
-         /* But if the initializer isn't constexpr, leave it in so we
-            complain later.  */
-         if (potential_constant_expression (init))
-           return true;
        }
     }
   if (TREE_CODE (member) == ADDR_EXPR)
@@ -5900,6 +5904,44 @@ check_constexpr_ctor_body (tree last, tree list)
   return ok;
 }
 
+/* VEC is a vector of constructor elements built up for the base and member
+   initializers of a constructor for TYPE.  They need to be in increasing
+   offset order, which they might not be yet if TYPE has a primary base
+   which is not first in the base-clause or a vptr and at least one base
+   all of which are non-primary.  */
+
+static VEC(constructor_elt,gc) *
+sort_constexpr_mem_initializers (tree type, VEC(constructor_elt,gc) *vec)
+{
+  tree pri = CLASSTYPE_PRIMARY_BINFO (type);
+  tree field_type;
+  constructor_elt elt;
+  int i;
+
+  if (pri)
+    field_type = BINFO_TYPE (pri);
+  else if (TYPE_CONTAINS_VPTR_P (type))
+    field_type = vtbl_ptr_type_node;
+  else
+    return vec;
+
+  /* Find the element for the primary base or vptr and move it to the
+     beginning of the vec.  */
+  for (i = 0; ; ++i)
+    if (TREE_TYPE (VEC_index (constructor_elt, vec, i)->index) == field_type)
+      break;
+
+  if (i > 0)
+    {
+      elt = *VEC_index (constructor_elt, vec, i);
+      for (; i > 0; --i)
+       VEC_replace (constructor_elt, vec, i,
+                    VEC_index (constructor_elt, vec, i-1));
+      VEC_replace (constructor_elt, vec, 0, &elt);
+    }
+  return vec;
+}
+
 /* Build compile-time evalable representations of member-initializer list
    for a constexpr constructor.  */
 
@@ -5956,6 +5998,7 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
              return body;
            }
        }
+      vec = sort_constexpr_mem_initializers (type, vec);
       return build_constructor (type, vec);
     }
   else
@@ -6043,13 +6086,28 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
   bool bad;
   tree field;
   unsigned i, nelts;
+  tree ctype;
 
   if (TREE_CODE (body) != CONSTRUCTOR)
     return false;
 
-  bad = false;
   nelts = CONSTRUCTOR_NELTS (body);
-  field = TYPE_FIELDS (DECL_CONTEXT (fun));
+  ctype = DECL_CONTEXT (fun);
+  field = TYPE_FIELDS (ctype);
+
+  if (TREE_CODE (ctype) == UNION_TYPE)
+    {
+      if (nelts == 0 && next_initializable_field (field))
+       {
+         if (complain)
+           error ("%<constexpr%> constructor for union %qT must "
+                  "initialize exactly one non-static data member", ctype);
+         return true;
+       }
+      return false;
+    }
+
+  bad = false;
   for (i = 0; i <= nelts; ++i)
     {
       tree index;
@@ -6059,17 +6117,17 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
        {
          index = CONSTRUCTOR_ELT (body, i)->index;
          /* Skip base and vtable inits.  */
-         if (TREE_CODE (index) != FIELD_DECL)
+         if (TREE_CODE (index) != FIELD_DECL
+             || DECL_ARTIFICIAL (index))
            continue;
        }
       for (; field != index; field = DECL_CHAIN (field))
        {
          tree ftype;
          if (TREE_CODE (field) != FIELD_DECL
-             || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)))
+             || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
+             || DECL_ARTIFICIAL (field))
            continue;
-         if (!complain)
-           return true;
          ftype = strip_array_types (TREE_TYPE (field));
          if (type_has_constexpr_default_constructor (ftype))
            {
@@ -6080,6 +6138,8 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
                                   || errorcount != 0);
              continue;
            }
+         if (!complain)
+           return true;
          error ("uninitialized member %qD in %<constexpr%> constructor",
                 field);
          bad = true;
@@ -7043,6 +7103,12 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
          constructor_elt *inner = base_field_constructor_elt (n, ce->index);
          inner->value = elt;
        }
+      else if (TREE_CODE (ce->index) == NOP_EXPR)
+       {
+         /* This is an initializer for an empty base; now that we've
+            checked that it's constant, we can ignore it.  */
+         gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (ce->index))));
+       }
       else
        CONSTRUCTOR_APPEND_ELT (n, ce->index, elt);
     }
@@ -7205,7 +7271,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
   sub = op0;
   STRIP_NOPS (sub);
   subtype = TREE_TYPE (sub);
-  gcc_assert (POINTER_TYPE_P (subtype));
+  if (!POINTER_TYPE_P (subtype))
+    return NULL_TREE;
 
   if (TREE_CODE (sub) == ADDR_EXPR)
     {
@@ -7345,15 +7412,17 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
            }
        }
     }
-  /* *(foo *)fooarrptreturn> (*fooarrptr)[0] */
+  /* *(foo *)fooarrptr => (*fooarrptr)[0] */
   else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
           && (same_type_ignoring_top_level_qualifiers_p
               (type, TREE_TYPE (TREE_TYPE (subtype)))))
     {
       tree type_domain;
       tree min_val = size_zero_node;
-      sub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
-      if (!sub)
+      tree newsub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
+      if (newsub)
+       sub = newsub;
+      else
        sub = build1_loc (loc, INDIRECT_REF, TREE_TYPE (subtype), sub);
       type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
       if (type_domain && TYPE_MIN_VALUE (type_domain))
@@ -7422,7 +7491,11 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t,
     }
 
   if (r == NULL_TREE)
-    return t;
+    {
+      if (!addr)
+       VERIFY_CONSTANT (t);
+      return t;
+    }
   return r;
 }
 
@@ -7646,6 +7719,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
            /* Check that the LHS is constant and then discard it.  */
            cxx_eval_constant_expression (call, op0, allow_non_constant,
                                          false, non_constant_p);
+           op1 = TREE_OPERAND (t, 1);
            r = cxx_eval_constant_expression (call, op1, allow_non_constant,
                                              addr, non_constant_p);
          }
@@ -8469,6 +8543,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case UNGT_EXPR:
     case UNGE_EXPR:
     case UNEQ_EXPR:
+    case LTGT_EXPR:
     case RANGE_EXPR:
     case COMPLEX_EXPR:
       want_rval = true;
@@ -8677,7 +8752,7 @@ begin_lambda_type (tree lambda)
   xref_basetypes (type, /*bases=*/NULL_TREE);
 
   /* Start the class.  */
-  type = begin_class_definition (type, /*attributes=*/NULL_TREE);
+  type = begin_class_definition (type);
   if (type == error_mark_node)
     return error_mark_node;
 
@@ -8740,7 +8815,8 @@ tree
 lambda_capture_field_type (tree expr)
 {
   tree type;
-  if (type_dependent_expression_p (expr))
+  if (type_dependent_expression_p (expr)
+      && !(TREE_TYPE (expr) && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE))
     {
       type = cxx_make_type (DECLTYPE_TYPE);
       DECLTYPE_TYPE_EXPR (type) = expr;
@@ -8885,13 +8961,12 @@ void
 insert_capture_proxy (tree var)
 {
   cp_binding_level *b;
-  int skip;
   tree stmt_list;
 
   /* Put the capture proxy in the extra body block so that it won't clash
      with a later local variable.  */
   b = current_binding_level;
-  for (skip = 0; ; ++skip)
+  for (;;)
     {
       cp_binding_level *n = b->level_chain;
       if (n->kind == sk_function_parms)
@@ -8902,8 +8977,7 @@ insert_capture_proxy (tree var)
 
   /* And put a DECL_EXPR in the STATEMENT_LIST for the same block.  */
   var = build_stmt (DECL_SOURCE_LOCATION (var), DECL_EXPR, var);
-  stmt_list = VEC_index (tree, stmt_list_stack,
-                        VEC_length (tree, stmt_list_stack) - 1 - skip);
+  stmt_list = VEC_index (tree, stmt_list_stack, 1);
   gcc_assert (stmt_list);
   append_to_statement_list_force (var, &stmt_list);
 }
@@ -8945,7 +9019,8 @@ lambda_proxy_type (tree ref)
   if (REFERENCE_REF_P (ref))
     ref = TREE_OPERAND (ref, 0);
   type = TREE_TYPE (ref);
-  if (!dependent_type_p (type))
+  if (!dependent_type_p (type)
+      || (type && TREE_CODE (type) == POINTER_TYPE))
     return type;
   type = cxx_make_type (DECLTYPE_TYPE);
   DECLTYPE_TYPE_EXPR (type) = ref;
@@ -9359,6 +9434,8 @@ maybe_add_lambda_conv_op (tree type)
   body = begin_function_body ();
   compound_stmt = begin_compound_stmt (0);
 
+  /* decl_needed_p needs to see that it's used.  */
+  TREE_USED (statfn) = 1;
   finish_return_stmt (decay_conversion (statfn));
 
   finish_compound_stmt (compound_stmt);