Index: ChangeLog
2003-07-10 Geoffrey Keating <geoffk@apple.com> * c-decl.c (finish_decl): Handle 'used' here... * cgraphunit.c (cgraph_finalize_function): ... and here ... * c-common.c: (handle_used_attribute): ... not here. * configure.in (onstep): Support --enable-intermodule. * Makefile.in (OBJS-common): New. (OBJS-md): New. (OBJS-archive): New. (OBJS): Build from OBJS-common, OBJS-md, OBJS-archive. (OBJS-onestep): New. (libbackend.a): Support @onestep@. (libbackend.o): New. * configure: Regenerate. * c-common.h (c_reset_state): New prototype. (c_parse_file): New prototype. (finish_file): Move prototype from c-tree.h. * c-decl.c: Include <hashtab.h>. (builtin_decls): New. (current_file_decl): New. (duplicate_decls): Add extra parameter. Change all callers. Don't output duplicate common symbols. (link_hash_hash): New. (link_hash_eq): New. (poplevel): Handle popping of the top level. (warn_if_shadowing): Handle TRANSLATION_UNIT_DECL. (pushdecl): Set DECL_CONTEXT to TRANSLATION_UNIT_DECL if appropriate. (pushdecl_top_level): Likewise. (redeclaration_error_message): Handle TRANSLATION_UNIT_DECL. (c_init_decl_processing): Create TRANSLATION_UNIT_DECL. (finish_decl): Handle TRANSLATION_UNIT_DECL. (merge_translation_unit_decls): New. (c_write_global_declarations): New. (c_reset_state): New. (implicitly_declare): Handle TRANSLATION_UNIT_DECL. * c-lang.c (LANG_HOOKS_WRITE_GLOBALS): New. * c-objc-common.c (c_cannot_inline_tree_fn): Handle TRANSLATION_UNIT_DECL. (c_objc_common_finish_file): Call merge_translation_unit_decls. * c-opts.c (in_fnames): Rename from in_fname. (c_common_decode_option): Handle multiple input filenames. (c_common_post_options): Likewise. (c_common_parse_file): Likewise; also, call c_parse_file rather than yyparse. * c-parse.in: Move cleanup code to c_parse_file. (free_parser_stacks): Move contents to c_parse_file. (c_parse_file): New. * c-tree.h (union lang_tree_node): Chain along TYPE_NEXT_VARIANT for integer types. (C_DECL_FILE_SCOPE): New. (finish_file): Move prototype to c-common.h. (merge_translation_unit_decls): New prototype. (comptypes): Add extra parameter to prototype. (c_write_global_declarations): New prototype. * c-typeck.c (tagged_types_tu_compatible_p): New. (function_types_compatible_p): Add extra parameter, change all callers. (type_lists_compatible_p): Likewise. (comptypes): Likewise. (struct tagged_tu_seen): New. (tagged_tu_seen_base): New. (build_unary_op): Handle TRANSLATION_UNIT_DECL. (c_mark_addressable): Remove #if 0 code. * calls.c (special_function_p): Handle TRANSLATION_UNIT_DECL, add comment explaining why it shouldn't have to. * cgraph.h (struct cgraph_node): Add chain_next and chain_prev GTY options. * cppinit.c (cpp_read_next_file): New. (cpp_read_main_file): Use it. * cpplib.c (undefine_macros): New. (cpp_undef_all): New. * cpplib.h (cpp_read_next_file): Prototype. (cpp_undef_all): Prototype. * langhooks-def.h (write_global_declarations): Remove prototype. * toplev.h (write_global_declarations): Add prototype. * tree.c (decl_type_context): Use switch statement, handle TRANSLATION_UNIT_DECL. * tree.def: Update documentation for TRANSLATION_UNIT_DECL. (TRANSLATION_UNIT_DECL): New kind of tree. * tree.h: Update documentation for TRANSLATION_UNIT_DECL. * Makefile.in (c-decl.o): Add $(HASHTAB_H) to dependencies. * doc/invoke.texi: Make attempt to document new functionality. 2003-05-19 Per Bothner <bothner@apple.com> * gcc.c (combine_inputs): New. (process_command): Set combine_inputs. (do_spec_1): Handle combine_inputs. (main): Likewise. Index: cp/ChangeLog 2003-07-10 Geoffrey Keating <geoffk@apple.com> * decl.c (cp_finish_decl): Handle 'used' attribute. * cp-lang.c (c_reset_state): New dummy routine. * cp-tree.h (finish_file): Move prototype to c-common.h. * parser.c (c_parse_file): Rename from yyparse; don't call finish_file. From-SVN: r69224
This commit is contained in:
parent
6eeba0cc43
commit
d1bd0ded61
32 changed files with 1150 additions and 448 deletions
|
@ -1,3 +1,94 @@
|
|||
2003-07-11 Geoffrey Keating <geoffk@apple.com>
|
||||
|
||||
* c-decl.c (finish_decl): Handle 'used' here...
|
||||
* cgraphunit.c (cgraph_finalize_function): ... and here ...
|
||||
* c-common.c: (handle_used_attribute): ... not here.
|
||||
|
||||
* configure.in (onstep): Support --enable-intermodule.
|
||||
* Makefile.in (OBJS-common): New.
|
||||
(OBJS-md): New.
|
||||
(OBJS-archive): New.
|
||||
(OBJS): Build from OBJS-common, OBJS-md, OBJS-archive.
|
||||
(OBJS-onestep): New.
|
||||
(libbackend.a): Support @onestep@.
|
||||
(libbackend.o): New.
|
||||
* configure: Regenerate.
|
||||
|
||||
* c-common.h (c_reset_state): New prototype.
|
||||
(c_parse_file): New prototype.
|
||||
(finish_file): Move prototype from c-tree.h.
|
||||
* c-decl.c: Include <hashtab.h>.
|
||||
(builtin_decls): New.
|
||||
(current_file_decl): New.
|
||||
(duplicate_decls): Add extra parameter. Change all callers. Don't
|
||||
output duplicate common symbols.
|
||||
(link_hash_hash): New.
|
||||
(link_hash_eq): New.
|
||||
(poplevel): Handle popping of the top level.
|
||||
(warn_if_shadowing): Handle TRANSLATION_UNIT_DECL.
|
||||
(pushdecl): Set DECL_CONTEXT to TRANSLATION_UNIT_DECL if appropriate.
|
||||
(pushdecl_top_level): Likewise.
|
||||
(redeclaration_error_message): Handle TRANSLATION_UNIT_DECL.
|
||||
(c_init_decl_processing): Create TRANSLATION_UNIT_DECL.
|
||||
(finish_decl): Handle TRANSLATION_UNIT_DECL.
|
||||
(merge_translation_unit_decls): New.
|
||||
(c_write_global_declarations): New.
|
||||
(c_reset_state): New.
|
||||
(implicitly_declare): Handle TRANSLATION_UNIT_DECL.
|
||||
* c-lang.c (LANG_HOOKS_WRITE_GLOBALS): New.
|
||||
* c-objc-common.c (c_cannot_inline_tree_fn): Handle
|
||||
TRANSLATION_UNIT_DECL.
|
||||
(c_objc_common_finish_file): Call merge_translation_unit_decls.
|
||||
* c-opts.c (in_fnames): Rename from in_fname.
|
||||
(c_common_decode_option): Handle multiple input filenames.
|
||||
(c_common_post_options): Likewise.
|
||||
(c_common_parse_file): Likewise; also, call c_parse_file rather than
|
||||
yyparse.
|
||||
* c-parse.in: Move cleanup code to c_parse_file.
|
||||
(free_parser_stacks): Move contents to c_parse_file.
|
||||
(c_parse_file): New.
|
||||
* c-tree.h (union lang_tree_node): Chain along TYPE_NEXT_VARIANT
|
||||
for integer types.
|
||||
(C_DECL_FILE_SCOPE): New.
|
||||
(finish_file): Move prototype to c-common.h.
|
||||
(merge_translation_unit_decls): New prototype.
|
||||
(comptypes): Add extra parameter to prototype.
|
||||
(c_write_global_declarations): New prototype.
|
||||
* c-typeck.c (tagged_types_tu_compatible_p): New.
|
||||
(function_types_compatible_p): Add extra parameter, change all callers.
|
||||
(type_lists_compatible_p): Likewise.
|
||||
(comptypes): Likewise.
|
||||
(struct tagged_tu_seen): New.
|
||||
(tagged_tu_seen_base): New.
|
||||
(build_unary_op): Handle TRANSLATION_UNIT_DECL.
|
||||
(c_mark_addressable): Remove #if 0 code.
|
||||
* calls.c (special_function_p): Handle TRANSLATION_UNIT_DECL, add
|
||||
comment explaining why it shouldn't have to.
|
||||
* cgraph.h (struct cgraph_node): Add chain_next and chain_prev GTY
|
||||
options.
|
||||
* cppinit.c (cpp_read_next_file): New.
|
||||
(cpp_read_main_file): Use it.
|
||||
* cpplib.c (undefine_macros): New.
|
||||
(cpp_undef_all): New.
|
||||
* cpplib.h (cpp_read_next_file): Prototype.
|
||||
(cpp_undef_all): Prototype.
|
||||
* langhooks-def.h (write_global_declarations): Remove prototype.
|
||||
* toplev.h (write_global_declarations): Add prototype.
|
||||
* tree.c (decl_type_context): Use switch statement, handle
|
||||
TRANSLATION_UNIT_DECL.
|
||||
* tree.def: Update documentation for TRANSLATION_UNIT_DECL.
|
||||
(TRANSLATION_UNIT_DECL): New kind of tree.
|
||||
* tree.h: Update documentation for TRANSLATION_UNIT_DECL.
|
||||
* Makefile.in (c-decl.o): Add $(HASHTAB_H) to dependencies.
|
||||
* doc/invoke.texi: Make attempt to document new functionality.
|
||||
|
||||
2003-05-19 Per Bothner <bothner@apple.com>
|
||||
|
||||
* gcc.c (combine_inputs): New.
|
||||
(process_command): Set combine_inputs.
|
||||
(do_spec_1): Handle combine_inputs.
|
||||
(main): Likewise.
|
||||
|
||||
2003-07-10 James E Wilson <wilson@tuliptree.org>
|
||||
|
||||
PR optimization/9745
|
||||
|
|
|
@ -801,7 +801,8 @@ C_OBJS = c-parse.o c-lang.o c-pretty-print.o $(C_AND_OBJC_OBJS)
|
|||
|
||||
# Language-independent object files.
|
||||
|
||||
OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
|
||||
OBJS-common = \
|
||||
alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
|
||||
cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
|
||||
cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \
|
||||
cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \
|
||||
|
@ -809,7 +810,7 @@ OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
|
|||
dwarf2asm.o dwarf2out.o dwarfout.o emit-rtl.o except.o explow.o \
|
||||
expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \
|
||||
genrtl.o ggc-common.o global.o graph.o gtype-desc.o \
|
||||
haifa-sched.o hashtable.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o \
|
||||
haifa-sched.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o \
|
||||
insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o \
|
||||
integrate.o intl.o jump.o langhooks.o lcm.o lists.o local-alloc.o \
|
||||
loop.o optabs.o options.o opts.o params.o postreload.o predict.o \
|
||||
|
@ -820,9 +821,16 @@ OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
|
|||
sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o \
|
||||
sibcall.o simplify-rtx.o sreal.o ssa.o ssa-ccp.o ssa-dce.o stmt.o \
|
||||
stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
|
||||
tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \
|
||||
alloc-pool.o et-forest.o cgraph.o cgraphunit.o cfghooks.o bt-load.o \
|
||||
$(GGC) $(out_object_file) $(EXTRA_OBJS) $(host_hook_obj)
|
||||
unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \
|
||||
alloc-pool.o et-forest.o cfghooks.o bt-load.o $(GGC)
|
||||
|
||||
OBJS-md = $(out_object_file)
|
||||
OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) hashtable.o tree-inline.o \
|
||||
cgraph.o cgraphunit.o
|
||||
|
||||
OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive)
|
||||
|
||||
OBJS-onestep = libbackend.o $(OBJS-archive)
|
||||
|
||||
BACKEND = main.o libbackend.a
|
||||
|
||||
|
@ -1026,9 +1034,9 @@ rest.cross: $(LIBGCC) specs
|
|||
compilations: $(BACKEND)
|
||||
|
||||
# Like libcpp.a, this archive is strictly for the host.
|
||||
libbackend.a: $(OBJS)
|
||||
libbackend.a: $(OBJS@onestep@)
|
||||
-rm -rf libbackend.a
|
||||
$(AR) $(AR_FLAGS) libbackend.a $(OBJS)
|
||||
$(AR) $(AR_FLAGS) libbackend.a $(OBJS@onestep@)
|
||||
-$(RANLIB) libbackend.a
|
||||
|
||||
# We call this executable `xgcc' rather than `gcc'
|
||||
|
@ -1817,6 +1825,15 @@ mips-tdump: mips-tdump.o version.o $(LIBDEPS)
|
|||
|
||||
mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h $(TM_H) version.h
|
||||
|
||||
# FIXME: writing proper dependencies for this is a *LOT* of work.
|
||||
libbackend.o : $(OBJS-common:.o=.c) $(out_file) \
|
||||
insn-config.h insn-flags.h insn-codes.h insn-constants.h \
|
||||
insn-attr.h options_.h
|
||||
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
|
||||
-DTARGET_NAME=\"$(target_alias)\" \
|
||||
-DLOCALEDIR=\"$(localedir)\" \
|
||||
-c $(filter %.c,$^) -o $@
|
||||
|
||||
#
|
||||
# Generate header and source files from the machine description,
|
||||
# and compile them.
|
||||
|
|
|
@ -4680,7 +4680,6 @@ handle_used_attribute (tree *pnode, tree name, tree args ATTRIBUTE_UNUSED,
|
|||
if (TREE_CODE (node) == FUNCTION_DECL
|
||||
|| (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
|
||||
{
|
||||
mark_referenced (DECL_ASSEMBLER_NAME (node));
|
||||
TREE_USED (node) = 1;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -963,6 +963,14 @@ extern bool c_promoting_integer_type_p (tree);
|
|||
extern int self_promoting_args_p (tree);
|
||||
extern tree strip_array_types (tree);
|
||||
|
||||
/* This function resets the parsers' state in preparation for parsing
|
||||
a new file. */
|
||||
extern void c_reset_state (void);
|
||||
/* This is the basic parsing function. */
|
||||
extern void c_parse_file (void);
|
||||
/* This is misnamed, it actually performs end-of-compilation processing. */
|
||||
extern void finish_file (void);
|
||||
|
||||
/* These macros provide convenient access to the various _STMT nodes. */
|
||||
|
||||
/* Nonzero if this statement should be considered a full-expression,
|
||||
|
|
280
gcc/c-decl.c
280
gcc/c-decl.c
|
@ -127,6 +127,14 @@ static GTY(()) tree shadowed_labels;
|
|||
some other global meaning for that identifier. */
|
||||
static GTY(()) tree truly_local_externals;
|
||||
|
||||
/* A list of the builtin file-scope DECLs. */
|
||||
|
||||
static GTY(()) tree builtin_decls;
|
||||
|
||||
/* A DECL for the current file-scope context. */
|
||||
|
||||
static GTY(()) tree current_file_decl;
|
||||
|
||||
/* Set to 0 at beginning of a function definition, set to 1 if
|
||||
a return statement that specifies a return value is seen. */
|
||||
|
||||
|
@ -265,7 +273,7 @@ tree static_ctors, static_dtors;
|
|||
|
||||
static struct binding_level *make_binding_level (void);
|
||||
static void pop_binding_level (struct binding_level **);
|
||||
static int duplicate_decls (tree, tree, int);
|
||||
static int duplicate_decls (tree, tree, int, int);
|
||||
static int redeclaration_error_message (tree, tree);
|
||||
static void implicit_decl_warning (tree);
|
||||
static void storedecls (tree);
|
||||
|
@ -282,6 +290,8 @@ static void record_external_decl (tree);
|
|||
static void warn_if_shadowing (tree, tree);
|
||||
static void clone_underlying_type (tree);
|
||||
static bool flexible_array_type_p (tree);
|
||||
static hashval_t link_hash_hash (const void *);
|
||||
static int link_hash_eq (const void *, const void *);
|
||||
|
||||
/* States indicating how grokdeclarator() should handle declspecs marked
|
||||
with __attribute__((deprecated)). An object declared as
|
||||
|
@ -482,8 +492,12 @@ poplevel (int keep, int reverse, int functionbody)
|
|||
/* We used to warn about unused variables in expand_end_bindings,
|
||||
i.e. while generating RTL. But in function-at-a-time mode we may
|
||||
choose to never expand a function at all (e.g. auto inlining), so
|
||||
we do this explicitly now. */
|
||||
warn_about_unused_variables (decls);
|
||||
we do this explicitly now.
|
||||
No warnings when the global scope is popped because the global
|
||||
scope isn't popped for the last translation unit, so the warnings
|
||||
are done in c_write_global_declaration. */
|
||||
if (current_binding_level != global_binding_level)
|
||||
warn_about_unused_variables (decls);
|
||||
|
||||
/* Clear out the name-meanings declared on this level.
|
||||
Propagate TREE_ADDRESSABLE from nested functions to their
|
||||
|
@ -492,7 +506,8 @@ poplevel (int keep, int reverse, int functionbody)
|
|||
{
|
||||
if (DECL_NAME (link) != 0)
|
||||
{
|
||||
if (DECL_EXTERNAL (link))
|
||||
if (DECL_EXTERNAL (link)
|
||||
&& current_binding_level != global_binding_level)
|
||||
/* External decls stay in the symbol-value slot but are
|
||||
inaccessible. */
|
||||
C_DECL_INVISIBLE (link) = 1;
|
||||
|
@ -626,7 +641,7 @@ poplevel (int keep, int reverse, int functionbody)
|
|||
/* Dispose of the block that we just made inside some higher level. */
|
||||
if (functionbody)
|
||||
DECL_INITIAL (current_function_decl) = block;
|
||||
else if (block)
|
||||
else if (block && current_binding_level)
|
||||
current_binding_level->blocks
|
||||
= chainon (current_binding_level->blocks, block);
|
||||
/* If we did not make a block for the level just exited,
|
||||
|
@ -634,7 +649,7 @@ poplevel (int keep, int reverse, int functionbody)
|
|||
(since they cannot be recorded as subblocks in that level)
|
||||
must be carried forward so they will later become subblocks
|
||||
of something else. */
|
||||
else if (subblocks)
|
||||
else if (! block && subblocks)
|
||||
current_binding_level->blocks
|
||||
= chainon (current_binding_level->blocks, subblocks);
|
||||
|
||||
|
@ -784,9 +799,13 @@ pushtag (tree name, tree type)
|
|||
and OLDDECL is in an outer binding level and should thus not be changed. */
|
||||
|
||||
static int
|
||||
duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
|
||||
duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
|
||||
int different_tu)
|
||||
{
|
||||
int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
|
||||
int comptype_flags = (different_tu ? COMPARE_DIFFERENT_TU
|
||||
: COMPARE_STRICT);
|
||||
int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl),
|
||||
comptype_flags);
|
||||
int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
|
||||
&& DECL_INITIAL (newdecl) != 0);
|
||||
tree oldtype = TREE_TYPE (olddecl);
|
||||
|
@ -908,7 +927,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
|
|||
trytype = build_type_attribute_variant (trytype,
|
||||
TYPE_ATTRIBUTES (oldtype));
|
||||
|
||||
types_match = comptypes (newtype, trytype);
|
||||
types_match = comptypes (newtype, trytype, comptype_flags);
|
||||
if (types_match)
|
||||
oldtype = trytype;
|
||||
}
|
||||
|
@ -931,7 +950,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
|
|||
trytype = build_type_attribute_variant (trytype,
|
||||
TYPE_ATTRIBUTES (oldtype));
|
||||
|
||||
types_match = comptypes (newtype, trytype);
|
||||
types_match = comptypes (newtype, trytype, comptype_flags);
|
||||
if (types_match)
|
||||
oldtype = trytype;
|
||||
}
|
||||
|
@ -1030,7 +1049,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
|
|||
&& ! pedantic
|
||||
/* Return types must still match. */
|
||||
&& comptypes (TREE_TYPE (oldtype),
|
||||
TREE_TYPE (newtype))
|
||||
TREE_TYPE (newtype), comptype_flags)
|
||||
&& TYPE_ARG_TYPES (newtype) == 0))
|
||||
{
|
||||
error_with_decl (newdecl, "conflicting types for `%s'");
|
||||
|
@ -1038,7 +1057,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
|
|||
involving an empty arglist vs a nonempty one. */
|
||||
if (TREE_CODE (olddecl) == FUNCTION_DECL
|
||||
&& comptypes (TREE_TYPE (oldtype),
|
||||
TREE_TYPE (newtype))
|
||||
TREE_TYPE (newtype), comptype_flags)
|
||||
&& ((TYPE_ARG_TYPES (oldtype) == 0
|
||||
&& DECL_INITIAL (olddecl) == 0)
|
||||
||
|
||||
|
@ -1166,7 +1185,8 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
|
|||
}
|
||||
/* Type for passing arg must be consistent
|
||||
with that declared for the arg. */
|
||||
if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)))
|
||||
if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type),
|
||||
comptype_flags))
|
||||
{
|
||||
error_with_decl (newdecl,
|
||||
"prototype for `%s' follows and argument %d doesn't match",
|
||||
|
@ -1393,7 +1413,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
|
|||
}
|
||||
if (DECL_EXTERNAL (newdecl))
|
||||
{
|
||||
if (! different_binding_level)
|
||||
if (! different_binding_level || different_tu)
|
||||
{
|
||||
/* Don't mess with these flags on local externs; they remain
|
||||
external even if there's a declaration at file scope which
|
||||
|
@ -1404,7 +1424,13 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level)
|
|||
/* An extern decl does not override previous storage class. */
|
||||
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
|
||||
if (! DECL_EXTERNAL (newdecl))
|
||||
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
|
||||
{
|
||||
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
|
||||
/* If we have two non-EXTERNAL file-scope decls that are
|
||||
the same, only one of them should be written out. */
|
||||
if (different_tu)
|
||||
TREE_ASM_WRITTEN (newdecl) = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1586,7 +1612,7 @@ warn_if_shadowing (tree x, tree old)
|
|||
|
||||
if (TREE_CODE (old) == PARM_DECL)
|
||||
shadow_warning (SW_PARAM, name, old);
|
||||
else if (DECL_CONTEXT (old) == 0)
|
||||
else if (C_DECL_FILE_SCOPE (old))
|
||||
shadow_warning (SW_GLOBAL, name, old);
|
||||
else
|
||||
shadow_warning (SW_LOCAL, name, old);
|
||||
|
@ -1685,12 +1711,13 @@ pushdecl (tree x)
|
|||
/* A local extern declaration for a function doesn't constitute nesting.
|
||||
A local auto declaration does, since it's a forward decl
|
||||
for a nested function coming later. */
|
||||
if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
|
||||
&& DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
|
||||
DECL_CONTEXT (x) = 0;
|
||||
if (current_function_decl == NULL
|
||||
|| ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
|
||||
&& DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x)))
|
||||
DECL_CONTEXT (x) = current_file_decl;
|
||||
else
|
||||
DECL_CONTEXT (x) = current_function_decl;
|
||||
|
||||
|
||||
if (name)
|
||||
{
|
||||
tree old;
|
||||
|
@ -1703,7 +1730,7 @@ pushdecl (tree x)
|
|||
IDENTIFIER_POINTER (name));
|
||||
|
||||
old = lookup_name_current_level (name);
|
||||
if (old && duplicate_decls (x, old, 0))
|
||||
if (old && duplicate_decls (x, old, 0, false))
|
||||
return old;
|
||||
if (DECL_EXTERNAL (x) || scope == global_binding_level)
|
||||
{
|
||||
|
@ -1714,7 +1741,8 @@ pushdecl (tree x)
|
|||
tree ext = any_external_decl (name);
|
||||
if (ext)
|
||||
{
|
||||
if (duplicate_decls (x, ext, scope != global_binding_level))
|
||||
if (duplicate_decls (x, ext, scope != global_binding_level,
|
||||
false))
|
||||
x = copy_node (ext);
|
||||
}
|
||||
else
|
||||
|
@ -1788,13 +1816,13 @@ pushdecl_top_level (tree x)
|
|||
if (DECL_CONTEXT (old))
|
||||
abort ();
|
||||
|
||||
if (!duplicate_decls (x, old, 0))
|
||||
if (!duplicate_decls (x, old, 0, false))
|
||||
abort ();
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
DECL_CONTEXT (x) = 0;
|
||||
DECL_CONTEXT (x) = current_file_decl;
|
||||
IDENTIFIER_SYMBOL_VALUE (name) = x;
|
||||
TREE_CHAIN (x) = global_binding_level->names;
|
||||
global_binding_level->names = x;
|
||||
|
@ -1855,7 +1883,7 @@ implicitly_declare (tree functionid)
|
|||
if (!C_DECL_IMPLICIT (decl))
|
||||
{
|
||||
implicit_decl_warning (DECL_NAME (decl));
|
||||
if (DECL_CONTEXT (decl))
|
||||
if (! C_DECL_FILE_SCOPE (decl))
|
||||
warning_with_decl (decl, "previous declaration of `%s'");
|
||||
C_DECL_IMPLICIT (decl) = 1;
|
||||
}
|
||||
|
@ -1935,7 +1963,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
|
|||
return 1;
|
||||
return 0;
|
||||
}
|
||||
else if (DECL_CONTEXT (newdecl) == NULL_TREE)
|
||||
else if (C_DECL_FILE_SCOPE (newdecl))
|
||||
{
|
||||
/* Objects declared at top level: */
|
||||
/* If at least one is a reference, it's ok. */
|
||||
|
@ -2245,6 +2273,9 @@ c_init_decl_processing (void)
|
|||
input_location.file = "<internal>";
|
||||
input_location.line = 0;
|
||||
|
||||
/* Make the DECL for the toplevel file scope. */
|
||||
current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
|
||||
|
||||
build_common_tree_nodes (flag_signed_char);
|
||||
|
||||
c_common_nodes_and_builtins ();
|
||||
|
@ -2277,6 +2308,8 @@ c_init_decl_processing (void)
|
|||
|
||||
make_fname_decl = c_make_fname_decl;
|
||||
start_fname_decls ();
|
||||
|
||||
builtin_decls = global_binding_level->names;
|
||||
}
|
||||
|
||||
/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
|
||||
|
@ -2692,7 +2725,7 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
|
|||
and we preserved the rtl from the previous one
|
||||
(which may or may not happen). */
|
||||
&& !DECL_RTL_SET_P (tem)
|
||||
&& !DECL_CONTEXT (tem))
|
||||
&& C_DECL_FILE_SCOPE (tem))
|
||||
{
|
||||
if (TREE_TYPE (tem) != error_mark_node
|
||||
&& COMPLETE_TYPE_P (TREE_TYPE (tem)))
|
||||
|
@ -2795,7 +2828,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
|
|||
Otherwise, let it through, but if it is not `extern'
|
||||
then it may cause an error message later. */
|
||||
(DECL_INITIAL (decl) != 0
|
||||
|| DECL_CONTEXT (decl) != 0)
|
||||
|| !C_DECL_FILE_SCOPE (decl))
|
||||
:
|
||||
/* An automatic variable with an incomplete type
|
||||
is an error. */
|
||||
|
@ -2860,7 +2893,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
|
|||
if (c_dialect_objc ())
|
||||
objc_check_decl (decl);
|
||||
|
||||
if (!DECL_CONTEXT (decl))
|
||||
if (C_DECL_FILE_SCOPE (decl))
|
||||
{
|
||||
if (DECL_INITIAL (decl) == NULL_TREE
|
||||
|| DECL_INITIAL (decl) == error_mark_node)
|
||||
|
@ -2868,9 +2901,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
|
|||
when a tentative file-scope definition is seen.
|
||||
But at end of compilation, do output code for them. */
|
||||
DECL_DEFER_OUTPUT (decl) = 1;
|
||||
rest_of_decl_compilation (decl, asmspec,
|
||||
(DECL_CONTEXT (decl) == 0
|
||||
|| TREE_ASM_WRITTEN (decl)), 0);
|
||||
rest_of_decl_compilation (decl, asmspec, true, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2902,7 +2933,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
|
|||
add_decl_stmt (decl);
|
||||
}
|
||||
|
||||
if (DECL_CONTEXT (decl) != 0)
|
||||
if (!C_DECL_FILE_SCOPE (decl))
|
||||
{
|
||||
/* Recompute the RTL of a local array now
|
||||
if it used to be an incomplete type. */
|
||||
|
@ -2918,12 +2949,16 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
|
|||
}
|
||||
}
|
||||
|
||||
/* If this was marked 'used', be sure it will be output. */
|
||||
if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
|
||||
mark_referenced (DECL_ASSEMBLER_NAME (decl));
|
||||
|
||||
if (TREE_CODE (decl) == TYPE_DECL)
|
||||
{
|
||||
/* This is a no-op in c-lang.c or something real in objc-act.c. */
|
||||
if (c_dialect_objc ())
|
||||
objc_check_decl (decl);
|
||||
rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
|
||||
rest_of_decl_compilation (decl, NULL, C_DECL_FILE_SCOPE (decl), 0);
|
||||
}
|
||||
|
||||
/* At the end of a declaration, throw away any variable type sizes
|
||||
|
@ -5970,7 +6005,8 @@ store_parm_decls (void)
|
|||
declared for the arg. ISO C says we take the unqualified
|
||||
type for parameters declared with qualified type. */
|
||||
if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
|
||||
TYPE_MAIN_VARIANT (TREE_VALUE (type))))
|
||||
TYPE_MAIN_VARIANT (TREE_VALUE (type)),
|
||||
COMPARE_STRICT))
|
||||
{
|
||||
if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
|
||||
== TYPE_MAIN_VARIANT (TREE_VALUE (type)))
|
||||
|
@ -6697,7 +6733,7 @@ tree
|
|||
identifier_global_value (tree t)
|
||||
{
|
||||
tree decl = IDENTIFIER_SYMBOL_VALUE (t);
|
||||
if (decl == 0 || DECL_CONTEXT (decl) == 0)
|
||||
if (decl == 0 || C_DECL_FILE_SCOPE (decl))
|
||||
return decl;
|
||||
|
||||
/* Shadowed by something else; find the true global value. */
|
||||
|
@ -6751,4 +6787,176 @@ make_pointer_declarator (tree type_quals_attrs, tree target)
|
|||
return build1 (INDIRECT_REF, quals, itarget);
|
||||
}
|
||||
|
||||
/* Hash and equality functions for link_hash_table: key off
|
||||
DECL_ASSEMBLER_NAME. */
|
||||
|
||||
static hashval_t
|
||||
link_hash_hash (const void *x_p)
|
||||
{
|
||||
tree x = (tree)x_p;
|
||||
return (hashval_t) DECL_ASSEMBLER_NAME (x);
|
||||
}
|
||||
|
||||
static int
|
||||
link_hash_eq (const void *x1_p, const void *x2_p)
|
||||
{
|
||||
tree x1 = (tree)x1_p;
|
||||
tree x2 = (tree)x2_p;
|
||||
return DECL_ASSEMBLER_NAME (x1) == DECL_ASSEMBLER_NAME (x2);
|
||||
}
|
||||
|
||||
/* Propagate information between definitions and uses between multiple
|
||||
translation units in TU_LIST based on linkage rules. */
|
||||
|
||||
void
|
||||
merge_translation_unit_decls (void)
|
||||
{
|
||||
const tree tu_list = current_file_decl;
|
||||
tree tu;
|
||||
tree decl;
|
||||
htab_t link_hash_table;
|
||||
tree block;
|
||||
|
||||
/* Create the BLOCK that poplevel would have created, but don't
|
||||
actually call poplevel since that's expensive. */
|
||||
block = make_node (BLOCK);
|
||||
BLOCK_VARS (block) = current_binding_level->names;
|
||||
TREE_USED (block) = 1;
|
||||
DECL_INITIAL (current_file_decl) = block;
|
||||
|
||||
/* If only one translation unit seen, no copying necessary. */
|
||||
if (TREE_CHAIN (tu_list) == NULL_TREE)
|
||||
return;
|
||||
|
||||
link_hash_table = htab_create (1021, link_hash_hash, link_hash_eq, NULL);
|
||||
|
||||
/* Enter any actual definitions into the hash table. */
|
||||
for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
|
||||
for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
|
||||
if (TREE_PUBLIC (decl) && ! DECL_EXTERNAL (decl))
|
||||
{
|
||||
PTR *slot;
|
||||
slot = htab_find_slot (link_hash_table, decl, INSERT);
|
||||
|
||||
/* If we've already got a definition, work out which one is
|
||||
the real one, put it into the hash table, and make the
|
||||
other one DECL_EXTERNAL. This is important to avoid
|
||||
putting out two definitions of the same symbol in the
|
||||
assembly output. */
|
||||
if (*slot != NULL)
|
||||
{
|
||||
tree old_decl = (tree) *slot;
|
||||
|
||||
/* If this is weak or common or whatever, suppress it
|
||||
in favour of the other definition. */
|
||||
if (DECL_WEAK (decl))
|
||||
DECL_EXTERNAL (decl) = 1;
|
||||
else if (DECL_WEAK (old_decl) && ! DECL_WEAK (decl))
|
||||
DECL_EXTERNAL (old_decl) = 1;
|
||||
else if (DECL_COMMON (decl) || DECL_ONE_ONLY (decl))
|
||||
DECL_EXTERNAL (decl) = 1;
|
||||
else if (DECL_COMMON (old_decl) || DECL_ONE_ONLY (old_decl))
|
||||
DECL_EXTERNAL (old_decl) = 1;
|
||||
|
||||
if (DECL_EXTERNAL (decl))
|
||||
{
|
||||
DECL_INITIAL (decl) = NULL_TREE;
|
||||
DECL_COMMON (decl) = 0;
|
||||
DECL_ONE_ONLY (decl) = 0;
|
||||
DECL_WEAK (decl) = 0;
|
||||
}
|
||||
else if (DECL_EXTERNAL (old_decl))
|
||||
{
|
||||
DECL_INITIAL (old_decl) = NULL_TREE;
|
||||
DECL_COMMON (old_decl) = 0;
|
||||
DECL_ONE_ONLY (old_decl) = 0;
|
||||
DECL_WEAK (old_decl) = 0;
|
||||
*slot = decl;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_with_decl (decl, "redefinition of global `%s'");
|
||||
error_with_decl (old_decl, "`%s' previously defined here");
|
||||
}
|
||||
}
|
||||
else
|
||||
*slot = decl;
|
||||
}
|
||||
|
||||
/* Now insert the desired information from all the definitions
|
||||
into any plain declarations. */
|
||||
for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
|
||||
for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
|
||||
if (TREE_PUBLIC (decl) && DECL_EXTERNAL (decl))
|
||||
{
|
||||
tree global_decl;
|
||||
global_decl = (tree) htab_find (link_hash_table, decl);
|
||||
|
||||
if (! global_decl)
|
||||
continue;
|
||||
|
||||
/* Print any appropriate error messages, and partially merge
|
||||
the decls. */
|
||||
(void) duplicate_decls (decl, global_decl, true, true);
|
||||
}
|
||||
|
||||
htab_delete (link_hash_table);
|
||||
}
|
||||
|
||||
/* Perform final processing on file-scope data. */
|
||||
|
||||
void
|
||||
c_write_global_declarations(void)
|
||||
{
|
||||
tree link;
|
||||
|
||||
for (link = current_file_decl; link; link = TREE_CHAIN (link))
|
||||
{
|
||||
tree globals = BLOCK_VARS (DECL_INITIAL (link));
|
||||
int len = list_length (globals);
|
||||
tree *vec = (tree *) xmalloc (sizeof (tree) * len);
|
||||
int i;
|
||||
tree decl;
|
||||
|
||||
/* Process the decls in reverse order--earliest first.
|
||||
Put them into VEC from back to front, then take out from front. */
|
||||
|
||||
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
|
||||
vec[len - i - 1] = decl;
|
||||
|
||||
wrapup_global_declarations (vec, len);
|
||||
|
||||
check_global_declarations (vec, len);
|
||||
|
||||
/* Clean up. */
|
||||
free (vec);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the parser's state in preparation for a new file. */
|
||||
|
||||
void
|
||||
c_reset_state (void)
|
||||
{
|
||||
tree link;
|
||||
tree file_scope_decl;
|
||||
|
||||
/* Pop the global binding level. */
|
||||
if (current_binding_level != global_binding_level)
|
||||
current_binding_level = global_binding_level;
|
||||
file_scope_decl = current_file_decl;
|
||||
DECL_INITIAL (file_scope_decl) = poplevel (1, 0, 0);
|
||||
truly_local_externals = NULL_TREE;
|
||||
|
||||
/* Start a new global binding level. */
|
||||
pushlevel (0);
|
||||
global_binding_level = current_binding_level;
|
||||
current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
|
||||
TREE_CHAIN (current_file_decl) = file_scope_decl;
|
||||
|
||||
/* Reintroduce the global declarations. */
|
||||
for (link = builtin_decls; link; link = TREE_CHAIN (link))
|
||||
pushdecl (copy_node (link));
|
||||
}
|
||||
|
||||
#include "gt-c-decl.h"
|
||||
|
|
|
@ -125,6 +125,9 @@ enum c_language_kind c_language = clk_c;
|
|||
#undef LANG_HOOKS_TYPE_PROMOTES_TO
|
||||
#define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
|
||||
|
||||
#undef LANG_HOOKS_WRITE_GLOBALS
|
||||
#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
|
||||
|
||||
/* ### When changing hooks, consider if ObjC needs changing too!! ### */
|
||||
|
||||
/* Each front end provides its own. */
|
||||
|
|
|
@ -127,7 +127,7 @@ inline_forbidden_p (tree *nodep, int *walk_subtrees ATTRIBUTE_UNUSED,
|
|||
/* We cannot inline a nested function that jumps to a nonlocal
|
||||
label. */
|
||||
if (TREE_CODE (t) == LABEL_DECL
|
||||
&& DECL_CONTEXT (t) && DECL_CONTEXT (t) != fn)
|
||||
&& !C_DECL_FILE_SCOPE (t) && DECL_CONTEXT (t) != fn)
|
||||
return node;
|
||||
|
||||
break;
|
||||
|
@ -184,7 +184,7 @@ c_cannot_inline_tree_fn (tree *fnp)
|
|||
goto cannot_inline;
|
||||
}
|
||||
|
||||
if (DECL_CONTEXT (fn))
|
||||
if (! C_DECL_FILE_SCOPE (fn))
|
||||
{
|
||||
/* If a nested function has pending sizes, we may have already
|
||||
saved them. */
|
||||
|
@ -357,6 +357,10 @@ c_objc_common_finish_file (void)
|
|||
if (pch_file)
|
||||
c_common_write_pch ();
|
||||
|
||||
/* If multiple translation units were built, copy information between
|
||||
them based on linkage rules. */
|
||||
merge_translation_unit_decls ();
|
||||
|
||||
if (flag_unit_at_a_time)
|
||||
{
|
||||
cgraph_finalize_compilation_unit ();
|
||||
|
|
61
gcc/c-opts.c
61
gcc/c-opts.c
|
@ -52,7 +52,8 @@ static int saved_lineno;
|
|||
static cpp_options *cpp_opts;
|
||||
|
||||
/* Input filename. */
|
||||
static const char *in_fname;
|
||||
static const char **in_fnames;
|
||||
static unsigned num_in_fnames;
|
||||
|
||||
/* Filename and stream for preprocessed output. */
|
||||
static const char *out_fname;
|
||||
|
@ -1039,12 +1040,9 @@ c_common_handle_option (size_t scode, const char *arg, int value)
|
|||
void
|
||||
c_common_handle_filename (const char *filename)
|
||||
{
|
||||
if (!in_fname)
|
||||
in_fname = filename;
|
||||
else if (!out_fname)
|
||||
out_fname = filename;
|
||||
else
|
||||
error ("output filename specified twice");
|
||||
num_in_fnames++;
|
||||
in_fnames = xrealloc (in_fnames, num_in_fnames * sizeof (in_fnames[0]));
|
||||
in_fnames[num_in_fnames - 1] = filename;
|
||||
}
|
||||
|
||||
/* Post-switch processing. */
|
||||
|
@ -1052,8 +1050,13 @@ bool
|
|||
c_common_post_options (const char **pfilename)
|
||||
{
|
||||
/* Canonicalize the input and output filenames. */
|
||||
if (in_fname == NULL || !strcmp (in_fname, "-"))
|
||||
in_fname = "";
|
||||
if (in_fnames == NULL)
|
||||
{
|
||||
in_fnames = xmalloc (sizeof (in_fnames[0]));
|
||||
in_fnames[0] = "";
|
||||
}
|
||||
else if (strcmp (in_fnames[0], "-") == 0)
|
||||
in_fnames[0] = "";
|
||||
|
||||
if (out_fname == NULL || !strcmp (out_fname, "-"))
|
||||
out_fname = "";
|
||||
|
@ -1119,6 +1122,10 @@ c_common_post_options (const char **pfilename)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (num_in_fnames > 1)
|
||||
error ("too many filenames given. Type %s --help for usage",
|
||||
progname);
|
||||
|
||||
init_pp_output (out_stream);
|
||||
}
|
||||
else
|
||||
|
@ -1132,7 +1139,7 @@ c_common_post_options (const char **pfilename)
|
|||
cpp_get_callbacks (parse_in)->file_change = cb_file_change;
|
||||
|
||||
/* NOTE: we use in_fname here, not the one supplied. */
|
||||
*pfilename = cpp_read_main_file (parse_in, in_fname);
|
||||
*pfilename = cpp_read_main_file (parse_in, in_fnames[0]);
|
||||
|
||||
saved_lineno = input_line;
|
||||
input_line = 0;
|
||||
|
@ -1176,23 +1183,43 @@ c_common_init (void)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* A thin wrapper around the real parser that initializes the
|
||||
integrated preprocessor after debug output has been initialized.
|
||||
Also, make sure the start_source_file debug hook gets called for
|
||||
the primary source file. */
|
||||
/* Initialize the integrated preprocessor after debug output has been
|
||||
initialized; loop over each input file. */
|
||||
void
|
||||
c_common_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
|
||||
{
|
||||
unsigned file_index;
|
||||
|
||||
#if YYDEBUG != 0
|
||||
yydebug = set_yydebug;
|
||||
#else
|
||||
warning ("YYDEBUG not defined");
|
||||
#endif
|
||||
|
||||
finish_options();
|
||||
pch_init();
|
||||
yyparse ();
|
||||
file_index = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (file_index > 0)
|
||||
{
|
||||
/* Reset the state of the parser. */
|
||||
c_reset_state();
|
||||
|
||||
/* Reset cpplib's macros and start a new file. */
|
||||
cpp_undef_all (parse_in);
|
||||
cpp_read_next_file (parse_in, in_fnames[file_index]);
|
||||
}
|
||||
|
||||
finish_options();
|
||||
if (file_index == 0)
|
||||
pch_init();
|
||||
c_parse_file ();
|
||||
|
||||
file_index++;
|
||||
} while (file_index < num_in_fnames);
|
||||
|
||||
free_parser_stacks ();
|
||||
finish_file ();
|
||||
}
|
||||
|
||||
/* Common finish hook for the C, ObjC and C++ front ends. */
|
||||
|
|
|
@ -352,20 +352,8 @@ c_parse_init (void)
|
|||
program: /* empty */
|
||||
{ if (pedantic)
|
||||
pedwarn ("ISO C forbids an empty source file");
|
||||
finish_file ();
|
||||
}
|
||||
| extdefs
|
||||
{
|
||||
/* In case there were missing closebraces,
|
||||
get us back to the global binding level. */
|
||||
while (! global_bindings_p ())
|
||||
poplevel (0, 0, 0);
|
||||
/* __FUNCTION__ is defined at file scope (""). This
|
||||
call may not be necessary as my tests indicate it
|
||||
still works without it. */
|
||||
finish_fname_decls ();
|
||||
finish_file ();
|
||||
}
|
||||
;
|
||||
|
||||
/* the reason for the strange actions in this rule
|
||||
|
@ -718,7 +706,7 @@ primary:
|
|||
e1 = TYPE_MAIN_VARIANT (groktypename ($3));
|
||||
e2 = TYPE_MAIN_VARIANT (groktypename ($5));
|
||||
|
||||
$$ = comptypes (e1, e2)
|
||||
$$ = comptypes (e1, e2, COMPARE_STRICT)
|
||||
? build_int_2 (1, 0) : build_int_2 (0, 0);
|
||||
}
|
||||
| primary '[' expr ']' %prec '.'
|
||||
|
@ -3795,10 +3783,27 @@ yyprint (FILE *file, int yychar, YYSTYPE yyl)
|
|||
void
|
||||
free_parser_stacks (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Parse the file. */
|
||||
void
|
||||
c_parse_file (void)
|
||||
{
|
||||
yyparse ();
|
||||
/* In case there were missing closebraces, get us back to the global
|
||||
binding level. */
|
||||
while (! global_bindings_p ())
|
||||
poplevel (0, 0, 0);
|
||||
/* __FUNCTION__ is defined at file scope (""). This
|
||||
call may not be necessary as my tests indicate it
|
||||
still works without it. */
|
||||
finish_fname_decls ();
|
||||
|
||||
if (malloced_yyss)
|
||||
{
|
||||
free (malloced_yyss);
|
||||
free (malloced_yyvs);
|
||||
malloced_yyss = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
20
gcc/c-tree.h
20
gcc/c-tree.h
|
@ -46,7 +46,7 @@ struct lang_identifier GTY(())
|
|||
|
||||
union lang_tree_node
|
||||
GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
|
||||
chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
|
||||
chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *)TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
|
||||
{
|
||||
union tree_node GTY ((tag ("0"),
|
||||
desc ("tree_node_structure (&%h)")))
|
||||
|
@ -146,6 +146,11 @@ struct lang_type GTY(())
|
|||
|| (TYPE_ARG_TYPES (TREE_TYPE (EXP)) == 0 \
|
||||
&& !DECL_BUILT_IN (EXP)))
|
||||
|
||||
/* Nonzero for a decl which is at file scope. */
|
||||
#define C_DECL_FILE_SCOPE(EXP) \
|
||||
(! DECL_CONTEXT (EXP) \
|
||||
|| TREE_CODE (DECL_CONTEXT (EXP)) == TRANSLATION_UNIT_DECL)
|
||||
|
||||
/* For FUNCTION_TYPE, a hidden list of types of arguments. The same as
|
||||
TYPE_ARG_TYPES for functions with prototypes, but created for functions
|
||||
without prototypes. */
|
||||
|
@ -157,7 +162,6 @@ extern tree lookup_interface (tree);
|
|||
extern tree is_class_name (tree);
|
||||
extern tree objc_is_id (tree);
|
||||
extern void objc_check_decl (tree);
|
||||
extern void finish_file (void);
|
||||
extern int objc_comptypes (tree, tree, int);
|
||||
extern tree objc_message_selector (void);
|
||||
extern tree lookup_objc_ivar (tree);
|
||||
|
@ -226,6 +230,7 @@ extern tree c_begin_compound_stmt (void);
|
|||
extern void c_expand_deferred_function (tree);
|
||||
extern void c_expand_decl_stmt (tree);
|
||||
extern tree make_pointer_declarator (tree, tree);
|
||||
extern void merge_translation_unit_decls (void);
|
||||
|
||||
/* in c-objc-common.c */
|
||||
extern int c_disregard_inline_limits (tree);
|
||||
|
@ -242,9 +247,17 @@ extern bool c_warn_unused_global_decl (tree);
|
|||
((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
|
||||
|
||||
#define c_sizeof_nowarn(T) c_sizeof_or_alignof_type (T, SIZEOF_EXPR, 0)
|
||||
|
||||
/* in c-typeck.c */
|
||||
|
||||
/* For use with comptypes. */
|
||||
enum {
|
||||
COMPARE_STRICT = 0,
|
||||
COMPARE_DIFFERENT_TU = 1
|
||||
};
|
||||
|
||||
extern tree require_complete_type (tree);
|
||||
extern int comptypes (tree, tree);
|
||||
extern int comptypes (tree, tree, int);
|
||||
extern tree c_size_in_bytes (tree);
|
||||
extern bool c_mark_addressable (tree);
|
||||
extern void c_incomplete_type_error (tree, tree);
|
||||
|
@ -301,6 +314,7 @@ extern int system_header_p;
|
|||
|
||||
/* In c-decl.c */
|
||||
extern void c_finish_incomplete_decl (tree);
|
||||
extern void c_write_global_declarations (void);
|
||||
|
||||
extern GTY(()) tree static_ctors;
|
||||
extern GTY(()) tree static_dtors;
|
||||
|
|
233
gcc/c-typeck.c
233
gcc/c-typeck.c
|
@ -53,9 +53,10 @@ static int missing_braces_mentioned;
|
|||
static int undeclared_variable_notice;
|
||||
|
||||
static tree qualify_type (tree, tree);
|
||||
static int tagged_types_tu_compatible_p (tree, tree, int);
|
||||
static int comp_target_types (tree, tree, int);
|
||||
static int function_types_compatible_p (tree, tree);
|
||||
static int type_lists_compatible_p (tree, tree);
|
||||
static int function_types_compatible_p (tree, tree, int);
|
||||
static int type_lists_compatible_p (tree, tree, int);
|
||||
static tree decl_constant_value_for_broken_optimization (tree);
|
||||
static tree default_function_array_conversion (tree);
|
||||
static tree lookup_field (tree, tree);
|
||||
|
@ -409,7 +410,8 @@ common_type (tree t1, tree t2)
|
|||
tree memb;
|
||||
for (memb = TYPE_FIELDS (TREE_VALUE (p1));
|
||||
memb; memb = TREE_CHAIN (memb))
|
||||
if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2)))
|
||||
if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2),
|
||||
COMPARE_STRICT))
|
||||
{
|
||||
TREE_VALUE (n) = TREE_VALUE (p2);
|
||||
if (pedantic)
|
||||
|
@ -423,7 +425,8 @@ common_type (tree t1, tree t2)
|
|||
tree memb;
|
||||
for (memb = TYPE_FIELDS (TREE_VALUE (p2));
|
||||
memb; memb = TREE_CHAIN (memb))
|
||||
if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1)))
|
||||
if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1),
|
||||
COMPARE_STRICT))
|
||||
{
|
||||
TREE_VALUE (n) = TREE_VALUE (p1);
|
||||
if (pedantic)
|
||||
|
@ -452,7 +455,7 @@ common_type (tree t1, tree t2)
|
|||
but a warning may be needed if you use them together. */
|
||||
|
||||
int
|
||||
comptypes (tree type1, tree type2)
|
||||
comptypes (tree type1, tree type2, int flags)
|
||||
{
|
||||
tree t1 = type1;
|
||||
tree t2 = type2;
|
||||
|
@ -512,11 +515,11 @@ comptypes (tree type1, tree type2)
|
|||
{
|
||||
case POINTER_TYPE:
|
||||
val = (TREE_TYPE (t1) == TREE_TYPE (t2)
|
||||
? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
|
||||
? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags));
|
||||
break;
|
||||
|
||||
case FUNCTION_TYPE:
|
||||
val = function_types_compatible_p (t1, t2);
|
||||
val = function_types_compatible_p (t1, t2, flags);
|
||||
break;
|
||||
|
||||
case ARRAY_TYPE:
|
||||
|
@ -529,7 +532,8 @@ comptypes (tree type1, tree type2)
|
|||
|
||||
/* Target types must match incl. qualifiers. */
|
||||
if (TREE_TYPE (t1) != TREE_TYPE (t2)
|
||||
&& 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2))))
|
||||
&& 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2),
|
||||
flags)))
|
||||
return 0;
|
||||
|
||||
/* Sizes must match unless one is missing or variable. */
|
||||
|
@ -561,6 +565,11 @@ comptypes (tree type1, tree type2)
|
|||
case RECORD_TYPE:
|
||||
if (c_dialect_objc () && objc_comptypes (t1, t2, 0) == 1)
|
||||
val = 1;
|
||||
|
||||
case ENUMERAL_TYPE:
|
||||
case UNION_TYPE:
|
||||
if (val != 1 && (flags & COMPARE_DIFFERENT_TU))
|
||||
val = tagged_types_tu_compatible_p (t1, t2, flags);
|
||||
break;
|
||||
|
||||
case VECTOR_TYPE:
|
||||
|
@ -592,7 +601,7 @@ comp_target_types (tree ttl, tree ttr, int reflexive)
|
|||
return val;
|
||||
|
||||
val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
|
||||
TYPE_MAIN_VARIANT (TREE_TYPE (ttr)));
|
||||
TYPE_MAIN_VARIANT (TREE_TYPE (ttr)), COMPARE_STRICT);
|
||||
|
||||
if (val == 2 && pedantic)
|
||||
pedwarn ("types are not quite compatible");
|
||||
|
@ -601,6 +610,159 @@ comp_target_types (tree ttl, tree ttr, int reflexive)
|
|||
|
||||
/* Subroutines of `comptypes'. */
|
||||
|
||||
/* The C standard says that two structures in different translation
|
||||
units are compatible with each other only if the types of their
|
||||
fields are compatible (among other things). So, consider two copies
|
||||
of this structure: */
|
||||
|
||||
struct tagged_tu_seen {
|
||||
const struct tagged_tu_seen * next;
|
||||
tree t1;
|
||||
tree t2;
|
||||
};
|
||||
|
||||
/* Can they be compatible with each other? We choose to break the
|
||||
recursion by allowing those types to be compatible. */
|
||||
|
||||
static const struct tagged_tu_seen * tagged_tu_seen_base;
|
||||
|
||||
/* Return 1 if two 'struct', 'union', or 'enum' types T1 and T2 are
|
||||
compatible. If the two types are not the same (which has been
|
||||
checked earlier), this can only happen when multiple translation
|
||||
units are being compiled. See C99 6.2.7 paragraph 1 for the exact
|
||||
rules. */
|
||||
|
||||
static int
|
||||
tagged_types_tu_compatible_p (tree t1, tree t2, int flags)
|
||||
{
|
||||
tree s1, s2;
|
||||
bool needs_warning = false;
|
||||
|
||||
/* We have to verify that the tags of the types are the same. This
|
||||
is harder than it looks because this may be a typedef, so we have
|
||||
to go look at the original type. It may even be a typedef of a
|
||||
typedef... */
|
||||
while (TYPE_NAME (t1) && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL)
|
||||
t1 = DECL_ORIGINAL_TYPE (TYPE_NAME (t1));
|
||||
|
||||
while (TYPE_NAME (t2) && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL)
|
||||
t2 = DECL_ORIGINAL_TYPE (TYPE_NAME (t2));
|
||||
|
||||
/* C90 didn't have the requirement that the two tags be the same. */
|
||||
if (flag_isoc99 && TYPE_NAME (t1) != TYPE_NAME (t2))
|
||||
return 0;
|
||||
|
||||
/* C90 didn't say what happened if one or both of the types were
|
||||
incomplete; we choose to follow C99 rules here, which is that they
|
||||
are compatible. */
|
||||
if (TYPE_SIZE (t1) == NULL
|
||||
|| TYPE_SIZE (t2) == NULL)
|
||||
return 1;
|
||||
|
||||
{
|
||||
const struct tagged_tu_seen * tts_i;
|
||||
for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
|
||||
if (tts_i->t1 == t1 && tts_i->t2 == t2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (TREE_CODE (t1))
|
||||
{
|
||||
case ENUMERAL_TYPE:
|
||||
{
|
||||
if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
|
||||
return 0;
|
||||
|
||||
for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
|
||||
{
|
||||
s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
|
||||
if (s2 == NULL
|
||||
|| simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
case UNION_TYPE:
|
||||
{
|
||||
if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
|
||||
return 0;
|
||||
|
||||
for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
|
||||
{
|
||||
bool ok = false;
|
||||
struct tagged_tu_seen tts;
|
||||
|
||||
tts.next = tagged_tu_seen_base;
|
||||
tts.t1 = t1;
|
||||
tts.t2 = t2;
|
||||
tagged_tu_seen_base = &tts;
|
||||
|
||||
if (DECL_NAME (s1) != NULL)
|
||||
for (s2 = TYPE_VALUES (t2); s2; s2 = TREE_CHAIN (s2))
|
||||
if (DECL_NAME (s1) == DECL_NAME (s2))
|
||||
{
|
||||
int result;
|
||||
result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags);
|
||||
if (result == 0)
|
||||
break;
|
||||
if (result == 2)
|
||||
needs_warning = true;
|
||||
|
||||
if (TREE_CODE (s1) == FIELD_DECL
|
||||
&& simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
|
||||
DECL_FIELD_BIT_OFFSET (s2)) != 1)
|
||||
break;
|
||||
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
tagged_tu_seen_base = tts.next;
|
||||
if (! ok)
|
||||
return 0;
|
||||
}
|
||||
return needs_warning ? 2 : 1;
|
||||
}
|
||||
|
||||
case RECORD_TYPE:
|
||||
{
|
||||
struct tagged_tu_seen tts;
|
||||
|
||||
tts.next = tagged_tu_seen_base;
|
||||
tts.t1 = t1;
|
||||
tts.t2 = t2;
|
||||
tagged_tu_seen_base = &tts;
|
||||
|
||||
for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
|
||||
s1 && s2;
|
||||
s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
|
||||
{
|
||||
int result;
|
||||
if (TREE_CODE (s1) != TREE_CODE (s2)
|
||||
|| DECL_NAME (s1) != DECL_NAME (s2))
|
||||
break;
|
||||
result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags);
|
||||
if (result == 0)
|
||||
break;
|
||||
if (result == 2)
|
||||
needs_warning = true;
|
||||
|
||||
if (TREE_CODE (s1) == FIELD_DECL
|
||||
&& simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
|
||||
DECL_FIELD_BIT_OFFSET (s2)) != 1)
|
||||
break;
|
||||
}
|
||||
tagged_tu_seen_base = tts.next;
|
||||
if (s1 && s2)
|
||||
return 0;
|
||||
return needs_warning ? 2 : 1;
|
||||
}
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if two function types F1 and F2 are compatible.
|
||||
If either type specifies no argument types,
|
||||
the other must specify a fixed number of self-promoting arg types.
|
||||
|
@ -609,7 +771,7 @@ comp_target_types (tree ttl, tree ttr, int reflexive)
|
|||
Otherwise, the argument types must match. */
|
||||
|
||||
static int
|
||||
function_types_compatible_p (tree f1, tree f2)
|
||||
function_types_compatible_p (tree f1, tree f2, int flags)
|
||||
{
|
||||
tree args1, args2;
|
||||
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
|
||||
|
@ -630,7 +792,7 @@ function_types_compatible_p (tree f1, tree f2)
|
|||
if (TYPE_VOLATILE (ret2))
|
||||
ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
|
||||
TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
|
||||
val = comptypes (ret1, ret2);
|
||||
val = comptypes (ret1, ret2, flags);
|
||||
if (val == 0)
|
||||
return 0;
|
||||
|
||||
|
@ -648,7 +810,8 @@ function_types_compatible_p (tree f1, tree f2)
|
|||
compare that with the other type's arglist.
|
||||
If they don't match, ask for a warning (but no error). */
|
||||
if (TYPE_ACTUAL_ARG_TYPES (f1)
|
||||
&& 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1)))
|
||||
&& 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
|
||||
flags))
|
||||
val = 2;
|
||||
return val;
|
||||
}
|
||||
|
@ -657,13 +820,14 @@ function_types_compatible_p (tree f1, tree f2)
|
|||
if (!self_promoting_args_p (args1))
|
||||
return 0;
|
||||
if (TYPE_ACTUAL_ARG_TYPES (f2)
|
||||
&& 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2)))
|
||||
&& 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
|
||||
flags))
|
||||
val = 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Both types have argument lists: compare them and propagate results. */
|
||||
val1 = type_lists_compatible_p (args1, args2);
|
||||
val1 = type_lists_compatible_p (args1, args2, flags);
|
||||
return val1 != 1 ? val1 : val;
|
||||
}
|
||||
|
||||
|
@ -672,7 +836,7 @@ function_types_compatible_p (tree f1, tree f2)
|
|||
or 2 for compatible with warning. */
|
||||
|
||||
static int
|
||||
type_lists_compatible_p (tree args1, tree args2)
|
||||
type_lists_compatible_p (tree args1, tree args2, int flags)
|
||||
{
|
||||
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
|
||||
int val = 1;
|
||||
|
@ -701,7 +865,8 @@ type_lists_compatible_p (tree args1, tree args2)
|
|||
return 0;
|
||||
}
|
||||
else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)),
|
||||
TYPE_MAIN_VARIANT (TREE_VALUE (args2)))))
|
||||
TYPE_MAIN_VARIANT (TREE_VALUE (args2)),
|
||||
flags)))
|
||||
{
|
||||
/* Allow wait (union {union wait *u; int *i} *)
|
||||
and wait (union wait *) to be compatible. */
|
||||
|
@ -715,7 +880,8 @@ type_lists_compatible_p (tree args1, tree args2)
|
|||
tree memb;
|
||||
for (memb = TYPE_FIELDS (TREE_VALUE (args1));
|
||||
memb; memb = TREE_CHAIN (memb))
|
||||
if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2)))
|
||||
if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2),
|
||||
flags))
|
||||
break;
|
||||
if (memb == 0)
|
||||
return 0;
|
||||
|
@ -730,7 +896,8 @@ type_lists_compatible_p (tree args1, tree args2)
|
|||
tree memb;
|
||||
for (memb = TYPE_FIELDS (TREE_VALUE (args2));
|
||||
memb; memb = TREE_CHAIN (memb))
|
||||
if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1)))
|
||||
if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1),
|
||||
flags))
|
||||
break;
|
||||
if (memb == 0)
|
||||
return 0;
|
||||
|
@ -1409,7 +1576,7 @@ build_external_ref (tree id, int fun)
|
|||
/* Properly declared variable or function reference. */
|
||||
if (!objc_ivar)
|
||||
ref = decl;
|
||||
else if (decl != objc_ivar && DECL_CONTEXT (decl) != 0)
|
||||
else if (decl != objc_ivar && !C_DECL_FILE_SCOPE (decl))
|
||||
{
|
||||
warning ("local declaration of `%s' hides instance variable",
|
||||
IDENTIFIER_POINTER (id));
|
||||
|
@ -1449,7 +1616,7 @@ build_external_ref (tree id, int fun)
|
|||
TREE_CONSTANT (ref) = 1;
|
||||
}
|
||||
else if (current_function_decl != 0
|
||||
&& DECL_CONTEXT (current_function_decl) != 0
|
||||
&& !C_DECL_FILE_SCOPE (current_function_decl)
|
||||
&& (TREE_CODE (ref) == VAR_DECL
|
||||
|| TREE_CODE (ref) == PARM_DECL
|
||||
|| TREE_CODE (ref) == FUNCTION_DECL))
|
||||
|
@ -3031,7 +3198,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
|||
file-scope function counts as a constant. */
|
||||
if (staticp (arg)
|
||||
&& ! (TREE_CODE (arg) == FUNCTION_DECL
|
||||
&& DECL_CONTEXT (arg) != 0))
|
||||
&& !C_DECL_FILE_SCOPE (arg)))
|
||||
TREE_CONSTANT (addr) = 1;
|
||||
return addr;
|
||||
}
|
||||
|
@ -3258,6 +3425,7 @@ c_mark_addressable (tree exp)
|
|||
/* drops in */
|
||||
case FUNCTION_DECL:
|
||||
TREE_ADDRESSABLE (x) = 1;
|
||||
/* drops out */
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
@ -3523,7 +3691,7 @@ build_c_cast (tree type, tree expr)
|
|||
|
||||
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
|
||||
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
|
||||
TYPE_MAIN_VARIANT (TREE_TYPE (value))))
|
||||
TYPE_MAIN_VARIANT (TREE_TYPE (value)), COMPARE_STRICT))
|
||||
break;
|
||||
|
||||
if (field)
|
||||
|
@ -3917,7 +4085,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
|
|||
This code doesn't fully support references, it's just for the
|
||||
special case of va_start and va_copy. */
|
||||
if (codel == REFERENCE_TYPE
|
||||
&& comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
|
||||
&& comptypes (TREE_TYPE (type), TREE_TYPE (rhs), COMPARE_STRICT) == 1)
|
||||
{
|
||||
if (!lvalue_p (rhs))
|
||||
{
|
||||
|
@ -3966,7 +4134,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype,
|
|||
tree memb_type = TREE_TYPE (memb_types);
|
||||
|
||||
if (comptypes (TYPE_MAIN_VARIANT (memb_type),
|
||||
TYPE_MAIN_VARIANT (rhstype)))
|
||||
TYPE_MAIN_VARIANT (rhstype), COMPARE_STRICT))
|
||||
break;
|
||||
|
||||
if (TREE_CODE (memb_type) != POINTER_TYPE)
|
||||
|
@ -4543,7 +4711,7 @@ digest_init (tree type, tree init, int require_constant)
|
|||
&& ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
|
||||
{
|
||||
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
|
||||
TYPE_MAIN_VARIANT (type)))
|
||||
TYPE_MAIN_VARIANT (type), COMPARE_STRICT))
|
||||
return inside_init;
|
||||
|
||||
if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
|
||||
|
@ -4585,12 +4753,13 @@ digest_init (tree type, tree init, int require_constant)
|
|||
vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
|
||||
below and handle as a constructor. */
|
||||
if (code == VECTOR_TYPE
|
||||
&& comptypes (TREE_TYPE (inside_init), type)
|
||||
&& comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)
|
||||
&& TREE_CONSTANT (inside_init))
|
||||
{
|
||||
if (TREE_CODE (inside_init) == VECTOR_CST
|
||||
&& comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
|
||||
TYPE_MAIN_VARIANT (type)))
|
||||
TYPE_MAIN_VARIANT (type),
|
||||
COMPARE_STRICT))
|
||||
return inside_init;
|
||||
else
|
||||
return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
|
||||
|
@ -4601,16 +4770,16 @@ digest_init (tree type, tree init, int require_constant)
|
|||
|
||||
if (inside_init && TREE_TYPE (inside_init) != 0
|
||||
&& (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
|
||||
TYPE_MAIN_VARIANT (type))
|
||||
TYPE_MAIN_VARIANT (type), COMPARE_STRICT)
|
||||
|| (code == ARRAY_TYPE
|
||||
&& comptypes (TREE_TYPE (inside_init), type))
|
||||
&& comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT))
|
||||
|| (code == VECTOR_TYPE
|
||||
&& comptypes (TREE_TYPE (inside_init), type))
|
||||
&& comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT))
|
||||
|| (code == POINTER_TYPE
|
||||
&& (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE)
|
||||
&& comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
|
||||
TREE_TYPE (type)))))
|
||||
TREE_TYPE (type), COMPARE_STRICT))))
|
||||
{
|
||||
if (code == POINTER_TYPE)
|
||||
inside_init = default_function_array_conversion (inside_init);
|
||||
|
@ -6039,7 +6208,7 @@ output_init_element (tree value, tree type, tree field, int pending)
|
|||
&& TREE_CODE (type) == ARRAY_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
|
||||
&& !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
|
||||
TYPE_MAIN_VARIANT (type))))
|
||||
TYPE_MAIN_VARIANT (type), COMPARE_STRICT)))
|
||||
value = default_conversion (value);
|
||||
|
||||
if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
|
||||
|
|
10
gcc/calls.c
10
gcc/calls.c
|
@ -600,8 +600,14 @@ special_function_p (tree fndecl, int flags)
|
|||
&& IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
|
||||
/* Exclude functions not at the file scope, or not `extern',
|
||||
since they are not the magic functions we would otherwise
|
||||
think they are. */
|
||||
&& DECL_CONTEXT (fndecl) == NULL_TREE && TREE_PUBLIC (fndecl))
|
||||
think they are.
|
||||
FIXME: this should be handled with attributes, not with this
|
||||
hacky imitation of DECL_ASSEMBLER_NAME. It's (also) wrong
|
||||
because you can declare fork() inside a function if you
|
||||
wish. */
|
||||
&& (DECL_CONTEXT (fndecl) == NULL_TREE
|
||||
|| TREE_CODE (DECL_CONTEXT (fndecl)) == TRANSLATION_UNIT_DECL)
|
||||
&& TREE_PUBLIC (fndecl))
|
||||
{
|
||||
const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
|
||||
const char *tname = name;
|
||||
|
|
|
@ -62,7 +62,7 @@ struct cgraph_rtl_info GTY(())
|
|||
/* The cgraph data strutcture.
|
||||
Each function decl has assigned cgraph_node listing callees and callers. */
|
||||
|
||||
struct cgraph_node GTY(())
|
||||
struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
|
||||
{
|
||||
tree decl;
|
||||
struct cgraph_edge *callees;
|
||||
|
|
|
@ -71,7 +71,8 @@ cgraph_finalize_function (decl, body)
|
|||
It is possible to assemble the name later after finalizing the function
|
||||
and the fact is noticed in assemble_name then. */
|
||||
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
|
||||
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
|
||||
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|
||||
|| lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
|
||||
{
|
||||
cgraph_mark_needed_node (node, 1);
|
||||
}
|
||||
|
|
548
gcc/configure
vendored
548
gcc/configure
vendored
File diff suppressed because it is too large
Load diff
|
@ -569,6 +569,16 @@ AC_SUBST(TARGET_SYSTEM_ROOT)
|
|||
AC_SUBST(TARGET_SYSTEM_ROOT_DEFINE)
|
||||
AC_SUBST(CROSS_SYSTEM_HEADER_DIR)
|
||||
|
||||
# Build with intermodule optimisations
|
||||
local_prefix=
|
||||
AC_ARG_ENABLE(intermodule,
|
||||
[ --enable-intermodule build the compiler in one step],
|
||||
[case "${enable_intermodule}" in
|
||||
yes) onestep=-onestep : ;;
|
||||
*) onestep= : ;;
|
||||
esac])
|
||||
AC_SUBST(onestep)
|
||||
|
||||
# -------------------------
|
||||
# Checks for other programs
|
||||
# -------------------------
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2003-07-11 Geoffrey Keating <geoffk@apple.com>
|
||||
|
||||
* decl.c (cp_finish_decl): Handle 'used' attribute.
|
||||
|
||||
* cp-lang.c (c_reset_state): New dummy routine.
|
||||
* cp-tree.h (finish_file): Move prototype to c-common.h.
|
||||
* parser.c (c_parse_file): Rename from yyparse; don't call finish_file.
|
||||
|
||||
2003-07-11 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/8327
|
||||
|
|
|
@ -372,3 +372,9 @@ cp_var_mod_type_p (tree type)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Stub routine to tell people that this doesn't work yet. */
|
||||
void
|
||||
c_reset_state (void)
|
||||
{
|
||||
sorry ("inter-module optimisations not implemented yet");
|
||||
}
|
||||
|
|
|
@ -3773,7 +3773,6 @@ extern void comdat_linkage (tree);
|
|||
extern void import_export_vtable (tree, tree, int);
|
||||
extern void import_export_decl (tree);
|
||||
extern void import_export_tinfo (tree, tree, bool);
|
||||
extern void finish_file (void);
|
||||
extern tree build_cleanup (tree);
|
||||
extern tree build_offset_ref_call_from_tree (tree, tree);
|
||||
extern void set_decl_namespace (tree, tree, bool);
|
||||
|
|
|
@ -8259,6 +8259,10 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
|
|||
|
||||
if (was_readonly)
|
||||
TREE_READONLY (decl) = 1;
|
||||
|
||||
/* If this was marked 'used', be sure it will be output. */
|
||||
if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
|
||||
mark_referenced (DECL_ASSEMBLER_NAME (decl));
|
||||
}
|
||||
|
||||
/* This is here for a midend callback from c-common.c */
|
||||
|
|
|
@ -14617,10 +14617,10 @@ static GTY (()) cp_parser *the_parser;
|
|||
|
||||
/* External interface. */
|
||||
|
||||
/* Parse the entire translation unit. */
|
||||
/* Parse one entire translation unit. */
|
||||
|
||||
int
|
||||
yyparse (void)
|
||||
void
|
||||
c_parse_file (void)
|
||||
{
|
||||
bool error_occurred;
|
||||
|
||||
|
@ -14629,10 +14629,6 @@ yyparse (void)
|
|||
? dk_no_deferred : dk_no_check);
|
||||
error_occurred = cp_parser_translation_unit (the_parser);
|
||||
the_parser = NULL;
|
||||
|
||||
finish_file ();
|
||||
|
||||
return error_occurred;
|
||||
}
|
||||
|
||||
/* Clean up after parsing the entire translation unit. */
|
||||
|
|
|
@ -427,6 +427,15 @@ cpp_add_dependency_target (cpp_reader *pfile, const char *target, int quote)
|
|||
deps_add_target (pfile->deps, target, quote);
|
||||
}
|
||||
|
||||
/* This sets up for processing input from the file FNAME.
|
||||
It returns false on error. */
|
||||
bool
|
||||
cpp_read_next_file (cpp_reader *pfile, const char *fname)
|
||||
{
|
||||
/* Open the main input file. */
|
||||
return _cpp_read_file (pfile, fname);
|
||||
}
|
||||
|
||||
/* This is called after options have been parsed, and partially
|
||||
processed. Setup for processing input from the file named FNAME,
|
||||
or stdin if it is the empty string. Return the original filename
|
||||
|
@ -451,9 +460,8 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname)
|
|||
deps_add_default_target (pfile->deps, fname);
|
||||
}
|
||||
|
||||
/* Open the main input file. */
|
||||
pfile->line = 1;
|
||||
if (!_cpp_read_file (pfile, fname))
|
||||
if (!cpp_read_next_file (pfile, fname))
|
||||
return NULL;
|
||||
|
||||
/* Set this here so the client can change the option if it wishes,
|
||||
|
|
40
gcc/cpplib.c
40
gcc/cpplib.c
|
@ -109,6 +109,7 @@ static unsigned int read_flag (cpp_reader *, unsigned int);
|
|||
static int strtoul_for_line (const uchar *, unsigned int, unsigned long *);
|
||||
static void do_diagnostic (cpp_reader *, int, int);
|
||||
static cpp_hashnode *lex_macro_node (cpp_reader *);
|
||||
static int undefine_macros (cpp_reader *, cpp_hashnode *, void *);
|
||||
static void do_include_common (cpp_reader *, enum include_type);
|
||||
static struct pragma_entry *lookup_pragma_entry (struct pragma_entry *,
|
||||
const cpp_hashnode *);
|
||||
|
@ -540,6 +541,45 @@ do_undef (cpp_reader *pfile)
|
|||
check_eol (pfile);
|
||||
}
|
||||
|
||||
/* Undefine a single macro/assertion/whatever. */
|
||||
|
||||
static int
|
||||
undefine_macros (cpp_reader *pfile, cpp_hashnode *h,
|
||||
void *data_p ATTRIBUTE_UNUSED)
|
||||
{
|
||||
switch (h->type)
|
||||
{
|
||||
case NT_VOID:
|
||||
break;
|
||||
|
||||
case NT_MACRO:
|
||||
if (pfile->cb.undef)
|
||||
(*pfile->cb.undef) (pfile, pfile->directive_line, h);
|
||||
|
||||
if (CPP_OPTION (pfile, warn_unused_macros))
|
||||
_cpp_warn_if_unused_macro (pfile, h, NULL);
|
||||
|
||||
/* and fall through... */
|
||||
case NT_ASSERTION:
|
||||
_cpp_free_definition (h);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
h->flags &= ~NODE_POISONED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Undefine all macros and assertions. */
|
||||
|
||||
void
|
||||
cpp_undef_all (cpp_reader *pfile)
|
||||
{
|
||||
cpp_forall_identifiers (pfile, undefine_macros, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Helper routine used by parse_include. Reinterpret the current line
|
||||
as an h-char-sequence (< ... >); we are looking at the first token
|
||||
after the <. Returns a malloced filename. */
|
||||
|
|
|
@ -535,6 +535,10 @@ extern void cpp_set_callbacks (cpp_reader *, cpp_callbacks *);
|
|||
too. If there was an error opening the file, it returns NULL. */
|
||||
extern const char *cpp_read_main_file (cpp_reader *, const char *);
|
||||
|
||||
/* This continues processing to a new file. It will return false if
|
||||
there was an error opening the file. */
|
||||
extern bool cpp_read_next_file (cpp_reader *, const char *);
|
||||
|
||||
/* Set up built-ins like __FILE__. */
|
||||
extern void cpp_init_builtins (cpp_reader *, int);
|
||||
|
||||
|
@ -584,6 +588,9 @@ extern void cpp_assert (cpp_reader *, const char *);
|
|||
extern void cpp_undef (cpp_reader *, const char *);
|
||||
extern void cpp_unassert (cpp_reader *, const char *);
|
||||
|
||||
/* Undefine all macros and assertions. */
|
||||
extern void cpp_undef_all (cpp_reader *);
|
||||
|
||||
extern cpp_buffer *cpp_push_buffer (cpp_reader *, const unsigned char *,
|
||||
size_t, int, int);
|
||||
extern int cpp_defined (cpp_reader *, const unsigned char *, int);
|
||||
|
|
|
@ -710,10 +710,12 @@ in the following sections.
|
|||
@section Options Controlling the Kind of Output
|
||||
|
||||
Compilation can involve up to four stages: preprocessing, compilation
|
||||
proper, assembly and linking, always in that order. The first three
|
||||
stages apply to an individual source file, and end by producing an
|
||||
object file; linking combines all the object files (those newly
|
||||
compiled, and those specified as input) into an executable file.
|
||||
proper, assembly and linking, always in that order. GCC is capable of
|
||||
preprocessing and compiling several files either into several
|
||||
assembler input files, or into one assembler input file; then each
|
||||
assembler input file produces an object file, and linking combines all
|
||||
the object files (those newly compiled, and those specified as input)
|
||||
into an executable file.
|
||||
|
||||
@cindex file name suffix
|
||||
For any given input file, the file name suffix determines what kind of
|
||||
|
@ -885,9 +887,9 @@ Place output in file @var{file}. This applies regardless to whatever
|
|||
sort of output is being produced, whether it be an executable file,
|
||||
an object file, an assembler file or preprocessed C code.
|
||||
|
||||
Since only one output file can be specified, it does not make sense to
|
||||
use @option{-o} when compiling more than one input file, unless you are
|
||||
producing an executable file as output.
|
||||
If you specify @option{-o} when compiling more than one input file, or
|
||||
you are producing an executable file as output, all the source files
|
||||
on the command line will be compiled at once.
|
||||
|
||||
If @option{-o} is not specified, the default is to put an executable file
|
||||
in @file{a.out}, the object file for @file{@var{source}.@var{suffix}} in
|
||||
|
@ -3471,6 +3473,14 @@ Turning on optimization flags makes the compiler attempt to improve
|
|||
the performance and/or code size at the expense of compilation time
|
||||
and possibly the ability to debug the program.
|
||||
|
||||
The compiler performs optimisation based on the knowledge it has of
|
||||
the program. Using the @option{-funit-at-a-time} flag will allow the
|
||||
compiler to consider information gained from later functions in the
|
||||
file when compiling a function. Compiling multiple files at once to a
|
||||
single output file (and using @option{-funit-at-a-time}) will allow
|
||||
the compiler to use information gained from all of the files when
|
||||
compiling each of them.
|
||||
|
||||
Not all optimizations are controlled directly by a flag. Only
|
||||
optimizations that have a flag are listed.
|
||||
|
||||
|
@ -4362,8 +4372,9 @@ better job.
|
|||
|
||||
@item -funit-at-a-time
|
||||
@opindex funit-at-a-time
|
||||
Parse the whole compilation unit before starting to produce code. This allows some
|
||||
extra optimizations to take place but consumes more memory.
|
||||
Parse the whole compilation unit before starting to produce code.
|
||||
This allows some extra optimizations to take place but consumes more
|
||||
memory.
|
||||
|
||||
@item -funroll-loops
|
||||
@opindex funroll-loops
|
||||
|
|
50
gcc/gcc.c
50
gcc/gcc.c
|
@ -2891,6 +2891,11 @@ static struct infile *infiles;
|
|||
|
||||
int n_infiles;
|
||||
|
||||
/* True if multiple input files are being compiled to a single
|
||||
assembly file. */
|
||||
|
||||
static bool combine_inputs;
|
||||
|
||||
/* This counts the number of libraries added by lang_specific_driver, so that
|
||||
we can tell if there were any user supplied any files or libraries. */
|
||||
|
||||
|
@ -3715,8 +3720,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
|
|||
}
|
||||
}
|
||||
|
||||
if (have_c && have_o && lang_n_infiles > 1)
|
||||
fatal ("cannot specify -o with -c or -S and multiple compilations");
|
||||
combine_inputs = (have_c && have_o && lang_n_infiles > 1);
|
||||
|
||||
if ((save_temps_flag || report_times) && use_pipes)
|
||||
{
|
||||
|
@ -4760,8 +4764,16 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
|
|||
break;
|
||||
|
||||
case 'i':
|
||||
obstack_grow (&obstack, input_filename, input_filename_length);
|
||||
arg_going = 1;
|
||||
if (combine_inputs)
|
||||
{
|
||||
for (i = 0; (int) i < n_infiles; i++)
|
||||
store_arg (infiles[i].name, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
obstack_grow (&obstack, input_filename, input_filename_length);
|
||||
arg_going = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
|
@ -6291,7 +6303,28 @@ main (int argc, const char *const *argv)
|
|||
|
||||
explicit_link_files = xcalloc (1, n_infiles);
|
||||
|
||||
for (i = 0; (int) i < n_infiles; i++)
|
||||
if (combine_inputs)
|
||||
{
|
||||
int lang_n_infiles = 0;
|
||||
for (i = 0; (int) i < n_infiles; i++)
|
||||
{
|
||||
const char *name = infiles[i].name;
|
||||
struct compiler *compiler
|
||||
= lookup_compiler (name, strlen (name), infiles[i].language);
|
||||
if (compiler == NULL)
|
||||
error ("%s: linker input file unused because linking not done",
|
||||
name);
|
||||
else if (lang_n_infiles > 0 && compiler != input_file_compiler)
|
||||
fatal ("cannot specify -o with -c or -S and multiple languages");
|
||||
else
|
||||
{
|
||||
lang_n_infiles++;
|
||||
input_file_compiler = compiler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; (int) i < (combine_inputs ? 1 : n_infiles); i++)
|
||||
{
|
||||
int this_file_error = 0;
|
||||
|
||||
|
@ -6306,9 +6339,10 @@ main (int argc, const char *const *argv)
|
|||
|
||||
/* Figure out which compiler from the file's suffix. */
|
||||
|
||||
input_file_compiler
|
||||
= lookup_compiler (infiles[i].name, input_filename_length,
|
||||
infiles[i].language);
|
||||
if (! combine_inputs)
|
||||
input_file_compiler
|
||||
= lookup_compiler (infiles[i].name, input_filename_length,
|
||||
infiles[i].language);
|
||||
|
||||
if (input_file_compiler)
|
||||
{
|
||||
|
|
|
@ -80,8 +80,6 @@ extern int lhd_tree_inlining_start_inlining (tree);
|
|||
extern void lhd_tree_inlining_end_inlining (tree);
|
||||
extern tree lhd_tree_inlining_convert_parm_for_inlining (tree, tree, tree);
|
||||
|
||||
extern void write_global_declarations (void);
|
||||
|
||||
#define LANG_HOOKS_NAME "GNU unknown"
|
||||
#define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier)
|
||||
#define LANG_HOOKS_INIT hook_bool_void_false
|
||||
|
|
|
@ -3521,7 +3521,7 @@ check_ivars (inter, imp)
|
|||
|
||||
t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
|
||||
|
||||
if (!comptypes (t1, t2))
|
||||
if (!comptypes (t1, t2, false))
|
||||
{
|
||||
if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
|
||||
{
|
||||
|
@ -4905,7 +4905,7 @@ finish_message_expr (receiver, sel_name, method_params)
|
|||
;
|
||||
else if (! IS_ID (rtype)
|
||||
/* Allow any type that matches objc_class_type. */
|
||||
&& ! comptypes (rtype, objc_class_type))
|
||||
&& ! comptypes (rtype, objc_class_type, false))
|
||||
{
|
||||
warning ("invalid receiver type `%s'",
|
||||
gen_declaration (rtype, errbuf));
|
||||
|
@ -7064,7 +7064,8 @@ comp_method_with_proto (method, proto)
|
|||
/* install return type */
|
||||
TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto));
|
||||
|
||||
return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
|
||||
return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template,
|
||||
false);
|
||||
}
|
||||
|
||||
/* Return 1 if PROTO1 is consistent with PROTO2. */
|
||||
|
@ -7087,7 +7088,7 @@ comp_proto_with_proto (proto0, proto1)
|
|||
TREE_TYPE (function1_template) = groktypename (TREE_TYPE (proto0));
|
||||
TREE_TYPE (function2_template) = groktypename (TREE_TYPE (proto1));
|
||||
|
||||
return comptypes (function1_template, function2_template);
|
||||
return comptypes (function1_template, function2_template, false);
|
||||
}
|
||||
|
||||
/* - Generate an identifier for the function. the format is "_n_cls",
|
||||
|
|
|
@ -91,6 +91,7 @@ extern void fnotice (FILE *, const char *, ...)
|
|||
|
||||
extern int wrapup_global_declarations (tree *, int);
|
||||
extern void check_global_declarations (tree *, int);
|
||||
extern void write_global_declarations (void);
|
||||
|
||||
/* A unique local time stamp, might be zero if none is available. */
|
||||
extern unsigned local_tick;
|
||||
|
|
32
gcc/tree.c
32
gcc/tree.c
|
@ -4370,26 +4370,30 @@ decl_type_context (tree decl)
|
|||
tree context = DECL_CONTEXT (decl);
|
||||
|
||||
while (context)
|
||||
{
|
||||
if (TREE_CODE (context) == NAMESPACE_DECL)
|
||||
switch (TREE_CODE (context))
|
||||
{
|
||||
case NAMESPACE_DECL:
|
||||
case TRANSLATION_UNIT_DECL:
|
||||
return NULL_TREE;
|
||||
|
||||
if (TREE_CODE (context) == RECORD_TYPE
|
||||
|| TREE_CODE (context) == UNION_TYPE
|
||||
|| TREE_CODE (context) == QUAL_UNION_TYPE)
|
||||
case RECORD_TYPE:
|
||||
case UNION_TYPE:
|
||||
case QUAL_UNION_TYPE:
|
||||
return context;
|
||||
|
||||
if (TREE_CODE (context) == TYPE_DECL
|
||||
|| TREE_CODE (context) == FUNCTION_DECL)
|
||||
|
||||
case TYPE_DECL:
|
||||
case FUNCTION_DECL:
|
||||
context = DECL_CONTEXT (context);
|
||||
|
||||
else if (TREE_CODE (context) == BLOCK)
|
||||
break;
|
||||
|
||||
case BLOCK:
|
||||
context = BLOCK_SUPERCONTEXT (context);
|
||||
|
||||
else
|
||||
/* Unhandled CONTEXT!? */
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
|
33
gcc/tree.def
33
gcc/tree.def
|
@ -277,17 +277,18 @@ DEFTREECODE (VECTOR_CST, "vector_cst", 'c', 0)
|
|||
/* Contents are TREE_STRING_LENGTH and TREE_STRING_POINTER fields. */
|
||||
DEFTREECODE (STRING_CST, "string_cst", 'c', 0)
|
||||
|
||||
/* Declarations. All references to names are represented as ..._DECL nodes.
|
||||
The decls in one binding context are chained through the TREE_CHAIN field.
|
||||
Each DECL has a DECL_NAME field which contains an IDENTIFIER_NODE.
|
||||
(Some decls, most often labels, may have zero as the DECL_NAME).
|
||||
DECL_CONTEXT points to the node representing the context in which
|
||||
this declaration has its scope. For FIELD_DECLs, this is the
|
||||
RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE node that the field
|
||||
is a member of. For VAR_DECL, PARM_DECL, FUNCTION_DECL, LABEL_DECL,
|
||||
and CONST_DECL nodes, this points to either the FUNCTION_DECL for the
|
||||
containing function, the RECORD_TYPE or UNION_TYPE for the containing
|
||||
type, or NULL_TREE if the given decl has "file scope".
|
||||
/* Declarations. All references to names are represented as ..._DECL
|
||||
nodes. The decls in one binding context are chained through the
|
||||
TREE_CHAIN field. Each DECL has a DECL_NAME field which contains
|
||||
an IDENTIFIER_NODE. (Some decls, most often labels, may have zero
|
||||
as the DECL_NAME). DECL_CONTEXT points to the node representing
|
||||
the context in which this declaration has its scope. For
|
||||
FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
|
||||
QUAL_UNION_TYPE node that the field is a member of. For VAR_DECL,
|
||||
PARM_DECL, FUNCTION_DECL, LABEL_DECL, and CONST_DECL nodes, this
|
||||
points to either the FUNCTION_DECL for the containing function, the
|
||||
RECORD_TYPE or UNION_TYPE for the containing type, or NULL_TREE or
|
||||
a TRANSLATION_UNIT_DECL if the given decl has "file scope".
|
||||
DECL_ABSTRACT_ORIGIN, if non-NULL, points to the original (abstract)
|
||||
..._DECL node of which this decl is an (inlined or template expanded)
|
||||
instance.
|
||||
|
@ -298,9 +299,9 @@ DEFTREECODE (STRING_CST, "string_cst", 'c', 0)
|
|||
and DECL_MODE fields exist in decl nodes just as in type nodes.
|
||||
They are unused in LABEL_DECL, TYPE_DECL and CONST_DECL nodes.
|
||||
|
||||
DECL_OFFSET holds an integer number of bits offset for the location.
|
||||
DECL_VOFFSET holds an expression for a variable offset; it is
|
||||
to be multiplied by DECL_VOFFSET_UNIT (an integer).
|
||||
DECL_FIELD_BIT_OFFSET holds an integer number of bits offset for
|
||||
the location. DECL_VOFFSET holds an expression for a variable
|
||||
offset; it is to be multiplied by DECL_VOFFSET_UNIT (an integer).
|
||||
These fields are relevant only in FIELD_DECLs and PARM_DECLs.
|
||||
|
||||
DECL_INITIAL holds the value to initialize a variable to,
|
||||
|
@ -346,6 +347,10 @@ DEFTREECODE (FIELD_DECL, "field_decl", 'd', 0)
|
|||
/* A namespace declaration. Namespaces appear in DECL_CONTEXT of other
|
||||
_DECLs, providing a hierarchy of names. */
|
||||
DEFTREECODE (NAMESPACE_DECL, "namespace_decl", 'd', 0)
|
||||
|
||||
/* A translation unit. This is not technically a declaration, since it
|
||||
can't be looked up, but it's close enough. */
|
||||
DEFTREECODE (TRANSLATION_UNIT_DECL, "translation_unit_decl", 'd', 0)
|
||||
|
||||
/* References to storage. */
|
||||
|
||||
|
|
14
gcc/tree.h
14
gcc/tree.h
|
@ -1253,12 +1253,13 @@ struct tree_type GTY(())
|
|||
the name from decl_attributes to make_function_rtl and make_decl_rtl. */
|
||||
#define DECL_SECTION_NAME(NODE) (DECL_CHECK (NODE)->decl.section_name)
|
||||
|
||||
/* For FIELD_DECLs, this is the
|
||||
RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE node that the field is
|
||||
a member of. For VAR_DECL, PARM_DECL, FUNCTION_DECL, LABEL_DECL,
|
||||
and CONST_DECL nodes, this points to either the FUNCTION_DECL for the
|
||||
containing function, the RECORD_TYPE or UNION_TYPE for the containing
|
||||
type, or NULL_TREE if the given decl has "file scope". */
|
||||
/* For FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
|
||||
QUAL_UNION_TYPE node that the field is a member of. For VAR_DECL,
|
||||
PARM_DECL, FUNCTION_DECL, LABEL_DECL, and CONST_DECL nodes, this
|
||||
points to either the FUNCTION_DECL for the containing function,
|
||||
the RECORD_TYPE or UNION_TYPE for the containing type, or
|
||||
NULL_TREE or a TRANSLATION_UNIT_DECL if the given decl has "file
|
||||
scope". */
|
||||
#define DECL_CONTEXT(NODE) (DECL_CHECK (NODE)->decl.context)
|
||||
#define DECL_FIELD_CONTEXT(NODE) (FIELD_DECL_CHECK (NODE)->decl.context)
|
||||
/* In a DECL this is the field where attributes are stored. */
|
||||
|
@ -1287,6 +1288,7 @@ struct tree_type GTY(())
|
|||
/* In PARM_DECL, holds the type as written (perhaps a function or array). */
|
||||
#define DECL_ARG_TYPE_AS_WRITTEN(NODE) (PARM_DECL_CHECK (NODE)->decl.result)
|
||||
/* For a FUNCTION_DECL, holds the tree of BINDINGs.
|
||||
For a TRANSLATION_UNIT_DECL, holds the namespace's BLOCK.
|
||||
For a VAR_DECL, holds the initial value.
|
||||
For a PARM_DECL, not used--default
|
||||
values for parameters are encoded in the type of the function,
|
||||
|
|
Loading…
Add table
Reference in a new issue