summaryrefslogtreecommitdiff
path: root/gcc/c-typeck.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-03 06:06:01 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-03 06:06:01 +0000
commit2dda64a6258fe213cb75f8a1b381d6a8ce338bb4 (patch)
tree69dc5d71503b8283d8144704ac5beaf98a8a2c94 /gcc/c-typeck.c
parentd3ed35175e394ed9bf2721192f14f57c91c1fbe9 (diff)
downloadgcc-2dda64a6258fe213cb75f8a1b381d6a8ce338bb4.tar.gz
2009-06-03 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk r148111 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@148114 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-typeck.c')
-rw-r--r--gcc/c-typeck.c136
1 files changed, 99 insertions, 37 deletions
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 1a1b009398c..28fb8b8c049 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -4055,6 +4055,93 @@ build_compound_expr (tree expr1, tree expr2)
return ret;
}
+/* Issue -Wcast-qual warnings when appropriate. TYPE is the type to
+ which we are casting. OTYPE is the type of the expression being
+ cast. Both TYPE and OTYPE are pointer types. -Wcast-qual appeared
+ on the command line. */
+
+static void
+handle_warn_cast_qual (tree type, tree otype)
+{
+ tree in_type = type;
+ tree in_otype = otype;
+ int added = 0;
+ int discarded = 0;
+ bool is_const;
+
+ /* Check that the qualifiers on IN_TYPE are a superset of the
+ qualifiers of IN_OTYPE. The outermost level of POINTER_TYPE
+ nodes is uninteresting and we stop as soon as we hit a
+ non-POINTER_TYPE node on either type. */
+ do
+ {
+ in_otype = TREE_TYPE (in_otype);
+ in_type = TREE_TYPE (in_type);
+
+ /* GNU C allows cv-qualified function types. 'const' means the
+ function is very pure, 'volatile' means it can't return. We
+ need to warn when such qualifiers are added, not when they're
+ taken away. */
+ if (TREE_CODE (in_otype) == FUNCTION_TYPE
+ && TREE_CODE (in_type) == FUNCTION_TYPE)
+ added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
+ else
+ discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
+ }
+ while (TREE_CODE (in_type) == POINTER_TYPE
+ && TREE_CODE (in_otype) == POINTER_TYPE);
+
+ if (added)
+ warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
+
+ if (discarded)
+ /* There are qualifiers present in IN_OTYPE that are not present
+ in IN_TYPE. */
+ warning (OPT_Wcast_qual,
+ "cast discards qualifiers from pointer target type");
+
+ if (added || discarded)
+ return;
+
+ /* A cast from **T to const **T is unsafe, because it can cause a
+ const value to be changed with no additional warning. We only
+ issue this warning if T is the same on both sides, and we only
+ issue the warning if there are the same number of pointers on
+ both sides, as otherwise the cast is clearly unsafe anyhow. A
+ cast is unsafe when a qualifier is added at one level and const
+ is not present at all outer levels.
+
+ To issue this warning, we check at each level whether the cast
+ adds new qualifiers not already seen. We don't need to special
+ case function types, as they won't have the same
+ TYPE_MAIN_VARIANT. */
+
+ if (TYPE_MAIN_VARIANT (in_type) != TYPE_MAIN_VARIANT (in_otype))
+ return;
+ if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE)
+ return;
+
+ in_type = type;
+ in_otype = otype;
+ is_const = TYPE_READONLY (TREE_TYPE (in_type));
+ do
+ {
+ in_type = TREE_TYPE (in_type);
+ in_otype = TREE_TYPE (in_otype);
+ if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
+ && !is_const)
+ {
+ warning (OPT_Wcast_qual,
+ ("new qualifiers in middle of multi-level non-const cast "
+ "are unsafe"));
+ break;
+ }
+ if (is_const)
+ is_const = TYPE_READONLY (in_type);
+ }
+ while (TREE_CODE (in_type) == POINTER_TYPE);
+}
+
/* Build an expression representing a cast to type TYPE of expression EXPR. */
tree
@@ -4139,46 +4226,10 @@ build_c_cast (tree type, tree expr)
otype = TREE_TYPE (value);
/* Optionally warn about potentially worrisome casts. */
-
if (warn_cast_qual
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE)
- {
- tree in_type = type;
- tree in_otype = otype;
- int added = 0;
- int discarded = 0;
-
- /* Check that the qualifiers on IN_TYPE are a superset of
- the qualifiers of IN_OTYPE. The outermost level of
- POINTER_TYPE nodes is uninteresting and we stop as soon
- as we hit a non-POINTER_TYPE node on either type. */
- do
- {
- in_otype = TREE_TYPE (in_otype);
- in_type = TREE_TYPE (in_type);
-
- /* GNU C allows cv-qualified function types. 'const'
- means the function is very pure, 'volatile' means it
- can't return. We need to warn when such qualifiers
- are added, not when they're taken away. */
- if (TREE_CODE (in_otype) == FUNCTION_TYPE
- && TREE_CODE (in_type) == FUNCTION_TYPE)
- added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
- else
- discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
- }
- while (TREE_CODE (in_type) == POINTER_TYPE
- && TREE_CODE (in_otype) == POINTER_TYPE);
-
- if (added)
- warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
-
- if (discarded)
- /* There are qualifiers present in IN_OTYPE that are not
- present in IN_TYPE. */
- warning (OPT_Wcast_qual, "cast discards qualifiers from pointer target type");
- }
+ handle_warn_cast_qual (type, otype);
/* Warn about possible alignment problems. */
if (STRICT_ALIGNMENT
@@ -9976,3 +10027,14 @@ c_build_qualified_type (tree type, int type_quals)
return build_qualified_type (type, type_quals);
}
+
+/* Build a VA_ARG_EXPR for the C parser. */
+
+tree
+c_build_va_arg (tree expr, tree type, location_t loc)
+{
+ if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE)
+ warning_at (loc, OPT_Wc___compat,
+ "C++ requires promoted type, not enum type, in %<va_arg%>");
+ return build_va_arg (expr, type);
+}