summaryrefslogtreecommitdiff
path: root/gcc/c-typeck.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-typeck.c')
-rw-r--r--gcc/c-typeck.c135
1 files changed, 95 insertions, 40 deletions
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 083b5a15ac3..dade1e53391 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -29,21 +29,16 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "rtl.h"
#include "tree.h"
#include "langhooks.h"
#include "c-tree.h"
#include "c-lang.h"
-#include "tm_p.h"
#include "flags.h"
#include "output.h"
-#include "expr.h"
#include "toplev.h"
#include "intl.h"
-#include "ggc.h"
#include "target.h"
#include "tree-iterator.h"
-#include "gimple.h"
#include "tree-flow.h"
/* Possible cases of implicit bad conversions. Used to select
@@ -80,10 +75,12 @@ static int require_constant_elements;
static bool null_pointer_constant_p (const_tree);
static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *);
+static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *,
+ bool *);
static int comp_target_types (location_t, tree, tree);
-static int function_types_compatible_p (const_tree, const_tree, bool *);
-static int type_lists_compatible_p (const_tree, const_tree, bool *);
+static int function_types_compatible_p (const_tree, const_tree, bool *,
+ bool *);
+static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
static tree lookup_field (tree, tree);
static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
tree);
@@ -110,7 +107,7 @@ static void readonly_error (tree, enum lvalue_use);
static void readonly_warning (tree, enum lvalue_use);
static int lvalue_or_else (const_tree, enum lvalue_use);
static void record_maybe_used_decl (tree);
-static int comptypes_internal (const_tree, const_tree, bool *);
+static int comptypes_internal (const_tree, const_tree, bool *, bool *);
/* Return true if EXP is a null pointer constant, false otherwise. */
@@ -976,7 +973,7 @@ comptypes (tree type1, tree type2)
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
int val;
- val = comptypes_internal (type1, type2, NULL);
+ val = comptypes_internal (type1, type2, NULL, NULL);
free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
return val;
@@ -991,7 +988,23 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
int val;
- val = comptypes_internal (type1, type2, enum_and_int_p);
+ val = comptypes_internal (type1, type2, enum_and_int_p, NULL);
+ free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+
+ return val;
+}
+
+/* Like comptypes, but if it returns nonzero for different types, it
+ sets *DIFFERENT_TYPES_P to true. */
+
+int
+comptypes_check_different_types (tree type1, tree type2,
+ bool *different_types_p)
+{
+ const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
+ int val;
+
+ val = comptypes_internal (type1, type2, NULL, different_types_p);
free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
return val;
@@ -1002,11 +1015,17 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
but a warning may be needed if you use them together. If
ENUM_AND_INT_P is not NULL, and one type is an enum and the other a
compatible integer type, then this sets *ENUM_AND_INT_P to true;
- *ENUM_AND_INT_P is never set to false. This differs from
- comptypes, in that we don't free the seen types. */
+ *ENUM_AND_INT_P is never set to false. If DIFFERENT_TYPES_P is not
+ NULL, and the types are compatible but different enough not to be
+ permitted in C1X typedef redeclarations, then this sets
+ *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
+ false, but may or may not be set if the types are incompatible.
+ This differs from comptypes, in that we don't free the seen
+ types. */
static int
-comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
+comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
+ bool *different_types_p)
{
const_tree t1 = type1;
const_tree t2 = type2;
@@ -1036,14 +1055,24 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
{
t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
- if (enum_and_int_p != NULL && TREE_CODE (t2) != VOID_TYPE)
- *enum_and_int_p = true;
+ if (TREE_CODE (t2) != VOID_TYPE)
+ {
+ if (enum_and_int_p != NULL)
+ *enum_and_int_p = true;
+ if (different_types_p != NULL)
+ *different_types_p = true;
+ }
}
else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
{
t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
- if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE)
- *enum_and_int_p = true;
+ if (TREE_CODE (t1) != VOID_TYPE)
+ {
+ if (enum_and_int_p != NULL)
+ *enum_and_int_p = true;
+ if (different_types_p != NULL)
+ *different_types_p = true;
+ }
}
if (t1 == t2)
@@ -1083,11 +1112,12 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
break;
val = (TREE_TYPE (t1) == TREE_TYPE (t2)
? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- enum_and_int_p));
+ enum_and_int_p, different_types_p));
break;
case FUNCTION_TYPE:
- val = function_types_compatible_p (t1, t2, enum_and_int_p);
+ val = function_types_compatible_p (t1, t2, enum_and_int_p,
+ different_types_p);
break;
case ARRAY_TYPE:
@@ -1101,9 +1131,13 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
/* Target types must match incl. qualifiers. */
if (TREE_TYPE (t1) != TREE_TYPE (t2)
&& 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- enum_and_int_p)))
+ enum_and_int_p,
+ different_types_p)))
return 0;
+ if (different_types_p != NULL
+ && (d1 == 0) != (d2 == 0))
+ *different_types_p = true;
/* Sizes must match unless one is missing or variable. */
if (d1 == 0 || d2 == 0 || d1 == d2)
break;
@@ -1120,6 +1154,9 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
+ if (different_types_p != NULL
+ && d1_variable != d2_variable)
+ *different_types_p = true;
if (d1_variable || d2_variable)
break;
if (d1_zero && d2_zero)
@@ -1145,15 +1182,17 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
break;
if (attrval != 2)
- return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
- val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
+ return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+ different_types_p);
+ val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+ different_types_p);
}
break;
case VECTOR_TYPE:
val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
&& comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- enum_and_int_p));
+ enum_and_int_p, different_types_p));
break;
default:
@@ -1285,11 +1324,12 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
compatible. If the two types are not the same (which has been
checked earlier), this can only happen when multiple translation
units are being compiled. See C99 6.2.7 paragraph 1 for the exact
- rules. ENUM_AND_INT_P is as in comptypes_internal. */
+ rules. ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+ comptypes_internal. */
static int
tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
- bool *enum_and_int_p)
+ bool *enum_and_int_p, bool *different_types_p)
{
tree s1, s2;
bool needs_warning = false;
@@ -1400,7 +1440,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
if (DECL_NAME (s1) != DECL_NAME (s2))
break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
- enum_and_int_p);
+ enum_and_int_p, different_types_p);
if (result != 1 && !DECL_NAME (s1))
break;
@@ -1436,7 +1476,8 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
int result;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
- enum_and_int_p);
+ enum_and_int_p,
+ different_types_p);
if (result != 1 && !DECL_NAME (s1))
continue;
@@ -1479,7 +1520,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
|| DECL_NAME (s1) != DECL_NAME (s2))
break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
- enum_and_int_p);
+ enum_and_int_p, different_types_p);
if (result == 0)
break;
if (result == 2)
@@ -1508,11 +1549,11 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
Otherwise, if one type specifies only the number of arguments,
the other must specify that number of self-promoting arg types.
Otherwise, the argument types must match.
- ENUM_AND_INT_P is as in comptypes_internal. */
+ ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal. */
static int
function_types_compatible_p (const_tree f1, const_tree f2,
- bool *enum_and_int_p)
+ bool *enum_and_int_p, bool *different_types_p)
{
tree args1, args2;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
@@ -1533,13 +1574,17 @@ function_types_compatible_p (const_tree f1, const_tree f2,
if (TYPE_VOLATILE (ret2))
ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
- val = comptypes_internal (ret1, ret2, enum_and_int_p);
+ val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p);
if (val == 0)
return 0;
args1 = TYPE_ARG_TYPES (f1);
args2 = TYPE_ARG_TYPES (f2);
+ if (different_types_p != NULL
+ && (args1 == 0) != (args2 == 0))
+ *different_types_p = true;
+
/* An unspecified parmlist matches any specified parmlist
whose argument types don't need default promotions. */
@@ -1552,7 +1597,7 @@ function_types_compatible_p (const_tree f1, const_tree f2,
If they don't match, ask for a warning (but no error). */
if (TYPE_ACTUAL_ARG_TYPES (f1)
&& 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
- enum_and_int_p))
+ enum_and_int_p, different_types_p))
val = 2;
return val;
}
@@ -1562,23 +1607,25 @@ function_types_compatible_p (const_tree f1, const_tree f2,
return 0;
if (TYPE_ACTUAL_ARG_TYPES (f2)
&& 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
- enum_and_int_p))
+ enum_and_int_p, different_types_p))
val = 2;
return val;
}
/* Both types have argument lists: compare them and propagate results. */
- val1 = type_lists_compatible_p (args1, args2, enum_and_int_p);
+ val1 = type_lists_compatible_p (args1, args2, enum_and_int_p,
+ different_types_p);
return val1 != 1 ? val1 : val;
}
/* Check two lists of types for compatibility, returning 0 for
incompatible, 1 for compatible, or 2 for compatible with
- warning. ENUM_AND_INT_P is as in comptypes_internal. */
+ warning. ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+ comptypes_internal. */
static int
type_lists_compatible_p (const_tree args1, const_tree args2,
- bool *enum_and_int_p)
+ bool *enum_and_int_p, bool *different_types_p)
{
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
int val = 1;
@@ -1603,6 +1650,9 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
means there is supposed to be an argument
but nothing is specified about what type it has.
So match anything that self-promotes. */
+ if (different_types_p != NULL
+ && (a1 == 0) != (a2 == 0))
+ *different_types_p = true;
if (a1 == 0)
{
if (c_type_promotes_to (a2) != a2)
@@ -1617,8 +1667,11 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
else if (TREE_CODE (a1) == ERROR_MARK
|| TREE_CODE (a2) == ERROR_MARK)
;
- else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p)))
+ else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p,
+ different_types_p)))
{
+ if (different_types_p != NULL)
+ *different_types_p = true;
/* Allow wait (union {union wait *u; int *i} *)
and wait (union wait *) to be compatible. */
if (TREE_CODE (a1) == UNION_TYPE
@@ -1636,7 +1689,8 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3);
- if (comptypes_internal (mv3, mv2, enum_and_int_p))
+ if (comptypes_internal (mv3, mv2, enum_and_int_p,
+ different_types_p))
break;
}
if (memb == 0)
@@ -1657,7 +1711,8 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3);
- if (comptypes_internal (mv3, mv1, enum_and_int_p))
+ if (comptypes_internal (mv3, mv1, enum_and_int_p,
+ different_types_p))
break;
}
if (memb == 0)