OSDN Git Service

PR c++/29016
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck.c
index 5861f23..4713f05 100644 (file)
@@ -228,7 +228,9 @@ commonparms (tree p1, tree p2)
 static tree
 original_type (tree t)
 {
-  while (TYPE_NAME (t) != NULL_TREE)
+  int quals = cp_type_quals (t);
+  while (t != error_mark_node
+        && TYPE_NAME (t) != NULL_TREE)
     {
       tree x = TYPE_NAME (t);
       if (TREE_CODE (x) != TYPE_DECL)
@@ -238,7 +240,7 @@ original_type (tree t)
        break;
       t = x;
     }
-  return t;
+  return cp_build_qualified_type (t, quals);
 }
 
 /* T1 and T2 are arithmetic or enumeration types.  Return the type
@@ -729,7 +731,13 @@ merge_types (tree t1, tree t2)
 
     default:;
     }
-  return cp_build_type_attribute_variant (t1, attributes);
+
+  if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
+    return t1;
+  else if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
+    return t2;
+  else
+    return cp_build_type_attribute_variant (t1, attributes);
 }
 
 /* Return the common type of two types.
@@ -1317,7 +1325,7 @@ static tree
 cxx_alignof_expr (tree e)
 {
   tree t;
-  
+
   if (e == error_mark_node)
     return error_mark_node;
 
@@ -1504,7 +1512,7 @@ decay_conversion (tree exp)
       adr = build_unary_op (ADDR_EXPR, exp, 1);
       return cp_convert (ptrtype, adr);
     }
-  
+
   /* If a bitfield is used in a context where integral promotion
      applies, then the caller is expected to have used
      default_conversion.  That function promotes bitfields correctly
@@ -1545,7 +1553,7 @@ default_conversion (tree exp)
 {
   /* Perform the integral promotions first so that bitfield
      expressions (which may promote to "int", even if the bitfield is
-     declared "unsigned") are promoted correctly.  */  
+     declared "unsigned") are promoted correctly.  */
   if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (exp)))
     exp = perform_integral_promotions (exp);
   /* Perform the other conversions.  */
@@ -1626,7 +1634,9 @@ string_conv_p (tree totype, tree exp, int warn)
 
   /* This warning is not very useful, as it complains about printf.  */
   if (warn)
-    warning (OPT_Wwrite_strings, "deprecated conversion from string constant to %qT'", totype);
+    warning (OPT_Wwrite_strings,
+            "deprecated conversion from string constant to %qT",
+            totype);
 
   return 1;
 }
@@ -1722,7 +1732,7 @@ build_class_member_access_expr (tree object, tree member,
   tree member_scope;
   tree result = NULL_TREE;
 
-  if (object == error_mark_node || member == error_mark_node)
+  if (error_operand_p (object) || error_operand_p (member))
     return error_mark_node;
 
   gcc_assert (DECL_P (member) || BASELINK_P (member));
@@ -1989,8 +1999,8 @@ check_template_keyword (tree decl)
       template, the program is ill-formed.
 
      DR 228 removed the restriction that the template be a member
-     template.  
-     
+     template.
+
      DR 96, if accepted would add the further restriction that explicit
      template arguments must be provided if the template keyword is
      used, but, as of 2005-10-16, that DR is still in "drafting".  If
@@ -2198,7 +2208,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p)
                                orig_object, orig_name,
                                NULL_TREE);
     }
-  
+
   return expr;
 }
 
@@ -3040,16 +3050,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
   switch (code)
     {
-    case PLUS_EXPR:
-      /* Handle the pointer + int case.  */
-      if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
-       return cp_pointer_int_sum (PLUS_EXPR, op0, op1);
-      else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
-       return cp_pointer_int_sum (PLUS_EXPR, op1, op0);
-      else
-       common = 1;
-      break;
-
     case MINUS_EXPR:
       /* Subtraction of two similar pointers.
         We must subtract them as integers, then divide by object size.  */
@@ -3057,11 +3057,33 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0),
                                                        TREE_TYPE (type1)))
        return pointer_diff (op0, op1, common_type (type0, type1));
-      /* Handle pointer minus int.  Just like pointer plus int.  */
-      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
-       return cp_pointer_int_sum (MINUS_EXPR, op0, op1);
-      else
-       common = 1;
+      /* In all other cases except pointer - int, the usual arithmetic
+        rules aply.  */
+      else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE))
+       {
+         common = 1;
+         break;
+       }
+      /* The pointer - int case is just like pointer + int; fall
+        through.  */
+    case PLUS_EXPR:
+      if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE)
+         && (code0 == INTEGER_TYPE || code1 == INTEGER_TYPE))
+       {
+         tree ptr_operand;
+         tree int_operand;
+         ptr_operand = ((code0 == POINTER_TYPE) ? op0 : op1);
+         int_operand = ((code0 == INTEGER_TYPE) ? op0 : op1);
+         if (processing_template_decl)
+           {
+             result_type = TREE_TYPE (ptr_operand);
+             break;
+           }
+         return cp_pointer_int_sum (code,
+                                    ptr_operand, 
+                                    int_operand);
+       }
+      common = 1;
       break;
 
     case MULT_EXPR:
@@ -3214,8 +3236,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case EQ_EXPR:
     case NE_EXPR:
       if (code0 == REAL_TYPE || code1 == REAL_TYPE)
-       warning (OPT_Wfloat_equal, 
-                 "comparing floating point with == or != is unsafe");
+       warning (OPT_Wfloat_equal,
+                "comparing floating point with == or != is unsafe");
       if ((TREE_CODE (orig_op0) == STRING_CST && !integer_zerop (op1))
          || (TREE_CODE (orig_op1) == STRING_CST && !integer_zerop (op0)))
        warning (OPT_Wstring_literal_comparison,
@@ -3981,7 +4003,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
       else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM,
                                                   arg, true)))
        errstring = "wrong type argument to bit-complement";
-      else if (!noconvert)
+      else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
        arg = perform_integral_promotions (arg);
       break;
 
@@ -4289,6 +4311,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
            pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression");
          break;
 
+       case BASELINK:
+         arg = BASELINK_FUNCTIONS (arg);
+         /* Fall through.  */
+
        case OVERLOAD:
          arg = OVL_CURRENT (arg);
          break;
@@ -5706,11 +5732,19 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
       /* Allow array assignment in compiler-generated code.  */
       if (! DECL_ARTIFICIAL (current_function_decl))
-       pedwarn ("ISO C++ forbids assignment of arrays");
+       {
+          /* This routine is used for both initialization and assignment.
+             Make sure the diagnostic message differentiates the context.  */
+          if (modifycode == INIT_EXPR)
+            error ("array used as initializer");
+          else
+            error ("invalid array assignment");
+         return error_mark_node;
+       }
 
       from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
                   ? 1 + (modifycode != INIT_EXPR): 0;
-      return build_vec_init (lhs, NULL_TREE, newrhs, 
+      return build_vec_init (lhs, NULL_TREE, newrhs,
                             /*explicit_default_init_p=*/false,
                             from_array);
     }
@@ -6200,7 +6234,7 @@ convert_for_assignment (tree type, tree rhs,
                 "%s might be a candidate for a format attribute",
                 errtype);
     }
-  
+
   return perform_implicit_conversion (strip_top_quals (type), rhs);
 }
 
@@ -6335,6 +6369,10 @@ maybe_warn_about_returning_address_of_local (tree retval)
        }
     }
 
+  while (TREE_CODE (whats_returned) == COMPONENT_REF
+        || TREE_CODE (whats_returned) == ARRAY_REF)
+    whats_returned = TREE_OPERAND (whats_returned, 0);
+
   if (DECL_P (whats_returned)
       && DECL_NAME (whats_returned)
       && DECL_FUNCTION_SCOPE_P (whats_returned)
@@ -6420,8 +6458,8 @@ check_return_expr (tree retval, bool *no_warning)
         return!).  */
       current_function_returns_null = 0;
       /* And signal caller that TREE_NO_WARNING should be set on the
-         RETURN_EXPR to avoid control reaches end of non-void function
-         warnings in tree-cfg.c.  */
+        RETURN_EXPR to avoid control reaches end of non-void function
+        warnings in tree-cfg.c.  */
       *no_warning = true;
     }
   /* Check for a return statement with a value in a function that
@@ -6550,7 +6588,7 @@ check_return_expr (tree retval, bool *no_warning)
         was an incomplete type.  Just treat this as 'return;' */
       if (VOID_TYPE_P (functype))
        return error_mark_node;
-      
+
       /* First convert the value to the function's return type, then
         to the type of return value's location to handle the
         case that functype is smaller than the valtype.  */