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
This commit is contained in:
Mark Mitchell 1998-10-21 09:53:40 +00:00 committed by Mark Mitchell
parent 52e90c5508
commit 3932261a55
21 changed files with 800 additions and 318 deletions

View File

@ -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> Wed Oct 21 09:15:06 1998 Nick Clifton <nickc@cygnus.com>
* config/arm/arm.h (TARGET_SWITCHES): Document arm specific * config/arm/arm.h (TARGET_SWITCHES): Document arm specific

View File

@ -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-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 \ 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 \ 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 # 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 # 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 $(LN_S) $(srcdir)/../libiberty/vfprintf.c vfprintf.c
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) 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 underscore.c: s-under ; @true
s-under: $(GCC_PASSES) s-under: $(GCC_PASSES)
@ -1337,7 +1344,7 @@ s-under: $(GCC_PASSES)
# A file used by all variants of C. # 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 \ 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. # Language-independent files.

View File

@ -28,6 +28,49 @@ Boston, MA 02111-1307, USA. */
#include "flags.h" #include "flags.h"
#include "output.h" #include "output.h"
#include "toplev.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 rtx canon_rtx PROTO((rtx));
static int rtx_equal_for_memref_p PROTO((rtx, 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, static int base_alias_check PROTO((rtx, rtx, enum machine_mode,
enum machine_mode)); enum machine_mode));
static rtx find_base_value PROTO((rtx)); 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. */ /* Set up all info needed to perform alias analysis on memory references. */
#define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X))) #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 /* Returns nonzero if MEM1 and MEM2 do not alias because they are in
different alias sets. We ignore alias sets in functions making use different alias sets. We ignore alias sets in functions making use
of variable arguments because the va_arg macros on some systems are of variable arguments because the va_arg macros on some systems are
not legal ANSI C. */ not legal ANSI C. */
#define DIFFERENT_ALIAS_SETS_P(MEM1, MEM2) \ #define DIFFERENT_ALIAS_SETS_P(MEM1, MEM2) \
(CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2), \ mems_in_disjoint_alias_sets_p (MEM1, MEM2)
MEM_ALIAS_SET (MEM1) && MEM_ALIAS_SET (MEM2) \
&& MEM_ALIAS_SET (MEM1) != MEM_ALIAS_SET (MEM2) \
&& !current_function_stdarg && !current_function_varargs)
/* Cap the number of passes we make over the insns propagating alias /* Cap the number of passes we make over the insns propagating alias
information through set chains. information through set chains.
@ -131,6 +162,167 @@ char *reg_known_equiv_p;
static int copying_arguments; 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. */ /* Inside SRC, the source of a SET, find a base address. */
static rtx static rtx
@ -1063,6 +1255,8 @@ init_alias_once ()
if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i)) if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i))
&& HARD_REGNO_MODE_OK (i, Pmode)) && HARD_REGNO_MODE_OK (i, Pmode))
SET_HARD_REG_BIT (argument_registers, i); SET_HARD_REG_BIT (argument_registers, i);
alias_sets = splay_tree_new (&alias_set_compare, 0, 0);
} }
void void

View File

@ -478,8 +478,8 @@ gen_type (ret_val, t, style)
case INTEGER_TYPE: case INTEGER_TYPE:
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t))); data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
/* Normally, `unsigned' is part of the deal. Not so if it comes /* Normally, `unsigned' is part of the deal. Not so if it comes
with `const' or `volatile'. */ with a type qualifier. */
if (TREE_UNSIGNED (t) && (TYPE_READONLY (t) || TYPE_VOLATILE (t))) if (TREE_UNSIGNED (t) && TYPE_QUALS (t))
data_type = concat ("unsigned ", data_type); data_type = concat ("unsigned ", data_type);
break; break;
@ -503,6 +503,8 @@ gen_type (ret_val, t, style)
ret_val = concat ("const ", ret_val); ret_val = concat ("const ", ret_val);
if (TYPE_VOLATILE (t)) if (TYPE_VOLATILE (t))
ret_val = concat ("volatile ", ret_val); ret_val = concat ("volatile ", ret_val);
if (TYPE_RESTRICT (t))
ret_val = concat ("restrict ", ret_val);
return ret_val; return ret_val;
} }

View File

@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h" #include "toplev.h"
#include "output.h" #include "output.h"
#include "c-pragma.h" #include "c-pragma.h"
#include "rtl.h"
#if USE_CPPLIB #if USE_CPPLIB
#include "cpplib.h" #include "cpplib.h"
@ -66,6 +67,7 @@ static void init_attributes PROTO((void));
static void record_function_format PROTO((tree, tree, enum format_type, static void record_function_format PROTO((tree, tree, enum format_type,
int, int)); int, int));
static void record_international_format PROTO((tree, tree, 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 /* 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 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. */ down to the element type of an array. */
tree tree
c_build_type_variant (type, constp, volatilep) c_build_qualified_type (type, type_quals)
tree type; 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) if (TREE_CODE (type) == ARRAY_TYPE)
return build_array_type (c_build_type_variant (TREE_TYPE (type), return build_array_type (c_build_qualified_type (TREE_TYPE (type),
constp, volatilep), type_quals),
TYPE_DOMAIN (type)); 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 /* 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. */ says that such accesses have implementation-defined behavior. */
return 0; 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. */ /* From here on, only the type matters. */
if (TYPE_ALIAS_SET_KNOWN_P (type)) if (TYPE_ALIAS_SET_KNOWN_P (type))

View File

@ -468,6 +468,10 @@ int flag_no_nonansi_builtin;
int flag_traditional; 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 */ /* Nonzero means that we have builtin functions, and main is an int */
int flag_hosted = 1; int flag_hosted = 1;
@ -648,6 +652,8 @@ c_decode_option (argc, argv)
flag_traditional = 0; flag_traditional = 0;
flag_writable_strings = 0; flag_writable_strings = 0;
} }
else if (!strcmp (p, "-flang-isoc9x"))
flag_isoc9x = 1;
else if (!strcmp (p, "-fdollars-in-identifiers")) else if (!strcmp (p, "-fdollars-in-identifiers"))
dollars_in_ident = 1; dollars_in_ident = 1;
else if (!strcmp (p, "-fno-dollars-in-identifiers")) else if (!strcmp (p, "-fno-dollars-in-identifiers"))
@ -4322,7 +4328,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
tree type = NULL_TREE; tree type = NULL_TREE;
int longlong = 0; int longlong = 0;
int constp; int constp;
int restrictp;
int volatilep; int volatilep;
int type_quals = TYPE_UNQUALIFIED;
int inlinep; int inlinep;
int explicit_int = 0; int explicit_int = 0;
int explicit_char = 0; int explicit_char = 0;
@ -4632,19 +4640,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = build_complex_type (type); type = build_complex_type (type);
} }
/* Set CONSTP if this declaration is `const', whether by /* Figure out the type qualifiers for the declaration. There are
explicit specification or via a typedef. two ways a declaration can become qualified. One is something
Likewise for VOLATILEP. */ 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); 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); volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
inlinep = !! (specbits & (1 << (int) RID_INLINE)); inlinep = !! (specbits & (1 << (int) RID_INLINE));
if (constp > 1) if (constp > 1)
pedwarn ("duplicate `const'"); pedwarn ("duplicate `const'");
if (restrictp > 1)
pedwarn ("duplicate `restrict'");
if (volatilep > 1) if (volatilep > 1)
pedwarn ("duplicate `volatile'"); 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 = 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'. */ /* Warn if two storage classes are given. Default to `auto'. */
@ -4878,13 +4893,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
is set correctly. */ is set correctly. */
type = build_array_type (type, itype); type = build_array_type (type, itype);
if (constp || volatilep) if (type_quals)
type = c_build_type_variant (type, constp, volatilep); type = c_build_qualified_type (type, type_quals);
#if 0 /* don't clear these; leave them set so that the array type #if 0 /* don't clear these; leave them set so that the array type
or the variable is itself const or volatile. */ or the variable is itself const or volatile. */
constp = 0; type_quals = TYPE_UNQUALIFIED;
volatilep = 0;
#endif #endif
if (size_varies) if (size_varies)
@ -4949,12 +4963,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
flag_traditional flag_traditional
? NULL_TREE : arg_types); ? NULL_TREE : arg_types);
#endif #endif
/* ANSI seems to say that `const int foo ();' /* Type qualifiers before the return type of the function
does not make the function foo const. */ qualify the return type, not the function type. */
if (constp || volatilep) if (type_quals)
type = c_build_type_variant (type, constp, volatilep); type = c_build_qualified_type (type, type_quals);
constp = 0; type_quals = TYPE_UNQUALIFIED;
volatilep = 0;
type = build_function_type (type, arg_types); type = build_function_type (type, arg_types);
declarator = TREE_OPERAND (declarator, 0); declarator = TREE_OPERAND (declarator, 0);
@ -4978,12 +4991,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
for the pointer. */ for the pointer. */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& (constp || volatilep)) && type_quals)
pedwarn ("ANSI C forbids const or volatile function types"); pedwarn ("ANSI C forbids qualified function types");
if (constp || volatilep) if (type_quals)
type = c_build_type_variant (type, constp, volatilep); type = c_build_qualified_type (type, type_quals);
constp = 0; type_quals = TYPE_UNQUALIFIED;
volatilep = 0;
size_varies = 0; size_varies = 0;
type = build_pointer_type (type); type = build_pointer_type (type);
@ -4995,13 +5007,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
{ {
register tree typemodlist; register tree typemodlist;
int erred = 0; int erred = 0;
constp = 0;
volatilep = 0;
restrictp = 0;
for (typemodlist = TREE_TYPE (declarator); typemodlist; for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (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++; constp++;
else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE]) else if (qualifier == ridpointers[(int) RID_VOLATILE])
volatilep++; volatilep++;
else if (qualifier == ridpointers[(int) RID_RESTRICT])
restrictp++;
else if (!erred) else if (!erred)
{ {
erred = 1; erred = 1;
@ -5012,6 +5032,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
pedwarn ("duplicate `const'"); pedwarn ("duplicate `const'");
if (volatilep > 1) if (volatilep > 1)
pedwarn ("duplicate `volatile'"); 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); declarator = TREE_OPERAND (declarator, 0);
@ -5038,10 +5064,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* Note that the grammar rejects storage classes /* Note that the grammar rejects storage classes
in typenames, fields or parameters */ in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& (constp || volatilep)) && type_quals)
pedwarn ("ANSI C forbids const or volatile function types"); pedwarn ("ANSI C forbids qualified function types");
if (constp || volatilep) if (type_quals)
type = c_build_type_variant (type, constp, volatilep); type = c_build_qualified_type (type, type_quals);
decl = build_decl (TYPE_DECL, declarator, type); decl = build_decl (TYPE_DECL, declarator, type);
if ((specbits & (1 << (int) RID_SIGNED)) if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) || (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 /* Note that the grammar rejects storage classes
in typenames, fields or parameters */ in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& (constp || volatilep)) && type_quals)
pedwarn ("ANSI C forbids const or volatile function types"); pedwarn ("ANSI C forbids const or volatile function types");
if (constp || volatilep) if (type_quals)
type = c_build_type_variant (type, constp, volatilep); type = c_build_qualified_type (type, type_quals);
pop_obstacks (); pop_obstacks ();
return type; return type;
} }
@ -5116,20 +5142,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
{ {
/* Transfer const-ness of array into that of type pointed to. */ /* Transfer const-ness of array into that of type pointed to. */
type = TREE_TYPE (type); type = TREE_TYPE (type);
if (constp || volatilep) if (type_quals)
type = c_build_type_variant (type, constp, volatilep); type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type); type = build_pointer_type (type);
volatilep = constp = 0; type_quals = TYPE_UNQUALIFIED;
size_varies = 0; size_varies = 0;
} }
else if (TREE_CODE (type) == FUNCTION_TYPE) else if (TREE_CODE (type) == FUNCTION_TYPE)
{ {
if (pedantic && (constp || volatilep)) if (pedantic && type_quals)
pedwarn ("ANSI C forbids const or volatile function types"); pedwarn ("ANSI C forbids qualified function types");
if (constp || volatilep) if (type_quals)
type = c_build_type_variant (type, constp, volatilep); type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type); type = build_pointer_type (type);
volatilep = constp = 0; type_quals = TYPE_UNQUALIFIED;
} }
decl = build_decl (PARM_DECL, declarator, type); decl = build_decl (PARM_DECL, declarator, type);
@ -5177,13 +5203,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = error_mark_node; type = error_mark_node;
} }
/* Move type qualifiers down to element of an array. */ /* 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), type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
constp, volatilep), type_quals),
TYPE_DOMAIN (type)); TYPE_DOMAIN (type));
#if 0 /* Leave the field const or volatile as well. */ #if 0 /* Leave the field const or volatile as well. */
constp = volatilep = 0; type_quals = TYPE_UNQUALIFIED;
#endif #endif
} }
decl = build_decl (FIELD_DECL, declarator, type); 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 (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_machine_attr); decl = build_decl_attribute_variant (decl, decl_machine_attr);
if (pedantic && (constp || volatilep) if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
&& ! DECL_IN_SYSTEM_HEADER (decl)) pedwarn ("ANSI C forbids qualified function types");
pedwarn ("ANSI C forbids const or volatile functions");
if (pedantic if (pedantic
&& TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
&& (TYPE_READONLY (TREE_TYPE (TREE_TYPE (decl))) && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
|| TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (decl))))
&& ! DECL_IN_SYSTEM_HEADER (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) && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
warning ("`noreturn' function returns non-void value"); 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)); int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
/* Move type qualifiers down to element of an array. */ /* 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), type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
constp, volatilep), type_quals),
TYPE_DOMAIN (type)); TYPE_DOMAIN (type));
#if 0 /* Leave the variable const or volatile as well. */ #if 0 /* Leave the variable const or volatile as well. */
constp = volatilep = 0; type_quals = TYPE_UNQUALIFIED;
#endif #endif
} }
@ -5316,14 +5342,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
DECL_REGISTER (decl) = 1; DECL_REGISTER (decl) = 1;
/* Record constancy and volatility. */ /* 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. /* If a type has volatile components, it should be stored in memory.
Otherwise, the fact that those components are volatile Otherwise, the fact that those components are volatile
will be ignored, and would even crash the compiler. */ will be ignored, and would even crash the compiler. */

View File

@ -1,14 +1,14 @@
/* KR-C code produced by gperf version 2.7.1 (19981006 egcs) */ /* 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 */ /* 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; }; struct resword { char *name; short token; enum rid rid; };
#define TOTAL_KEYWORDS 80 #define TOTAL_KEYWORDS 83
#define MIN_WORD_LENGTH 2 #define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 20 #define MAX_WORD_LENGTH 20
#define MIN_HASH_VALUE 10 #define MIN_HASH_VALUE 8
#define MAX_HASH_VALUE 162 #define MAX_HASH_VALUE 141
/* maximum key range = 153, duplicates = 0 */ /* maximum key range = 134, duplicates = 0 */
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
@ -20,32 +20,32 @@ hash (str, len)
{ {
static unsigned char asso_values[] = static unsigned char asso_values[] =
{ {
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 8, 163, 163, 163, 163, 163, 142, 142, 142, 142, 35, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 1, 163, 24, 8, 61, 142, 142, 142, 142, 142, 1, 142, 90, 1, 28,
37, 6, 47, 49, 2, 5, 163, 3, 51, 30, 40, 6, 1, 24, 3, 13, 142, 36, 60, 14,
58, 91, 35, 163, 33, 13, 1, 18, 49, 2, 49, 3, 6, 142, 19, 8, 1, 50, 33, 11,
2, 5, 3, 163, 163, 163, 163, 163, 163, 163, 2, 23, 4, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
163, 163, 163, 163, 163, 163 142, 142, 142, 142, 142, 142
}; };
register int hval = len; register int hval = len;
@ -64,120 +64,112 @@ hash (str, len)
static struct resword wordlist[] = 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},
{"float", TYPESPEC, RID_FLOAT},
{"__typeof", TYPEOF, NORID},
{"", 0, 0}, {"", 0, 0},
{"int", TYPESPEC, RID_INT},
{"", 0, 0}, {"", 0, 0},
{"__typeof__", TYPEOF, NORID}, {"__typeof__", TYPEOF, NORID},
{"", 0, 0}, {"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}, {"__imag__", IMAGPART, NORID},
{"", 0, 0}, {"else", ELSE, NORID},
{"__inline__", SCSPEC, RID_INLINE}, {"__inline__", SCSPEC, RID_INLINE},
{"while", WHILE, NORID}, {"byref", TYPE_QUAL, RID_BYREF},
{"__iterator__", SCSPEC, RID_ITERATOR}, {"__iterator__", SCSPEC, RID_ITERATOR},
{"__inline", SCSPEC, RID_INLINE}, {"__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}, {"__real__", REALPART, NORID},
{"id", OBJECTNAME, RID_ID}, {"switch", SWITCH, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"__restrict", TYPE_QUAL, RID_RESTRICT},
{"__iterator", SCSPEC, RID_ITERATOR}, {"goto", GOTO, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"__restrict__", TYPE_QUAL, RID_RESTRICT},
{"struct", STRUCT, NORID}, {"struct", STRUCT, NORID},
{"if", IF, NORID}, {"while", WHILE, NORID},
{"@private", PRIVATE, NORID}, {"restrict", TYPE_QUAL, RID_RESTRICT},
{"@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},
{"__const", TYPE_QUAL, RID_CONST}, {"__const", TYPE_QUAL, RID_CONST},
{"extern", SCSPEC, RID_EXTERN}, {"oneway", TYPE_QUAL, RID_ONEWAY},
{"__const__", TYPE_QUAL, RID_CONST}, {"__const__", TYPE_QUAL, RID_CONST},
{"__complex", TYPESPEC, RID_COMPLEX}, {"__complex", TYPESPEC, RID_COMPLEX},
{"__complex__", TYPESPEC, RID_COMPLEX}, {"__complex__", TYPESPEC, RID_COMPLEX},
{"", 0, 0},
{"unsigned", TYPESPEC, RID_UNSIGNED},
{"", 0, 0},
{"@class", CLASS, NORID},
{"@encode", ENCODE, NORID},
{"bycopy", TYPE_QUAL, RID_BYCOPY},
{"__alignof", ALIGNOF, NORID},
{"@interface", INTERFACE, NORID},
{"", 0, 0},
{"case", CASE, NORID},
{"", 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},
{"", 0, 0},
{"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},
{"@end", END, NORID},
{"oneway", TYPE_QUAL, RID_ONEWAY},
{"", 0, 0},
{"short", TYPESPEC, RID_SHORT},
{"@implementation", IMPLEMENTATION, NORID},
{"", 0, 0}, {"", 0, 0},
{"volatile", TYPE_QUAL, RID_VOLATILE},
{"", 0, 0},
{"for", FOR, NORID}, {"for", FOR, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"__iterator", SCSPEC, RID_ITERATOR},
{"auto", SCSPEC, RID_AUTO}, {"__imag", IMAGPART, NORID},
{"", 0, 0},
{"char", TYPESPEC, RID_CHAR},
{"register", SCSPEC, RID_REGISTER},
{"", 0, 0},
{"const", TYPE_QUAL, RID_CONST},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"do", DO, 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},
{"__signed", TYPESPEC, RID_SIGNED},
{"bycopy", TYPE_QUAL, RID_BYCOPY},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"extern", SCSPEC, RID_EXTERN},
{"", 0, 0},
{"in", TYPE_QUAL, RID_IN},
{"", 0, 0}, {"", 0, 0},
{"@compatibility_alias", ALIAS, NORID}, {"@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}, {"", 0, 0},
{"float", TYPESPEC, RID_FLOAT}, {"@private", PRIVATE, NORID},
{"goto", GOTO, NORID}, {"@selector", SELECTOR, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"register", SCSPEC, RID_REGISTER},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"__label__", LABEL, NORID},
{"long", TYPESPEC, RID_LONG} {"", 0, 0}, {"", 0, 0},
{"enum", ENUM, NORID},
{"return", RETURN, NORID},
{"", 0, 0}, {"", 0, 0},
{"signed", TYPESPEC, RID_SIGNED},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"const", TYPE_QUAL, RID_CONST},
{"", 0, 0},
{"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},
{"@public", PUBLIC, NORID},
{"asm", ASM_KEYWORD, NORID},
{"", 0, 0},
{"@protocol", PROTOCOL, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"@end", END, NORID},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"static", SCSPEC, RID_STATIC},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"long", TYPESPEC, RID_LONG},
{"", 0, 0}, {"", 0, 0}, {"", 0, 0},
{"char", TYPESPEC, RID_CHAR}
}; };
#ifdef __GNUC__ #ifdef __GNUC__

View File

@ -245,6 +245,7 @@ init_lex ()
ridpointers[(int) RID_SIGNED] = get_identifier ("signed"); ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
ridpointers[(int) RID_INLINE] = get_identifier ("inline"); ridpointers[(int) RID_INLINE] = get_identifier ("inline");
ridpointers[(int) RID_CONST] = get_identifier ("const"); ridpointers[(int) RID_CONST] = get_identifier ("const");
ridpointers[(int) RID_RESTRICT] = get_identifier ("restrict");
ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile"); ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
ridpointers[(int) RID_AUTO] = get_identifier ("auto"); ridpointers[(int) RID_AUTO] = get_identifier ("auto");
ridpointers[(int) RID_STATIC] = get_identifier ("static"); ridpointers[(int) RID_STATIC] = get_identifier ("static");
@ -274,6 +275,7 @@ init_lex ()
if (flag_traditional) if (flag_traditional)
{ {
UNSET_RESERVED_WORD ("const"); UNSET_RESERVED_WORD ("const");
UNSET_RESERVED_WORD ("restrict");
UNSET_RESERVED_WORD ("volatile"); UNSET_RESERVED_WORD ("volatile");
UNSET_RESERVED_WORD ("typeof"); UNSET_RESERVED_WORD ("typeof");
UNSET_RESERVED_WORD ("signed"); UNSET_RESERVED_WORD ("signed");
@ -281,6 +283,9 @@ init_lex ()
UNSET_RESERVED_WORD ("iterator"); UNSET_RESERVED_WORD ("iterator");
UNSET_RESERVED_WORD ("complex"); UNSET_RESERVED_WORD ("complex");
} }
else if (!flag_isoc9x)
UNSET_RESERVED_WORD ("restrict");
if (flag_no_asm) if (flag_no_asm)
{ {
UNSET_RESERVED_WORD ("asm"); UNSET_RESERVED_WORD ("asm");

View File

@ -40,6 +40,7 @@ enum rid
RID_TYPEDEF, RID_TYPEDEF,
RID_SIGNED, RID_SIGNED,
RID_CONST, RID_CONST,
RID_RESTRICT,
RID_VOLATILE, RID_VOLATILE,
RID_INLINE, RID_INLINE,
RID_NOALIAS, RID_NOALIAS,

View File

@ -1164,7 +1164,7 @@ static const short yycheck[] = { 38,
52 52
}; };
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ /* -*-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, /* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
@ -1357,7 +1357,7 @@ __yy_memcpy (char *to, char *from, int count)
#endif #endif
#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 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *. into yyparse. The argument should have type void *.
@ -3676,7 +3676,7 @@ case 401:
break;} break;}
} }
/* the action file gets copied in in place of this dollarsign */ /* 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; yyvsp -= yylen;
yyssp -= yylen; yyssp -= yylen;

View File

@ -35,6 +35,8 @@ __iterator__, SCSPEC, RID_ITERATOR
__label__, LABEL, NORID __label__, LABEL, NORID
__real, REALPART, NORID __real, REALPART, 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
__signed__, TYPESPEC, RID_SIGNED __signed__, TYPESPEC, RID_SIGNED
__typeof, TYPEOF, NORID __typeof, TYPEOF, NORID
@ -69,6 +71,7 @@ long, TYPESPEC, RID_LONG
oneway, TYPE_QUAL, RID_ONEWAY oneway, TYPE_QUAL, RID_ONEWAY
out, TYPE_QUAL, RID_OUT out, TYPE_QUAL, RID_OUT
register, SCSPEC, RID_REGISTER register, SCSPEC, RID_REGISTER
restrict, TYPE_QUAL, RID_RESTRICT
return, RETURN, NORID return, RETURN, NORID
short, TYPESPEC, RID_SHORT short, TYPESPEC, RID_SHORT
signed, TYPESPEC, RID_SIGNED signed, TYPESPEC, RID_SIGNED

View File

@ -116,7 +116,7 @@ end ifc
yylval contains an IDENTIFIER_NODE which indicates which one. */ yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPESPEC %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. */ yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPE_QUAL %token TYPE_QUAL

View File

@ -104,7 +104,7 @@ char *language_string = "GNU C";
yylval contains an IDENTIFIER_NODE which indicates which one. */ yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPESPEC %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. */ yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPE_QUAL %token TYPE_QUAL

View File

@ -80,6 +80,22 @@ extern int pedantic;
nonzero if the definition of the type has already started. */ nonzero if the definition of the type has already started. */
#define C_TYPE_BEING_DEFINED(type) TYPE_LANG_FLAG_0 (type) #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. */ /* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_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 init_function_format_info PROTO((void));
extern void check_function_format PROTO((tree, tree, tree)); extern void check_function_format PROTO((tree, tree, tree));
extern int c_get_alias_set PROTO((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. /* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */ NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code)); 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. */ /* Declare a predefined function. Return the declaration. */
extern tree builtin_function PROTO((char *, tree, enum built_in_function function_, char *)); extern tree builtin_function PROTO((char *, tree, enum built_in_function function_, char *));
/* Add qualifiers to a type, in the fashion for C. */ /* 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 int c_decode_option PROTO((int, char **));
extern void c_mark_varargs PROTO((void)); extern void c_mark_varargs PROTO((void));
extern tree check_identifier PROTO((tree, tree)); extern tree check_identifier PROTO((tree, tree));
@ -497,6 +518,10 @@ extern int warn_main;
extern int flag_traditional; 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 /* Nonzero means to allow single precision math even if we're generally
being traditional. */ being traditional. */
extern int flag_allow_single_precision; extern int flag_allow_single_precision;

View File

@ -163,9 +163,7 @@ static tree
qualify_type (type, like) qualify_type (type, like)
tree type, like; tree type, like;
{ {
int constflag = TYPE_READONLY (type) || TYPE_READONLY (like); return c_build_qualified_type (type, TYPE_QUALS (like));
int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);
return c_build_type_variant (type, constflag, volflag);
} }
/* Return the common type of two types. /* Return the common type of two types.
@ -283,14 +281,14 @@ common_type (t1, t2)
But ANSI C specifies doing this with the qualifiers. But ANSI C specifies doing this with the qualifiers.
So I turned it on again. */ So I turned it on again. */
{ {
tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)), tree pointed_to_1 = TREE_TYPE (t1);
TYPE_MAIN_VARIANT (TREE_TYPE (t2))); tree pointed_to_2 = TREE_TYPE (t2);
int constp tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1),
= TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2)); TYPE_MAIN_VARIANT (pointed_to_2));
int volatilep t1 = build_pointer_type (c_build_qualified_type
= TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2)); (target,
t1 = build_pointer_type (c_build_type_variant (target, constp, TYPE_QUALS (pointed_to_1) |
volatilep)); TYPE_QUALS (pointed_to_2)));
return build_type_attribute_variant (t1, attributes); return build_type_attribute_variant (t1, attributes);
} }
#if 0 #if 0
@ -447,9 +445,7 @@ comptypes (type1, type2)
/* Qualifiers must match. */ /* Qualifiers must match. */
if (TYPE_READONLY (t1) != TYPE_READONLY (t2)) if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
return 0;
if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
return 0; return 0;
/* Allow for two different type nodes which have essentially the same /* Allow for two different type nodes which have essentially the same
@ -1084,11 +1080,12 @@ default_conversion (exp)
volatilep = TREE_THIS_VOLATILE (exp); volatilep = TREE_THIS_VOLATILE (exp);
} }
if (TYPE_READONLY (type) || TYPE_VOLATILE (type) if (TYPE_QUALS (type) || constp || volatilep)
|| constp || volatilep) restype
restype = c_build_type_variant (restype, = c_build_qualified_type (restype,
TYPE_READONLY (type) || constp, TYPE_QUALS (type)
TYPE_VOLATILE (type) || volatilep); | (constp * TYPE_QUAL_CONST)
| (volatilep * TYPE_QUAL_VOLATILE));
if (TREE_CODE (exp) == INDIRECT_REF) if (TREE_CODE (exp) == INDIRECT_REF)
return convert (TYPE_POINTER_TO (restype), 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. */ /* Ordinary case; arg is a COMPONENT_REF or a decl. */
argtype = TREE_TYPE (arg); argtype = TREE_TYPE (arg);
/* If the lvalue is const or volatile, /* If the lvalue is const or volatile, merge that into the type
merge that into the type that the address will point to. */ 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' if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
|| TREE_CODE_CLASS (TREE_CODE (arg)) == 'r') || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
{ {
@ -3779,11 +3778,11 @@ build_c_cast (type, expr)
in_type = TREE_TYPE (in_type); in_type = TREE_TYPE (in_type);
while (TREE_CODE (in_otype) == POINTER_TYPE) while (TREE_CODE (in_otype) == POINTER_TYPE)
in_otype = TREE_TYPE (in_otype); in_otype = TREE_TYPE (in_otype);
if (TYPE_VOLATILE (in_otype) && ! TYPE_VOLATILE (in_type)) if (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type))
pedwarn ("cast discards `volatile' from pointer target type"); /* There are qualifiers present in IN_OTYPE that are not
if (TYPE_READONLY (in_otype) && ! TYPE_READONLY (in_type)) present in IN_TYPE. */
pedwarn ("cast discards `const' from pointer target type"); pedwarn ("cast discards qualifiers from pointer target type");
} }
/* Warn about possible alignment problems. */ /* Warn about possible alignment problems. */
@ -4114,12 +4113,13 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
|| comp_target_types (memb_type, rhstype)) || comp_target_types (memb_type, rhstype))
{ {
/* If this type won't generate any warnings, use it. */ /* If this type won't generate any warnings, use it. */
if ((TREE_CODE (ttr) == FUNCTION_TYPE if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
&& TREE_CODE (ttl) == FUNCTION_TYPE) || ((TREE_CODE (ttr) == FUNCTION_TYPE
? ((! TYPE_READONLY (ttl) | TYPE_READONLY (ttr)) && TREE_CODE (ttl) == FUNCTION_TYPE)
& (! TYPE_VOLATILE (ttl) | TYPE_VOLATILE (ttr))) ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
: ((TYPE_READONLY (ttl) | ! TYPE_READONLY (ttr)) == TYPE_QUALS (ttr))
& (TYPE_VOLATILE (ttl) | ! TYPE_VOLATILE (ttr)))) : (TYPE_QUALS (ttl) | TYPE_QUALS (ttr)
== TYPE_QUALS (ttl))))
break; break;
/* Keep looking for a better type, but remember this one. */ /* 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 certain things, it is okay to use a const or volatile
function where an ordinary one is wanted, but not function where an ordinary one is wanted, but not
vice-versa. */ vice-versa. */
if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr)) if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
warn_for_assignment ("%s makes `const *' function pointer from non-const", warn_for_assignment ("%s makes qualified function pointer from unqualified",
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",
get_spelling (errtype), funname, get_spelling (errtype), funname,
parmnum); 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)) 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 else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE) && TREE_CODE (ttl) != FUNCTION_TYPE)
{ {
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr)) if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
warn_for_assignment ("%s discards `const' from pointer target type", warn_for_assignment ("%s discards qualifiers 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",
get_spelling (errtype), funname, parmnum); get_spelling (errtype), funname, parmnum);
/* If this is not a case of ignoring a mismatch in signedness, /* If this is not a case of ignoring a mismatch in signedness,
no warning. */ no warning. */
@ -4241,11 +4227,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
that say the function will not do certain things, that say the function will not do certain things,
it is okay to use a const or volatile function it is okay to use a const or volatile function
where an ordinary one is wanted, but not vice-versa. */ where an ordinary one is wanted, but not vice-versa. */
if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr)) if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
warn_for_assignment ("%s makes `const *' function pointer from non-const", warn_for_assignment ("%s makes qualified function pointer from unqualified",
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); get_spelling (errtype), funname, parmnum);
} }
} }

View File

@ -93,7 +93,7 @@ in the following sections.
@item C Language Options @item C Language Options
@xref{C Dialect Options,,Options Controlling C Dialect}. @xref{C Dialect Options,,Options Controlling C Dialect}.
@smallexample @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 -fno-builtin -ffreestanding -fhosted -fsigned-bitfields -fsigned-char
-funsigned-bitfields -funsigned-char -fwritable-strings -funsigned-bitfields -funsigned-char -fwritable-strings
-traditional -traditional-cpp -trigraphs -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 The functions @code{alloca}, @code{abort}, @code{exit}, and
@code{_exit} are not builtin functions when @samp{-ansi} is used. @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 @item -fno-asm
Do not recognize @code{asm}, @code{inline} or @code{typeof} as a 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 keyword, so that code can use these words as identifiers. You can use

View File

@ -404,6 +404,8 @@ print_node (file, prefix, node, indent)
fprintf (file, " built-in code %d", DECL_FUNCTION_CODE (node)); fprintf (file, " built-in code %d", DECL_FUNCTION_CODE (node));
if (TREE_CODE (node) == FIELD_DECL) if (TREE_CODE (node) == FIELD_DECL)
print_node (file, "bitpos", DECL_FIELD_BITPOS (node), indent + 4); 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, "context", DECL_CONTEXT (node), indent + 4);
print_node_brief (file, "machine_attributes", DECL_MACHINE_ATTRIBUTES (node), indent + 4); print_node_brief (file, "machine_attributes", DECL_MACHINE_ATTRIBUTES (node), indent + 4);
print_node_brief (file, "abstract_origin", print_node_brief (file, "abstract_origin",

View File

@ -1505,5 +1505,6 @@ extern void init_alias_analysis PROTO ((void));
extern void end_alias_analysis PROTO ((void)); extern void end_alias_analysis PROTO ((void));
extern void record_base_value PROTO ((int, rtx, int)); extern void record_base_value PROTO ((int, rtx, int));
extern void record_alias_subset PROTO ((int, int));
#endif /* _RTL_H */ #endif /* _RTL_H */

View File

@ -949,6 +949,7 @@ documented_lang_options[] =
{ "-traditional", "Attempt to support traditional K&R style C"}, { "-traditional", "Attempt to support traditional K&R style C"},
{ "-fnotraditional", "" }, { "-fnotraditional", "" },
{ "-fno-traditional", "" }, { "-fno-traditional", "" },
{ "-flang-isoc9x", "Enable C9X features"},
{ "-fasm", "" }, { "-fasm", "" },
{ "-fno-asm", "Do not recognise the 'asm' keyword" }, { "-fno-asm", "Do not recognise the 'asm' keyword" },

View File

@ -264,6 +264,8 @@ int (*lang_get_alias_set) PROTO((tree));
codes are made. */ codes are made. */
#define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777) #define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
static void set_type_quals PROTO((tree, int));
extern char *mode_name[]; extern char *mode_name[];
void gcc_obstack_init (); void gcc_obstack_init ();
@ -1100,6 +1102,9 @@ make_node (code)
DECL_SOURCE_LINE (t) = lineno; DECL_SOURCE_LINE (t) = lineno;
DECL_SOURCE_FILE (t) = (input_filename) ? input_filename : "<built-in>"; DECL_SOURCE_FILE (t) = (input_filename) ? input_filename : "<built-in>";
DECL_UID (t) = next_decl_uid++; 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; break;
case 't': case 't':
@ -3294,7 +3299,7 @@ build_type_attribute_variant (ttype, attribute)
/* Create a new main variant of TYPE. */ /* Create a new main variant of TYPE. */
TYPE_MAIN_VARIANT (ntype) = ntype; TYPE_MAIN_VARIANT (ntype) = ntype;
TYPE_NEXT_VARIANT (ntype) = 0; TYPE_NEXT_VARIANT (ntype) = 0;
TYPE_READONLY (ntype) = TYPE_VOLATILE (ntype) = 0; set_type_quals (ntype, TYPE_UNQUALIFIED);
hashcode = TYPE_HASH (TREE_CODE (ntype)) hashcode = TYPE_HASH (TREE_CODE (ntype))
+ TYPE_HASH (TREE_TYPE (ntype)) + TYPE_HASH (TREE_TYPE (ntype))
@ -3319,8 +3324,7 @@ build_type_attribute_variant (ttype, attribute)
} }
ntype = type_hash_canon (hashcode, ntype); ntype = type_hash_canon (hashcode, ntype);
ttype = build_type_variant (ntype, TYPE_READONLY (ttype), ttype = build_qualified_type (ntype, TYPE_QUALS (ttype));
TYPE_VOLATILE (ttype));
} }
return ttype; return ttype;
@ -3576,45 +3580,44 @@ merge_machine_decl_attributes (olddecl, newdecl)
#endif #endif
} }
/* Return a type like TYPE except that its TYPE_READONLY is CONSTP /* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
and its TYPE_VOLATILE is VOLATILEP. of the various TYPE_QUAL values. */
Such variant types already made are recorded so that duplicates static void
are not made. 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. /* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
Always copy the variant information into the TREE_READONLY the same kind of data as TYPE describes. Variants point to the
and TREE_THIS_VOLATILE of the expression, and then give the expression "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
as its type the "main variant", the variant whose TYPE_READONLY and it points to a chain of other variants so that duplicate
and TYPE_VOLATILE are zero. Use TYPE_MAIN_VARIANT to find the variants are never made. Only main variants should ever appear as
main variant. */ types of expressions. */
tree tree
build_type_variant (type, constp, volatilep) build_qualified_type (type, type_quals)
tree type; tree type;
int constp, volatilep; int type_quals;
{ {
register tree t; 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 /* 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 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. */ preserve the TYPE_NAME, since there is code that depends on this. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
if (constp == TYPE_READONLY (t) && volatilep == TYPE_VOLATILE (t) if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type))
&& TYPE_NAME (t) == TYPE_NAME (type))
return t; return t;
/* We need a new one. */ /* We need a new one. */
t = build_type_copy (type); t = build_type_copy (type);
TYPE_READONLY (t) = constp; set_type_quals (t, type_quals);
TYPE_VOLATILE (t) = volatilep;
return t; return t;
} }
@ -4422,8 +4425,7 @@ build_complex_type (component_type)
t = make_node (COMPLEX_TYPE); t = make_node (COMPLEX_TYPE);
TREE_TYPE (t) = TYPE_MAIN_VARIANT (component_type); TREE_TYPE (t) = TYPE_MAIN_VARIANT (component_type);
TYPE_VOLATILE (t) = TYPE_VOLATILE (component_type); set_type_quals (t, TYPE_QUALS (component_type));
TYPE_READONLY (t) = TYPE_READONLY (component_type);
/* If we already have such a type, use the old one and free this one. */ /* If we already have such a type, use the old one and free this one. */
hashcode = TYPE_HASH (component_type); hashcode = TYPE_HASH (component_type);

View File

@ -830,6 +830,25 @@ struct tree_block
/* Means this type is const-qualified. */ /* Means this type is const-qualified. */
#define TYPE_READONLY(NODE) ((NODE)->common.readonly_flag) #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. */ /* 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_0(NODE) (TYPE_CHECK (NODE)->type.lang_flag_0)
#define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type.lang_flag_1) #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 needs_constructing_flag : 1;
unsigned transparent_union_flag : 1; unsigned transparent_union_flag : 1;
unsigned packed_flag : 1; unsigned packed_flag : 1;
unsigned restrict_flag : 1;
unsigned lang_flag_0 : 1; unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1; unsigned lang_flag_1 : 1;
unsigned lang_flag_2 : 1; unsigned lang_flag_2 : 1;
@ -888,7 +909,7 @@ struct tree_type
unsigned lang_flag_4 : 1; unsigned lang_flag_4 : 1;
unsigned lang_flag_5 : 1; unsigned lang_flag_5 : 1;
unsigned lang_flag_6 : 1; unsigned lang_flag_6 : 1;
/* room for 4 more bits */ /* room for 3 more bits */
unsigned int align; unsigned int align;
union tree_node *pointer_to; union tree_node *pointer_to;
@ -1244,6 +1265,16 @@ struct tree_type
an address constant. */ an address constant. */
#define DECL_NON_ADDR_CONST_P(NODE) (DECL_CHECK (NODE)->decl.non_addr_const_p) #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 struct tree_decl
{ {
char common[sizeof (struct tree_common)]; char common[sizeof (struct tree_common)];
@ -1316,6 +1347,7 @@ struct tree_decl
HOST_WIDE_INT i; HOST_WIDE_INT i;
} saved_insns; } saved_insns;
union tree_node *vindex; union tree_node *vindex;
int pointer_alias_set;
/* Points to a structure whose details depend on the language in use. */ /* Points to a structure whose details depend on the language in use. */
struct lang_decl *lang_specific; struct lang_decl *lang_specific;
}; };
@ -1502,14 +1534,24 @@ extern tree lookup_attribute PROTO((char *, tree));
extern tree merge_attributes PROTO((tree, tree)); extern tree merge_attributes PROTO((tree, tree));
/* Given a type node TYPE, and CONSTP and VOLATILEP, return a type /* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
for the same kind of data as TYPE describes. the same kind of data as TYPE describes. Variants point to the
Variants point to the "main variant" (which has neither CONST nor VOLATILE) "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
via TYPE_MAIN_VARIANT, and it points to a chain of other variants and it points to a chain of other variants so that duplicate
so that duplicate variants are never made. variants are never made. Only main variants should ever appear as
Only main variants should ever appear as types of expressions. */ types of expressions. */
extern tree build_type_variant PROTO((tree, int, int)); 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. */
#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. */ /* Make a copy of a type node. */