/* Subroutines shared by all languages that are variants of C.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GCC.
#define PID_TYPE "int"
#endif
+#ifndef CHAR16_TYPE
+#define CHAR16_TYPE "short unsigned int"
+#endif
+
+#ifndef CHAR32_TYPE
+#define CHAR32_TYPE "unsigned int"
+#endif
+
#ifndef WCHAR_TYPE
#define WCHAR_TYPE "int"
#endif
tree signed_wchar_type_node;
tree unsigned_wchar_type_node;
+ tree char16_type_node;
+ tree char32_type_node;
+
tree float_type_node;
tree double_type_node;
tree long_double_type_node;
tree wchar_array_type_node;
+ Type `char16_t[SOMENUMBER]' or something like it.
+ Used when a UTF-16 string literal is created.
+
+ tree char16_array_type_node;
+
+ Type `char32_t[SOMENUMBER]' or something like it.
+ Used when a UTF-32 string literal is created.
+
+ tree char32_array_type_node;
+
Type `int ()' -- used for implicit declaration of functions.
tree default_function_type;
int flag_use_cxa_get_exception_ptr = 2;
-/* Nonzero means make the default pedwarns warnings instead of errors.
- The value of this flag is ignored if -pedantic is specified. */
-
-int flag_permissive;
-
/* Nonzero means to implement standard semantics for exception
specifications, calling unexpected if an exception is thrown that
doesn't match the specification. Zero means to treat them as
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_always_inline_attribute (tree *, tree, tree, int,
bool *);
-static tree handle_gnu_inline_attribute (tree *, tree, tree, int,
- bool *);
+static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
+static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
+static tree handle_error_attribute (tree *, tree, tree, int, bool *);
static tree handle_used_attribute (tree *, tree, tree, int, bool *);
static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
static tree handle_externally_visible_attribute (tree *, tree, tree, int,
handle_always_inline_attribute },
{ "gnu_inline", 0, 0, true, false, false,
handle_gnu_inline_attribute },
+ { "artificial", 0, 0, true, false, false,
+ handle_artificial_attribute },
{ "flatten", 0, 0, true, false, false,
handle_flatten_attribute },
{ "used", 0, 0, true, false, false,
handle_cold_attribute },
{ "hot", 0, 0, true, false, false,
handle_hot_attribute },
+ { "warning", 1, 1, true, false, false,
+ handle_error_attribute },
+ { "error", 1, 1, true, false, false,
+ handle_error_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
{
const char *name = "top level";
char *namep;
- int vrb = 2;
+ int vrb = 2, len;
+ cpp_string cstr = { 0, 0 }, strname;
if (!pretty_p)
{
if (current_function_decl)
name = lang_hooks.decl_printable_name (current_function_decl, vrb);
- if (c_lex_string_translate)
- {
- int len = strlen (name) + 3; /* Two for '"'s. One for NULL. */
- cpp_string cstr = { 0, 0 }, strname;
+ len = strlen (name) + 3; /* Two for '"'s. One for NULL. */
- namep = XNEWVEC (char, len);
- snprintf (namep, len, "\"%s\"", name);
- strname.text = (unsigned char *) namep;
- strname.len = len - 1;
+ namep = XNEWVEC (char, len);
+ snprintf (namep, len, "\"%s\"", name);
+ strname.text = (unsigned char *) namep;
+ strname.len = len - 1;
- if (cpp_interpret_string (parse_in, &strname, 1, &cstr, false))
- {
- XDELETEVEC (namep);
- return (const char *) cstr.text;
- }
+ if (cpp_interpret_string (parse_in, &strname, 1, &cstr, CPP_STRING))
+ {
+ XDELETEVEC (namep);
+ return (const char *) cstr.text;
}
- else
- namep = xstrdup (name);
return namep;
}
it from appearing in the RTL. */
tree stmts;
location_t saved_location = input_location;
-#ifdef USE_MAPPED_LOCATION
input_location = UNKNOWN_LOCATION;
-#else
- input_line = 0;
-#endif
stmts = push_stmt_list ();
decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
tree
fix_string_type (tree value)
{
- const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
- const int wide_flag = TREE_TYPE (value) == wchar_array_type_node;
int length = TREE_STRING_LENGTH (value);
int nchars;
tree e_type, i_type, a_type;
/* Compute the number of elements, for the array type. */
- nchars = wide_flag ? length / wchar_bytes : length;
+ if (TREE_TYPE (value) == char_array_type_node || !TREE_TYPE (value))
+ {
+ nchars = length;
+ e_type = char_type_node;
+ }
+ else if (TREE_TYPE (value) == char16_array_type_node)
+ {
+ nchars = length / (TYPE_PRECISION (char16_type_node) / BITS_PER_UNIT);
+ e_type = char16_type_node;
+ }
+ else if (TREE_TYPE (value) == char32_array_type_node)
+ {
+ nchars = length / (TYPE_PRECISION (char32_type_node) / BITS_PER_UNIT);
+ e_type = char32_type_node;
+ }
+ else
+ {
+ nchars = length / (TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT);
+ e_type = wchar_type_node;
+ }
/* C89 2.2.4.1, C99 5.2.4.1 (Translation limits). The analogous
limit in C++98 Annex B is very large (65536) and is not normative,
construct the matching unqualified array type first. The C front
end does not require this, but it does no harm, so we do it
unconditionally. */
- e_type = wide_flag ? wchar_type_node : char_type_node;
i_type = build_index_type (build_int_cst (NULL_TREE, nchars - 1));
a_type = build_array_type (e_type, i_type);
if (c_dialect_cxx() || warn_write_strings)
void
constant_expression_warning (tree value)
{
+ if (warn_overflow && pedantic
+ && (TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
+ || TREE_CODE (value) == FIXED_CST
+ || TREE_CODE (value) == VECTOR_CST
+ || TREE_CODE (value) == COMPLEX_CST)
+ && TREE_OVERFLOW (value))
+ pedwarn ("overflow in constant expression");
+}
+
+/* The same as above but print an unconditional error. */
+void
+constant_expression_error (tree value)
+{
if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
|| TREE_CODE (value) == FIXED_CST
|| TREE_CODE (value) == VECTOR_CST
|| TREE_CODE (value) == COMPLEX_CST)
- && TREE_OVERFLOW (value)
- && warn_overflow
- && pedantic)
- pedwarn ("overflow in constant expression");
+ && TREE_OVERFLOW (value))
+ error ("overflow in constant expression");
}
/* Print a warning if an expression had overflow in folding and its
return convertible_lax;
if (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
- && comptypes (TREE_TYPE (t1), TREE_TYPE (t2)))
+ && lang_hooks.types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
return true;
if (emit_lax_note && !emitted_lax_note)
else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
&& TREE_CODE (type) == INTEGER_TYPE)
{
+ /* Don't warn about unsigned char y = 0xff, x = (int) y; */
+ expr = get_unwidened (expr, 0);
+
/* Warn for integer types converted to smaller integer types. */
if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
give_warning = true;
&& DECL_NAME (list->expr))
{
warned_ids = new_tlist (warned_ids, written, NULL_TREE);
- warning (0, "operation on %qE may be undefined", list->expr);
+ warning (OPT_Wsequence_point, "operation on %qE may be undefined",
+ list->expr);
}
list = list->next;
}
bool both_p, bool fallback_p, bool nonansi_p,
tree fnattrs, bool implicit_p);
-/* Make a variant type in the proper way for C/C++, propagating qualifiers
- down to the element type of an array. */
-
-tree
-c_build_qualified_type (tree type, int type_quals)
-{
- if (type == error_mark_node)
- return type;
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree t;
- tree element_type = c_build_qualified_type (TREE_TYPE (type),
- type_quals);
-
- /* See if we already have an identically qualified type. */
- for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- {
- if (TYPE_QUALS (strip_array_types (t)) == type_quals
- && TYPE_NAME (t) == TYPE_NAME (type)
- && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
- && attribute_list_equal (TYPE_ATTRIBUTES (t),
- TYPE_ATTRIBUTES (type)))
- break;
- }
- if (!t)
- {
- tree domain = TYPE_DOMAIN (type);
-
- t = build_variant_type_copy (type);
- TREE_TYPE (t) = element_type;
-
- if (TYPE_STRUCTURAL_EQUALITY_P (element_type)
- || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain)))
- SET_TYPE_STRUCTURAL_EQUALITY (t);
- else if (TYPE_CANONICAL (element_type) != element_type
- || (domain && TYPE_CANONICAL (domain) != domain))
- {
- tree unqualified_canon
- = build_array_type (TYPE_CANONICAL (element_type),
- domain? TYPE_CANONICAL (domain)
- : NULL_TREE);
- TYPE_CANONICAL (t)
- = c_build_qualified_type (unqualified_canon, type_quals);
- }
- else
- TYPE_CANONICAL (t) = t;
- }
- return t;
- }
-
- /* A restrict-qualified pointer type must be a pointer to object or
- incomplete type. Note that the use of POINTER_TYPE_P also allows
- REFERENCE_TYPEs, which is appropriate for C++. */
- if ((type_quals & TYPE_QUAL_RESTRICT)
- && (!POINTER_TYPE_P (type)
- || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
- {
- error ("invalid use of %<restrict%>");
- type_quals &= ~TYPE_QUAL_RESTRICT;
- }
-
- return build_qualified_type (type, type_quals);
-}
/* Apply the TYPE_QUALS to the new DECL. */
}
for (; t2; t2 = TREE_CHAIN (t2))
i++;
- size = TREE_INT_CST_LOW (TYPE_SIZE (t));
+ /* We might have a VLA here. */
+ if (TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
+ size = 0;
+ else
+ size = TREE_INT_CST_LOW (TYPE_SIZE (t));
return ((size << 24) | (i << shift));
}
{
if (complain && (pedantic || warn_pointer_arith))
pedwarn ("invalid application of %<sizeof%> to a function type");
+ else if (!complain)
+ return error_mark_node;
value = size_one_node;
}
else
if (type_code == VOID_TYPE
&& complain && (pedantic || warn_pointer_arith))
pedwarn ("invalid application of %qs to a void type", op_name);
+ else if (!complain)
+ return error_mark_node;
value = size_one_node;
}
else if (!COMPLETE_TYPE_P (type))
void
c_common_nodes_and_builtins (void)
{
+ int char16_type_size;
+ int char32_type_size;
int wchar_type_size;
tree array_domain_type;
tree va_list_ref_type_node;
wchar_array_type_node
= build_array_type (wchar_type_node, array_domain_type);
+ /* Define 'char16_t'. */
+ char16_type_node = get_identifier (CHAR16_TYPE);
+ char16_type_node = TREE_TYPE (identifier_global_value (char16_type_node));
+ char16_type_size = TYPE_PRECISION (char16_type_node);
+ if (c_dialect_cxx ())
+ {
+ char16_type_node = make_unsigned_type (char16_type_size);
+
+ if (cxx_dialect == cxx0x)
+ record_builtin_type (RID_CHAR16, "char16_t", char16_type_node);
+ }
+
+ /* This is for UTF-16 string constants. */
+ char16_array_type_node
+ = build_array_type (char16_type_node, array_domain_type);
+
+ /* Define 'char32_t'. */
+ char32_type_node = get_identifier (CHAR32_TYPE);
+ char32_type_node = TREE_TYPE (identifier_global_value (char32_type_node));
+ char32_type_size = TYPE_PRECISION (char32_type_node);
+ if (c_dialect_cxx ())
+ {
+ char32_type_node = make_unsigned_type (char32_type_size);
+
+ if (cxx_dialect == cxx0x)
+ record_builtin_type (RID_CHAR32, "char32_t", char32_type_node);
+ }
+
+ /* This is for UTF-32 string constants. */
+ char32_array_type_node
+ = build_array_type (char32_type_node, array_domain_type);
+
wint_type_node =
TREE_TYPE (identifier_global_value (get_identifier (WINT_TYPE)));
return type;
}
-const_tree
-const_strip_array_types (const_tree type)
-{
- while (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
-
- return type;
-}
-
/* Recursively remove any '*' or '&' operator from TYPE. */
tree
strip_pointer_operator (tree t)
-TREE_INT_CST_LOW (key));
else
snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_DOUBLE_HEX,
- TREE_INT_CST_HIGH (key), TREE_INT_CST_LOW (key));
+ (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (key),
+ (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (key));
if (TYPE_NAME (type) == 0)
- warning (0, "%Jcase value %qs not in enumerated type",
+ warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
+ "%Jcase value %qs not in enumerated type",
CASE_LABEL (label), buf);
else
- warning (0, "%Jcase value %qs not in enumerated type %qT",
+ warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
+ "%Jcase value %qs not in enumerated type %qT",
CASE_LABEL (label), buf, type);
}
splay_tree_node default_node;
splay_tree_node node;
tree chain;
+ int saved_warn_switch;
if (!warn_switch && !warn_switch_enum && !warn_switch_default)
return;
if (cond && tree_int_cst_compare (cond, value))
continue;
- warning (0, "%Henumeration value %qE not handled in switch",
+ /* If there is a default_node, the only relevant option is
+ Wswitch-enum. Otherwise, if both are enabled then we prefer
+ to warn using -Wswitch because -Wswitch is enabled by -Wall
+ while -Wswitch-enum is explicit. */
+ warning ((default_node || !warn_switch)
+ ? OPT_Wswitch_enum : OPT_Wswitch,
+ "%Henumeration value %qE not handled in switch",
&switch_location, TREE_PURPOSE (chain));
}
we should have marked both the lower bound and upper bound of
every disjoint case label, with CASE_LOW_SEEN and CASE_HIGH_SEEN
above. This scan also resets those fields. */
+
+ /* If there is a default_node, the only relevant option is
+ Wswitch-enum. Otherwise, if both are enabled then we prefer
+ to warn using -Wswitch because -Wswitch is enabled by -Wall
+ while -Wswitch-enum is explicit. */
+ saved_warn_switch = warn_switch;
+ if (default_node)
+ warn_switch = 0;
splay_tree_foreach (cases, match_case_to_enum, type);
+ warn_switch = saved_warn_switch;
+
}
/* Finish an expression taking the address of LABEL (an
}
}
-
-/* Generate the RTL for the body of FNDECL. */
-
-void
-c_expand_body (tree fndecl)
-{
- tree_rest_of_compilation (fndecl);
-}
-
/* Hook used by staticp to handle language-specific tree codes. */
tree
return NULL_TREE;
}
+/* Handle an "artificial" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_artificial_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
+ {
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "flatten" attribute; arguments as in
struct attribute_spec.handler. */
return NULL_TREE;
}
+/* Handle a "warning" or "error" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_error_attribute (tree *node, tree name, tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL
+ || TREE_CODE (TREE_VALUE (args)) == STRING_CST)
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ ;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
/* Handle a "used" attribute; arguments as in
struct attribute_spec.handler. */
tree ARG_UNUSED (args), int flags,
bool *no_add_attrs)
{
- tree type = NULL;
+ tree type;
*no_add_attrs = true;
- if (DECL_P (*node))
- {
- if (TREE_CODE (*node) != TYPE_DECL)
- goto ignored;
- node = &TREE_TYPE (*node);
- type = *node;
- }
- else if (TYPE_P (*node))
- type = *node;
- else
- goto ignored;
+ if (TREE_CODE (*node) == TYPE_DECL)
+ node = &TREE_TYPE (*node);
+ type = *node;
if (TREE_CODE (type) == UNION_TYPE)
{
bool * ARG_UNUSED (no_add_attrs))
{
if (TREE_CODE (*node) == FUNCTION_DECL
- || TREE_CODE (*node) == VAR_DECL)
+ && DECL_DECLARED_INLINE_P (*node))
+ {
+ error ("inline function %q+D cannot be declared weak", *node);
+ *no_add_attrs = true;
+ }
+ else if (TREE_CODE (*node) == FUNCTION_DECL
+ || TREE_CODE (*node) == VAR_DECL)
declare_weak (*node);
else
warning (OPT_Wattributes, "%qE attribute ignored", name);
-
return NULL_TREE;
}
while (POINTER_TYPE_P (type)
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE
- || TREE_CODE (type) == ARRAY_TYPE)
+ || TREE_CODE (type) == ARRAY_TYPE
+ || TREE_CODE (type) == OFFSET_TYPE)
type = TREE_TYPE (type);
/* Get the mode of the type being modified. */
orig_mode = TYPE_MODE (type);
- if (TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE
- || TREE_CODE (type) == VECTOR_TYPE
+ if ((!INTEGRAL_TYPE_P (type)
+ && !SCALAR_FLOAT_TYPE_P (type)
+ && !FIXED_POINT_TYPE_P (type))
|| (!SCALAR_FLOAT_MODE_P (orig_mode)
&& GET_MODE_CLASS (orig_mode) != MODE_INT
&& !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
if (token == CPP_EOF)
message = catenate_messages (gmsgid, " at end of input");
- else if (token == CPP_CHAR || token == CPP_WCHAR)
+ else if (token == CPP_CHAR || token == CPP_WCHAR || token == CPP_CHAR16
+ || token == CPP_CHAR32)
{
unsigned int val = TREE_INT_CST_LOW (value);
- const char *const ell = (token == CPP_CHAR) ? "" : "L";
+ const char *prefix;
+
+ switch (token)
+ {
+ default:
+ prefix = "";
+ break;
+ case CPP_WCHAR:
+ prefix = "L";
+ break;
+ case CPP_CHAR16:
+ prefix = "u";
+ break;
+ case CPP_CHAR32:
+ prefix = "U";
+ break;
+ }
+
if (val <= UCHAR_MAX && ISGRAPH (val))
message = catenate_messages (gmsgid, " before %s'%c'");
else
message = catenate_messages (gmsgid, " before %s'\\x%x'");
- error (message, ell, val);
+ error (message, prefix, val);
free (message);
message = NULL;
}
- else if (token == CPP_STRING || token == CPP_WSTRING)
+ else if (token == CPP_STRING || token == CPP_WSTRING || token == CPP_STRING16
+ || token == CPP_STRING32)
message = catenate_messages (gmsgid, " before string constant");
else if (token == CPP_NUMBER)
message = catenate_messages (gmsgid, " before numeric constant");
hashcode);
main_type = type_hash_canon (hashcode, main_type);
+ /* Fix the canonical type. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
+ || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
+ SET_TYPE_STRUCTURAL_EQUALITY (main_type);
+ else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
+ || (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
+ != TYPE_DOMAIN (main_type)))
+ TYPE_CANONICAL (main_type)
+ = build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
+ TYPE_CANONICAL (TYPE_DOMAIN (main_type)));
+ else
+ TYPE_CANONICAL (main_type) = main_type;
+
if (quals == 0)
type = main_type;
else
type = c_build_qualified_type (main_type, quals);
+ if (COMPLETE_TYPE_P (type)
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
+ && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
+ {
+ error ("size of array is too large");
+ /* If we proceed with the array type as it is, we'll eventually
+ crash in tree_low_cst(). */
+ type = error_mark_node;
+ }
+
*ptype = type;
return failure;
}