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> 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): * genautomata.c (make_automaton, NDFA_to_DFA):
Print progress bars with '.' characters instead of '*'. Print progress bars with '.' characters instead of '*'.
(build_automaton): Change notes to match. (build_automaton): Change notes to match.
......
...@@ -306,9 +306,6 @@ tree static_ctors, static_dtors; ...@@ -306,9 +306,6 @@ tree static_ctors, static_dtors;
static struct c_scope *make_scope (void); static struct c_scope *make_scope (void);
static void pop_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 tree make_label (tree, location_t);
static void bind_label (tree, tree, struct c_scope *); static void bind_label (tree, tree, struct c_scope *);
static void implicit_decl_warning (tree); static void implicit_decl_warning (tree);
...@@ -755,12 +752,12 @@ pushtag (tree name, tree type) ...@@ -755,12 +752,12 @@ pushtag (tree name, tree type)
TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (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 and argument types provided that the type modes match. This function
return a unified type given a suitable match, and 0 otherwise. */ return a unified type given a suitable match, and 0 otherwise. */
static tree static tree
match_builtin_function_types (tree oldtype, tree newtype) match_builtin_function_types (tree newtype, tree oldtype)
{ {
tree newrettype, oldrettype; tree newrettype, oldrettype;
tree newargs, oldargs; tree newargs, oldargs;
...@@ -795,206 +792,186 @@ match_builtin_function_types (tree oldtype, tree newtype) ...@@ -795,206 +792,186 @@ match_builtin_function_types (tree oldtype, tree newtype)
return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype)); return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype));
} }
/* Handle when a new declaration NEWDECL /* Subroutine of diagnose_mismathed_decls. Check for function type
has the same name as an old one OLDDECL mismatch involving an empty arglist vs a nonempty one and give clearer
in the same binding contour. diagnostics. */
Prints an error message if appropriate. 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. if (TREE_CODE (olddecl) != FUNCTION_DECL
Otherwise, return 0. || !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, t = TYPE_ARG_TYPES (oldtype);
and OLDDECL is in an outer scope and should thus not be changed. */ if (t == 0)
t = TYPE_ARG_TYPES (newtype);
for (; t; t = TREE_CHAIN (t))
{
tree type = TREE_VALUE (t);
static int if (TREE_CHAIN (t) == 0
duplicate_decls (tree newdecl, tree olddecl, int different_binding_level, && TYPE_MAIN_VARIANT (type) != void_type_node)
int different_tu) {
{ inform ("a parameter list with an ellipsis can't match"
int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), "an empty parameter name list declaration");
COMPARE_STRICT); break;
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 (DECL_P (olddecl)) if (c_type_promotes_to (type) != type)
{ {
if (TREE_CODE (newdecl) == FUNCTION_DECL inform ("an argument type that has a default promotion can't match"
&& TREE_CODE (olddecl) == FUNCTION_DECL "an empty parameter name list declaration");
&& (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl))) break;
}
}
}
/* 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 (DECL_DECLARED_INLINE_P (newdecl) if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
&& DECL_UNINLINABLE (newdecl) && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
&& 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", /* End of list. */
warning ("%Jprototype for '%D' follows non-prototype definition",
newdecl, newdecl); newdecl, newdecl);
warning ("%Jprevious declaration of function '%D' " return true;
"with attribute noinline", olddecl, olddecl);
} }
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl) if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))) || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{ {
warning ("%Jfunction '%D' redeclared with attribute noinline", error ("%Jprototype for '%D' with different number of arguments "
newdecl, newdecl); "follows non-prototype definition", newdecl, newdecl);
warning ("%Jprevious declaration of function '%D' was inline", return false;
olddecl, olddecl);
} }
/* 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;
} }
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
} }
}
if (TREE_CODE (newtype) == ERROR_MARK /* Subroutine of diagnose_mismatched_decls. Report the location of DECL,
|| TREE_CODE (oldtype) == ERROR_MARK) first in a pair of mismatched declarations, using the diagnostic
types_match = 0; 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);
}
/* 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. */
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;
/* New decl is completely inconsistent with the old one => /* Two different categories of symbol altogether. This is an error
tell caller to replace the old one. unless OLDDECL is a builtin. OLDDECL will be discarded in any case. */
This is always an error except in the case of shadowing a builtin. */
if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{ {
if (TREE_CODE (olddecl) == FUNCTION_DECL if (TREE_CODE (olddecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
&& 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))
{ {
if (warn_shadow) error ("%J'%D' redeclared as different kind of symbol",
warning ("%Jshadowing built-in function '%D'",
newdecl, newdecl); newdecl, newdecl);
locate_old_decl (olddecl, error);
} }
else else if (TREE_PUBLIC (newdecl))
warning ("%Jbuilt-in function '%D' declared as non-function", warning ("%Jbuilt-in function '%D' declared as non-function",
newdecl, newdecl); newdecl, newdecl);
} else if (warn_shadow)
else warning ("%Jshadowing built-in function '%D'",
{
error ("%J'%D' redeclared as different kind of symbol",
newdecl, newdecl); newdecl, newdecl);
error ("%Jprevious declaration of '%D'", olddecl, olddecl); return false;
}
return 0;
} }
/* For real parm decl following a forward decl, return 1 so old decl if (!comptypes (oldtype, newtype, COMPARE_STRICT))
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))
{ {
TREE_ASM_WRITTEN (olddecl) = 0;
return 1;
}
/* 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)) if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl))
{ {
/* A function declaration for a built-in function. */
if (!TREE_PUBLIC (newdecl))
{
/* If you declare a built-in function name as static, the
built-in definition is overridden,
but optionally warn this was a bad choice of name. */
if (warn_shadow)
warning ("%Jshadowing built-in function '%D'", newdecl, newdecl);
/* Discard the old built-in function. */
return 0;
}
if (!types_match)
{
/* Accept harmless mismatch in function types. /* Accept harmless mismatch in function types.
This is for the ffs and fprintf builtins. */ This is for the ffs and fprintf builtins. */
tree trytype = match_builtin_function_types (oldtype, newtype); tree trytype = match_builtin_function_types (newtype, oldtype);
if (trytype) if (trytype && comptypes (newtype, trytype, COMPARE_STRICT))
{
types_match = comptypes (newtype, trytype, COMPARE_STRICT);
if (types_match)
oldtype = trytype; oldtype = trytype;
if (! different_binding_level) else
TREE_TYPE (olddecl) = oldtype;
}
}
if (!types_match)
{ {
/* If types don't match for a built-in, throw away the built-in. */ /* 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'", warning ("%Jconflicting types for built-in function '%D'",
newdecl, newdecl); newdecl, newdecl);
return 0; return false;
} }
} }
else if (TREE_CODE (olddecl) == FUNCTION_DECL else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_SOURCE_LINE (olddecl) == 0) && DECL_SOURCE_LINE (olddecl) == 0)
{ {
/* A function declaration for a predeclared function /* A conflicting function declaration for a predeclared
that isn't actually built in. */ function that isn't actually built in. Objective C uses
if (!TREE_PUBLIC (newdecl)) these. The new declaration silently overrides everything
{ but the volatility (i.e. noreturn) indication. See also
/* If you declare it as static, the below. FIXME: Make Objective C use normal builtins. */
default definition is overridden. */
return 0;
}
else if (!types_match)
{
/* 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); TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
return false;
} }
} /* Permit void foo (...) to match int foo (...) if the latter is
/* Permit char *foo () to match void *foo (...) if not pedantic, the definition and implicit int was used. See
if one of them came from a system header file. */ c-torture/compile/920625-2.c. */
else if (!types_match else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl)
&& 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 (oldtype)) == void_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
&& C_FUNCTION_IMPLICIT_INT (newdecl)) && C_FUNCTION_IMPLICIT_INT (newdecl))
...@@ -1003,241 +980,290 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level, ...@@ -1003,241 +980,290 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
/* Make sure we keep void as the return type. */ /* Make sure we keep void as the return type. */
TREE_TYPE (newdecl) = newtype = oldtype; TREE_TYPE (newdecl) = newtype = oldtype;
C_FUNCTION_IMPLICIT_INT (newdecl) = 0; C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
pedwarned = true;
} }
else if (!types_match else
/* 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); error ("%Jconflicting types for '%D'", newdecl, newdecl);
/* Check for function type mismatch diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
involving an empty arglist vs a nonempty one. */ locate_old_decl (olddecl, error);
if (TREE_CODE (olddecl) == FUNCTION_DECL return false;
&& comptypes (TREE_TYPE (oldtype), }
TREE_TYPE (newtype), COMPARE_STRICT) }
&& ((TYPE_ARG_TYPES (oldtype) == 0
&& DECL_INITIAL (olddecl) == 0) /* Redeclaration of a type is a constraint violation (6.7.2.3p1),
|| but silently ignore the redeclaration if either is in a system
(TYPE_ARG_TYPES (newtype) == 0 header. (Conflicting redeclarations were handled above.) */
&& DECL_INITIAL (newdecl) == 0))) if (TREE_CODE (newdecl) == TYPE_DECL)
{
/* Classify the problem further. */
tree t = TYPE_ARG_TYPES (oldtype);
if (t == 0)
t = TYPE_ARG_TYPES (newtype);
for (; t; t = TREE_CHAIN (t))
{ {
tree type = TREE_VALUE (t); if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl))
return true; /* allow OLDDECL to continue in use */
if (TREE_CHAIN (t) == 0 error ("%Jredefinition of typedef '%D'", newdecl, newdecl);
&& TYPE_MAIN_VARIANT (type) != void_type_node) locate_old_decl (olddecl, error);
return false;
}
/* 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)
{ {
error ("a parameter list with an ellipsis can't match an empty parameter name list declaration"); if (DECL_BUILT_IN (olddecl) && !TREE_PUBLIC (newdecl))
break; {
/* If you declare a built-in function name as static, the
built-in definition is overridden,
but optionally warn this was a bad choice of name. */
if (warn_shadow)
warning ("%Jshadowing built-in function '%D'", newdecl, newdecl);
/* Discard the old built-in function. */
return false;
} }
if (c_type_promotes_to (type) != type) if (DECL_INITIAL (newdecl))
{ {
error ("an argument type that has a default promotion can't match an empty parameter name list declaration"); if (DECL_INITIAL (olddecl)
break; && !(DECL_DECLARED_INLINE_P (olddecl)
&& DECL_EXTERNAL (olddecl)
&& !(DECL_DECLARED_INLINE_P (newdecl)
&& DECL_EXTERNAL (newdecl))))
{
error ("%Jredefinition of '%D'", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
} }
} }
/* 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))
{
locate_old_decl (olddecl, error);
return false;
} }
if (C_DECL_IMPLICIT (olddecl)) /* Mismatched non-static and static is considered poor style.
error ("%Jprevious implicit declaration of '%D'", olddecl, olddecl); 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 else
error ("%Jprevious declaration of '%D'", olddecl, olddecl);
/* 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 " warning ("%Jstatic declaration of '%D' follows "
"declaration", newdecl, newdecl); "non-static declaration", newdecl, newdecl);
error ("%Jprevious declaration of '%D'", olddecl, olddecl); warned = true;
}
} }
/* non-TLS declaration cannot follow TLS declaration. */ else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl)
else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL && warn_traditional)
&& DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl))
{ {
error ("%Jnon thread-local declaration of '%D' follows " warning ("%Jnon-static declaration of '%D' follows "
"thread-local declaration", newdecl, newdecl); "static declaration", newdecl, newdecl);
error ("%Jprevious declaration of '%D'", olddecl, olddecl); warned = true;
} }
else }
else if (TREE_CODE (newdecl) == VAR_DECL)
{ {
errmsg = redeclaration_error_message (newdecl, olddecl); /* Only variables can be thread-local, and all declarations must
if (errmsg) agree on this property. */
if (DECL_THREAD_LOCAL (newdecl) != DECL_THREAD_LOCAL (olddecl))
{ {
switch (errmsg) 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;
}
/* Multiple initialized definitions are not allowed (6.9p3,5). */
if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
{ {
case 1:
error ("%Jredefinition of '%D'", newdecl, newdecl); error ("%Jredefinition of '%D'", newdecl, newdecl);
break; locate_old_decl (olddecl, error);
case 2: return false;
error ("%Jredeclaration of '%D'", newdecl, newdecl);
break;
case 3:
error ("%Jconflicting declarations of '%D'", newdecl, newdecl);
break;
default:
abort ();
} }
if (DECL_INITIAL (olddecl) /* Objects declared at file scope: if at least one is 'extern',
&& current_scope == global_scope) it's fine (6.2.2p4); otherwise the linkage must agree (6.2.2p7). */
error ("%J'%D' previously defined here", olddecl, olddecl); if (DECL_FILE_SCOPE_P (newdecl))
{
if (!DECL_EXTERNAL (newdecl)
&& !DECL_EXTERNAL (olddecl)
&& TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
{
if (TREE_PUBLIC (newdecl))
error ("%Jnon-static declaration of '%D' follows "
"static declaration", newdecl, newdecl);
else else
error ("%J'%D' previously declared here", olddecl, olddecl); error ("%Jstatic declaration of '%D' follows "
return 0; "non-static declaration", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
} }
else if (TREE_CODE (newdecl) == TYPE_DECL /* Two objects with the same name declared at the same block
&& (DECL_IN_SYSTEM_HEADER (olddecl) scope must both be external references (6.7p3). */
|| DECL_IN_SYSTEM_HEADER (newdecl))) else if (DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl)
&& (!DECL_EXTERNAL (newdecl) || !DECL_EXTERNAL (olddecl)))
{ {
warning ("%Jredefinition of '%D'", newdecl, newdecl); if (DECL_EXTERNAL (newdecl))
if (DECL_INITIAL (olddecl) && current_scope == global_scope) error ("%Jextern declaration of '%D' follows "
warning ("%J'%D' previously defined here", olddecl, olddecl); "declaration with no linkage", newdecl, newdecl);
else if (DECL_EXTERNAL (olddecl))
error ("%Jdeclaration of '%D' with no linkage follows "
"extern declaration", newdecl, newdecl);
else else
warning ("%J'%D' previously declared here", olddecl, olddecl); error ("%Jredeclaration of '%D' with no linkage",
newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
} }
else if (TREE_CODE (olddecl) == FUNCTION_DECL }
&& DECL_INITIAL (olddecl) != 0
&& TYPE_ARG_TYPES (oldtype) == 0 /* warnings */
&& TYPE_ARG_TYPES (newtype) != 0 /* All decls must agree on a non-default visibility. */
&& TYPE_ACTUAL_ARG_TYPES (oldtype) != 0) if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
&& DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{ {
tree type, parm; warning ("%Jredeclaration of '%D' with different visibility "
int nargs; "(old visibility preserved)", newdecl, newdecl);
/* Prototype decl follows defn w/o prototype. */ warned = true;
}
for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype), if (TREE_CODE (newdecl) == FUNCTION_DECL)
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 /* Diagnose inline __attribute__ ((noinline)) which is silly. */
&& TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) if (DECL_DECLARED_INLINE_P (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{ {
warning ("%Jprototype for '%D' follows", newdecl, newdecl); warning ("%Jinline declaration of '%D' follows "
warning ("%Jnon-prototype definition here", olddecl); "declaration with attribute noinline", newdecl, newdecl);
break; warned = true;
} }
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node else if (DECL_DECLARED_INLINE_P (olddecl)
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{ {
error ("%Jprototype for '%D' follows and number of " warning ("%Jdeclaration of '%D' with attribute noinline follows "
"arguments doesn't match", newdecl, newdecl); "inline declaration ", newdecl, newdecl);
error ("%Jnon-prototype definition here", olddecl); warned = true;
errmsg = 1;
break;
} }
/* Type for passing arg must be consistent
with that declared for the arg. */ /* Inline declaration after use or definition.
if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type), ??? Should we still warn about this now we have unit-at-a-time
COMPARE_STRICT)) mode and can get it right? */
if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl))
{ {
error ("%Jprototype for '%D' follows and argument %d " if (TREE_USED (olddecl))
"doesn't match", newdecl, newdecl, nargs); {
error ("%Jnon-prototype definition here", olddecl); warning ("%J'%D' declared inline after being called");
errmsg = 1; warned = true;
break; }
else if (DECL_INITIAL (olddecl))
{
warning ("%J'%D' declared inline after its definition");
warned = true;
} }
} }
} }
/* Warn about mismatches in various flags. */ else /* VAR_DECL */
{
/* These bits are only type qualifiers when applied to objects. */
if (TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
{
if (TREE_THIS_VOLATILE (newdecl))
pedwarn ("%Jvolatile declaration of '%D' follows "
"non-volatile declaration", newdecl, newdecl);
else else
pedwarn ("%Jnon-volatile declaration of '%D' follows "
"volatile declaration", newdecl, newdecl);
pedwarned = true;
}
if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl))
{ {
/* Warn if function is now inline if (TREE_READONLY (newdecl))
but was previously declared not inline and has been called. */ pedwarn ("%Jconst declaration of '%D' follows "
if (TREE_CODE (olddecl) == FUNCTION_DECL "non-const declaration", newdecl, newdecl);
&& ! DECL_DECLARED_INLINE_P (olddecl) else
&& DECL_DECLARED_INLINE_P (newdecl) pedwarn ("%Jnon-const declaration of '%D' follows "
&& TREE_USED (olddecl)) "const declaration", newdecl, newdecl);
warning ("%J'%D' declared inline after being called", pedwarned = true;
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 /* Optional warning for completely redundant decls. */
declaration. Otherwise, do so only for functions. */ if (!warned && !pedwarned
if ((pedantic || TREE_CODE (olddecl) == FUNCTION_DECL) && warn_redundant_decls
&& TREE_PUBLIC (olddecl) /* Don't warn about a function declaration followed by a
&& !TREE_PUBLIC (newdecl)) definition. */
warning ("%Jstatic declaration for '%D' follows non-static", && !(TREE_CODE (newdecl) == FUNCTION_DECL
newdecl, newdecl); && 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'", newdecl, newdecl);
warned = true;
}
/* If warn_traditional, warn when a non-static function /* Report location of previous decl/defn in a consistent manner. */
declaration follows a static one. */ if (warned || pedwarned)
if (warn_traditional && !in_system_header locate_old_decl (olddecl, pedwarned ? pedwarn : warning);
&& 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 *newtypep = newtype;
declaration, but not for functions. */ *oldtypep = oldtype;
if (TREE_CODE (olddecl) != FUNCTION_DECL return true;
&& !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);
}
}
/* 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)))
{
warning ("%Jredundant redeclaration of '%D' in same scope",
newdecl, newdecl);
warning ("%Jprevious declaration of '%D'", olddecl, olddecl);
}
/* Copy all the DECL_... slots specified in the new decl /* Subroutine of duplicate_decls. NEWDECL has been found to be
except for any that we copy here from the old type. 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. */
Past this point, we don't change OLDTYPE and NEWTYPE static void
even if we change the types of NEWDECL and OLDDECL. */ 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);
if (types_match)
{
/* When copying info to olddecl, we store into write_olddecl /* When copying info to olddecl, we store into write_olddecl
instead. This allows us to avoid modifying olddecl when instead. This allows us to avoid modifying olddecl when
different_binding_level is true. */ different_binding_level is true. */
tree write_olddecl = different_binding_level ? newdecl : olddecl; 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))
{
TREE_ASM_WRITTEN (olddecl) = 0;
return;
}
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
/* Merge the data types specified in the two decls. */ /* Merge the data types specified in the two decls. */
if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl)) if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
{ {
...@@ -1293,14 +1319,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level, ...@@ -1293,14 +1319,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
if (TREE_THIS_VOLATILE (newdecl)) if (TREE_THIS_VOLATILE (newdecl))
{ {
TREE_THIS_VOLATILE (write_olddecl) = 1; TREE_THIS_VOLATILE (write_olddecl) = 1;
if (TREE_CODE (newdecl) == VAR_DECL 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); make_var_volatile (newdecl);
} }
...@@ -1337,16 +1356,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level, ...@@ -1337,16 +1356,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
/* If either declaration has a nondefault visibility, use it. */ /* If either declaration has a nondefault visibility, use it. */
if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT) 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); DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL) if (TREE_CODE (newdecl) == FUNCTION_DECL)
{ {
...@@ -1360,16 +1370,6 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level, ...@@ -1360,16 +1370,6 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
DECL_IS_PURE (newdecl) |= DECL_IS_PURE (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)
{
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);
}
/* Merge the storage class information. */ /* Merge the storage class information. */
merge_weak (newdecl, olddecl); merge_weak (newdecl, olddecl);
...@@ -1448,9 +1448,9 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level, ...@@ -1448,9 +1448,9 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
if (DECL_BUILT_IN (olddecl)) if (DECL_BUILT_IN (olddecl))
{ {
/* Get rid of any built-in function if new arg types don't match it /* Get rid of any built-in function if we have a function
or if we have a function definition. */ definition. */
if (! types_match || new_is_definition) if (new_is_definition)
{ {
if (! different_binding_level) if (! different_binding_level)
{ {
...@@ -1502,7 +1502,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level, ...@@ -1502,7 +1502,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
} }
} }
if (different_binding_level) if (different_binding_level)
return 0; return;
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL. /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID. */ But preserve OLDDECL's DECL_UID. */
...@@ -1515,10 +1515,6 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level, ...@@ -1515,10 +1515,6 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
DECL_UID (olddecl) = olddecl_uid; 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 /* 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 so that encode_section_info has a chance to look at the new decl
flags and attributes. */ flags and attributes. */
...@@ -1527,10 +1523,34 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level, ...@@ -1527,10 +1523,34 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
|| (TREE_CODE (olddecl) == VAR_DECL || (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl)))) && TREE_STATIC (olddecl))))
make_decl_rtl (olddecl, NULL); 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 /* Return any external DECL associated with ID, whether or not it is
currently in scope. */ currently in scope. */
...@@ -1890,69 +1910,6 @@ implicit_decl_warning (tree id) ...@@ -1890,69 +1910,6 @@ implicit_decl_warning (tree id)
warning ("implicit declaration of function `%s'", name); 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 /* Issue an error message for a reference to an undeclared variable
ID, including a reference to a builtin outside of function-call ID, including a reference to a builtin outside of function-call
context. Establish a binding of the identifier to error_mark_node context. Establish a binding of the identifier to error_mark_node
......
2004-01-10 Zack Weinberg <zack@codesourcery.com> 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-2.c: Delete; dup of 20021120-1.c.
* gcc.c-torture/compile/20021123-3.c: Delete; dup of 20021120-2.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" } */ ...@@ -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" } */ double d; /* { dg-bogus "warning" "warning in place of error" } */
/* { dg-error "redeclared as different" "" { target *-*-* } 15 } */ /* { dg-error "redeclared as different" "" { target *-*-* } 15 } */
......
...@@ -13,33 +13,33 @@ static inline void __attribute__((__noinline__)) function_declaration_both_after ...@@ -13,33 +13,33 @@ static inline void __attribute__((__noinline__)) function_declaration_both_after
static void function_declaration_both_after(void) {} 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 void function_declaration_inline_noinline_before(void) {}
static inline void function_declaration_inline_noinline_after(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) {} static void function_declaration_noinline_inline_before(void) {}
......
/* PR c/9928 */ /* PR c/9928 */
/* { dg-do compile } */ /* { dg-do compile } */
enum { CODES }; /* { dg-error "previous declaration" } */ enum { CODES }; /* { dg-error "previous definition" } */
enum { CODES }; /* { dg-error "conflicting types" } */ enum { CODES }; /* { dg-error "conflicting types" } */
...@@ -24,7 +24,6 @@ int main () ...@@ -24,7 +24,6 @@ int main ()
return 0; 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 1 of" "1st incompatible" { target *-*-* } 16 } */
/* { dg-warning "passing arg 2 of" "2nd incompatible" { target *-*-* } 16 } */ /* { dg-warning "passing arg 2 of" "2nd incompatible" { target *-*-* } 16 } */
/* { dg-warning "passing arg 1 of" "1st incompatible" { target *-*-* } 18 } */ /* { dg-warning "passing arg 1 of" "1st incompatible" { target *-*-* } 18 } */
......
...@@ -6,7 +6,7 @@ int foo (const char*, const char*); ...@@ -6,7 +6,7 @@ int foo (const char*, const char*);
void bar (void) void bar (void)
{ {
const char *s = "bar"; const char *s = "bar";
int i; /* { dg-error "previously declared here" } */ int i; /* { dg-error "previous declaration" } */
int size = 2; int size = 2;
int i = foo (s, s + size); /* { dg-error "redeclaration of" } */ int i = foo (s, s + size); /* { dg-error "redeclaration of" } */
} }
...@@ -74,7 +74,7 @@ void test5(void) ...@@ -74,7 +74,7 @@ void test5(void)
/* Extern then static, both at file scope. */ /* 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) static int test6(int x)
{ return x; } /* { dg-warning "follows non-static" } */ { return x; } /* { dg-warning "follows non-static" } */
...@@ -83,7 +83,7 @@ static int test6(int x) ...@@ -83,7 +83,7 @@ static int test6(int x)
void prime7(void) void prime7(void)
{ {
extern int test7(int); /* { dg-warning "previous" "" { xfail *-*-* } } */ extern int test7(int); /* { dg-warning "previous" "" } */
} }
static int test7(int x) static int test7(int x)
...@@ -93,7 +93,7 @@ static int test7(int x) ...@@ -93,7 +93,7 @@ static int test7(int x)
void prime8(void) void prime8(void)
{ {
test8(); /* { dg-warning "previous" "" { xfail *-*-* } } */ test8(); /* { dg-warning "previous" "" } */
/* { dg-warning "implicit" "" { target *-*-* } 96 } */ /* { dg-warning "implicit" "" { target *-*-* } 96 } */
} }
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
extern int extern int
__attribute__((visibility ("hidden"))) __attribute__((visibility ("hidden")))
xyzzy; /* { dg-warning "previous declaration here" "" } */ xyzzy; /* { dg-warning "previous declaration" "" } */
int int
__attribute__((visibility ("protected"))) __attribute__((visibility ("protected")))
xyzzy = 5; /* { dg-warning "visibility attribute ignored" "" } */ xyzzy = 5; /* { dg-warning "different visibility" "" } */
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-Wtraditional" } */ /* { 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" } */ void testfunc1() {} /* { dg-warning "non-static.*follows static" "non-static follows static" } */
# 11 "sys-header.h" 3 # 11 "sys-header.h" 3
......
...@@ -16,9 +16,8 @@ ...@@ -16,9 +16,8 @@
@end @end
@implementation class3 @implementation class3
- (int) meth1 { return 0; } - (int) meth1 { return 0; } /* { dg-error "previous definition" } */
- (int) meth1 { return 0; } /* { dg-error "redefinition of" } */ - (int) meth1 { return 0; } /* { dg-error "redefinition of" } */
/* { dg-error "previously defined here" "" { target *-*-* } 19 } */
@end @end
@interface class4 @interface class4
...@@ -26,7 +25,6 @@ ...@@ -26,7 +25,6 @@
@end @end
@implementation class4 @implementation class4
+ (void) meth1 {} + (void) meth1 {} /* { dg-error "previous definition" } */
+ (void) meth1 {} /* { dg-error "redefinition of" } */ + (void) meth1 {} /* { dg-error "redefinition of" } */
/* { dg-error "previously defined here" "" { target *-*-* } 29 } */
@end @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