aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-10-21 09:53:40 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-10-21 09:53:40 +0000
commit3932261a55eb9840491d2cee5bb58d6fff0533fa (patch)
tree9768c9c789a7b2a0a685cf74859c95d943a2cae0 /gcc
parent52e90c5508e2a90aaf2e85d923b175f4d9a92dc5 (diff)
downloadgcc-3932261a55eb9840491d2cee5bb58d6fff0533fa.zip
gcc-3932261a55eb9840491d2cee5bb58d6fff0533fa.tar.gz
gcc-3932261a55eb9840491d2cee5bb58d6fff0533fa.tar.bz2
invoke.texi: Document -flang-isoc9x.
* invoke.texi: Document -flang-isoc9x. * Makefile.in (OBJS): Add splay-tree.o. (c-common.o): Depend on rtl.h. (splay-tree.o): List dependencies and provide build rule. * rtl.h (record_alias_subset): New function. * alias.c: Include splay-tree.h. (alias_set_entry): New type. (CHECK_ALIAS_SETS_FOR_CONSISTENCY): Remove. (DIFFERENT_ALIAS_SETS_P): Use mem_in_disjoint_alias_sets_p. (mems_in_disjoin_alias_sets_p): New function. (alias_set_compare): Likewise. (insert_subset_children): Likewise. (get_alias_set_entry): Likewise. * tree.h (TYPE_RESTRICT): New macro. (TYPE_UNQUALIFIED): New manifest constant. (TYPE_QUAL_CONST): Likewise (TYPE_QUAL_VOLATILE): Likewise. (TYPE_QUAL_RESTRICT): Likewise. (tree_type): Add restrict_flag. Reduce count of free bits. (DECL_POINTER_ALIAS_SET): New macro. (DECL_POINTER_ALIAS_SET_KNOWN_P): Likewise. (tree_decl): Add pointer_alias_set. (build_qualified_type): New function. (build_type_variant): Define in terms of build_qualified_type. * tree.c (set_type_quals): New function. (make_node): Initializae DECL_POINTER_ALIAS_SET. (build_type_attribute_variant): Use build_qualified_type and set_type_quals. (build_type_variant): Rename, and modify, to become... (build_qualified_type): New function. (build_complex_type): Use set_type_quals. * c-tree.h (C_TYPE_OBJECT_P): New macro. (C_TYPE_FUNCTION_P): Likewise. (C_TYPE_INCOMPLETE_P): Likewise. (C_TYPE_OBJECT_OR_INCOMPLETE_P): Likewise. (c_apply_type_quals_to_decl): New function. (c_build_qualified_type): New function. (c_build_type_variant): Define in terms of c_build_qualified_type. (flag_isoc9x): Declare. * c-typeck.c (qualify_type): Use c_build_qualified_type. (common_type): Change to use TYPE_QUALS. (comptypes): Likewise. (convert_for_assignment): Likewise. * c-aux-info.c (gen_type): Likewise. Deal with `restrict'. * c-decl.c (flag_isoc9x): Define. (c_decode_option): Handle -flang-isoc9x. (grokdeclarator): Update to handle restrict. Use TYPE_QUALS, c_build_qualified_type, etc. Use c_apply_type_quals_to_decl. * c-lex.c (init_lex): Deal with restrict. (init_lex): Don't treat restrict as a reserved word in -traditional mode, or without -flang-isoc9x. * c-lex.h (rid): Add RID_RESTRICT. * c-parse.gperf (restrict, __restrict, __restrict__): Make equivalent to RID_RESTRICT. * c-parse.in (TYPE_QUAL): Update comment. * c-common.c: Include rtl.h. (c_find_base_decl): New function. (c_build_type_variant): Rename, and modify, to become ... (c_build_qualified_type): New function. (c_apply_type_quals_to_decl): Likewise. (c_get_alias_set): For INDIRECT_REFs, check to see if we can find a particular alias set for the reference. * toplev.c (documented_lang_options): Add -flang-isoc9x. From-SVN: r23212
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog70
-rw-r--r--gcc/Makefile.in11
-rw-r--r--gcc/alias.c232
-rw-r--r--gcc/c-aux-info.c6
-rw-r--r--gcc/c-common.c133
-rw-r--r--gcc/c-decl.c140
-rw-r--r--gcc/c-gperf.h230
-rw-r--r--gcc/c-lex.c5
-rw-r--r--gcc/c-lex.h1
-rw-r--r--gcc/c-parse.c6
-rw-r--r--gcc/c-parse.gperf3
-rw-r--r--gcc/c-parse.in2
-rw-r--r--gcc/c-parse.y2
-rw-r--r--gcc/c-tree.h27
-rw-r--r--gcc/c-typeck.c101
-rw-r--r--gcc/invoke.texi11
-rw-r--r--gcc/print-tree.c2
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/toplev.c1
-rw-r--r--gcc/tree.c58
-rw-r--r--gcc/tree.h58
21 files changed, 791 insertions, 309 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c39081d..1d65b6d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,73 @@
+Wed Oct 21 09:18:58 1998 Mark Mitchell <mark@markmitchell.com>
+
+ * invoke.texi: Document -flang-isoc9x.
+
+ * Makefile.in (OBJS): Add splay-tree.o.
+ (c-common.o): Depend on rtl.h.
+ (splay-tree.o): List dependencies and provide build rule.
+
+ * rtl.h (record_alias_subset): New function.
+ * alias.c: Include splay-tree.h.
+ (alias_set_entry): New type.
+ (CHECK_ALIAS_SETS_FOR_CONSISTENCY): Remove.
+ (DIFFERENT_ALIAS_SETS_P): Use mem_in_disjoint_alias_sets_p.
+ (mems_in_disjoin_alias_sets_p): New function.
+ (alias_set_compare): Likewise.
+ (insert_subset_children): Likewise.
+ (get_alias_set_entry): Likewise.
+
+ * tree.h (TYPE_RESTRICT): New macro.
+ (TYPE_UNQUALIFIED): New manifest constant.
+ (TYPE_QUAL_CONST): Likewise
+ (TYPE_QUAL_VOLATILE): Likewise.
+ (TYPE_QUAL_RESTRICT): Likewise.
+ (tree_type): Add restrict_flag. Reduce count of free bits.
+ (DECL_POINTER_ALIAS_SET): New macro.
+ (DECL_POINTER_ALIAS_SET_KNOWN_P): Likewise.
+ (tree_decl): Add pointer_alias_set.
+ (build_qualified_type): New function.
+ (build_type_variant): Define in terms of build_qualified_type.
+ * tree.c (set_type_quals): New function.
+ (make_node): Initializae DECL_POINTER_ALIAS_SET.
+ (build_type_attribute_variant): Use build_qualified_type and
+ set_type_quals.
+ (build_type_variant): Rename, and modify, to become...
+ (build_qualified_type): New function.
+ (build_complex_type): Use set_type_quals.
+
+ * c-tree.h (C_TYPE_OBJECT_P): New macro.
+ (C_TYPE_FUNCTION_P): Likewise.
+ (C_TYPE_INCOMPLETE_P): Likewise.
+ (C_TYPE_OBJECT_OR_INCOMPLETE_P): Likewise.
+ (c_apply_type_quals_to_decl): New function.
+ (c_build_qualified_type): New function.
+ (c_build_type_variant): Define in terms of c_build_qualified_type.
+ (flag_isoc9x): Declare.
+ * c-typeck.c (qualify_type): Use c_build_qualified_type.
+ (common_type): Change to use TYPE_QUALS.
+ (comptypes): Likewise.
+ (convert_for_assignment): Likewise.
+ * c-aux-info.c (gen_type): Likewise. Deal with `restrict'.
+ * c-decl.c (flag_isoc9x): Define.
+ (c_decode_option): Handle -flang-isoc9x.
+ (grokdeclarator): Update to handle restrict. Use TYPE_QUALS,
+ c_build_qualified_type, etc. Use c_apply_type_quals_to_decl.
+ * c-lex.c (init_lex): Deal with restrict.
+ (init_lex): Don't treat restrict as a reserved word in
+ -traditional mode, or without -flang-isoc9x.
+ * c-lex.h (rid): Add RID_RESTRICT.
+ * c-parse.gperf (restrict, __restrict, __restrict__): Make
+ equivalent to RID_RESTRICT.
+ * c-parse.in (TYPE_QUAL): Update comment.
+ * c-common.c: Include rtl.h.
+ (c_find_base_decl): New function.
+ (c_build_type_variant): Rename, and modify, to become ...
+ (c_build_qualified_type): New function.
+ (c_apply_type_quals_to_decl): Likewise.
+ (c_get_alias_set): For INDIRECT_REFs, check to see if we can find
+ a particular alias set for the reference.
+ * toplev.c (documented_lang_options): Add -flang-isoc9x.
+
Wed Oct 21 09:15:06 1998 Nick Clifton <nickc@cygnus.com>
* config/arm/arm.h (TARGET_SWITCHES): Document arm specific
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 6ceb132..682f55a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -645,7 +645,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \
insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \
insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o \
profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \
- mbchar.o dyn-string.o
+ mbchar.o dyn-string.o splay-tree.o
# GEN files are listed separately, so they can be built before doing parallel
# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load
@@ -1319,6 +1319,13 @@ vfprintf.o: $(srcdir)/../libiberty/vfprintf.c $(CONFIG_H) system.h gansidecl.h
$(LN_S) $(srcdir)/../libiberty/vfprintf.c vfprintf.c
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) vfprintf.c
+splay-tree.o: $(srcdir)/../libiberty/splay-tree.c \
+ $(srcdir)/../include/splay-tree.h $(srcdir)/../include/libiberty.h \
+ gansidecl.h
+ rm -f splay-tree.c
+ $(LN_S) $(srcdir)/../libiberty/splay-tree.c splay-tree.c
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) splay-tree.c
+
underscore.c: s-under ; @true
s-under: $(GCC_PASSES)
@@ -1337,7 +1344,7 @@ s-under: $(GCC_PASSES)
# A file used by all variants of C.
c-common.o : c-common.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-lex.h \
- flags.h toplev.h output.h
+ flags.h toplev.h output.h rtl.h
# Language-independent files.
diff --git a/gcc/alias.c b/gcc/alias.c
index 27a069f..719b890 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -28,6 +28,49 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "output.h"
#include "toplev.h"
+#include "splay-tree.h"
+
+/* The alias sets assigned to MEMs assist the back-end in determining
+ which MEMs can alias which other MEMs. In general, two MEMs in
+ different alias sets to not alias each other. There is one
+ exception, however. Consider something like:
+
+ struct S {int i; double d; };
+
+ a store to an `S' can alias something of either type `int' or type
+ `double'. (However, a store to an `int' cannot alias a `double'
+ and vice versa.) We indicate this via a tree structure that looks
+ like:
+ struct S
+ / \
+ / \
+ |/_ _\|
+ int double
+
+ (The arrows are directed and point downwards.) If, when comparing
+ two alias sets, we can hold one set fixed, and trace the other set
+ downwards, and at some point find the first set, the two MEMs can
+ alias one another. In this situation we say the alias set for
+ `struct S' is the `superset' and that those for `int' and `double'
+ are `subsets'.
+
+ Alias set zero is implicitly a superset of all other alias sets.
+ However, this is no actual entry for alias set zero. It is an
+ error to attempt to explicitly construct a subset of zero. */
+
+typedef struct alias_set_entry {
+ /* The alias set number, as stored in MEM_ALIAS_SET. */
+ int alias_set;
+
+ /* The children of the alias set. These are not just the immediate
+ children, but, in fact, all children. So, if we have:
+
+ struct T { struct S s; float f; }
+
+ continuing our example above, the children here will be all of
+ `int', `double', `float', and `struct S'. */
+ splay_tree children;
+}* alias_set_entry;
static rtx canon_rtx PROTO((rtx));
static int rtx_equal_for_memref_p PROTO((rtx, rtx));
@@ -39,35 +82,23 @@ static rtx find_base_term PROTO((rtx));
static int base_alias_check PROTO((rtx, rtx, enum machine_mode,
enum machine_mode));
static rtx find_base_value PROTO((rtx));
+static int mems_in_disjoint_alias_sets_p PROTO((rtx, rtx));
+static int alias_set_compare PROTO((splay_tree_key,
+ splay_tree_key));
+static int insert_subset_children PROTO((splay_tree_node,
+ void*));
+static alias_set_entry get_alias_set_entry PROTO((int));
/* Set up all info needed to perform alias analysis on memory references. */
#define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
-/* Perform a basic sanity check. Namely, that there are
- no alias sets if we're not doing strict aliasing. This helps
- to catch bugs whereby someone uses PUT_CODE, but doesn't clear
- MEM_ALIAS_SET, or where a MEM is allocated in some way other
- than by the use of gen_rtx_MEM, and the MEM_ALIAS_SET is not
- cleared. */
-#ifdef ENABLE_CHECKING
-#define CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2) \
- (!flag_strict_aliasing \
- && (MEM_ALIAS_SET (MEM1) || MEM_ALIAS_SET (MEM2)) \
- ? (abort (), 0) : 0)
-#else
-#define CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2) ((void)0)
-#endif
-
/* Returns nonzero if MEM1 and MEM2 do not alias because they are in
different alias sets. We ignore alias sets in functions making use
of variable arguments because the va_arg macros on some systems are
not legal ANSI C. */
#define DIFFERENT_ALIAS_SETS_P(MEM1, MEM2) \
- (CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2), \
- MEM_ALIAS_SET (MEM1) && MEM_ALIAS_SET (MEM2) \
- && MEM_ALIAS_SET (MEM1) != MEM_ALIAS_SET (MEM2) \
- && !current_function_stdarg && !current_function_varargs)
+ mems_in_disjoint_alias_sets_p (MEM1, MEM2)
/* Cap the number of passes we make over the insns propagating alias
information through set chains.
@@ -131,6 +162,167 @@ char *reg_known_equiv_p;
static int copying_arguments;
+/* The splay-tree used to store the various alias set entries. */
+
+static splay_tree alias_sets;
+
+/* Returns -1, 0, 1 according to whether SET1 is less than, equal to,
+ or greater than SET2. */
+
+static int
+alias_set_compare (set1, set2)
+ splay_tree_key set1;
+ splay_tree_key set2;
+{
+ int s1 = (int) set1;
+ int s2 = (int) set2;
+
+ if (s1 < s2)
+ return -1;
+ else if (s1 > s2)
+ return 1;
+ else
+ return 0;
+}
+
+/* Returns a pointer to the alias set entry for ALIAS_SET, if there is
+ such an entry, or NULL otherwise. */
+
+static alias_set_entry
+get_alias_set_entry (alias_set)
+ int alias_set;
+{
+ splay_tree_node sn =
+ splay_tree_lookup (alias_sets, (splay_tree_key) alias_set);
+
+ return sn ? ((alias_set_entry) sn->value) : ((alias_set_entry) 0);
+}
+
+/* Returns nonzero value if the alias sets for MEM1 and MEM2 are such
+ that the two MEMs cannot alias each other. */
+
+static int
+mems_in_disjoint_alias_sets_p (mem1, mem2)
+ rtx mem1;
+ rtx mem2;
+{
+ alias_set_entry ase;
+
+#ifdef ENABLE_CHECKING
+/* Perform a basic sanity check. Namely, that there are no alias sets
+ if we're not using strict aliasing. This helps to catch bugs
+ whereby someone uses PUT_CODE, but doesn't clear MEM_ALIAS_SET, or
+ where a MEM is allocated in some way other than by the use of
+ gen_rtx_MEM, and the MEM_ALIAS_SET is not cleared. If we begin to
+ use alias sets to indicate that spilled registers cannot alias each
+ other, we might need to remove this check. */
+ if (!flag_strict_aliasing &&
+ (MEM_ALIAS_SET (mem1) || MEM_ALIAS_SET (mem2)))
+ abort ();
+#endif
+
+ /* The code used in varargs macros are often not conforming ANSI C,
+ which can trick the compiler into making incorrect aliasing
+ assumptions in these functions. So, we don't use alias sets in
+ such a function. FIXME: This should be moved into the front-end;
+ it is a language-dependent notion, and there's no reason not to
+ still use these checks to handle globals. */
+ if (current_function_stdarg || current_function_varargs)
+ return 0;
+
+ if (!MEM_ALIAS_SET (mem1) || !MEM_ALIAS_SET (mem2))
+ /* We have no alias set information for one of the MEMs, so we
+ have to assume it can alias anything. */
+ return 0;
+
+ if (MEM_ALIAS_SET (mem1) == MEM_ALIAS_SET (mem2))
+ /* The two alias sets are the same, so they may alias. */
+ return 0;
+
+ /* Iterate through each of the children of the first alias set,
+ comparing it with the second alias set. */
+ ase = get_alias_set_entry (MEM_ALIAS_SET (mem1));
+ if (ase && splay_tree_lookup (ase->children,
+ (splay_tree_key) MEM_ALIAS_SET (mem2)))
+ return 0;
+
+ /* Now do the same, but with the alias sets reversed. */
+ ase = get_alias_set_entry (MEM_ALIAS_SET (mem2));
+ if (ase && splay_tree_lookup (ase->children,
+ (splay_tree_key) MEM_ALIAS_SET (mem1)))
+ return 0;
+
+ /* The two MEMs are in distinct alias sets, and neither one is the
+ child of the other. Therefore, they cannot alias. */
+ return 1;
+}
+
+/* Insert the NODE into the splay tree given by DATA. Used by
+ record_alias_subset via splay_tree_foreach. */
+
+static int
+insert_subset_children (node, data)
+ splay_tree_node node;
+ void *data;
+{
+ splay_tree_insert ((splay_tree) data,
+ node->key,
+ node->value);
+
+ return 0;
+}
+
+/* Indicate that things in SUBSET can alias things in SUPERSET, but
+ not vice versa. For example, in C, a store to an `int' can alias a
+ structure containing an `int', but not vice versa. Here, the
+ structure would be the SUPERSET and `int' the SUBSET. This
+ function should be called only once per SUPERSET/SUBSET pair. At
+ present any given alias set may only be a subset of one superset.
+
+ It is illegal for SUPERSET to be zero; everything is implicitly a
+ subset of alias set zero. */
+
+void
+record_alias_subset (superset, subset)
+ int superset;
+ int subset;
+{
+ alias_set_entry superset_entry;
+ alias_set_entry subset_entry;
+
+ if (superset == 0)
+ abort ();
+
+ superset_entry = get_alias_set_entry (superset);
+ if (!superset_entry)
+ {
+ /* Create an entry for the SUPERSET, so that we have a place to
+ attach the SUBSET. */
+ superset_entry =
+ (alias_set_entry) xmalloc (sizeof (struct alias_set_entry));
+ superset_entry->alias_set = superset;
+ superset_entry->children
+ = splay_tree_new (&alias_set_compare, 0, 0);
+ splay_tree_insert (alias_sets,
+ (splay_tree_key) superset,
+ (splay_tree_value) superset_entry);
+
+ }
+
+ subset_entry = get_alias_set_entry (subset);
+ if (subset_entry)
+ /* There is an entry for the subset. Enter all of its children
+ (if they are not already present) as children of the SUPERSET. */
+ splay_tree_foreach (subset_entry->children,
+ &insert_subset_children,
+ superset_entry->children);
+
+ /* Enter the SUBSET itself as a child of the SUPERSET. */
+ splay_tree_insert (superset_entry->children,
+ (splay_tree_key) subset,
+ /*value=*/0);
+}
+
/* Inside SRC, the source of a SET, find a base address. */
static rtx
@@ -1063,6 +1255,8 @@ init_alias_once ()
if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i))
&& HARD_REGNO_MODE_OK (i, Pmode))
SET_HARD_REG_BIT (argument_registers, i);
+
+ alias_sets = splay_tree_new (&alias_set_compare, 0, 0);
}
void
diff --git a/gcc/c-aux-info.c b/gcc/c-aux-info.c
index 3e2edde..1125d5a 100644
--- a/gcc/c-aux-info.c
+++ b/gcc/c-aux-info.c
@@ -478,8 +478,8 @@ gen_type (ret_val, t, style)
case INTEGER_TYPE:
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
/* Normally, `unsigned' is part of the deal. Not so if it comes
- with `const' or `volatile'. */
- if (TREE_UNSIGNED (t) && (TYPE_READONLY (t) || TYPE_VOLATILE (t)))
+ with a type qualifier. */
+ if (TREE_UNSIGNED (t) && TYPE_QUALS (t))
data_type = concat ("unsigned ", data_type);
break;
@@ -503,6 +503,8 @@ gen_type (ret_val, t, style)
ret_val = concat ("const ", ret_val);
if (TYPE_VOLATILE (t))
ret_val = concat ("volatile ", ret_val);
+ if (TYPE_RESTRICT (t))
+ ret_val = concat ("restrict ", ret_val);
return ret_val;
}
diff --git a/gcc/c-common.c b/gcc/c-common.c
index a7b1ff1..4aaeb3c 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "output.h"
#include "c-pragma.h"
+#include "rtl.h"
#if USE_CPPLIB
#include "cpplib.h"
@@ -66,6 +67,7 @@ static void init_attributes PROTO((void));
static void record_function_format PROTO((tree, tree, enum format_type,
int, int));
static void record_international_format PROTO((tree, tree, int));
+static tree c_find_base_decl PROTO((tree));
/* Keep a stack of if statements. We record the number of compound
statements seen up to the if keyword, as well as the line number
@@ -2995,15 +2997,126 @@ get_directive_line (finput)
down to the element type of an array. */
tree
-c_build_type_variant (type, constp, volatilep)
+c_build_qualified_type (type, type_quals)
tree type;
- int constp, volatilep;
+ int type_quals;
{
+ /* A restrict-qualified pointer type must be a pointer to object or
+ incomplete type. Note that the use of POINTER_TYPE_P also allows
+ REFERENCE_TYPEs, which is appropriate for C++. Unfortunately,
+ the C++ front-end also use POINTER_TYPE for pointer-to-member
+ values, so even though it should be illegal to use `restrict'
+ with such an entity we don't flag that here. Thus, special case
+ code for that case is required in the C++ front-end. */
+ if ((type_quals & TYPE_QUAL_RESTRICT)
+ && (!POINTER_TYPE_P (type)
+ || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+ {
+ error ("invalid use of `restrict'");
+ type_quals &= ~TYPE_QUAL_RESTRICT;
+ }
+
if (TREE_CODE (type) == ARRAY_TYPE)
- return build_array_type (c_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
+ return build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
TYPE_DOMAIN (type));
- return build_type_variant (type, constp, volatilep);
+ return build_qualified_type (type, type_quals);
+}
+
+/* Apply the TYPE_QUALS to the new DECL. */
+
+void
+c_apply_type_quals_to_decl (type_quals, decl)
+ int type_quals;
+ tree decl;
+{
+ if (type_quals & TYPE_QUAL_CONST)
+ TREE_READONLY (decl) = 1;
+ if (type_quals & TYPE_QUAL_VOLATILE)
+ {
+ TREE_SIDE_EFFECTS (decl) = 1;
+ TREE_THIS_VOLATILE (decl) = 1;
+ }
+ if ((type_quals & TYPE_QUAL_RESTRICT) && flag_strict_aliasing)
+ {
+ /* No two restricted pointers can point at the same thing.
+ However, a restricted pointer can point at the same thing as
+ an unrestricted pointer, if that unrestricted pointer is
+ based on the restricted pointer. So, we make the alias set
+ for the restricted pointer a subset of the alias set for the
+ type pointed to by the type of the decl. */
+
+ int pointed_to_alias_set
+ = get_alias_set (TREE_TYPE (TREE_TYPE (decl)));
+
+ if (!pointed_to_alias_set)
+ /* It's not legal to make a subset of alias set zero. */
+ ;
+ else
+ {
+ DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
+ record_alias_subset (pointed_to_alias_set,
+ DECL_POINTER_ALIAS_SET (decl));
+ }
+ }
+}
+
+/* T is an expression with pointer type. Find the DECL on which this
+ expression is based. (For example, in `a[i]' this would be `a'.)
+ If there is no such DECL, or a unique decl cannot be determined,
+ NULL_TREE is retured. */
+
+static tree
+c_find_base_decl (t)
+ tree t;
+{
+ int i;
+ tree decl;
+
+ if (t == NULL_TREE || t == error_mark_node)
+ return NULL_TREE;
+
+ if (!POINTER_TYPE_P (TREE_TYPE (t)))
+ return NULL_TREE;
+
+ decl = NULL_TREE;
+
+ if (TREE_CODE (t) == FIELD_DECL
+ || TREE_CODE (t) == PARM_DECL
+ || TREE_CODE (t) == VAR_DECL)
+ /* Aha, we found a pointer-typed declaration. */
+ return t;
+
+ /* It would be nice to deal with COMPONENT_REFs here. If we could
+ tell that `a' and `b' were the same, then `a->f' and `b->f' are
+ also the same. */
+
+ /* Handle general expressions. */
+ switch (TREE_CODE_CLASS (TREE_CODE (t)))
+ {
+ case '1':
+ case '2':
+ case '3':
+ for (i = tree_code_length [(int) TREE_CODE (t)]; --i >= 0;)
+ {
+ tree d = c_find_base_decl (TREE_OPERAND (t, i));
+ if (d)
+ {
+ if (!decl)
+ decl = d;
+ else if (d && d != decl)
+ /* Two different declarations. That's confusing; let's
+ just assume we don't know what's going on. */
+ decl = NULL_TREE;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return decl;
}
/* Return the typed-based alias set for T, which may be an expression
@@ -3044,6 +3157,16 @@ c_get_alias_set (t)
says that such accesses have implementation-defined behavior. */
return 0;
+ if (TREE_CODE (t) == INDIRECT_REF)
+ {
+ /* Check for accesses through restrict-qualified pointers. */
+ tree decl = c_find_base_decl (TREE_OPERAND (t, 0));
+
+ if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
+ /* We use the alias set indicated in the declaration. */
+ return DECL_POINTER_ALIAS_SET (decl);
+ }
+
/* From here on, only the type matters. */
if (TYPE_ALIAS_SET_KNOWN_P (type))
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index df102ac..91e3510 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -468,6 +468,10 @@ int flag_no_nonansi_builtin;
int flag_traditional;
+/* Nonzero means use the ISO C9x dialect of C. */
+
+int flag_isoc9x = 0;
+
/* Nonzero means that we have builtin functions, and main is an int */
int flag_hosted = 1;
@@ -648,6 +652,8 @@ c_decode_option (argc, argv)
flag_traditional = 0;
flag_writable_strings = 0;
}
+ else if (!strcmp (p, "-flang-isoc9x"))
+ flag_isoc9x = 1;
else if (!strcmp (p, "-fdollars-in-identifiers"))
dollars_in_ident = 1;
else if (!strcmp (p, "-fno-dollars-in-identifiers"))
@@ -4322,7 +4328,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
tree type = NULL_TREE;
int longlong = 0;
int constp;
+ int restrictp;
int volatilep;
+ int type_quals = TYPE_UNQUALIFIED;
int inlinep;
int explicit_int = 0;
int explicit_char = 0;
@@ -4632,19 +4640,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = build_complex_type (type);
}
- /* Set CONSTP if this declaration is `const', whether by
- explicit specification or via a typedef.
- Likewise for VOLATILEP. */
-
+ /* Figure out the type qualifiers for the declaration. There are
+ two ways a declaration can become qualified. One is something
+ like `const int i' where the `const' is explicit. Another is
+ something like `typedef const int CI; CI i' where the type of the
+ declaration contains the `const'. */
constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (type);
+ restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type);
volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
inlinep = !! (specbits & (1 << (int) RID_INLINE));
if (constp > 1)
pedwarn ("duplicate `const'");
+ if (restrictp > 1)
+ pedwarn ("duplicate `restrict'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
- if (! flag_gen_aux_info && (TYPE_READONLY (type) || TYPE_VOLATILE (type)))
+ if (! flag_gen_aux_info && (TYPE_QUALS (type)))
type = TYPE_MAIN_VARIANT (type);
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
/* Warn if two storage classes are given. Default to `auto'. */
@@ -4878,13 +4893,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
is set correctly. */
type = build_array_type (type, itype);
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
#if 0 /* don't clear these; leave them set so that the array type
or the variable is itself const or volatile. */
- constp = 0;
- volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
#endif
if (size_varies)
@@ -4949,12 +4963,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
flag_traditional
? NULL_TREE : arg_types);
#endif
- /* ANSI seems to say that `const int foo ();'
- does not make the function foo const. */
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
- constp = 0;
- volatilep = 0;
+ /* Type qualifiers before the return type of the function
+ qualify the return type, not the function type. */
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+ type_quals = TYPE_UNQUALIFIED;
type = build_function_type (type, arg_types);
declarator = TREE_OPERAND (declarator, 0);
@@ -4978,12 +4991,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
for the pointer. */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
- constp = 0;
- volatilep = 0;
+ && type_quals)
+ pedwarn ("ANSI C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+ type_quals = TYPE_UNQUALIFIED;
size_varies = 0;
type = build_pointer_type (type);
@@ -4995,13 +5007,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
{
register tree typemodlist;
int erred = 0;
+
+ constp = 0;
+ volatilep = 0;
+ restrictp = 0;
for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
- if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
+ tree qualifier = TREE_VALUE (typemodlist);
+
+ if (qualifier == ridpointers[(int) RID_CONST])
constp++;
- else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
+ else if (qualifier == ridpointers[(int) RID_VOLATILE])
volatilep++;
+ else if (qualifier == ridpointers[(int) RID_RESTRICT])
+ restrictp++;
else if (!erred)
{
erred = 1;
@@ -5012,6 +5032,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
pedwarn ("duplicate `const'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
+ if (restrictp > 1)
+ pedwarn ("duplicate `restrict'");
+
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
}
declarator = TREE_OPERAND (declarator, 0);
@@ -5038,10 +5064,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* Note that the grammar rejects storage classes
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ && type_quals)
+ pedwarn ("ANSI C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
decl = build_decl (TYPE_DECL, declarator, type);
if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
@@ -5073,10 +5099,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* Note that the grammar rejects storage classes
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && (constp || volatilep))
+ && type_quals)
pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
pop_obstacks ();
return type;
}
@@ -5116,20 +5142,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
{
/* Transfer const-ness of array into that of type pointed to. */
type = TREE_TYPE (type);
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
- volatilep = constp = 0;
+ type_quals = TYPE_UNQUALIFIED;
size_varies = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- if (pedantic && (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (pedantic && type_quals)
+ pedwarn ("ANSI C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
- volatilep = constp = 0;
+ type_quals = TYPE_UNQUALIFIED;
}
decl = build_decl (PARM_DECL, declarator, type);
@@ -5177,13 +5203,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = error_mark_node;
}
/* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+ if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
{
- type = build_array_type (c_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
+ type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
TYPE_DOMAIN (type));
#if 0 /* Leave the field const or volatile as well. */
- constp = volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
#endif
}
decl = build_decl (FIELD_DECL, declarator, type);
@@ -5222,18 +5248,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_machine_attr);
- if (pedantic && (constp || volatilep)
- && ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids const or volatile functions");
+ if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
+ pedwarn ("ANSI C forbids qualified function types");
if (pedantic
&& TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
- && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (decl)))
- || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (decl))))
+ && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
&& ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids const or volatile void function return type");
+ pedwarn ("ANSI C forbids qualified void function return type");
- if (volatilep
+ /* GNU C interprets a `volatile void' return type to indicate
+ that the function does not return. */
+ if ((type_quals & TYPE_QUAL_VOLATILE)
&& TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
warning ("`noreturn' function returns non-void value");
@@ -5263,13 +5289,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
/* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+ if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
{
- type = build_array_type (c_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
+ type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
TYPE_DOMAIN (type));
#if 0 /* Leave the variable const or volatile as well. */
- constp = volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
#endif
}
@@ -5316,14 +5342,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
DECL_REGISTER (decl) = 1;
/* Record constancy and volatility. */
+ c_apply_type_quals_to_decl (type_quals, decl);
- if (constp)
- TREE_READONLY (decl) = 1;
- if (volatilep)
- {
- TREE_SIDE_EFFECTS (decl) = 1;
- TREE_THIS_VOLATILE (decl) = 1;
- }
/* If a type has volatile components, it should be stored in memory.
Otherwise, the fact that those components are volatile
will be ignored, and would even crash the compiler. */
diff --git a/gcc/c-gperf.h b/gcc/c-gperf.h
index 41b8d0f..7ee5060 100644
--- a/gcc/c-gperf.h
+++ b/gcc/c-gperf.h
@@ -1,14 +1,14 @@
/* KR-C code produced by gperf version 2.7.1 (19981006 egcs) */
-/* Command-line: gperf -L KR-C -F , 0, 0 -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,$ /hurl/puke/law/egcs/egcs/gcc/c-parse.gperf */
+/* Command-line: gperf -L KR-C -F , 0, 0 -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,$ ../../gcc/c-parse.gperf */
/* Command-line: gperf -L KR-C -F ', 0, 0' -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */
struct resword { char *name; short token; enum rid rid; };
-#define TOTAL_KEYWORDS 80
+#define TOTAL_KEYWORDS 83
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 20
-#define MIN_HASH_VALUE 10
-#define MAX_HASH_VALUE 162
-/* maximum key range = 153, duplicates = 0 */
+#define MIN_HASH_VALUE 8
+#define MAX_HASH_VALUE 141
+/* maximum key range = 134, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -20,32 +20,32 @@ hash (str, len)
{
static unsigned char asso_values[] =
{
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 8, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 1, 163, 24, 8, 61,
- 37, 6, 47, 49, 2, 5, 163, 3, 51, 30,
- 58, 91, 35, 163, 33, 13, 1, 18, 49, 2,
- 2, 5, 3, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 163, 163, 163, 163, 163
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 35, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 1, 142, 90, 1, 28,
+ 40, 6, 1, 24, 3, 13, 142, 36, 60, 14,
+ 49, 3, 6, 142, 19, 8, 1, 50, 33, 11,
+ 2, 23, 4, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142
};
register int hval = len;
@@ -64,120 +64,112 @@ hash (str, len)
static struct resword wordlist[] =
{
- {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"out", TYPE_QUAL, RID_OUT},
{"", 0, 0},
- {"int", TYPESPEC, RID_INT},
- {"", 0, 0}, {"", 0, 0},
- {"__typeof__", TYPEOF, NORID},
+ {"float", TYPESPEC, RID_FLOAT},
+ {"__typeof", TYPEOF, NORID},
{"", 0, 0},
+ {"__typeof__", TYPEOF, NORID},
+ {"typeof", TYPEOF, NORID},
+ {"typedef", SCSPEC, RID_TYPEDEF},
+ {"if", IF, NORID},
+ {"short", TYPESPEC, RID_SHORT},
+ {"int", TYPESPEC, RID_INT},
+ {"sizeof", SIZEOF, NORID},
+ {"__signed__", TYPESPEC, RID_SIGNED},
+ {"__extension__", EXTENSION, NORID},
+ {"inout", TYPE_QUAL, RID_INOUT},
{"__imag__", IMAGPART, NORID},
- {"", 0, 0},
+ {"else", ELSE, NORID},
{"__inline__", SCSPEC, RID_INLINE},
- {"while", WHILE, NORID},
+ {"byref", TYPE_QUAL, RID_BYREF},
{"__iterator__", SCSPEC, RID_ITERATOR},
{"__inline", SCSPEC, RID_INLINE},
- {"__extension__", EXTENSION, NORID},
- {"break", BREAK, NORID},
- {"", 0, 0}, {"", 0, 0},
- {"__signed__", TYPESPEC, RID_SIGNED},
- {"switch", SWITCH, NORID},
- {"", 0, 0}, {"", 0, 0},
- {"else", ELSE, NORID},
- {"", 0, 0}, {"", 0, 0},
- {"@defs", DEFS, NORID},
- {"__asm__", ASM_KEYWORD, NORID},
- {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
- {"__alignof__", ALIGNOF, NORID},
- {"", 0, 0},
- {"__attribute__", ATTRIBUTE, NORID},
- {"", 0, 0}, {"", 0, 0},
- {"__attribute", ATTRIBUTE, NORID},
{"__real__", REALPART, NORID},
- {"id", OBJECTNAME, RID_ID},
- {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
- {"__iterator", SCSPEC, RID_ITERATOR},
- {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"switch", SWITCH, NORID},
+ {"__restrict", TYPE_QUAL, RID_RESTRICT},
+ {"goto", GOTO, NORID},
+ {"__restrict__", TYPE_QUAL, RID_RESTRICT},
{"struct", STRUCT, NORID},
- {"if", IF, NORID},
- {"@private", PRIVATE, NORID},
- {"@selector", SELECTOR, NORID},
- {"__typeof", TYPEOF, NORID},
- {"enum", ENUM, NORID},
- {"__signed", TYPESPEC, RID_SIGNED},
- {"__asm", ASM_KEYWORD, NORID},
- {"__imag", IMAGPART, NORID},
- {"__label__", LABEL, NORID},
- {"__volatile__", TYPE_QUAL, RID_VOLATILE},
- {"", 0, 0},
- {"in", TYPE_QUAL, RID_IN},
- {"__volatile", TYPE_QUAL, RID_VOLATILE},
- {"double", TYPESPEC, RID_DOUBLE},
- {"inline", SCSPEC, RID_INLINE},
- {"sizeof", SIZEOF, NORID},
+ {"while", WHILE, NORID},
+ {"restrict", TYPE_QUAL, RID_RESTRICT},
{"__const", TYPE_QUAL, RID_CONST},
- {"extern", SCSPEC, RID_EXTERN},
+ {"oneway", TYPE_QUAL, RID_ONEWAY},
{"__const__", TYPE_QUAL, RID_CONST},
{"__complex", TYPESPEC, RID_COMPLEX},
{"__complex__", TYPESPEC, RID_COMPLEX},
+ {"for", FOR, NORID},
+ {"__iterator", SCSPEC, RID_ITERATOR},
+ {"__imag", IMAGPART, NORID},
+ {"do", DO, NORID},
+ {"case", CASE, NORID},
+ {"__volatile__", TYPE_QUAL, RID_VOLATILE},
+ {"break", BREAK, NORID},
+ {"default", DEFAULT, NORID},
+ {"__volatile", TYPE_QUAL, RID_VOLATILE},
+ {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"@defs", DEFS, NORID},
+ {"id", OBJECTNAME, RID_ID},
{"", 0, 0},
- {"unsigned", TYPESPEC, RID_UNSIGNED},
- {"", 0, 0},
- {"@class", CLASS, NORID},
- {"@encode", ENCODE, NORID},
+ {"__signed", TYPESPEC, RID_SIGNED},
{"bycopy", TYPE_QUAL, RID_BYCOPY},
- {"__alignof", ALIGNOF, NORID},
- {"@interface", INTERFACE, NORID},
+ {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"extern", SCSPEC, RID_EXTERN},
{"", 0, 0},
- {"case", CASE, NORID},
+ {"in", TYPE_QUAL, RID_IN},
{"", 0, 0},
- {"union", UNION, NORID},
- {"asm", ASM_KEYWORD, NORID},
- {"@protected", PROTECTED, NORID},
- {"typeof", TYPEOF, NORID},
- {"typedef", SCSPEC, RID_TYPEDEF},
- {"__real", REALPART, NORID},
- {"default", DEFAULT, NORID},
- {"byref", TYPE_QUAL, RID_BYREF},
- {"@public", PUBLIC, NORID},
- {"void", TYPESPEC, RID_VOID},
- {"out", TYPE_QUAL, RID_OUT},
+ {"@compatibility_alias", ALIAS, NORID},
{"", 0, 0},
+ {"@private", PRIVATE, NORID},
+ {"@selector", SELECTOR, NORID},
+ {"register", SCSPEC, RID_REGISTER},
+ {"__label__", LABEL, NORID},
+ {"", 0, 0}, {"", 0, 0},
+ {"enum", ENUM, NORID},
{"return", RETURN, NORID},
{"", 0, 0}, {"", 0, 0},
- {"@protocol", PROTOCOL, NORID},
- {"inout", TYPE_QUAL, RID_INOUT},
- {"", 0, 0},
- {"static", SCSPEC, RID_STATIC},
{"signed", TYPESPEC, RID_SIGNED},
+ {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"const", TYPE_QUAL, RID_CONST},
{"", 0, 0},
- {"@end", END, NORID},
- {"oneway", TYPE_QUAL, RID_ONEWAY},
- {"", 0, 0},
- {"short", TYPESPEC, RID_SHORT},
+ {"inline", SCSPEC, RID_INLINE},
+ {"__real", REALPART, NORID},
+ {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"void", TYPESPEC, RID_VOID},
+ {"continue", CONTINUE, NORID},
+ {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"@encode", ENCODE, NORID},
+ {"auto", SCSPEC, RID_AUTO},
+ {"__asm__", ASM_KEYWORD, NORID},
+ {"@interface", INTERFACE, NORID},
+ {"__alignof", ALIGNOF, NORID},
+ {"double", TYPESPEC, RID_DOUBLE},
+ {"__alignof__", ALIGNOF, NORID},
+ {"@protected", PROTECTED, NORID},
+ {"__attribute__", ATTRIBUTE, NORID},
+ {"unsigned", TYPESPEC, RID_UNSIGNED},
+ {"volatile", TYPE_QUAL, RID_VOLATILE},
+ {"__attribute", ATTRIBUTE, NORID},
+ {"@class", CLASS, NORID},
+ {"__asm", ASM_KEYWORD, NORID},
+ {"", 0, 0}, {"", 0, 0},
{"@implementation", IMPLEMENTATION, NORID},
+ {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"union", UNION, NORID},
{"", 0, 0}, {"", 0, 0},
- {"volatile", TYPE_QUAL, RID_VOLATILE},
+ {"@public", PUBLIC, NORID},
+ {"asm", ASM_KEYWORD, NORID},
{"", 0, 0},
- {"for", FOR, NORID},
+ {"@protocol", PROTOCOL, NORID},
+ {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"@end", END, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
- {"auto", SCSPEC, RID_AUTO},
- {"", 0, 0},
- {"char", TYPESPEC, RID_CHAR},
- {"register", SCSPEC, RID_REGISTER},
- {"", 0, 0},
- {"const", TYPE_QUAL, RID_CONST},
+ {"static", SCSPEC, RID_STATIC},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
- {"do", DO, NORID},
- {"", 0, 0},
- {"@compatibility_alias", ALIAS, NORID},
- {"continue", CONTINUE, NORID},
- {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
- {"", 0, 0},
- {"float", TYPESPEC, RID_FLOAT},
- {"goto", GOTO, NORID},
- {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
- {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
- {"long", TYPESPEC, RID_LONG}
+ {"long", TYPESPEC, RID_LONG},
+ {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
+ {"char", TYPESPEC, RID_CHAR}
};
#ifdef __GNUC__
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index 6c0d29f..10e9121 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -245,6 +245,7 @@ init_lex ()
ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
ridpointers[(int) RID_INLINE] = get_identifier ("inline");
ridpointers[(int) RID_CONST] = get_identifier ("const");
+ ridpointers[(int) RID_RESTRICT] = get_identifier ("restrict");
ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
ridpointers[(int) RID_AUTO] = get_identifier ("auto");
ridpointers[(int) RID_STATIC] = get_identifier ("static");
@@ -274,6 +275,7 @@ init_lex ()
if (flag_traditional)
{
UNSET_RESERVED_WORD ("const");
+ UNSET_RESERVED_WORD ("restrict");
UNSET_RESERVED_WORD ("volatile");
UNSET_RESERVED_WORD ("typeof");
UNSET_RESERVED_WORD ("signed");
@@ -281,6 +283,9 @@ init_lex ()
UNSET_RESERVED_WORD ("iterator");
UNSET_RESERVED_WORD ("complex");
}
+ else if (!flag_isoc9x)
+ UNSET_RESERVED_WORD ("restrict");
+
if (flag_no_asm)
{
UNSET_RESERVED_WORD ("asm");
diff --git a/gcc/c-lex.h b/gcc/c-lex.h
index 0ffc6a4..3aaa3a0 100644
--- a/gcc/c-lex.h
+++ b/gcc/c-lex.h
@@ -40,6 +40,7 @@ enum rid
RID_TYPEDEF,
RID_SIGNED,
RID_CONST,
+ RID_RESTRICT,
RID_VOLATILE,
RID_INLINE,
RID_NOALIAS,
diff --git a/gcc/c-parse.c b/gcc/c-parse.c
index 842d252..c20d2a0 100644
--- a/gcc/c-parse.c
+++ b/gcc/c-parse.c
@@ -1164,7 +1164,7 @@ static const short yycheck[] = { 38,
52
};
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
-#line 3 "/usr/cygnus/progressive-98r1/share/bison.simple"
+#line 3 "/usr/lib/bison.simple"
/* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
@@ -1357,7 +1357,7 @@ __yy_memcpy (char *to, char *from, int count)
#endif
#endif
-#line 196 "/usr/cygnus/progressive-98r1/share/bison.simple"
+#line 196 "/usr/lib/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *.
@@ -3676,7 +3676,7 @@ case 401:
break;}
}
/* the action file gets copied in in place of this dollarsign */
-#line 498 "/usr/cygnus/progressive-98r1/share/bison.simple"
+#line 498 "/usr/lib/bison.simple"
yyvsp -= yylen;
yyssp -= yylen;
diff --git a/gcc/c-parse.gperf b/gcc/c-parse.gperf
index 3ce33a4..324bd24 100644
--- a/gcc/c-parse.gperf
+++ b/gcc/c-parse.gperf
@@ -35,6 +35,8 @@ __iterator__, SCSPEC, RID_ITERATOR
__label__, LABEL, NORID
__real, REALPART, NORID
__real__, REALPART, NORID
+__restrict, TYPE_QUAL, RID_RESTRICT
+__restrict__, TYPE_QUAL, RID_RESTRICT
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
__typeof, TYPEOF, NORID
@@ -69,6 +71,7 @@ long, TYPESPEC, RID_LONG
oneway, TYPE_QUAL, RID_ONEWAY
out, TYPE_QUAL, RID_OUT
register, SCSPEC, RID_REGISTER
+restrict, TYPE_QUAL, RID_RESTRICT
return, RETURN, NORID
short, TYPESPEC, RID_SHORT
signed, TYPESPEC, RID_SIGNED
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index 16500c5..88a308c 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -116,7 +116,7 @@ end ifc
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPESPEC
-/* Reserved words that qualify type: "const" or "volatile".
+/* Reserved words that qualify type: "const", "volatile", or "restrict".
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPE_QUAL
diff --git a/gcc/c-parse.y b/gcc/c-parse.y
index ab0d7d1..99cf167 100644
--- a/gcc/c-parse.y
+++ b/gcc/c-parse.y
@@ -104,7 +104,7 @@ char *language_string = "GNU C";
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPESPEC
-/* Reserved words that qualify type: "const" or "volatile".
+/* Reserved words that qualify type: "const", "volatile", or "restrict".
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPE_QUAL
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index fec60cb..5ba7409 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -80,6 +80,22 @@ extern int pedantic;
nonzero if the definition of the type has already started. */
#define C_TYPE_BEING_DEFINED(type) TYPE_LANG_FLAG_0 (type)
+/* C types are partitioned into three subsets: object, function, and
+ incomplete types. */
+#define C_TYPE_OBJECT_P(type) \
+ (TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type))
+
+#define C_TYPE_FUNCTION_P(type) \
+ (TREE_CODE (type) == FUNCTION_TYPE)
+
+#define C_TYPE_INCOMPLETE_P(type) \
+ (TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type) == 0)
+
+/* For convenience we define a single macro to identify the class of
+ object or incomplete types. */
+#define C_TYPE_OBJECT_OR_INCOMPLETE_P(type) \
+ (!C_TYPE_FUNCTION_P (type))
+
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type
{
@@ -165,6 +181,7 @@ extern void decl_attributes PROTO((tree, tree, tree));
extern void init_function_format_info PROTO((void));
extern void check_function_format PROTO((tree, tree, tree));
extern int c_get_alias_set PROTO((tree));
+extern void c_apply_type_quals_to_decl PROTO((int, tree));
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code));
@@ -267,7 +284,11 @@ extern tree build_enumerator PROTO((tree, tree));
/* Declare a predefined function. Return the declaration. */
extern tree builtin_function PROTO((char *, tree, enum built_in_function function_, char *));
/* Add qualifiers to a type, in the fashion for C. */
-extern tree c_build_type_variant PROTO((tree, int, int));
+extern tree c_build_qualified_type PROTO((tree, int));
+#define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
+ c_build_qualified_type (TYPE, \
+ ((CONST_P) ? TYPE_QUAL_CONST : 0) | \
+ ((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
extern int c_decode_option PROTO((int, char **));
extern void c_mark_varargs PROTO((void));
extern tree check_identifier PROTO((tree, tree));
@@ -497,6 +518,10 @@ extern int warn_main;
extern int flag_traditional;
+/* Nonzero means use the ISO C9x dialect of C. */
+
+extern int flag_isoc9x;
+
/* Nonzero means to allow single precision math even if we're generally
being traditional. */
extern int flag_allow_single_precision;
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 0a1f490..caf2bf5 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -163,9 +163,7 @@ static tree
qualify_type (type, like)
tree type, like;
{
- int constflag = TYPE_READONLY (type) || TYPE_READONLY (like);
- int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);
- return c_build_type_variant (type, constflag, volflag);
+ return c_build_qualified_type (type, TYPE_QUALS (like));
}
/* Return the common type of two types.
@@ -283,14 +281,14 @@ common_type (t1, t2)
But ANSI C specifies doing this with the qualifiers.
So I turned it on again. */
{
- tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),
- TYPE_MAIN_VARIANT (TREE_TYPE (t2)));
- int constp
- = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
- int volatilep
- = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
- t1 = build_pointer_type (c_build_type_variant (target, constp,
- volatilep));
+ tree pointed_to_1 = TREE_TYPE (t1);
+ tree pointed_to_2 = TREE_TYPE (t2);
+ tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1),
+ TYPE_MAIN_VARIANT (pointed_to_2));
+ t1 = build_pointer_type (c_build_qualified_type
+ (target,
+ TYPE_QUALS (pointed_to_1) |
+ TYPE_QUALS (pointed_to_2)));
return build_type_attribute_variant (t1, attributes);
}
#if 0
@@ -447,9 +445,7 @@ comptypes (type1, type2)
/* Qualifiers must match. */
- if (TYPE_READONLY (t1) != TYPE_READONLY (t2))
- return 0;
- if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
+ if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
return 0;
/* Allow for two different type nodes which have essentially the same
@@ -1084,11 +1080,12 @@ default_conversion (exp)
volatilep = TREE_THIS_VOLATILE (exp);
}
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
- || constp || volatilep)
- restype = c_build_type_variant (restype,
- TYPE_READONLY (type) || constp,
- TYPE_VOLATILE (type) || volatilep);
+ if (TYPE_QUALS (type) || constp || volatilep)
+ restype
+ = c_build_qualified_type (restype,
+ TYPE_QUALS (type)
+ | (constp * TYPE_QUAL_CONST)
+ | (volatilep * TYPE_QUAL_VOLATILE));
if (TREE_CODE (exp) == INDIRECT_REF)
return convert (TYPE_POINTER_TO (restype),
@@ -3080,8 +3077,10 @@ build_unary_op (code, xarg, noconvert)
/* Ordinary case; arg is a COMPONENT_REF or a decl. */
argtype = TREE_TYPE (arg);
- /* If the lvalue is const or volatile,
- merge that into the type that the address will point to. */
+ /* If the lvalue is const or volatile, merge that into the type
+ to which the address will point. Note that you can't get a
+ restricted pointer by taking the address of something, so we
+ only have to deal with `const' and `volatile' here. */
if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
|| TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
{
@@ -3779,11 +3778,11 @@ build_c_cast (type, expr)
in_type = TREE_TYPE (in_type);
while (TREE_CODE (in_otype) == POINTER_TYPE)
in_otype = TREE_TYPE (in_otype);
-
- if (TYPE_VOLATILE (in_otype) && ! TYPE_VOLATILE (in_type))
- pedwarn ("cast discards `volatile' from pointer target type");
- if (TYPE_READONLY (in_otype) && ! TYPE_READONLY (in_type))
- pedwarn ("cast discards `const' from pointer target type");
+
+ if (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type))
+ /* There are qualifiers present in IN_OTYPE that are not
+ present in IN_TYPE. */
+ pedwarn ("cast discards qualifiers from pointer target type");
}
/* Warn about possible alignment problems. */
@@ -4114,12 +4113,13 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
|| comp_target_types (memb_type, rhstype))
{
/* If this type won't generate any warnings, use it. */
- if ((TREE_CODE (ttr) == FUNCTION_TYPE
- && TREE_CODE (ttl) == FUNCTION_TYPE)
- ? ((! TYPE_READONLY (ttl) | TYPE_READONLY (ttr))
- & (! TYPE_VOLATILE (ttl) | TYPE_VOLATILE (ttr)))
- : ((TYPE_READONLY (ttl) | ! TYPE_READONLY (ttr))
- & (TYPE_VOLATILE (ttl) | ! TYPE_VOLATILE (ttr))))
+ if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
+ || ((TREE_CODE (ttr) == FUNCTION_TYPE
+ && TREE_CODE (ttl) == FUNCTION_TYPE)
+ ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
+ == TYPE_QUALS (ttr))
+ : (TYPE_QUALS (ttl) | TYPE_QUALS (ttr)
+ == TYPE_QUALS (ttl))))
break;
/* Keep looking for a better type, but remember this one. */
@@ -4157,26 +4157,15 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
certain things, it is okay to use a const or volatile
function where an ordinary one is wanted, but not
vice-versa. */
- if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
- warn_for_assignment ("%s makes `const *' function pointer from non-const",
- get_spelling (errtype), funname,
- parmnum);
- if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
- get_spelling (errtype), funname,
- parmnum);
- }
- else
- {
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- warn_for_assignment ("%s discards `const' from pointer target type",
- get_spelling (errtype), funname,
- parmnum);
- if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s discards `volatile' from pointer target type",
+ if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+ warn_for_assignment ("%s makes qualified function pointer from unqualified",
get_spelling (errtype), funname,
parmnum);
}
+ else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+ warn_for_assignment ("%s discards qualifiers from pointer target type",
+ get_spelling (errtype), funname,
+ parmnum);
}
if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl))
@@ -4217,11 +4206,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE)
{
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- warn_for_assignment ("%s discards `const' from pointer target type",
- get_spelling (errtype), funname, parmnum);
- else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s discards `volatile' from pointer target type",
+ if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+ warn_for_assignment ("%s discards qualifiers from pointer target type",
get_spelling (errtype), funname, parmnum);
/* If this is not a case of ignoring a mismatch in signedness,
no warning. */
@@ -4241,11 +4227,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
that say the function will not do certain things,
it is okay to use a const or volatile function
where an ordinary one is wanted, but not vice-versa. */
- if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
- warn_for_assignment ("%s makes `const *' function pointer from non-const",
- get_spelling (errtype), funname, parmnum);
- if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
+ if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+ warn_for_assignment ("%s makes qualified function pointer from unqualified",
get_spelling (errtype), funname, parmnum);
}
}
diff --git a/gcc/invoke.texi b/gcc/invoke.texi
index 6bc075c..3e6356a 100644
--- a/gcc/invoke.texi
+++ b/gcc/invoke.texi
@@ -93,7 +93,7 @@ in the following sections.
@item C Language Options
@xref{C Dialect Options,,Options Controlling C Dialect}.
@smallexample
--ansi -fallow-single-precision -fcond-mismatch -fno-asm
+-ansi -flang-isoc9x -fallow-single-precision -fcond-mismatch -fno-asm
-fno-builtin -ffreestanding -fhosted -fsigned-bitfields -fsigned-char
-funsigned-bitfields -funsigned-char -fwritable-strings
-traditional -traditional-cpp -trigraphs
@@ -644,6 +644,15 @@ programs that might use these names for other things.
The functions @code{alloca}, @code{abort}, @code{exit}, and
@code{_exit} are not builtin functions when @samp{-ansi} is used.
+@item -flang-isoc9x
+Enable support for features found in the C9X standard. In particular,
+enable support for the C9X @code{restrict} keyword.
+
+Even when this option is not specified, you can still use some C9X
+features in so far as they do not conflict with previous C standards.
+For example, you may use @code{__restrict__} even when -flang-isoc9x
+is not specified.
+
@item -fno-asm
Do not recognize @code{asm}, @code{inline} or @code{typeof} as a
keyword, so that code can use these words as identifiers. You can use
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 6163b1f..afc082e 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -404,6 +404,8 @@ print_node (file, prefix, node, indent)
fprintf (file, " built-in code %d", DECL_FUNCTION_CODE (node));
if (TREE_CODE (node) == FIELD_DECL)
print_node (file, "bitpos", DECL_FIELD_BITPOS (node), indent + 4);
+ if (DECL_POINTER_ALIAS_SET_KNOWN_P (node))
+ fprintf (file, " alias set %d", DECL_POINTER_ALIAS_SET (node));
print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);
print_node_brief (file, "machine_attributes", DECL_MACHINE_ATTRIBUTES (node), indent + 4);
print_node_brief (file, "abstract_origin",
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 3c78edc..d655d4e 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1505,5 +1505,6 @@ extern void init_alias_analysis PROTO ((void));
extern void end_alias_analysis PROTO ((void));
extern void record_base_value PROTO ((int, rtx, int));
+extern void record_alias_subset PROTO ((int, int));
#endif /* _RTL_H */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 5040987..203b40e 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -949,6 +949,7 @@ documented_lang_options[] =
{ "-traditional", "Attempt to support traditional K&R style C"},
{ "-fnotraditional", "" },
{ "-fno-traditional", "" },
+ { "-flang-isoc9x", "Enable C9X features"},
{ "-fasm", "" },
{ "-fno-asm", "Do not recognise the 'asm' keyword" },
diff --git a/gcc/tree.c b/gcc/tree.c
index 35b83a4..04f7da8 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -264,6 +264,8 @@ int (*lang_get_alias_set) PROTO((tree));
codes are made. */
#define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
+static void set_type_quals PROTO((tree, int));
+
extern char *mode_name[];
void gcc_obstack_init ();
@@ -1100,6 +1102,9 @@ make_node (code)
DECL_SOURCE_LINE (t) = lineno;
DECL_SOURCE_FILE (t) = (input_filename) ? input_filename : "<built-in>";
DECL_UID (t) = next_decl_uid++;
+ /* Note that we have not yet computed the alias set for this
+ declaration. */
+ DECL_POINTER_ALIAS_SET (t) = -1;
break;
case 't':
@@ -3294,7 +3299,7 @@ build_type_attribute_variant (ttype, attribute)
/* Create a new main variant of TYPE. */
TYPE_MAIN_VARIANT (ntype) = ntype;
TYPE_NEXT_VARIANT (ntype) = 0;
- TYPE_READONLY (ntype) = TYPE_VOLATILE (ntype) = 0;
+ set_type_quals (ntype, TYPE_UNQUALIFIED);
hashcode = TYPE_HASH (TREE_CODE (ntype))
+ TYPE_HASH (TREE_TYPE (ntype))
@@ -3319,8 +3324,7 @@ build_type_attribute_variant (ttype, attribute)
}
ntype = type_hash_canon (hashcode, ntype);
- ttype = build_type_variant (ntype, TYPE_READONLY (ttype),
- TYPE_VOLATILE (ttype));
+ ttype = build_qualified_type (ntype, TYPE_QUALS (ttype));
}
return ttype;
@@ -3576,45 +3580,44 @@ merge_machine_decl_attributes (olddecl, newdecl)
#endif
}
-/* Return a type like TYPE except that its TYPE_READONLY is CONSTP
- and its TYPE_VOLATILE is VOLATILEP.
+/* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
+ of the various TYPE_QUAL values. */
- Such variant types already made are recorded so that duplicates
- are not made.
+static void
+set_type_quals (type, type_quals)
+ tree type;
+ int type_quals;
+{
+ TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
+ TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
+ TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+}
- A variant types should never be used as the type of an expression.
- Always copy the variant information into the TREE_READONLY
- and TREE_THIS_VOLATILE of the expression, and then give the expression
- as its type the "main variant", the variant whose TYPE_READONLY
- and TYPE_VOLATILE are zero. Use TYPE_MAIN_VARIANT to find the
- main variant. */
+/* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
+ the same kind of data as TYPE describes. Variants point to the
+ "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
+ and it points to a chain of other variants so that duplicate
+ variants are never made. Only main variants should ever appear as
+ types of expressions. */
tree
-build_type_variant (type, constp, volatilep)
+build_qualified_type (type, type_quals)
tree type;
- int constp, volatilep;
+ int type_quals;
{
register tree t;
-
- /* Treat any nonzero argument as 1. */
- constp = !!constp;
- volatilep = !!volatilep;
-
+
/* Search the chain of variants to see if there is already one there just
like the one we need to have. If so, use that existing one. We must
preserve the TYPE_NAME, since there is code that depends on this. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- if (constp == TYPE_READONLY (t) && volatilep == TYPE_VOLATILE (t)
- && TYPE_NAME (t) == TYPE_NAME (type))
+ if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type))
return t;
/* We need a new one. */
-
t = build_type_copy (type);
- TYPE_READONLY (t) = constp;
- TYPE_VOLATILE (t) = volatilep;
-
+ set_type_quals (t, type_quals);
return t;
}
@@ -4422,8 +4425,7 @@ build_complex_type (component_type)
t = make_node (COMPLEX_TYPE);
TREE_TYPE (t) = TYPE_MAIN_VARIANT (component_type);
- TYPE_VOLATILE (t) = TYPE_VOLATILE (component_type);
- TYPE_READONLY (t) = TYPE_READONLY (component_type);
+ set_type_quals (t, TYPE_QUALS (component_type));
/* If we already have such a type, use the old one and free this one. */
hashcode = TYPE_HASH (component_type);
diff --git a/gcc/tree.h b/gcc/tree.h
index 8bd8df3..8dd7843 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -830,6 +830,25 @@ struct tree_block
/* Means this type is const-qualified. */
#define TYPE_READONLY(NODE) ((NODE)->common.readonly_flag)
+/* If nonzero, this type is `restrict'-qualified, in the C sense of
+ the term. */
+#define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type.restrict_flag)
+
+/* There is a TYPE_QUAL value for each type qualifier. They can be
+ combined by bitwise-or to form the complete set of qualifiers for a
+ type. */
+
+#define TYPE_UNQUALIFIED 0x0
+#define TYPE_QUAL_CONST 0x1
+#define TYPE_QUAL_VOLATILE 0x2
+#define TYPE_QUAL_RESTRICT 0x4
+
+/* The set of type qualifiers for this type. */
+#define TYPE_QUALS(NODE) \
+ ((TYPE_READONLY(NODE) * TYPE_QUAL_CONST) | \
+ (TYPE_VOLATILE(NODE) * TYPE_QUAL_VOLATILE) | \
+ (TYPE_RESTRICT(NODE) * TYPE_QUAL_RESTRICT))
+
/* These flags are available for each language front end to use internally. */
#define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type.lang_flag_0)
#define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type.lang_flag_1)
@@ -881,6 +900,8 @@ struct tree_type
unsigned needs_constructing_flag : 1;
unsigned transparent_union_flag : 1;
unsigned packed_flag : 1;
+ unsigned restrict_flag : 1;
+
unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1;
unsigned lang_flag_2 : 1;
@@ -888,7 +909,7 @@ struct tree_type
unsigned lang_flag_4 : 1;
unsigned lang_flag_5 : 1;
unsigned lang_flag_6 : 1;
- /* room for 4 more bits */
+ /* room for 3 more bits */
unsigned int align;
union tree_node *pointer_to;
@@ -1244,6 +1265,16 @@ struct tree_type
an address constant. */
#define DECL_NON_ADDR_CONST_P(NODE) (DECL_CHECK (NODE)->decl.non_addr_const_p)
+/* Used to indicate an alias set for the memory pointed to by this
+ particular FIELD_DECL, PARM_DECL, or VAR_DECL, which must have
+ pointer (or reference) type. */
+#define DECL_POINTER_ALIAS_SET(NODE) \
+ (DECL_CHECK (NODE)->decl.pointer_alias_set)
+
+/* Nonzero if an alias set has been assigned to this declaration. */
+#define DECL_POINTER_ALIAS_SET_KNOWN_P(NODE) \
+ (DECL_POINTER_ALIAS_SET (NODE) != - 1)
+
struct tree_decl
{
char common[sizeof (struct tree_common)];
@@ -1316,6 +1347,7 @@ struct tree_decl
HOST_WIDE_INT i;
} saved_insns;
union tree_node *vindex;
+ int pointer_alias_set;
/* Points to a structure whose details depend on the language in use. */
struct lang_decl *lang_specific;
};
@@ -1502,14 +1534,24 @@ extern tree lookup_attribute PROTO((char *, tree));
extern tree merge_attributes PROTO((tree, tree));
-/* Given a type node TYPE, and CONSTP and VOLATILEP, return a type
- for the same kind of data as TYPE describes.
- Variants point to the "main variant" (which has neither CONST nor VOLATILE)
- via TYPE_MAIN_VARIANT, and it points to a chain of other variants
- so that duplicate variants are never made.
- Only main variants should ever appear as types of expressions. */
+/* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
+ the same kind of data as TYPE describes. Variants point to the
+ "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
+ and it points to a chain of other variants so that duplicate
+ variants are never made. Only main variants should ever appear as
+ types of expressions. */
+
+extern tree build_qualified_type PROTO((tree, int));
+
+/* Like build_qualified_type, but only deals with the `const' and
+ `volatile' qualifiers. This interface is retained for backwards
+ compatiblity with the various front-ends; new code should use
+ build_qualified_type instead. */
-extern tree build_type_variant PROTO((tree, int, int));
+#define build_type_variant(TYPE, CONST_P, VOLATILE_P) \
+ build_qualified_type (TYPE, \
+ ((CONST_P) ? TYPE_QUAL_CONST : 0) \
+ | ((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
/* Make a copy of a type node. */