Commit 3c6e6fbf by Zack Weinberg Committed by Zack Weinberg

c-decl.c (duplicate_decls): Break apart into...

	* c-decl.c (duplicate_decls): Break apart into...
	(diagnose_arglist_conflict, validate_proto_after_old_defn)
	(locate_old_defn, diagnose_mismatched_decls, merge_decls):
	... these new functions.  Restructure for comprehensibility.
	Remove various archaic special cases.  Always report the
	location of the previous declaration when a diagnostic is issued.
	(redeclaration_error_message): Fold into diagnose_mismatched_decls.
	(match_builtin_function_types): Delete unnecessary forward declaration.
testsuite:
	* gcc.dg/Wshadow-1.c, gcc.dg/attr-noinline.c, gcc.dg/decl3.c
	* gcc.dg/redecl-1.c, gcc.dg/visibility-7.c, gcc.dg/wtr-static-1.c
	* gcc.dg/noncompile/20020220-1.c, objc.dg/method-1.m:
	Update dg-error regexps.

From-SVN: r75667
parent 1e8dcb41
2004-01-10 Zack Weinberg <zack@codesourcery.com>
* c-decl.c (duplicate_decls): Break apart into...
(diagnose_arglist_conflict, validate_proto_after_old_defn)
(locate_old_defn, diagnose_mismatched_decls, merge_decls):
... these new functions. Restructure for comprehensibility.
Remove various archaic special cases. Always report the
location of the previous declaration when a diagnostic is issued.
(redeclaration_error_message): Fold into diagnose_mismatched_decls.
(match_builtin_function_types): Delete unnecessary forward declaration.
2004-01-10 Zack Weinberg <zack@codesourcery.com>
* genautomata.c (make_automaton, NDFA_to_DFA):
Print progress bars with '.' characters instead of '*'.
(build_automaton): Change notes to match.
......
......@@ -306,9 +306,6 @@ tree static_ctors, static_dtors;
static struct c_scope *make_scope (void);
static void pop_scope (void);
static tree match_builtin_function_types (tree, tree);
static int duplicate_decls (tree, tree, int, int);
static int redeclaration_error_message (tree, tree);
static tree make_label (tree, location_t);
static void bind_label (tree, tree, struct c_scope *);
static void implicit_decl_warning (tree);
......@@ -755,12 +752,12 @@ pushtag (tree name, tree type)
TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
}
/* Subroutine of duplicate_decls. Allow harmless mismatches in return
/* Subroutine of compare_decls. Allow harmless mismatches in return
and argument types provided that the type modes match. This function
return a unified type given a suitable match, and 0 otherwise. */
static tree
match_builtin_function_types (tree oldtype, tree newtype)
match_builtin_function_types (tree newtype, tree oldtype)
{
tree newrettype, oldrettype;
tree newargs, oldargs;
......@@ -795,121 +792,227 @@ match_builtin_function_types (tree oldtype, tree newtype)
return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype));
}
/* Handle when a new declaration NEWDECL
has the same name as an old one OLDDECL
in the same binding contour.
Prints an error message if appropriate.
/* Subroutine of diagnose_mismathed_decls. Check for function type
mismatch involving an empty arglist vs a nonempty one and give clearer
diagnostics. */
static void
diagnose_arglist_conflict (tree newdecl, tree olddecl,
tree newtype, tree oldtype)
{
tree t;
If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
Otherwise, return 0.
if (TREE_CODE (olddecl) != FUNCTION_DECL
|| !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype), COMPARE_STRICT)
|| !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0)
||
(TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0)))
return;
When DIFFERENT_BINDING_LEVEL is true, NEWDECL is an external declaration,
and OLDDECL is in an outer scope and should thus not be changed. */
t = TYPE_ARG_TYPES (oldtype);
if (t == 0)
t = TYPE_ARG_TYPES (newtype);
for (; t; t = TREE_CHAIN (t))
{
tree type = TREE_VALUE (t);
static int
duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
int different_tu)
{
int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl),
COMPARE_STRICT);
int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) != 0);
tree oldtype = TREE_TYPE (olddecl);
tree newtype = TREE_TYPE (newdecl);
int errmsg = 0;
if (TREE_CHAIN (t) == 0
&& TYPE_MAIN_VARIANT (type) != void_type_node)
{
inform ("a parameter list with an ellipsis can't match"
"an empty parameter name list declaration");
break;
}
if (DECL_P (olddecl))
{
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
if (c_type_promotes_to (type) != type)
{
if (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
/* Already warned elsewhere. */;
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
/* Already warned. */;
else if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
warning ("%Jfunction '%D' redeclared as inline",
newdecl, newdecl);
warning ("%Jprevious declaration of function '%D' "
"with attribute noinline", olddecl, olddecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
warning ("%Jfunction '%D' redeclared with attribute noinline",
newdecl, newdecl);
warning ("%Jprevious declaration of function '%D' was inline",
olddecl, olddecl);
}
inform ("an argument type that has a default promotion can't match"
"an empty parameter name list declaration");
break;
}
}
}
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
/* Another subroutine of diagnose_mismatched_decls. OLDDECL is an
old-style function definition, NEWDECL is a prototype declaration.
Diagnose inconsistencies in the argument list. Returns TRUE if
the prototype is compatible, FALSE if not. */
static bool
validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
{
tree type, parm;
int nargs;
/* Prototype decl follows defn w/o prototype. */
for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
type = TYPE_ARG_TYPES (newtype),
nargs = 1;
;
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++)
{
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
&& TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
/* End of list. */
warning ("%Jprototype for '%D' follows non-prototype definition",
newdecl, newdecl);
return true;
}
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
error ("%Jprototype for '%D' with different number of arguments "
"follows non-prototype definition", newdecl, newdecl);
return false;
}
/* Type for passing arg must be consistent
with that declared for the arg. */
if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type),
COMPARE_STRICT))
{
error ("%Jprototype for '%D' with incompatible argument %d "
"follows non-prototype definition", newdecl, newdecl, nargs);
return false;
}
}
}
/* Subroutine of diagnose_mismatched_decls. Report the location of DECL,
first in a pair of mismatched declarations, using the diagnostic
function DIAG. */
static void
locate_old_decl (tree decl, void (*diag)(const char *, ...))
{
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
;
else if (DECL_INITIAL (decl))
diag (N_("%Jprevious definition of '%D' was here"), decl, decl);
else if (C_DECL_IMPLICIT (decl))
diag (N_("%Jprevious implicit declaration of '%D' was here"), decl, decl);
else
diag (N_("%Jprevious declaration of '%D' was here"), decl, decl);
}
if (TREE_CODE (newtype) == ERROR_MARK
|| TREE_CODE (oldtype) == ERROR_MARK)
types_match = 0;
/* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL.
Returns true if the caller should proceed to merge the two, false
if OLDDECL should simply be discarded. As a side effect, issues
all necessary diagnostics for invalid or poor-style combinations.
If it returns true, writes the types of NEWDECL and OLDDECL to
*NEWTYPEP and *OLDTYPEP - these may have been adjusted from
TREE_TYPE (NEWDECL, OLDDECL) respectively. */
/* New decl is completely inconsistent with the old one =>
tell caller to replace the old one.
This is always an error except in the case of shadowing a builtin. */
static bool
diagnose_mismatched_decls (tree newdecl, tree olddecl,
tree *newtypep, tree *oldtypep)
{
tree newtype, oldtype;
bool pedwarned = false;
bool warned = false;
/* If we have error_mark_node for either decl or type, just discard
the previous decl - we're in an error cascade already. */
if (olddecl == error_mark_node || newdecl == error_mark_node)
return false;
oldtype = TREE_TYPE (olddecl);
newtype = TREE_TYPE (newdecl);
if (oldtype == error_mark_node || newtype == error_mark_node)
return false;
/* Two different categories of symbol altogether. This is an error
unless OLDDECL is a builtin. OLDDECL will be discarded in any case. */
if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_BUILT_IN (olddecl))
if (TREE_CODE (olddecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
{
/* If you declare a built-in or predefined function name as static,
the old definition is overridden,
but optionally warn this was a bad choice of name. */
if (!TREE_PUBLIC (newdecl))
error ("%J'%D' redeclared as different kind of symbol",
newdecl, newdecl);
locate_old_decl (olddecl, error);
}
else if (TREE_PUBLIC (newdecl))
warning ("%Jbuilt-in function '%D' declared as non-function",
newdecl, newdecl);
else if (warn_shadow)
warning ("%Jshadowing built-in function '%D'",
newdecl, newdecl);
return false;
}
if (!comptypes (oldtype, newtype, COMPARE_STRICT))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl))
{
/* Accept harmless mismatch in function types.
This is for the ffs and fprintf builtins. */
tree trytype = match_builtin_function_types (newtype, oldtype);
if (trytype && comptypes (newtype, trytype, COMPARE_STRICT))
oldtype = trytype;
else
{
if (warn_shadow)
warning ("%Jshadowing built-in function '%D'",
newdecl, newdecl);
/* If types don't match for a built-in, throw away the
built-in. No point in calling locate_old_decl here, it
won't print anything. */
warning ("%Jconflicting types for built-in function '%D'",
newdecl, newdecl);
return false;
}
else
warning ("%Jbuilt-in function '%D' declared as non-function",
newdecl, newdecl);
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_SOURCE_LINE (olddecl) == 0)
{
/* A conflicting function declaration for a predeclared
function that isn't actually built in. Objective C uses
these. The new declaration silently overrides everything
but the volatility (i.e. noreturn) indication. See also
below. FIXME: Make Objective C use normal builtins. */
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
return false;
}
/* Permit void foo (...) to match int foo (...) if the latter is
the definition and implicit int was used. See
c-torture/compile/920625-2.c. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl)
&& TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
&& C_FUNCTION_IMPLICIT_INT (newdecl))
{
pedwarn ("%Jconflicting types for '%D'", newdecl, newdecl);
/* Make sure we keep void as the return type. */
TREE_TYPE (newdecl) = newtype = oldtype;
C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
pedwarned = true;
}
else
{
error ("%J'%D' redeclared as different kind of symbol",
newdecl, newdecl);
error ("%Jprevious declaration of '%D'", olddecl, olddecl);
error ("%Jconflicting types for '%D'", newdecl, newdecl);
diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
locate_old_decl (olddecl, error);
return false;
}
return 0;
}
/* For real parm decl following a forward decl, return 1 so old decl
will be reused. Only allow this to happen once. */
if (types_match && TREE_CODE (newdecl) == PARM_DECL
&& TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
/* Redeclaration of a type is a constraint violation (6.7.2.3p1),
but silently ignore the redeclaration if either is in a system
header. (Conflicting redeclarations were handled above.) */
if (TREE_CODE (newdecl) == TYPE_DECL)
{
TREE_ASM_WRITTEN (olddecl) = 0;
return 1;
if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl))
return true; /* allow OLDDECL to continue in use */
error ("%Jredefinition of typedef '%D'", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
/* The new declaration is the same kind of object as the old one.
The declarations may partially match. Print warnings if they don't
match enough. Ultimately, copy most of the information from the new
decl to the old one, and keep using the old one. */
if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl))
/* Function declarations can either be 'static' or 'extern' (no
qualifier is equivalent to 'extern' - C99 6.2.2p5) and therefore
can never conflict with each other on account of linkage (6.2.2p4).
Multiple definitions are not allowed (6.9p3,5) but GCC permits
two definitions if one is 'extern inline' and one is not. The non-
extern-inline definition supersedes the extern-inline definition. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
/* A function declaration for a built-in function. */
if (!TREE_PUBLIC (newdecl))
if (DECL_BUILT_IN (olddecl) && !TREE_PUBLIC (newdecl))
{
/* If you declare a built-in function name as static, the
built-in definition is overridden,
......@@ -917,458 +1020,355 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
if (warn_shadow)
warning ("%Jshadowing built-in function '%D'", newdecl, newdecl);
/* Discard the old built-in function. */
return 0;
return false;
}
if (!types_match)
if (DECL_INITIAL (newdecl))
{
/* Accept harmless mismatch in function types.
This is for the ffs and fprintf builtins. */
tree trytype = match_builtin_function_types (oldtype, newtype);
if (trytype)
if (DECL_INITIAL (olddecl)
&& !(DECL_DECLARED_INLINE_P (olddecl)
&& DECL_EXTERNAL (olddecl)
&& !(DECL_DECLARED_INLINE_P (newdecl)
&& DECL_EXTERNAL (newdecl))))
{
types_match = comptypes (newtype, trytype, COMPARE_STRICT);
if (types_match)
oldtype = trytype;
if (! different_binding_level)
TREE_TYPE (olddecl) = oldtype;
error ("%Jredefinition of '%D'", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
}
if (!types_match)
/* If we have a prototype after an old-style function definition,
the argument types must be checked specially. */
else if (DECL_INITIAL (olddecl)
&& !TYPE_ARG_TYPES (oldtype) && TYPE_ARG_TYPES (newtype)
&& TYPE_ACTUAL_ARG_TYPES (oldtype)
&& !validate_proto_after_old_defn (newdecl, newtype, oldtype))
{
/* If types don't match for a built-in, throw away the built-in. */
warning ("%Jconflicting types for built-in function '%D'",
newdecl, newdecl);
return 0;
locate_old_decl (olddecl, error);
return false;
}
/* Mismatched non-static and static is considered poor style.
We only diagnose static then non-static if -Wtraditional,
because it is the most convenient way to get some effects
(see e.g. what unwind-dw2-fde-glibc.c does to the definition
of _Unwind_Find_FDE in unwind-dw2-fde.c). Revisit? */
if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl))
{
/* A static function declaration for a predeclared function
that isn't actually built in, silently overrides the
default. Objective C uses these. See also above.
FIXME: Make Objective C use normal builtins. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_SOURCE_LINE (olddecl) == 0)
return false;
else
{
warning ("%Jstatic declaration of '%D' follows "
"non-static declaration", newdecl, newdecl);
warned = true;
}
}
else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl)
&& warn_traditional)
{
warning ("%Jnon-static declaration of '%D' follows "
"static declaration", newdecl, newdecl);
warned = true;
}
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_SOURCE_LINE (olddecl) == 0)
else if (TREE_CODE (newdecl) == VAR_DECL)
{
/* A function declaration for a predeclared function
that isn't actually built in. */
if (!TREE_PUBLIC (newdecl))
/* Only variables can be thread-local, and all declarations must
agree on this property. */
if (DECL_THREAD_LOCAL (newdecl) != DECL_THREAD_LOCAL (olddecl))
{
/* If you declare it as static, the
default definition is overridden. */
return 0;
if (DECL_THREAD_LOCAL (newdecl))
error ("%Jthread-local declaration of '%D' follows "
"non-thread-local declaration", newdecl, newdecl);
else
error ("%Jnon-thread-local declaration of '%D' follows "
"thread-local declaration", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
else if (!types_match)
/* Multiple initialized definitions are not allowed (6.9p3,5). */
if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
{
/* If the types don't match, preserve volatility indication.
Later on, we will discard everything else about the
default declaration. */
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
error ("%Jredefinition of '%D'", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
}
/* Permit char *foo () to match void *foo (...) if not pedantic,
if one of them came from a system header file. */
else if (!types_match
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (TREE_TYPE (oldtype)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (newtype)) == POINTER_TYPE
&& (DECL_IN_SYSTEM_HEADER (olddecl)
|| DECL_IN_SYSTEM_HEADER (newdecl))
&& ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (newtype))) == void_type_node
&& TYPE_ARG_TYPES (oldtype) == 0
&& self_promoting_args_p (TYPE_ARG_TYPES (newtype))
&& TREE_TYPE (TREE_TYPE (oldtype)) == char_type_node)
||
(TREE_TYPE (TREE_TYPE (newtype)) == char_type_node
&& TYPE_ARG_TYPES (newtype) == 0
&& self_promoting_args_p (TYPE_ARG_TYPES (oldtype))
&& TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (oldtype))) == void_type_node)))
{
if (pedantic)
pedwarn ("%Jconflicting types for '%D'", newdecl, newdecl);
/* Make sure we keep void * as ret type, not char *. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (oldtype))) == void_type_node)
TREE_TYPE (newdecl) = newtype = oldtype;
/* Set DECL_IN_SYSTEM_HEADER, so that if we see another declaration
we will come back here again. */
DECL_IN_SYSTEM_HEADER (newdecl) = 1;
}
/* Permit void foo (...) to match int foo (...) if the latter is the
definition and implicit int was used. See c-torture/compile/920625-2.c. */
else if (!types_match && new_is_definition
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
&& C_FUNCTION_IMPLICIT_INT (newdecl))
{
pedwarn ("%Jconflicting types for '%D'", newdecl, newdecl);
/* Make sure we keep void as the return type. */
TREE_TYPE (newdecl) = newtype = oldtype;
C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
}
else if (!types_match
/* Permit char *foo (int, ...); followed by char *foo ();
if not pedantic. */
&& ! (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! pedantic
/* Return types must still match. */
&& comptypes (TREE_TYPE (oldtype),
TREE_TYPE (newtype), COMPARE_STRICT)
&& TYPE_ARG_TYPES (newtype) == 0))
{
error ("%Jconflicting types for '%D'", newdecl, newdecl);
/* Check for function type mismatch
involving an empty arglist vs a nonempty one. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& comptypes (TREE_TYPE (oldtype),
TREE_TYPE (newtype), COMPARE_STRICT)
&& ((TYPE_ARG_TYPES (oldtype) == 0
&& DECL_INITIAL (olddecl) == 0)
||
(TYPE_ARG_TYPES (newtype) == 0
&& DECL_INITIAL (newdecl) == 0)))
/* Objects declared at file scope: if at least one is 'extern',
it's fine (6.2.2p4); otherwise the linkage must agree (6.2.2p7). */
if (DECL_FILE_SCOPE_P (newdecl))
{
/* Classify the problem further. */
tree t = TYPE_ARG_TYPES (oldtype);
if (t == 0)
t = TYPE_ARG_TYPES (newtype);
for (; t; t = TREE_CHAIN (t))
if (!DECL_EXTERNAL (newdecl)
&& !DECL_EXTERNAL (olddecl)
&& TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
{
tree type = TREE_VALUE (t);
if (TREE_CHAIN (t) == 0
&& TYPE_MAIN_VARIANT (type) != void_type_node)
{
error ("a parameter list with an ellipsis can't match an empty parameter name list declaration");
break;
}
if (TREE_PUBLIC (newdecl))
error ("%Jnon-static declaration of '%D' follows "
"static declaration", newdecl, newdecl);
else
error ("%Jstatic declaration of '%D' follows "
"non-static declaration", newdecl, newdecl);
if (c_type_promotes_to (type) != type)
{
error ("an argument type that has a default promotion can't match an empty parameter name list declaration");
break;
}
locate_old_decl (olddecl, error);
return false;
}
}
if (C_DECL_IMPLICIT (olddecl))
error ("%Jprevious implicit declaration of '%D'", olddecl, olddecl);
else
error ("%Jprevious declaration of '%D'", olddecl, olddecl);
/* Two objects with the same name declared at the same block
scope must both be external references (6.7p3). */
else if (DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl)
&& (!DECL_EXTERNAL (newdecl) || !DECL_EXTERNAL (olddecl)))
{
if (DECL_EXTERNAL (newdecl))
error ("%Jextern declaration of '%D' follows "
"declaration with no linkage", newdecl, newdecl);
else if (DECL_EXTERNAL (olddecl))
error ("%Jdeclaration of '%D' with no linkage follows "
"extern declaration", newdecl, newdecl);
else
error ("%Jredeclaration of '%D' with no linkage",
newdecl, newdecl);
/* This is safer because the initializer might contain references
to variables that were declared between olddecl and newdecl. This
will make the initializer invalid for olddecl in case it gets
assigned to olddecl below. */
if (TREE_CODE (newdecl) == VAR_DECL)
DECL_INITIAL (newdecl) = 0;
}
/* TLS cannot follow non-TLS declaration. */
else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
&& !DECL_THREAD_LOCAL (olddecl) && DECL_THREAD_LOCAL (newdecl))
{
error ("%Jthread-local declaration of '%D' follows non thread-local "
"declaration", newdecl, newdecl);
error ("%Jprevious declaration of '%D'", olddecl, olddecl);
locate_old_decl (olddecl, error);
return false;
}
}
/* non-TLS declaration cannot follow TLS declaration. */
else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
&& DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl))
/* warnings */
/* All decls must agree on a non-default visibility. */
if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
&& DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
error ("%Jnon thread-local declaration of '%D' follows "
"thread-local declaration", newdecl, newdecl);
error ("%Jprevious declaration of '%D'", olddecl, olddecl);
warning ("%Jredeclaration of '%D' with different visibility "
"(old visibility preserved)", newdecl, newdecl);
warned = true;
}
else
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
/* Diagnose inline __attribute__ ((noinline)) which is silly. */
if (DECL_DECLARED_INLINE_P (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
switch (errmsg)
{
case 1:
error ("%Jredefinition of '%D'", newdecl, newdecl);
break;
case 2:
error ("%Jredeclaration of '%D'", newdecl, newdecl);
break;
case 3:
error ("%Jconflicting declarations of '%D'", newdecl, newdecl);
break;
default:
abort ();
}
if (DECL_INITIAL (olddecl)
&& current_scope == global_scope)
error ("%J'%D' previously defined here", olddecl, olddecl);
else
error ("%J'%D' previously declared here", olddecl, olddecl);
return 0;
warning ("%Jinline declaration of '%D' follows "
"declaration with attribute noinline", newdecl, newdecl);
warned = true;
}
else if (TREE_CODE (newdecl) == TYPE_DECL
&& (DECL_IN_SYSTEM_HEADER (olddecl)
|| DECL_IN_SYSTEM_HEADER (newdecl)))
else if (DECL_DECLARED_INLINE_P (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
warning ("%Jredefinition of '%D'", newdecl, newdecl);
if (DECL_INITIAL (olddecl) && current_scope == global_scope)
warning ("%J'%D' previously defined here", olddecl, olddecl);
else
warning ("%J'%D' previously declared here", olddecl, olddecl);
warning ("%Jdeclaration of '%D' with attribute noinline follows "
"inline declaration ", newdecl, newdecl);
warned = true;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != 0
&& TYPE_ARG_TYPES (oldtype) == 0
&& TYPE_ARG_TYPES (newtype) != 0
&& TYPE_ACTUAL_ARG_TYPES (oldtype) != 0)
/* Inline declaration after use or definition.
??? Should we still warn about this now we have unit-at-a-time
mode and can get it right? */
if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl))
{
tree type, parm;
int nargs;
/* Prototype decl follows defn w/o prototype. */
for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
type = TYPE_ARG_TYPES (newtype),
nargs = 1;
;
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++)
if (TREE_USED (olddecl))
{
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
&& TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
warning ("%Jprototype for '%D' follows", newdecl, newdecl);
warning ("%Jnon-prototype definition here", olddecl);
break;
}
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
error ("%Jprototype for '%D' follows and number of "
"arguments doesn't match", newdecl, newdecl);
error ("%Jnon-prototype definition here", olddecl);
errmsg = 1;
break;
}
/* Type for passing arg must be consistent
with that declared for the arg. */
if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type),
COMPARE_STRICT))
{
error ("%Jprototype for '%D' follows and argument %d "
"doesn't match", newdecl, newdecl, nargs);
error ("%Jnon-prototype definition here", olddecl);
errmsg = 1;
break;
}
warning ("%J'%D' declared inline after being called");
warned = true;
}
else if (DECL_INITIAL (olddecl))
{
warning ("%J'%D' declared inline after its definition");
warned = true;
}
}
/* Warn about mismatches in various flags. */
else
}
else /* VAR_DECL */
{
/* These bits are only type qualifiers when applied to objects. */
if (TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
{
/* Warn if function is now inline
but was previously declared not inline and has been called. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_DECLARED_INLINE_P (newdecl)
&& TREE_USED (olddecl))
warning ("%J'%D' declared inline after being called",
newdecl, newdecl);
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_DECLARED_INLINE_P (newdecl)
&& DECL_INITIAL (olddecl) != 0)
warning ("%J'%D' declared inline after its definition",
newdecl, newdecl);
/* If pedantic, warn when static declaration follows a non-static
declaration. Otherwise, do so only for functions. */
if ((pedantic || TREE_CODE (olddecl) == FUNCTION_DECL)
&& TREE_PUBLIC (olddecl)
&& !TREE_PUBLIC (newdecl))
warning ("%Jstatic declaration for '%D' follows non-static",
newdecl, newdecl);
/* If warn_traditional, warn when a non-static function
declaration follows a static one. */
if (warn_traditional && !in_system_header
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& !TREE_PUBLIC (olddecl)
&& TREE_PUBLIC (newdecl))
warning ("%Jnon-static declaration for '%D' follows static",
newdecl, newdecl);
/* Warn when const declaration follows a non-const
declaration, but not for functions. */
if (TREE_CODE (olddecl) != FUNCTION_DECL
&& !TREE_READONLY (olddecl)
&& TREE_READONLY (newdecl))
warning ("%Jconst declaration for '%D' follows non-const",
newdecl, newdecl);
/* These bits are logically part of the type, for variables.
But not for functions
(where qualifiers are not valid ANSI anyway). */
else if (pedantic && TREE_CODE (olddecl) != FUNCTION_DECL
&& (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
|| TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)))
pedwarn ("%Jtype qualifiers for '%D' conflict with previous "
"declaration", newdecl, newdecl);
if (TREE_THIS_VOLATILE (newdecl))
pedwarn ("%Jvolatile declaration of '%D' follows "
"non-volatile declaration", newdecl, newdecl);
else
pedwarn ("%Jnon-volatile declaration of '%D' follows "
"volatile declaration", newdecl, newdecl);
pedwarned = true;
}
if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl))
{
if (TREE_READONLY (newdecl))
pedwarn ("%Jconst declaration of '%D' follows "
"non-const declaration", newdecl, newdecl);
else
pedwarn ("%Jnon-const declaration of '%D' follows "
"const declaration", newdecl, newdecl);
pedwarned = true;
}
}
/* Optionally warn about more than one declaration for the same name. */
if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0
/* Don't warn about a function declaration
followed by a definition. */
&& !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0
&& DECL_INITIAL (olddecl) == 0)
/* Don't warn about extern decl followed by (tentative) definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl)))
/* Optional warning for completely redundant decls. */
if (!warned && !pedwarned
&& warn_redundant_decls
/* Don't warn about a function declaration followed by a
definition. */
&& !(TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
/* Don't warn about an extern followed by a definition. */
&& !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl)))
{
warning ("%Jredundant redeclaration of '%D' in same scope",
newdecl, newdecl);
warning ("%Jprevious declaration of '%D'", olddecl, olddecl);
warning ("%Jredundant redeclaration of '%D'", newdecl, newdecl);
warned = true;
}
/* Copy all the DECL_... slots specified in the new decl
except for any that we copy here from the old type.
/* Report location of previous decl/defn in a consistent manner. */
if (warned || pedwarned)
locate_old_decl (olddecl, pedwarned ? pedwarn : warning);
*newtypep = newtype;
*oldtypep = oldtype;
return true;
}
Past this point, we don't change OLDTYPE and NEWTYPE
even if we change the types of NEWDECL and OLDDECL. */
/* Subroutine of duplicate_decls. NEWDECL has been found to be
consistent with OLDDECL, but carries new information. Merge the
new information into OLDDECL. If DIFFERENT_BINDING_LEVEL or
DIFFERENT_TU is true, avoid completely merging the decls, as this
will break assumptions elsewhere. This function issues no
diagnostics. */
if (types_match)
static void
merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype,
bool different_binding_level, bool different_tu)
{
int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) != 0);
/* When copying info to olddecl, we store into write_olddecl
instead. This allows us to avoid modifying olddecl when
different_binding_level is true. */
tree write_olddecl = different_binding_level ? newdecl : olddecl;
/* For real parm decl following a forward decl, return 1 so old decl
will be reused. Only allow this to happen once. */
if (TREE_CODE (newdecl) == PARM_DECL
&& TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
{
/* When copying info to olddecl, we store into write_olddecl
instead. This allows us to avoid modifying olddecl when
different_binding_level is true. */
tree write_olddecl = different_binding_level ? newdecl : olddecl;
TREE_ASM_WRITTEN (olddecl) = 0;
return;
}
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
/* Merge the data types specified in the two decls. */
if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
/* Merge the data types specified in the two decls. */
if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
{
if (different_binding_level)
{
if (different_binding_level)
{
if (TYPE_ARG_TYPES (oldtype) != 0
&& TYPE_ARG_TYPES (newtype) == 0)
TREE_TYPE (newdecl) = common_type (newtype, oldtype);
else
TREE_TYPE (newdecl)
= build_type_attribute_variant
(newtype,
merge_attributes (TYPE_ATTRIBUTES (newtype),
TYPE_ATTRIBUTES (oldtype)));
}
if (TYPE_ARG_TYPES (oldtype) != 0
&& TYPE_ARG_TYPES (newtype) == 0)
TREE_TYPE (newdecl) = common_type (newtype, oldtype);
else
TREE_TYPE (newdecl)
= TREE_TYPE (olddecl)
= common_type (newtype, oldtype);
}
/* Lay the type out, unless already done. */
if (oldtype != TREE_TYPE (newdecl))
{
if (TREE_TYPE (newdecl) != error_mark_node)
layout_type (TREE_TYPE (newdecl));
if (TREE_CODE (newdecl) != FUNCTION_DECL
&& TREE_CODE (newdecl) != TYPE_DECL
&& TREE_CODE (newdecl) != CONST_DECL)
layout_decl (newdecl, 0);
= build_type_attribute_variant
(newtype,
merge_attributes (TYPE_ATTRIBUTES (newtype),
TYPE_ATTRIBUTES (oldtype)));
}
else
{
/* Since the type is OLDDECL's, make OLDDECL's size go with. */
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
DECL_MODE (newdecl) = DECL_MODE (olddecl);
if (TREE_CODE (olddecl) != FUNCTION_DECL)
if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
{
DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
}
}
TREE_TYPE (newdecl)
= TREE_TYPE (olddecl)
= common_type (newtype, oldtype);
}
/* Keep the old rtl since we can safely use it. */
COPY_DECL_RTL (olddecl, newdecl);
/* Lay the type out, unless already done. */
if (oldtype != TREE_TYPE (newdecl))
{
if (TREE_TYPE (newdecl) != error_mark_node)
layout_type (TREE_TYPE (newdecl));
if (TREE_CODE (newdecl) != FUNCTION_DECL
&& TREE_CODE (newdecl) != TYPE_DECL
&& TREE_CODE (newdecl) != CONST_DECL)
layout_decl (newdecl, 0);
}
else
{
/* Since the type is OLDDECL's, make OLDDECL's size go with. */
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
DECL_MODE (newdecl) = DECL_MODE (olddecl);
if (TREE_CODE (olddecl) != FUNCTION_DECL)
if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
{
DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
}
}
/* Merge the type qualifiers. */
if (TREE_READONLY (newdecl))
TREE_READONLY (write_olddecl) = 1;
/* Keep the old rtl since we can safely use it. */
COPY_DECL_RTL (olddecl, newdecl);
if (TREE_THIS_VOLATILE (newdecl))
{
TREE_THIS_VOLATILE (write_olddecl) = 1;
if (TREE_CODE (newdecl) == VAR_DECL
/* If an automatic variable is re-declared in the same
function scope, but the old declaration was not
volatile, make_var_volatile() would crash because the
variable would have been assigned to a pseudo, not a
MEM. Since this duplicate declaration is invalid
anyway, we just skip the call. */
&& errmsg == 0)
make_var_volatile (newdecl);
}
/* Merge the type qualifiers. */
if (TREE_READONLY (newdecl))
TREE_READONLY (write_olddecl) = 1;
/* Keep source location of definition rather than declaration. */
/* When called with different_binding_level set, keep the old
information so that meaningful diagnostics can be given. */
if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0
&& ! different_binding_level)
DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
/* Merge the unused-warning information. */
if (DECL_IN_SYSTEM_HEADER (olddecl))
DECL_IN_SYSTEM_HEADER (newdecl) = 1;
else if (DECL_IN_SYSTEM_HEADER (newdecl))
DECL_IN_SYSTEM_HEADER (write_olddecl) = 1;
/* Merge the initialization information. */
/* When called with different_binding_level set, don't copy over
DECL_INITIAL, so that we don't accidentally change function
declarations into function definitions. */
if (DECL_INITIAL (newdecl) == 0 && ! different_binding_level)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
/* Merge the section attribute.
We want to issue an error if the sections conflict but that must be
done later in decl_attributes since we are called before attributes
are assigned. */
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
/* Copy the assembler name.
Currently, it can only be defined in the prototype. */
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
/* If either declaration has a nondefault visibility, use it. */
if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
{
if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
warning ("%J'%D': visibility attribute ignored because it",
newdecl, newdecl);
warning ("%Jconflicts with previous declaration here", olddecl);
}
DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
}
if (TREE_THIS_VOLATILE (newdecl))
{
TREE_THIS_VOLATILE (write_olddecl) = 1;
if (TREE_CODE (newdecl) == VAR_DECL)
make_var_volatile (newdecl);
}
/* Keep source location of definition rather than declaration. */
/* When called with different_binding_level set, keep the old
information so that meaningful diagnostics can be given. */
if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0
&& ! different_binding_level)
DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
/* Merge the unused-warning information. */
if (DECL_IN_SYSTEM_HEADER (olddecl))
DECL_IN_SYSTEM_HEADER (newdecl) = 1;
else if (DECL_IN_SYSTEM_HEADER (newdecl))
DECL_IN_SYSTEM_HEADER (write_olddecl) = 1;
/* Merge the initialization information. */
/* When called with different_binding_level set, don't copy over
DECL_INITIAL, so that we don't accidentally change function
declarations into function definitions. */
if (DECL_INITIAL (newdecl) == 0 && ! different_binding_level)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
/* Merge the section attribute.
We want to issue an error if the sections conflict but that must be
done later in decl_attributes since we are called before attributes
are assigned. */
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
/* Copy the assembler name.
Currently, it can only be defined in the prototype. */
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
/* If either declaration has a nondefault visibility, use it. */
if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
}
}
/* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */
else if (! different_binding_level)
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
}
/* Merge the storage class information. */
......@@ -1448,9 +1448,9 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
if (DECL_BUILT_IN (olddecl))
{
/* Get rid of any built-in function if new arg types don't match it
or if we have a function definition. */
if (! types_match || new_is_definition)
/* Get rid of any built-in function if we have a function
definition. */
if (new_is_definition)
{
if (! different_binding_level)
{
......@@ -1502,7 +1502,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
}
}
if (different_binding_level)
return 0;
return;
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID. */
......@@ -1515,10 +1515,6 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
DECL_UID (olddecl) = olddecl_uid;
}
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
/* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
so that encode_section_info has a chance to look at the new decl
flags and attributes. */
......@@ -1527,10 +1523,34 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl, NULL);
return 1;
}
/* Handle when a new declaration NEWDECL has the same name as an old
one OLDDECL in the same binding contour. Prints an error message
if appropriate.
If safely possible, alter OLDDECL to look like NEWDECL, and return
true. Otherwise, return false.
When DIFFERENT_BINDING_LEVEL is true, NEWDECL is an external
declaration, and OLDDECL is in an outer scope and should thus not
be changed. */
static bool
duplicate_decls (tree newdecl, tree olddecl,
bool different_binding_level, bool different_tu)
{
tree newtype, oldtype;
if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
return false;
merge_decls (newdecl, olddecl, newtype, oldtype,
different_binding_level, different_tu);
return !different_binding_level;
}
/* Return any external DECL associated with ID, whether or not it is
currently in scope. */
......@@ -1890,69 +1910,6 @@ implicit_decl_warning (tree id)
warning ("implicit declaration of function `%s'", name);
}
/* Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
Otherwise return 1 if NEWDECL is a redefinition, 2 if it is a redeclaration,
and 3 if it is a conflicting declaration. */
static int
redeclaration_error_message (tree newdecl, tree olddecl)
{
if (TREE_CODE (newdecl) == TYPE_DECL)
{
/* Do not complain about type redeclarations where at least one
declaration was in a system header. */
if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
return 0;
return 1;
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
/* Declarations of functions can insist on internal linkage
but they can't be inconsistent with internal linkage,
so there can be no error on that account.
However defining the same name twice is no good. */
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0
/* However, defining once as extern inline and a second
time in another way is ok. */
&& ! (DECL_DECLARED_INLINE_P (olddecl) && DECL_EXTERNAL (olddecl)
&& ! (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_EXTERNAL (newdecl))))
return 1;
return 0;
}
else if (DECL_FILE_SCOPE_P (newdecl))
{
/* Objects declared at file scope: */
/* If at least one is a reference, it's ok. */
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
/* Reject two definitions. */
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0)
return 1;
/* Now we have two tentative defs, or one tentative and one real def. */
/* Insist that the linkage match. */
if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
return 3;
return 0;
}
else if (current_scope->parm_flag
&& TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
return 0;
else
{
/* Newdecl has block scope. If olddecl has block scope also, then
reject two definitions, and reject a definition together with an
external reference. Otherwise, it is OK, because newdecl must
be an extern reference to olddecl. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))
&& DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl))
return 2;
return 0;
}
}
/* Issue an error message for a reference to an undeclared variable
ID, including a reference to a builtin outside of function-call
context. Establish a binding of the identifier to error_mark_node
......
2004-01-10 Zack Weinberg <zack@codesourcery.com>
* gcc.dg/Wshadow-1.c, gcc.dg/attr-noinline.c, gcc.dg/decl3.c
* gcc.dg/redecl-1.c, gcc.dg/visibility-7.c, gcc.dg/wtr-static-1.c
* gcc.dg/noncompile/20020220-1.c, objc.dg/method-1.m:
Update dg-error regexps.
2004-01-10 Zack Weinberg <zack@codesourcery.com>
* gcc.c-torture/compile/20021123-2.c: Delete; dup of 20021120-1.c.
* gcc.c-torture/compile/20021123-3.c: Delete; dup of 20021120-2.c.
......
......@@ -10,7 +10,7 @@ void foo (double decl1) /* { dg-warning "shadows a global decl" } */
{
}
void foo1 (int d) /* { dg-warning "previous declaration" } */
void foo1 (int d) /* { dg-warning "previous definition" } */
{
double d; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "redeclared as different" "" { target *-*-* } 15 } */
......
......@@ -13,33 +13,33 @@ static inline void __attribute__((__noinline__)) function_declaration_both_after
static void function_declaration_both_after(void) {}
static void function_declaration_noinline_before(void) __attribute__((__noinline__)); /* { dg-warning "previous declaration \[^\n\]* with attribute noinline" "" } */
static void function_declaration_noinline_before(void) __attribute__((__noinline__)); /* { dg-warning "previous declaration" "" } */
static inline void function_declaration_noinline_before(void) {} /* { dg-warning "function \[^\n\]* redeclared as inline" "" } */
static inline void function_declaration_noinline_before(void) {} /* { dg-warning "follows declaration with attribute noinline" "" } */
static inline void function_declaration_noinline_after(void) {} /* { dg-warning "previous declaration \[^\n\]* was inline" "" } */
static inline void function_declaration_noinline_after(void) {} /* { dg-warning "previous definition" "" } */
static void function_declaration_noinline_after(void) __attribute__((__noinline__)); /* { dg-warning "function \[^\n\]* redeclared with attribute noinline" "" } */
static void function_declaration_noinline_after(void) __attribute__((__noinline__)); /* { dg-warning "follows inline declaration" "" } */
static inline void function_declaration_inline_before(void); /* { dg-warning "previous declaration \[^\n\]* was inline" "" } */
static inline void function_declaration_inline_before(void); /* { dg-warning "previous declaration" "" } */
static void __attribute__((__noinline__)) function_declaration_inline_before(void) {} /* { dg-warning "function \[^\n\]* redeclared with attribute noinline" "" } */
static void __attribute__((__noinline__)) function_declaration_inline_before(void) {} /* { dg-warning "follows inline declaration" "" } */
static inline void function_declaration_inline_noinline_before(void); /* { dg-warning "previous declaration \[^\n\]* was inline" "" } */
static inline void function_declaration_inline_noinline_before(void); /* { dg-warning "previous declaration" "" } */
static void function_declaration_inline_noinline_before(void) __attribute__((__noinline__)); /* { dg-warning "function \[^\n\]* redeclared with attribute noinline" "" } */
static void function_declaration_inline_noinline_before(void) __attribute__((__noinline__)); /* { dg-warning "follows inline declaration" "" } */
static void function_declaration_inline_noinline_before(void) {}
static inline void function_declaration_inline_noinline_after(void);
static void function_declaration_inline_noinline_after(void) {} /* { dg-warning "previous declaration \[^\n\]* was inline" "" } */
static void function_declaration_inline_noinline_after(void) {} /* { dg-warning "previous definition" "" } */
static void function_declaration_inline_noinline_after(void) __attribute__((__noinline__)); /* { dg-warning "function \[^\n\]* redeclared with attribute noinline" "" } */
static void function_declaration_inline_noinline_after(void) __attribute__((__noinline__)); /* { dg-warning "follows inline declaration" "" } */
static void function_declaration_noinline_inline_before(void) __attribute__((__noinline__)); /* { dg-warning "previous declaration\[^\n\]* with attribute noinline" "" } */
static void function_declaration_noinline_inline_before(void) __attribute__((__noinline__)); /* { dg-warning "previous declaration" "" } */
static inline void function_declaration_noinline_inline_before(void); /* { dg-warning "function \[^\n\]* redeclared as inline" "" } */
static inline void function_declaration_noinline_inline_before(void); /* { dg-warning "follows declaration with attribute noinline" "" } */
static void function_declaration_noinline_inline_before(void) {}
......
/* PR c/9928 */
/* { dg-do compile } */
enum { CODES }; /* { dg-error "previous declaration" } */
enum { CODES }; /* { dg-error "previous definition" } */
enum { CODES }; /* { dg-error "conflicting types" } */
......@@ -24,7 +24,6 @@ int main ()
return 0;
}
/* { dg-warning "passing arg 2 of" "2nd incompatible" { target *-*-* } 15 } */
/* { dg-warning "passing arg 1 of" "1st incompatible" { target *-*-* } 16 } */
/* { dg-warning "passing arg 2 of" "2nd incompatible" { target *-*-* } 16 } */
/* { dg-warning "passing arg 1 of" "1st incompatible" { target *-*-* } 18 } */
......
......@@ -6,7 +6,7 @@ int foo (const char*, const char*);
void bar (void)
{
const char *s = "bar";
int i; /* { dg-error "previously declared here" } */
int i; /* { dg-error "previous declaration" } */
int size = 2;
int i = foo (s, s + size); /* { dg-error "redeclaration of" } */
}
......@@ -74,7 +74,7 @@ void test5(void)
/* Extern then static, both at file scope. */
extern int test6(int); /* { dg-warning "previous" "" { xfail *-*-* } } */
extern int test6(int); /* { dg-warning "previous" "" } */
static int test6(int x)
{ return x; } /* { dg-warning "follows non-static" } */
......@@ -83,7 +83,7 @@ static int test6(int x)
void prime7(void)
{
extern int test7(int); /* { dg-warning "previous" "" { xfail *-*-* } } */
extern int test7(int); /* { dg-warning "previous" "" } */
}
static int test7(int x)
......@@ -93,7 +93,7 @@ static int test7(int x)
void prime8(void)
{
test8(); /* { dg-warning "previous" "" { xfail *-*-* } } */
test8(); /* { dg-warning "previous" "" } */
/* { dg-warning "implicit" "" { target *-*-* } 96 } */
}
......
......@@ -5,8 +5,8 @@
extern int
__attribute__((visibility ("hidden")))
xyzzy; /* { dg-warning "previous declaration here" "" } */
xyzzy; /* { dg-warning "previous declaration" "" } */
int
__attribute__((visibility ("protected")))
xyzzy = 5; /* { dg-warning "visibility attribute ignored" "" } */
xyzzy = 5; /* { dg-warning "different visibility" "" } */
......@@ -4,7 +4,7 @@
/* { dg-do compile } */
/* { dg-options "-Wtraditional" } */
static void testfunc1(void);
static void testfunc1(void); /* { dg-warning "previous declaration" } */
void testfunc1() {} /* { dg-warning "non-static.*follows static" "non-static follows static" } */
# 11 "sys-header.h" 3
......
......@@ -16,9 +16,8 @@
@end
@implementation class3
- (int) meth1 { return 0; }
- (int) meth1 { return 0; } /* { dg-error "previous definition" } */
- (int) meth1 { return 0; } /* { dg-error "redefinition of" } */
/* { dg-error "previously defined here" "" { target *-*-* } 19 } */
@end
@interface class4
......@@ -26,7 +25,6 @@
@end
@implementation class4
+ (void) meth1 {}
+ (void) meth1 {} /* { dg-error "previous definition" } */
+ (void) meth1 {} /* { dg-error "redefinition of" } */
/* { dg-error "previously defined here" "" { target *-*-* } 29 } */
@end
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