/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
int flag_traditional;
+/* Nonzero means that we have builtin functions, and main is an int */
+
+int flag_hosted = 1;
+
/* Nonzero means to allow single precision math even if we're generally
being traditional. */
int flag_allow_single_precision = 0;
int warn_missing_braces;
-/* Warn about comparison of signed and unsigned values. */
+/* Warn if main is suspicious. */
+
+int warn_main;
+
+/* Warn about comparison of signed and unsigned values.
+ If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */
-int warn_sign_compare;
+int warn_sign_compare = -1;
/* Nonzero means `$' can be in an identifier. */
}
else if (!strcmp (p, "-fallow-single-precision"))
flag_allow_single_precision = 1;
+ else if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
+ {
+ flag_hosted = 1;
+ flag_no_builtin = 0;
+ }
+ else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted"))
+ {
+ flag_hosted = 0;
+ flag_no_builtin = 1;
+ /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */
+ if (warn_main == 2)
+ warn_main = 0;
+ }
else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional"))
{
flag_traditional = 0;
; /* cpp handles this one. */
else if (!strcmp (p, "-Wno-trigraphs"))
; /* cpp handles this one. */
+ else if (!strcmp (p, "-Wundef"))
+ ; /* cpp handles this one. */
+ else if (!strcmp (p, "-Wno-undef"))
+ ; /* cpp handles this one. */
else if (!strcmp (p, "-Wimport"))
; /* cpp handles this one. */
else if (!strcmp (p, "-Wno-import"))
warn_missing_braces = 1;
else if (!strcmp (p, "-Wno-missing-braces"))
warn_missing_braces = 0;
+ else if (!strcmp (p, "-Wmain"))
+ warn_main = 1;
+ else if (!strcmp (p, "-Wno-main"))
+ warn_main = 0;
else if (!strcmp (p, "-Wsign-compare"))
warn_sign_compare = 1;
else if (!strcmp (p, "-Wno-sign-compare"))
warn_char_subscripts = 1;
warn_parentheses = 1;
warn_missing_braces = 1;
- warn_sign_compare = 1;
+ /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
+ it off only if it's not explicit. */
+ warn_main = 2;
}
else
return 0;
if (DECL_ABSTRACT_ORIGIN (decl) != 0
&& DECL_ABSTRACT_ORIGIN (decl) != decl)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
- else
+ else if (DECL_SAVED_INSNS (decl) != 0)
{
push_function_context ();
output_inline_function (decl);
tagged type. */
TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
+
+ /* An approximation for now, so we can tell this is a function-scope tag.
+ This will be updated in poplevel. */
+ TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
}
\f
/* Handle when a new declaration NEWDECL
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
+ if (DECL_INLINE (newdecl))
+ DECL_ABSTRACT_ORIGIN (newdecl) = olddecl;
}
}
if (different_binding_level)
tree traditional_ptr_type_node;
/* Data types of memcpy and strlen. */
tree memcpy_ftype, memset_ftype, strlen_ftype;
- tree void_ftype_any;
+ tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr;
int wchar_type_size;
tree temp;
tree array_domain_type;
sizetype,
endlink))));
+ ptr_ftype_void = build_function_type (ptr_type_node, endlink);
+ ptr_ftype_ptr
+ = build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node, endlink));
+
builtin_function ("__builtin_constant_p", default_function_type,
BUILT_IN_CONSTANT_P, NULL_PTR);
endlink)),
BUILT_IN_FRAME_ADDRESS, NULL_PTR);
+ builtin_function ("__builtin_aggregate_incoming_address",
+ build_function_type (ptr_type_node, NULL_TREE),
+ BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR);
+
+ /* Hooks for the DWARF 2 __throw routine. */
+ builtin_function ("__builtin_unwind_init",
+ build_function_type (void_type_node, endlink),
+ BUILT_IN_UNWIND_INIT, NULL_PTR);
+ builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
+ builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
+ builtin_function ("__builtin_dwarf_fp_regnum",
+ build_function_type (unsigned_type_node, endlink),
+ BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
+ builtin_function ("__builtin_dwarf_reg_size", int_ftype_int,
+ BUILT_IN_DWARF_REG_SIZE, NULL_PTR);
+ builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
+ BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
+ builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
+ BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
+ builtin_function ("__builtin_set_return_addr_reg",
+ build_function_type (void_type_node,
+ tree_cons (NULL_TREE,
+ ptr_type_node,
+ endlink)),
+ BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
+ builtin_function ("__builtin_eh_stub", ptr_ftype_void,
+ BUILT_IN_EH_STUB, NULL_PTR);
+ builtin_function
+ ("__builtin_set_eh_regs",
+ build_function_type (void_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE,
+ type_for_mode (ptr_mode, 0),
+ endlink))),
+ BUILT_IN_SET_EH_REGS, NULL_PTR);
+
builtin_function ("__builtin_alloca",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
/* The corresponding pop_obstacks is in finish_decl. */
push_obstacks_nochange ();
+ if (warn_main && !strcmp (IDENTIFIER_POINTER (declarator), "main"))
+ warning_with_decl (decl, "`%s' is usually a function");
+
if (initialized)
/* Is it valid for this decl to have an initializer at all?
If not, set INITIALIZED to zero, which will indirectly
TYPE_DOMAIN (type) = build_index_type (maxindex);
if (!TREE_TYPE (maxindex))
TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
-#if 0 /* I took out this change
- together with the change in build_array_type. --rms */
- change_main_variant (type,
- build_array_type (TREE_TYPE (type),
- TYPE_DOMAIN (type)));
-#endif
}
/* Lay out the type now that we can get the real answer. */
if (type == 0)
{
- if (funcdef_flag && warn_return_type
- && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
- | (1 << (int) RID_SIGNED) | (1 << (int) RID_UNSIGNED))))
- warn_about_return_type = 1;
+ if (! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
+ | (1 << (int) RID_SIGNED)
+ | (1 << (int) RID_UNSIGNED))))
+ {
+ /* C9x will probably require a diagnostic here.
+ For now, issue a warning if -Wreturn-type and this is a function,
+ or if -Wimplicit; prefer the former warning since it is more
+ explicit. */
+ if ((warn_implicit || warn_return_type) && funcdef_flag)
+ warn_about_return_type = 1;
+ else if (warn_implicit)
+ warning ("type defaults to `int' in declaration of `%s'", name);
+ }
+
defaulted_int = 1;
type = integer_type_node;
}
/* Long double is a special combination. */
- if ((specbits & 1 << (int) RID_LONG)
+ if ((specbits & 1 << (int) RID_LONG) && ! longlong
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
specbits &= ~ (1 << (int) RID_LONG);
{
int ok = 0;
- if (TREE_CODE (type) != INTEGER_TYPE)
- error ("long, short, signed or unsigned invalid for `%s'", name);
- else if ((specbits & 1 << (int) RID_LONG)
- && (specbits & 1 << (int) RID_SHORT))
- error ("long and short specified together for `%s'", name);
+ if ((specbits & 1 << (int) RID_LONG)
+ && (specbits & 1 << (int) RID_SHORT))
+ error ("both long and short specified for `%s'", name);
else if (((specbits & 1 << (int) RID_LONG)
|| (specbits & 1 << (int) RID_SHORT))
&& explicit_char)
else if (((specbits & 1 << (int) RID_LONG)
|| (specbits & 1 << (int) RID_SHORT))
&& TREE_CODE (type) == REAL_TYPE)
- error ("long or short specified with floating type for `%s'", name);
+ {
+ static int already = 0;
+
+ error ("long or short specified with floating type for `%s'", name);
+ if (! already && ! pedantic)
+ {
+ error ("the only valid combination is `long double'");
+ already = 1;
+ }
+ }
else if ((specbits & 1 << (int) RID_SIGNED)
&& (specbits & 1 << (int) RID_UNSIGNED))
- error ("signed and unsigned given together for `%s'", name);
+ error ("both signed and unsigned specified for `%s'", name);
+ else if (TREE_CODE (type) != INTEGER_TYPE)
+ error ("long, short, signed or unsigned invalid for `%s'", name);
else
{
ok = 1;
&& ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ANSI C forbids const or volatile functions");
+ if (pedantic
+ && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
+ && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (decl)))
+ || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (decl))))
+ && ! DECL_IN_SYSTEM_HEADER (decl))
+ pedwarn ("ANSI C forbids const or volatile void function return type");
+
if (volatilep
&& TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
warning ("`noreturn' function returns non-void value");
enum tree_code code = TREE_CODE (TREE_VALUE (elt));
/* An anonymous union parm type is meaningful as a GNU extension.
So don't warn for that. */
- if (code == UNION_TYPE && !pedantic)
+ if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic)
continue;
if (TREE_PURPOSE (elt) != 0)
warning ("`%s %s' declared inside parameter list",
if (current_function_decl != 0)
TREE_PUBLIC (decl1) = 0;
+ /* Warn for unlikely, improbable, or stupid declarations of `main'. */
+ if (warn_main
+ && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
+ {
+ tree args;
+ int argct = 0;
+
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
+ != integer_type_node)
+ pedwarn_with_decl (decl1, "return type of `%s' is not `int'");
+
+ for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
+ args = TREE_CHAIN (args))
+ {
+ tree type = args ? TREE_VALUE (args) : 0;
+
+ if (type == void_type_node)
+ break;
+
+ ++argct;
+ switch (argct)
+ {
+ case 1:
+ if (TYPE_MAIN_VARIANT (type) != integer_type_node)
+ pedwarn_with_decl (decl1,
+ "first argument of `%s' should be `int'");
+ break;
+
+ case 2:
+ if (TREE_CODE (type) != POINTER_TYPE
+ || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
+ || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
+ != char_type_node))
+ pedwarn_with_decl (decl1,
+ "second argument of `%s' should be `char **'");
+ break;
+
+ case 3:
+ if (TREE_CODE (type) != POINTER_TYPE
+ || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
+ || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
+ != char_type_node))
+ pedwarn_with_decl (decl1,
+ "third argument of `%s' should probably be `char **'");
+ break;
+ }
+ }
+
+ /* It is intentional that this message does not mention the third
+ argument, which is warned for only pedantically, because it's
+ blessed by mention in an appendix of the standard. */
+ if (argct > 0 && (argct < 2 || argct > 3))
+ pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments");
+
+ if (argct == 3 && pedantic)
+ pedwarn_with_decl (decl1, "third argument of `%s' is deprecated");
+
+ if (! TREE_PUBLIC (decl1))
+ pedwarn_with_decl (decl1, "`%s' is normally a non-static function");
+ }
+
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
!= integer_type_node)
- pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
+ {
+ /* You would expect the sense of this test to be the other way
+ around, but if warn_main is set, we will already have warned,
+ so this would be a duplicate. This is the warning you get
+ in some environments even if you *don't* ask for it, because
+ these are environments where it may be more of a problem than
+ usual. */
+ if (! warn_main)
+ pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
+ }
else
{
#ifdef DEFAULT_MAIN_RETURN