Commit 991d6621 by Joseph Myers Committed by Joseph Myers

re PR c/39556 (statics in C99 inline functions later declared extern)

	PR c/39556
	* c-tree.h (enum c_inline_static_type): New.
	(record_inline_static): Declare.
	* c-decl.c (struct c_inline_static, c_inline_statics,
	record_inline_static, check_inline_statics): New.
	(pop_file_scope): Call check_inline_statics.
	(start_decl): Call record_inline_static instead of pedwarning
	directly for static in inline function.
	* c-typeck.c (build_external_ref): Call record_inline_static
	instead of pedwarning directly for static referenced in inline
	function.

testsuite:
	* gcc.dg/inline-34.c: New test.

From-SVN: r146800
parent 4a81774c
2009-04-26 Joseph Myers <joseph@codesourcery.com>
PR c/39556
* c-tree.h (enum c_inline_static_type): New.
(record_inline_static): Declare.
* c-decl.c (struct c_inline_static, c_inline_statics,
record_inline_static, check_inline_statics): New.
(pop_file_scope): Call check_inline_statics.
(start_decl): Call record_inline_static instead of pedwarning
directly for static in inline function.
* c-typeck.c (build_external_ref): Call record_inline_static
instead of pedwarning directly for static referenced in inline
function.
2009-04-26 Steven Bosscher <steven@gcc.gnu.org>
* df-scan.c (df_insn_rescan): Salvage insn's LUID if the insn is
......
......@@ -393,6 +393,32 @@ static GTY((deletable)) struct c_binding *binding_freelist;
t_->to##_last = f_->from##_last; \
} while (0)
/* A c_inline_static structure stores details of a static identifier
referenced in a definition of a function that may be an inline
definition if no subsequent declaration of that function uses
"extern" or does not use "inline". */
struct GTY((chain_next ("%h.next"))) c_inline_static {
/* The location for a diagnostic. */
location_t location;
/* The function that may be an inline definition. */
tree function;
/* The object or function referenced. */
tree static_decl;
/* What sort of reference this is. */
enum c_inline_static_type type;
/* The next such structure or NULL. */
struct c_inline_static *next;
};
/* List of static identifiers used or referenced in functions that may
be inline definitions. */
static GTY(()) struct c_inline_static *c_inline_statics;
/* True means unconditionally make a BLOCK for the next scope pushed. */
static bool keep_next_level_flag;
......@@ -555,6 +581,53 @@ c_finish_incomplete_decl (tree decl)
}
}
/* Record that inline function FUNC contains a reference (location
LOC) to static DECL (file-scope or function-local according to
TYPE). */
void
record_inline_static (location_t loc, tree func, tree decl,
enum c_inline_static_type type)
{
struct c_inline_static *csi = GGC_NEW (struct c_inline_static);
csi->location = loc;
csi->function = func;
csi->static_decl = decl;
csi->type = type;
csi->next = c_inline_statics;
c_inline_statics = csi;
}
/* Check for references to static declarations in inline functions at
the end of the translation unit and diagnose them if the functions
are still inline definitions. */
static void
check_inline_statics (void)
{
struct c_inline_static *csi;
for (csi = c_inline_statics; csi; csi = csi->next)
{
if (DECL_EXTERNAL (csi->function))
switch (csi->type)
{
case csi_internal:
pedwarn (csi->location, 0,
"%qD is static but used in inline function %qD "
"which is not static", csi->static_decl, csi->function);
break;
case csi_modifiable:
pedwarn (csi->location, 0,
"%q+D is static but declared in inline function %qD "
"which is not static", csi->static_decl, csi->function);
break;
default:
gcc_unreachable ();
}
}
c_inline_statics = NULL;
}
/* The Objective-C front-end often needs to determine the current scope. */
void *
......@@ -944,6 +1017,8 @@ pop_file_scope (void)
still works without it. */
finish_fname_decls ();
check_inline_statics ();
/* This is the point to write out a PCH if we're doing that.
In that case we do not want to do anything else. */
if (pch_file)
......@@ -3324,9 +3399,8 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
&& !TREE_READONLY (decl)
&& DECL_DECLARED_INLINE_P (current_function_decl)
&& DECL_EXTERNAL (current_function_decl))
pedwarn (input_location, 0,
"%q+D is static but declared in inline function %qD "
"which is not static", decl, current_function_decl);
record_inline_static (input_location, current_function_decl,
decl, csi_modifiable);
/* Add this decl to the current scope.
TEM may equal DECL or it may be a previous decl of the same name. */
......
......@@ -467,6 +467,18 @@ struct c_enum_contents
int enum_overflow;
};
/* A type of reference to a static identifier in an inline
function. */
enum c_inline_static_type {
/* Identifier with internal linkage used in function that may be an
inline definition (i.e., file-scope static). */
csi_internal,
/* Modifiable object with static storage duration defined in
function that may be an inline definition (i.e., local
static). */
csi_modifiable
};
/* in c-parser.c */
extern void c_parse_init (void);
......@@ -483,6 +495,8 @@ extern int global_bindings_p (void);
extern void push_scope (void);
extern tree pop_scope (void);
extern void record_inline_static (location_t, tree, tree,
enum c_inline_static_type);
extern void c_init_decl_processing (void);
extern void c_dup_lang_specific_decl (tree);
extern void c_print_identifier (FILE *, tree, int);
......
......@@ -2285,8 +2285,8 @@ build_external_ref (tree id, int fun, location_t loc, tree *type)
&& (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
&& ! TREE_PUBLIC (ref)
&& DECL_CONTEXT (ref) != current_function_decl)
pedwarn (loc, 0, "%qD is static but used in inline function %qD "
"which is not static", ref, current_function_decl);
record_inline_static (loc, current_function_decl, ref,
csi_internal);
return ref;
}
......
2009-04-26 Joseph Myers <joseph@codesourcery.com>
PR c/39556
* gcc.dg/inline-34.c: New test.
2009-04-25 Joseph Myers <joseph@codesourcery.com>
* gcc.dg/enum-const-1.c, gcc.dg/enum-const-2.c,
......
/* Diagnostics for bad references to static objects and functions from
inline definitions must take account of declarations after the
definition which make it not an inline definition. PR 39556. */
/* { dg-do compile } */
/* { dg-options "-std=c99 -pedantic-errors" } */
static int a1;
inline int f1 (void) { return a1; }
int f1 (void);
static int a2;
inline int f2 (void) { return a2; }
extern inline int f2 (void);
inline void f3 (void) { static int a3; }
void f3 (void);
inline void f4 (void) { static int a4; }
extern inline void f4 (void);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment