GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Process declarations and symbol lookup for C front end.
Also constructs types; the standard scalar types at initialization,
static tree c_make_fname_decl (tree, int);
static tree grokdeclarator (const struct c_declarator *,
struct c_declspecs *,
- enum decl_context, bool, tree *,
+ enum decl_context, bool, tree *, tree *,
enum deprecated_states);
static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
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);
- }
+ if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
+ {
+ DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+ DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
+ }
}
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+
+ DECL_DISREGARD_INLINE_LIMITS (newdecl)
+ = DECL_DISREGARD_INLINE_LIMITS (olddecl)
+ = (DECL_DISREGARD_INLINE_LIMITS (newdecl)
+ || DECL_DISREGARD_INLINE_LIMITS (olddecl));
}
if (DECL_BUILT_IN (olddecl))
if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
{
- /* Avoid `unused variable' and other warnings warnings for OLDDECL. */
+ /* Avoid `unused variable' and other warnings for OLDDECL. */
TREE_NO_WARNING (olddecl) = 1;
return false;
}
Obviously, we don't want to generate a duplicate ..._TYPE node if
the TYPE_DECL node that we are now processing really represents a
- standard built-in type.
-
- Since all standard types are effectively declared at line zero
- in the source file, we can easily check to see if we are working
- on a standard type by checking the current value of lineno. */
+ standard built-in type. */
static void
clone_underlying_type (tree x)
struct c_binding *b;
bool nested = false;
- /* Functions need the lang_decl data. */
- if (TREE_CODE (x) == FUNCTION_DECL && !DECL_LANG_SPECIFIC (x))
- DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl);
-
/* Must set DECL_CONTEXT for everything not at file scope or
DECL_FILE_SCOPE_P won't work. Local externs don't count
unless they have initializers (which generate code). */
DECL_ARTIFICIAL (decl) = 1;
init = build_string (length + 1, name);
- free ((char *) name);
+ free (CONST_CAST (char *, name));
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
tree id = DECL_NAME (decl);
const char *name = IDENTIFIER_POINTER (id);
- DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
/* Should never be called on a symbol with a preexisting meaning. */
type_name->specs->attrs = NULL_TREE;
type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
- false, NULL, DEPRECATED_NORMAL);
+ false, NULL, &attrs, DEPRECATED_NORMAL);
/* Apply attributes. */
decl_attributes (&type, attrs, 0);
deprecated_state = DEPRECATED_SUPPRESS;
decl = grokdeclarator (declarator, declspecs,
- NORMAL, initialized, NULL,
+ NORMAL, initialized, NULL, &attributes,
deprecated_state);
if (!decl)
return 0;
tree
grokparm (const struct c_parm *parm)
{
+ tree attrs = parm->attrs;
tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
- NULL, DEPRECATED_NORMAL);
+ NULL, &attrs, DEPRECATED_NORMAL);
- decl_attributes (&decl, parm->attrs, 0);
+ decl_attributes (&decl, attrs, 0);
return decl;
}
void
push_parm_decl (const struct c_parm *parm)
{
+ tree attrs = parm->attrs;
tree decl;
decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
- DEPRECATED_NORMAL);
- decl_attributes (&decl, parm->attrs, 0);
+ &attrs, DEPRECATED_NORMAL);
+ decl_attributes (&decl, attrs, 0);
decl = pushdecl (decl);
&& type_mv != boolean_type_node)
pedwarn ("type of bit-field %qs is a GCC extension", name);
- if (type_mv == boolean_type_node)
- max_width = CHAR_TYPE_SIZE;
- else
- max_width = TYPE_PRECISION (*type);
+ max_width = TYPE_PRECISION (*type);
if (0 < compare_tree_int (*width, max_width))
{
INITIALIZED is true if the decl has an initializer.
WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
representing the width of the bit-field.
+ DECL_ATTRS points to the list of attributes that should be added to this
+ decl. Any nested attributes that belong on the decl itself will be
+ added to this list.
DEPRECATED_STATE is a deprecated_states value indicating whether
deprecation warnings should be suppressed.
grokdeclarator (const struct c_declarator *declarator,
struct c_declspecs *declspecs,
enum decl_context decl_context, bool initialized, tree *width,
- enum deprecated_states deprecated_state)
+ tree *decl_attrs, enum deprecated_states deprecated_state)
{
tree type = declspecs->type;
bool threadp = declspecs->thread_p;
"signed". */
if (bitfield && !flag_signed_bitfields && !declspecs->explicit_signed_p
&& TREE_CODE (type) == INTEGER_TYPE)
- type = unsigned_type_for (type);
+ type = c_common_unsigned_type (type);
/* Figure out the type qualifiers for the declaration. There are
two ways a declaration can become qualified. One is something
gcc_unreachable ();
}
}
+ *decl_attrs = chainon (returned_attrs, *decl_attrs);
/* Now TYPE has the actual type, apart from any qualifiers in
TYPE_QUALS. */
decl = build_decl (TYPE_DECL, declarator->u.id, type);
if (declspecs->explicit_signed_p)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
- decl_attributes (&decl, returned_attrs, 0);
if (declspecs->inline_p)
pedwarn ("typedef %q+D declared %<inline%>", decl);
return decl;
pedwarn ("ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- decl_attributes (&type, returned_attrs, 0);
return type;
}
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
type_quals = array_ptr_quals;
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
/* We don't yet implement attributes in this context. */
if (array_ptr_attrs != NULL_TREE)
decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
decl = build_decl_attribute_variant (decl, decl_attr);
- DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
-
if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
name of a variable. Thus, if it's known before this, die horribly. */
gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
- decl_attributes (&decl, returned_attrs, 0);
-
return decl;
}
}
/* Process the specs, declarator and width (NULL if omitted)
of a structure component, returning a FIELD_DECL node.
WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
+ DECL_ATTRS is as for grokdeclarator.
This is done during the parsing of the struct declaration.
The FIELD_DECL nodes are chained together and the lot of them
tree
grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs,
- tree width)
+ tree width, tree *decl_attrs)
{
tree value;
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
- width ? &width : NULL, DEPRECATED_NORMAL);
+ width ? &width : NULL, decl_attrs,
+ DEPRECATED_NORMAL);
finish_decl (value, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
c_break_label = c_cont_label = size_zero_node;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
- DEPRECATED_NORMAL);
+ &attributes, DEPRECATED_NORMAL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
declare_parm_level ();
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
- /* Promote the value to int before returning it. */
- if (c_promoting_integer_type_p (restype))
- {
- /* It retains unsignedness if not really getting wider. */
- if (TYPE_UNSIGNED (restype)
- && (TYPE_PRECISION (restype)
- == TYPE_PRECISION (integer_type_node)))
- restype = unsigned_type_node;
- else
- restype = integer_type_node;
- }
-
resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
DECL_ARTIFICIAL (resdecl) = 1;
DECL_IGNORED_P (resdecl) = 1;
/* Finalize the ELF visibility for the function. */
c_determine_visibility (fndecl);
+ /* For GNU C extern inline functions disregard inline limits. */
+ if (DECL_EXTERNAL (fndecl)
+ && DECL_DECLARED_INLINE_P (fndecl))
+ DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
+
/* Genericize before inlining. Delay genericizing nested functions
until their parent function is genericized. Since finalizing
requires GENERIC, delay that as well. */
This should be cleaned up later and this conditional removed. */
if (cgraph_global_info_ready)
{
- c_expand_body (fndecl);
+ cgraph_add_new_function (fndecl, false);
return;
}
/* We're leaving the context of this function, so zap cfun.
It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
tree_rest_of_compilation. */
- cfun = NULL;
+ set_cfun (NULL);
current_function_decl = NULL;
}
\f
C. */
int
-anon_aggr_type_p (tree ARG_UNUSED (node))
+anon_aggr_type_p (const_tree ARG_UNUSED (node))
{
return 0;
}
ret->const_p = false;
ret->volatile_p = false;
ret->restrict_p = false;
+ ret->saturating_p = false;
return ret;
}
}
if ((int) i <= (int) RID_LAST_MODIFIER)
{
- /* "long", "short", "signed", "unsigned" or "_Complex". */
+ /* "long", "short", "signed", "unsigned", "_Complex" or "_Sat". */
bool dupe = false;
switch (i)
{
else if (specs->typespec_word == cts_dfloat128)
error ("both %<complex%> and %<_Decimal128%> in "
"declaration specifiers");
+ else if (specs->typespec_word == cts_fract)
+ error ("both %<complex%> and %<_Fract%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_accum)
+ error ("both %<complex%> and %<_Accum%> in "
+ "declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<complex%> and %<_Sat%> in "
+ "declaration specifiers");
else
specs->complex_p = true;
break;
+ case RID_SAT:
+ dupe = specs->saturating_p;
+ if (pedantic)
+ pedwarn ("ISO C does not support saturating types");
+ if (specs->typespec_word == cts_void)
+ error ("both %<_Sat%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_char)
+ error ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_int)
+ error ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat32)
+ error ("both %<_Sat%> and %<_Decimal32%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat64)
+ error ("both %<_Sat%> and %<_Decimal64%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat128)
+ error ("both %<_Sat%> and %<_Decimal128%> in "
+ "declaration specifiers");
+ else if (specs->complex_p)
+ error ("both %<_Sat%> and %<complex%> in "
+ "declaration specifiers");
+ else
+ specs->saturating_p = true;
+ break;
default:
gcc_unreachable ();
}
}
else
{
- /* "void", "_Bool", "char", "int", "float" or "double". */
+ /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
+ "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
if (specs->typespec_word != cts_none)
{
error ("two or more data types in declaration specifiers");
else if (specs->complex_p)
error ("both %<complex%> and %<void%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<void%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_void;
return specs;
else if (specs->complex_p)
error ("both %<complex%> and %<_Bool%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_bool;
return specs;
else if (specs->short_p)
error ("both %<short%> and %<char%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_char;
return specs;
case RID_INT:
- specs->typespec_word = cts_int;
+ if (specs->saturating_p)
+ error ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_int;
return specs;
case RID_FLOAT:
if (specs->long_p)
else if (specs->unsigned_p)
error ("both %<unsigned%> and %<float%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_float;
return specs;
else if (specs->unsigned_p)
error ("both %<unsigned%> and %<double%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_double;
return specs;
else if (specs->complex_p)
error ("both %<complex%> and %<%s%> in "
"declaration specifiers", str);
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<%s%> in "
+ "declaration specifiers", str);
else if (i == RID_DFLOAT32)
specs->typespec_word = cts_dfloat32;
else if (i == RID_DFLOAT64)
if (pedantic)
pedwarn ("ISO C does not support decimal floating point");
return specs;
+ case RID_FRACT:
+ case RID_ACCUM:
+ {
+ const char *str;
+ if (i == RID_FRACT)
+ str = "_Fract";
+ else
+ str = "_Accum";
+ if (specs->complex_p)
+ error ("both %<complex%> and %<%s%> in "
+ "declaration specifiers", str);
+ else if (i == RID_FRACT)
+ specs->typespec_word = cts_fract;
+ else
+ specs->typespec_word = cts_accum;
+ }
+ if (!targetm.fixed_point_supported_p ())
+ error ("fixed-point types not supported for this target");
+ if (pedantic)
+ pedwarn ("ISO C does not support fixed-point types");
+ return specs;
default:
/* ObjC reserved word "id", handled below. */
break;
"_Complex short" is equivalent to "_Complex short int". */
if (specs->typespec_word == cts_none)
{
- if (specs->long_p || specs->short_p
- || specs->signed_p || specs->unsigned_p)
+ if (specs->saturating_p)
+ {
+ error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+ specs->typespec_word = cts_fract;
+ }
+ else if (specs->long_p || specs->short_p
+ || specs->signed_p || specs->unsigned_p)
{
specs->typespec_word = cts_int;
}
else
specs->type = dfloat128_type_node;
break;
+ case cts_fract:
+ gcc_assert (!specs->complex_p);
+ if (specs->saturating_p)
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_long_fract_type_node
+ : sat_long_long_fract_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_fract_type_node
+ : sat_long_fract_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_short_fract_type_node
+ : sat_short_fract_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_fract_type_node
+ : sat_fract_type_node;
+ }
+ else
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_long_fract_type_node
+ : long_long_fract_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_fract_type_node
+ : long_fract_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_short_fract_type_node
+ : short_fract_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? unsigned_fract_type_node
+ : fract_type_node;
+ }
+ break;
+ case cts_accum:
+ gcc_assert (!specs->complex_p);
+ if (specs->saturating_p)
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_long_accum_type_node
+ : sat_long_long_accum_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_accum_type_node
+ : sat_long_accum_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_short_accum_type_node
+ : sat_short_accum_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_accum_type_node
+ : sat_accum_type_node;
+ }
+ else
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_long_accum_type_node
+ : long_long_accum_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_accum_type_node
+ : long_accum_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_short_accum_type_node
+ : short_accum_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? unsigned_accum_type_node
+ : accum_type_node;
+ }
+ break;
default:
gcc_unreachable ();
}