/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#include "intl.h"
#include "tree.h"
#include "tree-inline.h"
-#include "rtl.h"
#include "flags.h"
#include "function.h"
#include "output.h"
-#include "expr.h"
#include "c-tree.h"
#include "toplev.h"
-#include "ggc.h"
#include "tm_p.h"
#include "cpplib.h"
#include "target.h"
#include "debug.h"
#include "opts.h"
#include "timevar.h"
-#include "c-common.h"
-#include "c-pragma.h"
+#include "c-family/c-common.h"
+#include "c-family/c-pragma.h"
+#include "c-lang.h"
#include "langhooks.h"
#include "tree-mudflap.h"
-#include "gimple.h"
#include "tree-iterator.h"
-#include "diagnostic.h"
+#include "diagnostic-core.h"
#include "tree-dump.h"
#include "cgraph.h"
#include "hashtab.h"
-#include "libfuncs.h"
-#include "except.h"
#include "langhooks-def.h"
#include "pointer-set.h"
-#include "gimple.h"
#include "plugin.h"
+#include "c-family/c-ada-spec.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
/* File and line to appear in the eventual error message. */
location_t pending_invalid_xref_location;
-/* True means we've initialized exception handling. */
-bool c_eh_initialized_p;
-
/* The file and line that the prototype came from if this is an
old-style definition; used for diagnostics in
store_parm_decls_oldstyle. */
tree c_break_label;
tree c_cont_label;
-/* True if we are currently parsing the fields of a struct or
- union. */
-
-static bool in_struct;
-
-/* A list of types defined in the current struct or union. */
-
-static VEC(tree,heap) *struct_types;
-
/* Linked list of TRANSLATION_UNIT_DECLS for the translation units
included in this invocation. Note that the current translation
unit is not included in this list. */
BOOL_BITFIELD invisible : 1; /* normal lookup should ignore this binding */
BOOL_BITFIELD nested : 1; /* do not set DECL_CONTEXT when popping */
BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
- /* one free bit */
+ BOOL_BITFIELD in_struct : 1; /* currently defined as struct field */
location_t locus; /* location for nested bindings */
};
#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
static bool next_is_function_body;
+/* A VEC of pointers to c_binding structures. */
+
+typedef struct c_binding *c_binding_ptr;
+DEF_VEC_P(c_binding_ptr);
+DEF_VEC_ALLOC_P(c_binding_ptr,heap);
+
+/* Information that we keep for a struct or union while it is being
+ parsed. */
+
+struct c_struct_parse_info
+{
+ /* If warn_cxx_compat, a list of types defined within this
+ struct. */
+ VEC(tree,heap) *struct_types;
+ /* If warn_cxx_compat, a list of field names which have bindings,
+ and which are defined in this struct, but which are not defined
+ in any enclosing struct. This is used to clear the in_struct
+ field of the c_bindings structure. */
+ VEC(c_binding_ptr,heap) *fields;
+ /* If warn_cxx_compat, a list of typedef names used when defining
+ fields in this struct. */
+ VEC(tree,heap) *typedefs_seen;
+};
+
+/* Information for the struct or union currently being parsed, or
+ NULL if not parsing a struct or union. */
+static struct c_struct_parse_info *struct_parse_info;
+
/* Forward declarations. */
static tree lookup_name_in_scope (tree, struct c_scope *);
static tree c_make_fname_decl (location_t, tree, int);
{
tree rid = ridpointers[C_RID_CODE (node)];
indent_to (file, indent + 4);
- fprintf (file, "rid %p \"%s\"",
+ fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
(void *) rid, IDENTIFIER_POINTER (rid));
}
}
binding_freelist = b->prev;
}
else
- b = GGC_NEW (struct c_binding);
+ b = ggc_alloc_c_binding ();
b->shadowed = 0;
b->decl = decl;
b->invisible = invisible;
b->nested = nested;
b->inner_comp = 0;
+ b->in_struct = 0;
b->locus = locus;
b->u.type = NULL;
record_inline_static (location_t loc, tree func, tree decl,
enum c_inline_static_type type)
{
- struct c_inline_static *csi = GGC_NEW (struct c_inline_static);
+ struct c_inline_static *csi = ggc_alloc_c_inline_static ();
csi->location = loc;
csi->function = func;
csi->static_decl = decl;
scope_freelist = scope->outer;
}
else
- scope = GGC_CNEW (struct c_scope);
+ scope = ggc_alloc_cleared_c_scope ();
/* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes. */
if (current_scope)
/* Update the bindings of any goto statements associated
with this label. */
- for (ix = 0;
- VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
- ++ix)
+ FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
update_spot_bindings (scope, &g->goto_bindings);
}
}
{
tree file_decl = build_decl (UNKNOWN_LOCATION,
TRANSLATION_UNIT_DECL, 0, 0);
- TREE_CHAIN (file_decl) = all_translation_units;
+ DECL_CHAIN (file_decl) = all_translation_units;
all_translation_units = file_decl;
context = file_decl;
}
error ("label %q+D used but not defined", p);
DECL_INITIAL (p) = error_mark_node;
}
- else
+ else
warn_for_unused_label (p);
/* Labels go in BLOCK_VARS. */
- TREE_CHAIN (p) = BLOCK_VARS (block);
+ DECL_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
gcc_assert (I_LABEL_BINDING (b->id) == b);
I_LABEL_BINDING (b->id) = b->shadowed;
case VAR_DECL:
/* Warnings for unused variables. */
- if (!TREE_USED (p)
+ if ((!TREE_USED (p) || !DECL_READ_P (p))
&& !TREE_NO_WARNING (p)
&& !DECL_IN_SYSTEM_HEADER (p)
&& DECL_NAME (p)
&& !DECL_ARTIFICIAL (p)
&& scope != file_scope
&& scope != external_scope)
- warning (OPT_Wunused_variable, "unused variable %q+D", p);
+ {
+ if (!TREE_USED (p))
+ warning (OPT_Wunused_variable, "unused variable %q+D", p);
+ else if (DECL_CONTEXT (p) == current_function_decl)
+ warning_at (DECL_SOURCE_LOCATION (p),
+ OPT_Wunused_but_set_variable,
+ "variable %qD set but not used", p);
+ }
if (b->inner_comp)
{
binding in the home scope. */
if (!b->nested)
{
- TREE_CHAIN (p) = BLOCK_VARS (block);
+ DECL_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
}
else if (VAR_OR_FUNCTION_DECL_P (p))
}
if (b->locus != UNKNOWN_LOCATION)
DECL_SOURCE_LOCATION (extp) = b->locus;
- TREE_CHAIN (extp) = BLOCK_VARS (block);
+ DECL_CHAIN (extp) = BLOCK_VARS (block);
BLOCK_VARS (block) = extp;
}
/* If this is the file scope, and we are processing more
start_fname_decls ();
- for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
+ for (decl = visible_builtins; decl; decl = DECL_CHAIN (decl))
bind (DECL_NAME (decl), decl, file_scope,
/*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl));
}
file_scope = 0;
maybe_apply_pending_pragma_weaks ();
- cgraph_finalize_compilation_unit ();
}
\f
/* Adjust the bindings for the start of a statement expression. */
continue;
label_vars = b->u.label;
++label_vars->label_bindings.stmt_exprs;
- for (ix = 0;
- VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
- ++ix)
+ FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
++g->goto_bindings.stmt_exprs;
}
}
label_vars->label_bindings.left_stmt_expr = true;
label_vars->label_bindings.stmt_exprs = 0;
}
- for (ix = 0;
- VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
- ++ix)
+ FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
{
--g->goto_bindings.stmt_exprs;
if (g->goto_bindings.stmt_exprs < 0)
}
else
{
- if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
- error ("conflicting type qualifiers for %q+D", newdecl);
+ int new_quals = TYPE_QUALS (newtype);
+ int old_quals = TYPE_QUALS (oldtype);
+
+ if (new_quals != old_quals)
+ {
+ addr_space_t new_addr = DECODE_QUAL_ADDR_SPACE (new_quals);
+ addr_space_t old_addr = DECODE_QUAL_ADDR_SPACE (old_quals);
+ if (new_addr != old_addr)
+ {
+ if (ADDR_SPACE_GENERIC_P (new_addr))
+ error ("conflicting named address spaces (generic vs %s) "
+ "for %q+D",
+ c_addr_space_name (old_addr), newdecl);
+ else if (ADDR_SPACE_GENERIC_P (old_addr))
+ error ("conflicting named address spaces (%s vs generic) "
+ "for %q+D",
+ c_addr_space_name (new_addr), newdecl);
+ else
+ error ("conflicting named address spaces (%s vs %s) "
+ "for %q+D",
+ c_addr_space_name (new_addr),
+ c_addr_space_name (old_addr),
+ newdecl);
+ }
+
+ if (CLEAR_QUAL_ADDR_SPACE (new_quals)
+ != CLEAR_QUAL_ADDR_SPACE (old_quals))
+ error ("conflicting type qualifiers for %q+D", newdecl);
+ }
else
error ("conflicting types for %q+D", newdecl);
diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
/* Redeclaration of a type is a constraint violation (6.7.2.3p1),
but silently ignore the redeclaration if either is in a system
- header. (Conflicting redeclarations were handled above.) */
+ header. (Conflicting redeclarations were handled above.) This
+ is allowed for C1X if the types are the same, not just
+ compatible. */
if (TREE_CODE (newdecl) == TYPE_DECL)
{
+ bool types_different = false;
+ int comptypes_result;
+
+ comptypes_result
+ = comptypes_check_different_types (oldtype, newtype, &types_different);
+
+ if (comptypes_result != 1 || types_different)
+ {
+ error ("redefinition of typedef %q+D with different type", newdecl);
+ locate_old_decl (olddecl);
+ return false;
+ }
+
if (DECL_IN_SYSTEM_HEADER (newdecl)
|| DECL_IN_SYSTEM_HEADER (olddecl)
|| TREE_NO_WARNING (newdecl)
|| TREE_NO_WARNING (olddecl))
return true; /* Allow OLDDECL to continue in use. */
- error ("redefinition of typedef %q+D", newdecl);
- locate_old_decl (olddecl);
- return false;
+ if (pedantic && !flag_isoc1x)
+ {
+ pedwarn (input_location, OPT_pedantic,
+ "redefinition of typedef %q+D", newdecl);
+ locate_old_decl (olddecl);
+ }
+ else if (variably_modified_type_p (newtype, NULL))
+ {
+ /* Whether there is a constraint violation for the types not
+ being the same cannot be determined at compile time; a
+ warning that there may be one at runtime is considered
+ appropriate (WG14 reflector message 11743, 8 May 2009). */
+ warning (0, "redefinition of typedef %q+D may be a constraint "
+ "violation at runtime", newdecl);
+ locate_old_decl (olddecl);
+ }
+
+ return true;
}
/* Function declarations can either be 'static' or 'extern' (no
}
else if (warn_traditional)
{
- warned |= warning (OPT_Wtraditional,
+ warned |= warning (OPT_Wtraditional,
"non-static declaration of %q+D "
"follows static declaration", newdecl);
}
DECL_ATTRIBUTES (olddecl)) != NULL;
if (newa != olda)
{
- error ("%<gnu_inline%> attribute present on %q+D",
- newa ? newdecl : olddecl);
- error ("%Jbut not here", newa ? olddecl : newdecl);
+ error_at (input_location, "%<gnu_inline%> attribute present on %q+D",
+ newa ? newdecl : olddecl);
+ error_at (DECL_SOURCE_LOCATION (newa ? olddecl : newdecl),
+ "but not here");
}
}
}
}
else if (warn_traditional)
{
- warned |= warning (OPT_Wtraditional,
+ warned |= warning (OPT_Wtraditional,
"non-static declaration of %q+D "
"follows static declaration", newdecl);
}
return false;
}
+
+ /* C++ does not permit a decl to appear multiple times at file
+ scope. */
+ if (warn_cxx_compat
+ && DECL_FILE_SCOPE_P (newdecl)
+ && !DECL_EXTERNAL (newdecl)
+ && !DECL_EXTERNAL (olddecl))
+ warned |= warning_at (DECL_SOURCE_LOCATION (newdecl),
+ OPT_Wc___compat,
+ ("duplicate declaration of %qD is "
+ "invalid in C++"),
+ newdecl);
}
/* warnings */
if (DECL_DECLARED_INLINE_P (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warned |= warning (OPT_Wattributes,
+ warned |= warning (OPT_Wattributes,
"inline declaration of %qD follows "
"declaration with attribute noinline", newdecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
- warned |= warning (OPT_Wattributes,
+ warned |= warning (OPT_Wattributes,
"declaration of %q+D with attribute "
"noinline follows inline declaration ", newdecl);
}
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
- gimple_set_body (newdecl, gimple_body (olddecl));
DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl));
- for (t = DECL_ARGUMENTS (newdecl); t ; t = TREE_CHAIN (t))
+ for (t = DECL_ARGUMENTS (newdecl); t ; t = DECL_CHAIN (t))
DECL_CONTEXT (t) = newdecl;
/* See if we've got a function to instantiate from. */
}
}
- extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
+ extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
- /* Merge the USED information. */
- if (TREE_USED (olddecl))
- TREE_USED (newdecl) = 1;
- else if (TREE_USED (newdecl))
- TREE_USED (olddecl) = 1;
+ /* Merge the USED information. */
+ if (TREE_USED (olddecl))
+ TREE_USED (newdecl) = 1;
+ else if (TREE_USED (newdecl))
+ TREE_USED (olddecl) = 1;
+ if (TREE_CODE (olddecl) == VAR_DECL || TREE_CODE (olddecl) == PARM_DECL)
+ DECL_READ_P (newdecl) |= DECL_READ_P (olddecl);
+ if (DECL_PRESERVE_P (olddecl))
+ DECL_PRESERVE_P (newdecl) = 1;
+ else if (DECL_PRESERVE_P (newdecl))
+ DECL_PRESERVE_P (olddecl) = 1;
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
- But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */
+ But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
+ DECL_ARGUMENTS (if appropriate). */
{
unsigned olddecl_uid = DECL_UID (olddecl);
tree olddecl_context = DECL_CONTEXT (olddecl);
switch (TREE_CODE (olddecl))
{
case FUNCTION_DECL:
- gimple_set_body (olddecl, gimple_body (newdecl));
- /* fall through */
-
case FIELD_DECL:
case VAR_DECL:
case PARM_DECL:
warning (OPT_Wshadow, "declaration of %q+D shadows a previous local",
new_decl);
- warning (OPT_Wshadow, "%Jshadowed declaration is here", old_decl);
+ warning_at (DECL_SOURCE_LOCATION (old_decl), OPT_Wshadow,
+ "shadowed declaration is here");
break;
}
if (flag_isoc99)
warned = pedwarn (input_location, OPT_Wimplicit_function_declaration,
"implicit declaration of function %qE", id);
- else
- warned = warning (OPT_Wimplicit_function_declaration,
+ else
+ warned = warning (OPT_Wimplicit_function_declaration,
G_("implicit declaration of function %qE"), id);
if (olddecl && warned)
locate_old_decl (olddecl);
if (current_function_decl == 0)
{
- error ("%H%qE undeclared here (not in a function)", &loc, id);
+ error_at (loc, "%qE undeclared here (not in a function)", id);
scope = current_scope;
}
else
{
- error ("%H%qE undeclared (first use in this function)", &loc, id);
-
+ error_at (loc, "%qE undeclared (first use in this function)", id);
if (!already)
{
- error ("%H(Each undeclared identifier is reported only once", &loc);
- error ("%Hfor each function it appears in.)", &loc);
+ inform (loc, "each undeclared identifier is reported only"
+ " once for each function it appears in");
already = true;
}
DECL_CONTEXT (label) = current_function_decl;
DECL_MODE (label) = VOIDmode;
- label_vars = GGC_NEW (struct c_label_vars);
+ label_vars = ggc_alloc_c_label_vars ();
label_vars->shadowed = NULL;
set_spot_bindings (&label_vars->label_bindings, defining);
label_vars->decls_in_scope = make_tree_vector ();
{
struct c_goto_bindings *g;
- g = GGC_NEW (struct c_goto_bindings);
+ g = ggc_alloc_c_goto_bindings ();
g->loc = loc;
set_spot_bindings (&g->goto_bindings, true);
VEC_safe_push (c_goto_bindings_p, gc, label_vars->gotos, g);
...
goto lab;
Issue a warning or error. */
- for (ix = 0; VEC_iterate (tree, label_vars->decls_in_scope, ix, decl); ++ix)
+ FOR_EACH_VEC_ELT (tree, label_vars->decls_in_scope, ix, decl)
warn_about_goto (loc, label, decl);
if (label_vars->label_bindings.left_stmt_expr)
unsigned int ix;
struct c_goto_bindings *g;
- for (ix = 0;
- VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
- ++ix)
+ FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
{
struct c_binding *b;
struct c_scope *scope;
pending_xref_error (void)
{
if (pending_invalid_xref != 0)
- error ("%H%qE defined as wrong kind of tag",
- &pending_invalid_xref_location, pending_invalid_xref);
+ error_at (pending_invalid_xref_location, "%qE defined as wrong kind of tag",
+ pending_invalid_xref);
pending_invalid_xref = 0;
}
using preprocessed headers. */
input_location = BUILTINS_LOCATION;
- build_common_tree_nodes (flag_signed_char, false);
+ build_common_tree_nodes (flag_signed_char);
c_common_nodes_and_builtins ();
if (current_function_decl
/* For invalid programs like this:
-
+
void foo()
const char* p = __FUNCTION__;
-
+
the __FUNCTION__ is believed to appear in K&R style function
parameter declarator. In that case we still don't have
function_scope. */
- && (!errorcount || current_function_scope))
+ && (!seen_error () || current_function_scope))
{
DECL_CONTEXT (decl) = current_function_decl;
bind (id, decl, current_function_scope,
needing to be explicitly declared. See push_file_scope. */
if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
{
- TREE_CHAIN (decl) = visible_builtins;
+ DECL_CHAIN (decl) = visible_builtins;
visible_builtins = decl;
}
needing to be explicitly declared. See push_file_scope. */
if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
{
- TREE_CHAIN (decl) = visible_builtins;
+ DECL_CHAIN (decl) = visible_builtins;
visible_builtins = decl;
}
else if (!declspecs->tag_defined_p
&& (declspecs->const_p
|| declspecs->volatile_p
- || declspecs->restrict_p))
+ || declspecs->restrict_p
+ || declspecs->address_space))
{
if (warned != 1)
pedwarn (input_location, 0,
if (!warned && !in_system_header && (declspecs->const_p
|| declspecs->volatile_p
- || declspecs->restrict_p))
+ || declspecs->restrict_p
+ || declspecs->address_space))
{
warning (0, "useless type qualifier in empty declaration");
warned = 2;
{
int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
| (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
- | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0));
+ | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+ | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
gcc_assert (!specs->type
&& !specs->decl_attr
&& specs->typespec_word == cts_none
if (ce->kind == cdk_function)
{
tree args = ce->u.arg_info->parms;
- for (; args; args = TREE_CHAIN (args))
+ for (; args; args = DECL_CHAIN (args))
{
tree type = TREE_TYPE (args);
if (type && INTEGRAL_TYPE_P (type)
return tem;
}
-/* Initialize EH if not initialized yet and exceptions are enabled. */
+/* Subroutine of finish_decl. TYPE is the type of an uninitialized object
+ DECL or the non-array element type if DECL is an uninitialized array.
+ If that type has a const member, diagnose this. */
-void
-c_maybe_initialize_eh (void)
+static void
+diagnose_uninitialized_cst_member (tree decl, tree type)
{
- if (!flag_exceptions || c_eh_initialized_p)
- return;
+ tree field;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ tree field_type;
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+ field_type = strip_array_types (TREE_TYPE (field));
+
+ if (TYPE_QUALS (field_type) & TYPE_QUAL_CONST)
+ {
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+ "uninitialized const member in %qT is invalid in C++",
+ strip_array_types (TREE_TYPE (decl)));
+ inform (DECL_SOURCE_LOCATION (field), "%qD should be initialized", field);
+ }
- c_eh_initialized_p = true;
- eh_personality_libfunc
- = init_one_libfunc (USING_SJLJ_EXCEPTIONS
- ? "__gcc_personality_sj0"
- : "__gcc_personality_v0");
- default_init_unwind_resume_libfunc ();
- using_eh_for_cleanups ();
+ if (TREE_CODE (field_type) == RECORD_TYPE
+ || TREE_CODE (field_type) == UNION_TYPE)
+ diagnose_uninitialized_cst_member (decl, field_type);
+ }
}
/* Finish processing of a declaration;
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
+ if (TREE_CODE (decl) == VAR_DECL
+ && TREE_STATIC (decl)
+ && global_bindings_p ())
+ /* So decl is a global variable. Record the types it uses
+ so that we can decide later to emit debug info for them. */
+ record_types_used_by_current_var_decl (decl);
+
/* If `start_decl' didn't like having an initialization, ignore it now. */
if (init != 0 && DECL_INITIAL (decl) == 0)
init = 0;
}
if (TREE_USED (type))
- TREE_USED (decl) = 1;
+ {
+ TREE_USED (decl) = 1;
+ DECL_READ_P (decl) = 1;
+ }
}
/* If this is a function and an assembler name is specified, reset DECL_RTL
/* Don't warn about decl unused; the cleanup uses it. */
TREE_USED (decl) = 1;
TREE_USED (cleanup_decl) = 1;
-
- /* Initialize EH, if we've been told to do so. */
- c_maybe_initialize_eh ();
+ DECL_READ_P (decl) = 1;
push_cleanup (decl, cleanup, false);
}
}
+
+ if (warn_cxx_compat
+ && TREE_CODE (decl) == VAR_DECL
+ && !DECL_EXTERNAL (decl)
+ && DECL_INITIAL (decl) == NULL_TREE)
+ {
+ type = strip_array_types (type);
+ if (TREE_READONLY (decl))
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+ "uninitialized const %qD is invalid in C++", decl);
+ else if ((TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE)
+ && C_TYPE_FIELDS_READONLY (type))
+ diagnose_uninitialized_cst_member (decl, type);
+ }
}
/* Given a parsed parameter declaration, decode it into a PARM_DECL. */
tree complit;
tree stmt;
- if (type == error_mark_node)
+ if (type == error_mark_node
+ || init == error_mark_node)
return error_mark_node;
decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
TREE_STATIC (decl) = (current_scope == file_scope);
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
+ DECL_READ_P (decl) = 1;
TREE_TYPE (decl) = type;
TREE_READONLY (decl) = TYPE_READONLY (type);
store_init_value (loc, decl, init, NULL_TREE);
x = TYPE_FIELDS (type);
if (x == NULL_TREE)
return false;
- while (TREE_CHAIN (x) != NULL_TREE)
- x = TREE_CHAIN (x);
+ while (DECL_CHAIN (x) != NULL_TREE)
+ x = DECL_CHAIN (x);
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
&& TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
return true;
return false;
case UNION_TYPE:
- for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x))
+ for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
{
if (flexible_array_type_p (TREE_TYPE (x)))
return true;
/* Detect and ignore out of range field width and process valid
field widths. */
- if (!INTEGRAL_TYPE_P (TREE_TYPE (*width))
- || TREE_CODE (*width) != INTEGER_CST)
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (*width)))
{
error ("bit-field %qs width not an integer constant", name);
*width = integer_one_node;
}
else
{
+ if (TREE_CODE (*width) != INTEGER_CST)
+ {
+ *width = c_fully_fold (*width, false, NULL);
+ if (TREE_CODE (*width) == INTEGER_CST)
+ pedwarn (input_location, OPT_pedantic,
+ "bit-field %qs width not an integer constant expression",
+ name);
+ }
+ if (TREE_CODE (*width) != INTEGER_CST)
+ {
+ error ("bit-field %qs width not an integer constant", name);
+ *width = integer_one_node;
+ }
constant_expression_warning (*width);
if (tree_int_cst_sgn (*width) < 0)
{
}
else
{
- if (name)
+ if (name)
pedwarn (input_location, OPT_Wvla,
"ISO C90 forbids variable length array %qE",
name);
tree name = NULL_TREE;
bool funcdef_flag = false;
bool funcdef_syntax = false;
- int size_varies = 0;
+ bool size_varies = false;
tree decl_attr = declspecs->decl_attr;
int array_ptr_quals = TYPE_UNQUALIFIED;
tree array_ptr_attrs = NULL_TREE;
bool bitfield = width != NULL;
tree element_type;
struct c_arg_info *arg_info = 0;
+ addr_space_t as1, as2, address_space;
location_t loc = UNKNOWN_LOCATION;
const char *errmsg;
tree expr_dummy;
type = integer_type_node;
}
- size_varies = C_TYPE_VARIABLE_SIZE (type);
+ size_varies = C_TYPE_VARIABLE_SIZE (type) != 0;
/* Diagnose defaulting to "int". */
else
{
if (name)
- pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wimplicit_int,
+ pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wimplicit_int,
"type defaults to %<int%> in declaration of %qE",
name);
else
- pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int,
+ pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int,
"type defaults to %<int%> in type name");
}
}
constp = declspecs->const_p + TYPE_READONLY (element_type);
restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+ as1 = declspecs->address_space;
+ as2 = TYPE_ADDR_SPACE (element_type);
+ address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
+
if (pedantic && !flag_isoc99)
{
if (constp > 1)
if (volatilep > 1)
pedwarn (loc, OPT_pedantic, "duplicate %<volatile%>");
}
+
+ if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
+ error_at (loc, "conflicting named address spaces (%s vs %s)",
+ c_addr_space_name (as1), c_addr_space_name (as2));
+
if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
type = TYPE_MAIN_VARIANT (type);
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0)
+ | ENCODE_QUAL_ADDR_SPACE (address_space));
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
|| storage_class == csc_typedef))
{
if (storage_class == csc_auto)
- pedwarn (loc,
- (current_scope == file_scope) ? 0 : OPT_pedantic,
+ pedwarn (loc,
+ (current_scope == file_scope) ? 0 : OPT_pedantic,
"function definition declared %<auto%>");
if (storage_class == csc_register)
error_at (loc, "function definition declared %<register%>");
"variably modified %qE at file scope",
name);
else
- this_size_varies = size_varies = 1;
+ this_size_varies = size_varies = true;
warn_variable_length_array (name, size);
}
}
/* Make sure the array size remains visibly
nonconstant even if it is (eg) a const variable
with known value. */
- this_size_varies = size_varies = 1;
+ this_size_varies = size_varies = true;
warn_variable_length_array (name, size);
}
- 1. Do the calculation in index_type, so that
if it is a variable the computations will be
done in the proper mode. */
- itype = fold_build2 (MINUS_EXPR, index_type,
- convert (index_type, size),
- convert (index_type,
- size_one_node));
+ itype = fold_build2_loc (loc, MINUS_EXPR, index_type,
+ convert (index_type, size),
+ convert (index_type,
+ size_one_node));
/* If that overflowed, the array is too big. ???
While a size of INT_MAX+1 technically shouldn't
the field variably modified, not through being
something other than a declaration with function
prototype scope. */
- size_varies = 1;
+ size_varies = true;
else
{
const struct c_declarator *t = declarator;
if (array_parm_vla_unspec_p)
{
itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
- size_varies = 1;
+ size_varies = true;
}
}
else if (decl_context == TYPENAME)
otherwise be modified below. */
itype = build_range_type (sizetype, size_zero_node,
NULL_TREE);
- size_varies = 1;
+ size_varies = true;
}
}
it, but here we want to make sure we don't ever
modify the shared type, so we gcc_assert (itype)
below. */
- type = build_array_type (type, itype);
+ {
+ addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals);
+ if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
+ type = build_qualified_type (type,
+ ENCODE_QUAL_ADDR_SPACE (as));
+
+ type = build_array_type (type, itype);
+ }
if (type != error_mark_node)
{
gcc_assert (itype);
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
+ SET_TYPE_STRUCTURAL_EQUALITY (type);
}
if (array_parm_vla_unspec_p)
{
/* The type is complete. C99 6.7.5.2p4 */
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
+ SET_TYPE_STRUCTURAL_EQUALITY (type);
}
}
if (type == error_mark_node)
continue;
- size_varies = 0;
+ size_varies = false;
/* Warn about some types functions can't return. */
if (TREE_CODE (type) == FUNCTION_TYPE)
the formal parameter list of this FUNCTION_TYPE to point to
the FUNCTION_TYPE node itself. */
{
- tree link;
+ c_arg_tag *tag;
+ unsigned ix;
- for (link = arg_info->tags;
- link;
- link = TREE_CHAIN (link))
- TYPE_CONTEXT (TREE_VALUE (link)) = type;
+ FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
+ TYPE_CONTEXT (tag->type) = type;
}
break;
}
"ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- size_varies = 0;
+ size_varies = false;
/* When the pointed-to type involves components of variable size,
care must be taken to ensure that the size evaluation code is
/* Now TYPE has the actual type, apart from any qualifiers in
TYPE_QUALS. */
+ /* Warn about address space used for things other than static memory or
+ pointers. */
+ address_space = DECODE_QUAL_ADDR_SPACE (type_quals);
+ if (!ADDR_SPACE_GENERIC_P (address_space))
+ {
+ if (decl_context == NORMAL)
+ {
+ switch (storage_class)
+ {
+ case csc_auto:
+ error ("%qs combined with %<auto%> qualifier for %qE",
+ c_addr_space_name (address_space), name);
+ break;
+ case csc_register:
+ error ("%qs combined with %<register%> qualifier for %qE",
+ c_addr_space_name (address_space), name);
+ break;
+ case csc_none:
+ if (current_function_scope)
+ {
+ error ("%qs specified for auto variable %qE",
+ c_addr_space_name (address_space), name);
+ break;
+ }
+ break;
+ case csc_static:
+ case csc_extern:
+ case csc_typedef:
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else if (decl_context == PARM && TREE_CODE (type) != ARRAY_TYPE)
+ {
+ if (name)
+ error ("%qs specified for parameter %qE",
+ c_addr_space_name (address_space), name);
+ else
+ error ("%qs specified for unnamed parameter",
+ c_addr_space_name (address_space));
+ }
+ else if (decl_context == FIELD)
+ {
+ if (name)
+ error ("%qs specified for structure field %qE",
+ c_addr_space_name (address_space), name);
+ else
+ error ("%qs specified for structure field",
+ c_addr_space_name (address_space));
+ }
+ }
+
/* Check the type and width of a bit-field. */
if (bitfield)
check_bitfield_type_and_width (&type, width, name);
warning_at (loc, OPT_Wattributes,
"attributes in parameter array declarator ignored");
- size_varies = 0;
+ size_varies = false;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
pedwarn (loc, OPT_pedantic,
"ISO C forbids qualified function types");
- /* GNU C interprets a volatile-qualified function type to indicate
- that the function does not return. */
- if ((type_quals & TYPE_QUAL_VOLATILE)
- && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
- warning_at (loc, 0, "%<noreturn%> function returns non-void value");
-
/* Every function declaration is an external reference
(DECL_EXTERNAL) except for those which are not at file
scope and are explicitly declared "auto". This is
name of a variable. Thus, if it's known before this, die horribly. */
gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
+ if (warn_cxx_compat
+ && TREE_CODE (decl) == VAR_DECL
+ && TREE_PUBLIC (decl)
+ && TREE_STATIC (decl)
+ && (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
+ || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ && TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE)
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+ ("non-local variable %qD with anonymous type is "
+ "questionable in C++"),
+ decl);
+
return decl;
}
}
for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
parm;
- parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
+ parm = DECL_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
{
type = TREE_VALUE (typelt);
if (type == error_mark_node)
if (funcdef_flag)
{
if (DECL_NAME (parm))
- error ("parameter %u (%q+D) has incomplete type",
- parmno, parm);
+ error_at (input_location,
+ "parameter %u (%q+D) has incomplete type",
+ parmno, parm);
else
- error ("%Jparameter %u has incomplete type",
- parm, parmno);
+ error_at (DECL_SOURCE_LOCATION (parm),
+ "parameter %u has incomplete type",
+ parmno);
TREE_VALUE (typelt) = error_mark_node;
TREE_TYPE (parm) = error_mark_node;
+ arg_types = NULL_TREE;
}
else if (VOID_TYPE_P (type))
{
if (DECL_NAME (parm))
- warning (0, "parameter %u (%q+D) has void type",
- parmno, parm);
+ warning_at (input_location, 0,
+ "parameter %u (%q+D) has void type",
+ parmno, parm);
else
- warning (0, "%Jparameter %u has void type",
- parm, parmno);
+ warning_at (DECL_SOURCE_LOCATION (parm), 0,
+ "parameter %u has void type",
+ parmno);
}
}
error (errmsg);
TREE_VALUE (typelt) = error_mark_node;
TREE_TYPE (parm) = error_mark_node;
+ arg_types = NULL_TREE;
}
if (DECL_NAME (parm) && TREE_USED (parm))
}
}
+/* Allocate and initialize a c_arg_info structure from the parser's
+ obstack. */
+
+struct c_arg_info *
+build_arg_info (void)
+{
+ struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
+ ret->parms = NULL_TREE;
+ ret->tags = NULL;
+ ret->types = NULL_TREE;
+ ret->others = NULL_TREE;
+ ret->pending_sizes = NULL;
+ ret->had_vla_unspec = 0;
+ return ret;
+}
+
/* Take apart the current scope and return a c_arg_info structure with
info on a parameter list just parsed.
get_parm_info (bool ellipsis)
{
struct c_binding *b = current_scope->bindings;
- struct c_arg_info *arg_info = XOBNEW (&parser_obstack,
- struct c_arg_info);
+ struct c_arg_info *arg_info = build_arg_info ();
+
tree parms = 0;
- tree tags = 0;
+ VEC(c_arg_tag,gc) *tags = NULL;
tree types = 0;
tree others = 0;
static bool explained_incomplete_types = false;
bool gave_void_only_once_err = false;
- arg_info->parms = 0;
- arg_info->tags = 0;
- arg_info->types = 0;
- arg_info->others = 0;
- arg_info->pending_sizes = 0;
arg_info->had_vla_unspec = current_scope->had_vla_unspec;
/* The bindings in this scope must not get put into a block.
{
tree decl = b->decl;
tree type = TREE_TYPE (decl);
+ c_arg_tag *tag;
const char *keyword;
switch (TREE_CODE (decl))
else
{
/* Valid parameter, add it to the list. */
- TREE_CHAIN (decl) = parms;
+ DECL_CHAIN (decl) = parms;
parms = decl;
/* Since there is a prototype, args are passed in their
}
}
- tags = tree_cons (b->id, decl, tags);
+ tag = VEC_safe_push (c_arg_tag, gc, tags, NULL);
+ tag->id = b->id;
+ tag->type = decl;
break;
case CONST_DECL:
type itself. FUNCTION_DECLs appear when there is an implicit
function declaration in the parameter list. */
- TREE_CHAIN (decl) = others;
+ /* When we reinsert this decl in the function body, we need
+ to reconstruct whether it was marked as nested. */
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+ ? b->nested
+ : !b->nested);
+ DECL_CHAIN (decl) = others;
others = decl;
/* fall through */
LOC is the location of the struct's definition.
CODE says which kind of tag NAME ought to be.
- This stores the current value of the file static IN_STRUCT in
- *ENCLOSING_IN_STRUCT, and sets IN_STRUCT to true. Similarly, this
- sets STRUCT_TYPES in *ENCLOSING_STRUCT_TYPES, and sets STRUCT_TYPES
- to an empty vector. The old values are restored in
- finish_struct. */
+ This stores the current value of the file static STRUCT_PARSE_INFO
+ in *ENCLOSING_STRUCT_PARSE_INFO, and points STRUCT_PARSE_INFO at a
+ new c_struct_parse_info structure. The old value of
+ STRUCT_PARSE_INFO is restored in finish_struct. */
tree
start_struct (location_t loc, enum tree_code code, tree name,
- bool *enclosing_in_struct,
- VEC(tree,heap) **enclosing_struct_types)
+ struct c_struct_parse_info **enclosing_struct_parse_info)
{
/* If there is already a tag defined at this scope
(as a forward reference), just return it. */
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
- *enclosing_in_struct = in_struct;
- *enclosing_struct_types = struct_types;
- in_struct = true;
- struct_types = VEC_alloc(tree, heap, 0);
+ *enclosing_struct_parse_info = struct_parse_info;
+ struct_parse_info = XNEW (struct c_struct_parse_info);
+ struct_parse_info->struct_types = VEC_alloc (tree, heap, 0);
+ struct_parse_info->fields = VEC_alloc (c_binding_ptr, heap, 0);
+ struct_parse_info->typedefs_seen = VEC_alloc (tree, heap, 0);
/* FIXME: This will issue a warning for a use of a type defined
within a statement expr used within sizeof, et. al. This is not
Otherwise this is a forward declaration of a structure tag.
If this is something of the form "foo;" and foo is a TYPE_DECL, then
+ If foo names a structure or union without a tag, then this
+ is an anonymous struct (this is permitted by C1X).
If MS extensions are enabled and foo names a structure, then
again this is an anonymous struct.
Otherwise this is an error.
|| TREE_CODE (type) == UNION_TYPE);
bool ok = false;
- if (type_ok
- && (flag_ms_extensions || !declspecs->typedef_p))
+ if (type_ok)
{
if (flag_ms_extensions)
ok = true;
- else if (flag_iso)
- ok = false;
- else if (TYPE_NAME (type) == NULL)
+ else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL)
ok = true;
else
ok = false;
pedwarn (loc, 0, "declaration does not declare anything");
return NULL_TREE;
}
- pedwarn (loc, OPT_pedantic, "ISO C doesn%'t support unnamed structs/unions");
+ if (!flag_isoc1x)
+ {
+ if (flag_isoc99)
+ pedwarn (loc, OPT_pedantic,
+ "ISO C99 doesn%'t support unnamed structs/unions");
+ else
+ pedwarn (loc, OPT_pedantic,
+ "ISO C90 doesn%'t support unnamed structs/unions");
+ }
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
+ if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE)
+ {
+ /* If we currently have a binding for this field, set the
+ in_struct field in the binding, so that we warn about lookups
+ which find it. */
+ struct c_binding *b = I_SYMBOL_BINDING (DECL_NAME (value));
+ if (b != NULL)
+ {
+ /* If the in_struct field is not yet set, push it on a list
+ to be cleared when this struct is finished. */
+ if (!b->in_struct)
+ {
+ VEC_safe_push (c_binding_ptr, heap,
+ struct_parse_info->fields, b);
+ b->in_struct = 1;
+ }
+ }
+ }
+
return value;
}
\f
+/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
+ to HTAB, giving errors for any duplicates. */
+
+static void
+detect_field_duplicates_hash (tree fieldlist, htab_t htab)
+{
+ tree x, y;
+ void **slot;
+
+ for (x = fieldlist; x ; x = DECL_CHAIN (x))
+ if ((y = DECL_NAME (x)) != 0)
+ {
+ slot = htab_find_slot (htab, y, INSERT);
+ if (*slot)
+ {
+ error ("duplicate member %q+D", x);
+ DECL_NAME (x) = NULL_TREE;
+ }
+ *slot = y;
+ }
+ else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+ detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
+}
+
/* Generate an error for any duplicate field names in FIELDLIST. Munge
the list such that this does not present a problem later. */
This is trivially true if there are zero or one fields. */
if (!fieldlist)
return;
- x = TREE_CHAIN (fieldlist);
+ x = DECL_CHAIN (fieldlist);
if (!x)
return;
do {
timeout--;
- x = TREE_CHAIN (x);
+ if (DECL_NAME (x) == NULL_TREE
+ && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+ timeout = 0;
+ x = DECL_CHAIN (x);
} while (timeout > 0 && x);
- /* If there were "few" fields, avoid the overhead of allocating
- a hash table. Instead just do the nested traversal thing. */
+ /* If there were "few" fields and no anonymous structures or unions,
+ avoid the overhead of allocating a hash table. Instead just do
+ the nested traversal thing. */
if (timeout > 0)
{
- for (x = TREE_CHAIN (fieldlist); x ; x = TREE_CHAIN (x))
+ for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x))
if (DECL_NAME (x))
{
for (y = fieldlist; y != x; y = TREE_CHAIN (y))
else
{
htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
- void **slot;
-
- for (x = fieldlist; x ; x = TREE_CHAIN (x))
- if ((y = DECL_NAME (x)) != 0)
- {
- slot = htab_find_slot (htab, y, INSERT);
- if (*slot)
- {
- error ("duplicate member %q+D", x);
- DECL_NAME (x) = NULL_TREE;
- }
- *slot = y;
- }
+ detect_field_duplicates_hash (fieldlist, htab);
htab_delete (htab);
}
}
+/* Finish up struct info used by -Wc++-compat. */
+
+static void
+warn_cxx_compat_finish_struct (tree fieldlist)
+{
+ unsigned int ix;
+ tree x;
+ struct c_binding *b;
+
+ /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
+ the current struct. We do this now at the end of the struct
+ because the flag is used to issue visibility warnings, and we
+ only want to issue those warnings if the type is referenced
+ outside of the struct declaration. */
+ FOR_EACH_VEC_ELT (tree, struct_parse_info->struct_types, ix, x)
+ C_TYPE_DEFINED_IN_STRUCT (x) = 1;
+
+ /* The TYPEDEFS_SEEN field of STRUCT_PARSE_INFO is a list of
+ typedefs used when declaring fields in this struct. If the name
+ of any of the fields is also a typedef name then the struct would
+ not parse in C++, because the C++ lookup rules say that the
+ typedef name would be looked up in the context of the struct, and
+ would thus be the field rather than the typedef. */
+ if (!VEC_empty (tree, struct_parse_info->typedefs_seen)
+ && fieldlist != NULL_TREE)
+ {
+ /* Use a pointer_set using the name of the typedef. We can use
+ a pointer_set because identifiers are interned. */
+ struct pointer_set_t *tset = pointer_set_create ();
+
+ FOR_EACH_VEC_ELT (tree, struct_parse_info->typedefs_seen, ix, x)
+ pointer_set_insert (tset, DECL_NAME (x));
+
+ for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
+ {
+ if (pointer_set_contains (tset, DECL_NAME (x)))
+ {
+ warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
+ ("using %qD as both field and typedef name is "
+ "invalid in C++"),
+ x);
+ /* FIXME: It would be nice to report the location where
+ the typedef name is used. */
+ }
+ }
+
+ pointer_set_destroy (tset);
+ }
+
+ /* For each field which has a binding and which was not defined in
+ an enclosing struct, clear the in_struct field. */
+ FOR_EACH_VEC_ELT (c_binding_ptr, struct_parse_info->fields, ix, b)
+ b->in_struct = 0;
+}
+
/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
LOC is the location of the RECORD_TYPE or UNION_TYPE's definition.
FIELDLIST is a chain of FIELD_DECL nodes for the fields.
ATTRIBUTES are attributes to be applied to the structure.
- ENCLOSING_IN_STRUCT is the value of IN_STRUCT, and
- ENCLOSING_STRUCT_TYPES is the value of STRUCT_TYPES, when the
- struct was started. This sets the C_TYPE_DEFINED_IN_STRUCT flag
- for any type defined in the current struct. */
+ ENCLOSING_STRUCT_PARSE_INFO is the value of STRUCT_PARSE_INFO when
+ the struct was started. */
tree
finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
- bool enclosing_in_struct,
- VEC(tree,heap) *enclosing_struct_types)
+ struct c_struct_parse_info *enclosing_struct_parse_info)
{
tree x;
bool toplevel = file_scope == current_scope;
int saw_named_field;
- unsigned int ix;
/* If this type was previously laid out as a forward reference,
make sure we lay it out again. */
if (pedantic)
{
- for (x = fieldlist; x; x = TREE_CHAIN (x))
- if (DECL_NAME (x) != 0)
- break;
+ for (x = fieldlist; x; x = DECL_CHAIN (x))
+ {
+ if (DECL_NAME (x) != 0)
+ break;
+ if (flag_isoc1x
+ && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+ break;
+ }
if (x == 0)
{
until now.) */
saw_named_field = 0;
- for (x = fieldlist; x; x = TREE_CHAIN (x))
+ for (x = fieldlist; x; x = DECL_CHAIN (x))
{
if (TREE_TYPE (x) == error_mark_node)
continue;
else
{
/* A field that is pseudo-const makes the structure likewise. */
- tree t1 = TREE_TYPE (x);
- while (TREE_CODE (t1) == ARRAY_TYPE)
- t1 = TREE_TYPE (t1);
+ tree t1 = strip_array_types (TREE_TYPE (x));
if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (t1))
C_TYPE_FIELDS_READONLY (t) = 1;
if (TREE_CODE (t) == UNION_TYPE)
{
error_at (DECL_SOURCE_LOCATION (x),
- "%Jflexible array member in union", x);
+ "flexible array member in union");
TREE_TYPE (x) = error_mark_node;
}
- else if (TREE_CHAIN (x) != NULL_TREE)
+ else if (DECL_CHAIN (x) != NULL_TREE)
{
error_at (DECL_SOURCE_LOCATION (x),
- "%Jflexible array member not at end of struct", x);
+ "flexible array member not at end of struct");
TREE_TYPE (x) = error_mark_node;
}
else if (!saw_named_field)
{
error_at (DECL_SOURCE_LOCATION (x),
- "%Jflexible array member in otherwise empty struct",
- x);
+ "flexible array member in otherwise empty struct");
TREE_TYPE (x) = error_mark_node;
}
}
- if (pedantic && !in_system_header && TREE_CODE (t) == RECORD_TYPE
+ if (pedantic && TREE_CODE (t) == RECORD_TYPE
&& flexible_array_type_p (TREE_TYPE (x)))
- pedwarn (loc, OPT_pedantic,
- "%Jinvalid use of structure with flexible array member", x);
+ pedwarn (DECL_SOURCE_LOCATION (x), OPT_pedantic,
+ "invalid use of structure with flexible array member");
- if (DECL_NAME (x))
+ if (DECL_NAME (x)
+ || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
saw_named_field = 1;
}
DECL_INITIAL (*fieldlistp) = 0;
}
else
- fieldlistp = &TREE_CHAIN (*fieldlistp);
+ fieldlistp = &DECL_CHAIN (*fieldlistp);
}
/* Now we have the truly final field list.
{
int len = 0;
- for (x = fieldlist; x; x = TREE_CHAIN (x))
+ for (x = fieldlist; x; x = DECL_CHAIN (x))
{
if (len > 15 || DECL_NAME (x) == NULL)
break;
ensure that this lives as long as the rest of the struct decl.
All decls in an inline function need to be saved. */
- space = GGC_CNEW (struct lang_type);
- space2 = GGC_NEWVAR (struct sorted_fields_type,
- sizeof (struct sorted_fields_type) + len * sizeof (tree));
+ space = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+ space2 = ggc_alloc_sorted_fields_type
+ (sizeof (struct sorted_fields_type) + len * sizeof (tree));
len = 0;
space->s = space2;
field_array = &space2->elts[0];
- for (x = fieldlist; x; x = TREE_CHAIN (x))
+ for (x = fieldlist; x; x = DECL_CHAIN (x))
{
field_array[len++] = x;
/* If this was supposed to be a transparent union, but we can't
make it one, warn and turn off the flag. */
if (TREE_CODE (t) == UNION_TYPE
- && TYPE_TRANSPARENT_UNION (t)
+ && TYPE_TRANSPARENT_AGGR (t)
&& (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))))
{
- TYPE_TRANSPARENT_UNION (t) = 0;
+ TYPE_TRANSPARENT_AGGR (t) = 0;
warning_at (loc, 0, "union cannot be made transparent");
}
}
C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
+ /* Update type location to the one of the definition, instead of e.g.
+ a forward declaration. */
+ if (TYPE_STUB_DECL (t))
+ DECL_SOURCE_LOCATION (TYPE_STUB_DECL (t)) = loc;
+
/* Finish debugging output for this type. */
rest_of_type_compilation (t, toplevel);
add_stmt (build_stmt (loc,
DECL_EXPR, build_decl (loc, TYPE_DECL, NULL, t)));
- /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
- the current struct. We do this now at the end of the struct
- because the flag is used to issue visibility warnings when using
- -Wc++-compat, and we only want to issue those warnings if the
- type is referenced outside of the struct declaration. */
- for (ix = 0; VEC_iterate (tree, struct_types, ix, x); ++ix)
- C_TYPE_DEFINED_IN_STRUCT (x) = 1;
+ if (warn_cxx_compat)
+ warn_cxx_compat_finish_struct (fieldlist);
- VEC_free (tree, heap, struct_types);
+ VEC_free (tree, heap, struct_parse_info->struct_types);
+ VEC_free (c_binding_ptr, heap, struct_parse_info->fields);
+ VEC_free (tree, heap, struct_parse_info->typedefs_seen);
+ XDELETE (struct_parse_info);
- in_struct = enclosing_in_struct;
- struct_types = enclosing_struct_types;
+ struct_parse_info = enclosing_struct_parse_info;
/* If this struct is defined inside a struct, add it to
- STRUCT_TYPES. */
- if (in_struct && !in_sizeof && !in_typeof && !in_alignof)
- VEC_safe_push (tree, heap, struct_types, t);
+ struct_types. */
+ if (warn_cxx_compat
+ && struct_parse_info != NULL
+ && !in_sizeof && !in_typeof && !in_alignof)
+ VEC_safe_push (tree, heap, struct_parse_info->struct_types, t);
return t;
}
/* Record the min/max values so that we can warn about bit-field
enumerations that are too small for the values. */
- lt = GGC_CNEW (struct lang_type);
+ lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
lt->enum_min = minnode;
lt->enum_max = maxnode;
TYPE_LANG_SPECIFIC (enumtype) = lt;
rest_of_type_compilation (enumtype, toplevel);
/* If this enum is defined inside a struct, add it to
- STRUCT_TYPES. */
- if (in_struct && !in_sizeof && !in_typeof && !in_alignof)
- VEC_safe_push (tree, heap, struct_types, enumtype);
+ struct_types. */
+ if (warn_cxx_compat
+ && struct_parse_info != NULL
+ && !in_sizeof && !in_typeof && !in_alignof)
+ VEC_safe_push (tree, heap, struct_parse_info->struct_types, enumtype);
return enumtype;
}
(6.4.4.3/2 in the C99 Standard). GCC allows any integer type as
an extension. */
else if (!int_fits_type_p (value, integer_type_node))
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C restricts enumerator values to range of %<int%>");
/* The ISO C Standard mandates enumerators to have type int, even
}
if (warn_about_return_type)
- pedwarn_c99 (loc, flag_isoc99 ? 0
+ pedwarn_c99 (loc, flag_isoc99 ? 0
: (warn_return_type ? OPT_Wreturn_type : OPT_Wimplicit_int),
"return type defaults to %<int%>");
error_mark_node is replaced below (in pop_scope) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
+ /* A nested function is not global. */
+ if (current_function_decl != 0)
+ TREE_PUBLIC (decl1) = 0;
+
/* If this definition isn't a prototype and we had a prototype declaration
before, copy the arg type info from that prototype. */
old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
- /* A nested function is not global. */
- if (current_function_decl != 0)
- TREE_PUBLIC (decl1) = 0;
-
/* This is the earliest point at which we might know the assembler
name of the function. Thus, if it's set before this, die horribly. */
gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1));
store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
{
tree decl;
+ c_arg_tag *tag;
+ unsigned ix;
if (current_scope->bindings)
{
- error ("%Jold-style parameter declarations in prototyped "
- "function definition", fndecl);
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "old-style parameter declarations in prototyped "
+ "function definition");
/* Get rid of the old-style declarations. */
pop_scope ();
its parameter list). */
else if (!in_system_header && !current_function_scope
&& arg_info->types != error_mark_node)
- warning (OPT_Wtraditional,
- "%Jtraditional C rejects ISO C style function definitions",
- fndecl);
+ warning_at (DECL_SOURCE_LOCATION (fndecl), OPT_Wtraditional,
+ "traditional C rejects ISO C style function definitions");
/* Now make all the parameter declarations visible in the function body.
We can bypass most of the grunt work of pushdecl. */
- for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->parms; decl; decl = DECL_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
warn_if_shadowing (decl);
}
else
- error ("%Jparameter name omitted", decl);
+ error_at (DECL_SOURCE_LOCATION (decl), "parameter name omitted");
}
/* Record the parameter list in the function declaration. */
DECL_ARGUMENTS (fndecl) = arg_info->parms;
/* Now make all the ancillary declarations visible, likewise. */
- for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->others; decl; decl = DECL_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
bind (DECL_NAME (decl), decl, current_scope,
- /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
+ /*invisible=*/false,
+ /*nested=*/(TREE_CODE (decl) == FUNCTION_DECL),
+ UNKNOWN_LOCATION);
}
/* And all the tag declarations. */
- for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl))
- if (TREE_PURPOSE (decl))
- bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
+ FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
+ if (tag->id)
+ bind (tag->id, tag->type, current_scope,
/*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
}
if (flag_isoc99)
pedwarn (DECL_SOURCE_LOCATION (decl),
0, "type of %qD defaults to %<int%>", decl);
- else
+ else
warning_at (DECL_SOURCE_LOCATION (decl),
OPT_Wmissing_parameter_type,
"type of %qD defaults to %<int%>", decl);
for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
if (TREE_PURPOSE (parm))
{
- TREE_CHAIN (last) = TREE_PURPOSE (parm);
+ DECL_CHAIN (last) = TREE_PURPOSE (parm);
last = TREE_PURPOSE (parm);
}
- TREE_CHAIN (last) = 0;
+ DECL_CHAIN (last) = 0;
}
pointer_set_destroy (seen_args);
type = current_function_prototype_arg_types;
parm || (type && TREE_VALUE (type) != error_mark_node
&& (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node));
- parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
+ parm = DECL_CHAIN (parm), type = TREE_CHAIN (type))
{
if (parm == 0 || type == 0
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
tree actual = 0, last = 0, type;
- for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
+ for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
{
type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
if (last)
thus won't naturally see the SAVE_EXPR containing the increment. All
other pending sizes would be handled by gimplify_parameters. */
{
+ VEC(tree,gc) *pending_sizes = get_pending_sizes ();
tree t;
- for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
- add_stmt (TREE_VALUE (t));
+ int i;
+
+ FOR_EACH_VEC_ELT (tree, pending_sizes, i, t)
+ add_stmt (t);
}
/* Even though we're inside a function body, we still don't want to
cfun->dont_save_pending_sizes_p = 1;
}
\f
-/* Emit diagnostics that require gimple input for detection. Operate on
- FNDECL and all its nested functions. */
-
-static void
-c_gimple_diagnostics_recursively (tree fndecl)
-{
- struct cgraph_node *cgn;
- gimple_seq body = gimple_body (fndecl);
-
- /* Handle attribute((warn_unused_result)). Relies on gimple input. */
- c_warn_unused_result (body);
-
- /* Notice when OpenMP structured block constraints are violated. */
- if (flag_openmp)
- diagnose_omp_structured_block_errors (fndecl);
-
- /* Finalize all nested functions now. */
- cgn = cgraph_node (fndecl);
- for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
- c_gimple_diagnostics_recursively (cgn->decl);
-}
/* Finish up a function declaration and compile that function
- all the way to assembler language output. The free the storage
+ all the way to assembler language output. Then free the storage
for the function definition.
This is called after parsing the body of the function definition. */
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
{
tree args = DECL_ARGUMENTS (fndecl);
- for (; args; args = TREE_CHAIN (args))
+ for (; args; args = DECL_CHAIN (args))
{
tree type = TREE_TYPE (args);
if (INTEGRAL_TYPE_P (type)
&& !current_function_returns_value && !current_function_returns_null
/* Don't complain if we are no-return. */
&& !current_function_returns_abnormally
+ /* Don't complain if we are declared noreturn. */
+ && !TREE_THIS_VOLATILE (fndecl)
/* Don't warn for main(). */
&& !MAIN_NAME_P (DECL_NAME (fndecl))
/* Or if they didn't actually specify a return type. */
TREE_NO_WARNING (fndecl) = 1;
}
+ /* Complain about parameters that are only set, but never otherwise used. */
+ if (warn_unused_but_set_parameter)
+ {
+ tree decl;
+
+ for (decl = DECL_ARGUMENTS (fndecl);
+ decl;
+ decl = DECL_CHAIN (decl))
+ if (TREE_USED (decl)
+ && TREE_CODE (decl) == PARM_DECL
+ && !DECL_READ_P (decl)
+ && DECL_NAME (decl)
+ && !DECL_ARTIFICIAL (decl)
+ && !TREE_NO_WARNING (decl))
+ warning_at (DECL_SOURCE_LOCATION (decl),
+ OPT_Wunused_but_set_parameter,
+ "parameter %qD set but not used", decl);
+ }
+
/* Store the end of the function, so that we get good line number
info for the epilogue. */
cfun->function_end_locus = input_location;
c_determine_visibility (fndecl);
/* For GNU C extern inline functions disregard inline limits. */
- if (DECL_EXTERNAL (fndecl)
+ if (DECL_EXTERNAL (fndecl)
&& DECL_DECLARED_INLINE_P (fndecl))
DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
{
if (!decl_function_context (fndecl))
{
+ invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
c_genericize (fndecl);
- c_gimple_diagnostics_recursively (fndecl);
/* ??? Objc emits functions after finalizing the compilation unit.
This should be cleaned up later and this conditional removed. */
c_push_function_context (void)
{
struct language_function *p;
- p = GGC_NEW (struct language_function);
+ p = ggc_alloc_language_function ();
cfun->language = p;
p->base.x_stmt_tree = c_stmt_tree;
warn_about_return_type = p->warn_about_return_type;
}
-/* Copy the DECL_LANG_SPECIFIC data associated with DECL. */
-
-void
-c_dup_lang_specific_decl (tree decl)
-{
- struct lang_decl *ld;
-
- if (!DECL_LANG_SPECIFIC (decl))
- return;
-
- ld = GGC_NEW (struct lang_decl);
- memcpy (ld, DECL_LANG_SPECIFIC (decl), sizeof (struct lang_decl));
- DECL_LANG_SPECIFIC (decl) = ld;
-}
-
/* The functions below are required for functionality of doing
function at once processing in the C front end. Currently these
functions are not called from anywhere in the C front end, but as
ret->volatile_p = false;
ret->restrict_p = false;
ret->saturating_p = false;
+ ret->address_space = ADDR_SPACE_GENERIC;
return ret;
}
+/* Add the address space ADDRSPACE to the declaration specifiers
+ SPECS, returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_addrspace (struct c_declspecs *specs, addr_space_t as)
+{
+ specs->non_sc_seen_p = true;
+ specs->declspecs_seen_p = true;
+
+ if (!ADDR_SPACE_GENERIC_P (specs->address_space)
+ && specs->address_space != as)
+ error ("incompatible address space qualifiers %qs and %qs",
+ c_addr_space_name (as),
+ c_addr_space_name (specs->address_space));
+ else
+ specs->address_space = as;
+ return specs;
+}
+
/* Add the type qualifier QUAL to the declaration specifiers SPECS,
returning SPECS. */
returning SPECS. */
struct c_declspecs *
-declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
+declspecs_add_type (location_t loc, struct c_declspecs *specs,
+ struct c_typespec spec)
{
tree type = spec.spec;
specs->non_sc_seen_p = true;
enum rid i = C_RID_CODE (type);
if (specs->type)
{
- error ("two or more data types in declaration specifiers");
+ error_at (loc, "two or more data types in declaration specifiers");
return specs;
}
if ((int) i <= (int) RID_LAST_MODIFIER)
case RID_LONG:
if (specs->long_long_p)
{
- error ("%<long long long%> is too long for GCC");
+ error_at (loc, "%<long long long%> is too long for GCC");
break;
}
if (specs->long_p)
{
if (specs->typespec_word == cts_double)
{
- error ("both %<long long%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long long%> and %<double%> in "
+ "declaration specifiers"));
break;
}
- pedwarn_c90 (input_location, OPT_Wlong_long,
+ pedwarn_c90 (loc, OPT_Wlong_long,
"ISO C90 does not support %<long long%>");
specs->long_long_p = 1;
break;
}
if (specs->short_p)
- error ("both %<long%> and %<short%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<short%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
- error ("both %<long%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<void%> in "
+ "declaration specifiers"));
+ else if (specs->typespec_word == cts_int128)
+ error_at (loc,
+ ("both %<long%> and %<__int128%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<long%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_char)
- error ("both %<long%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<long%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<long%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<long%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<long%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else
specs->long_p = true;
break;
case RID_SHORT:
dupe = specs->short_p;
if (specs->long_p)
- error ("both %<long%> and %<short%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<short%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
- error ("both %<short%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<void%> in "
+ "declaration specifiers"));
+ else if (specs->typespec_word == cts_int128)
+ error_at (loc,
+ ("both %<short%> and %<__int128%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<short%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_char)
- error ("both %<short%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<short%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_double)
- error ("both %<short%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<short%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<short%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<short%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else
specs->short_p = true;
break;
case RID_SIGNED:
dupe = specs->signed_p;
if (specs->unsigned_p)
- error ("both %<signed%> and %<unsigned%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
- error ("both %<signed%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<signed%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<signed%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_double)
- error ("both %<signed%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<signed%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<signed%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<signed%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else
specs->signed_p = true;
break;
case RID_UNSIGNED:
dupe = specs->unsigned_p;
if (specs->signed_p)
- error ("both %<signed%> and %<unsigned%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
- error ("both %<unsigned%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<unsigned%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<unsigned%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_double)
- error ("both %<unsigned%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<unsigned%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<unsigned%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<unsigned%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else
specs->unsigned_p = true;
break;
case RID_COMPLEX:
dupe = specs->complex_p;
if (!flag_isoc99 && !in_system_header)
- pedwarn (input_location, OPT_pedantic, "ISO C90 does not support complex types");
+ pedwarn (loc, OPT_pedantic,
+ "ISO C90 does not support complex types");
if (specs->typespec_word == cts_void)
- error ("both %<complex%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<complex%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<complex%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<complex%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<complex%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_fract)
- error ("both %<complex%> and %<_Fract%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Fract%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_accum)
- error ("both %<complex%> and %<_Accum%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Accum%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<complex%> and %<_Sat%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Sat%> in "
+ "declaration specifiers"));
else
specs->complex_p = true;
break;
case RID_SAT:
dupe = specs->saturating_p;
- pedwarn (input_location, OPT_pedantic, "ISO C does not support saturating types");
- if (specs->typespec_word == cts_void)
- error ("both %<_Sat%> and %<void%> in "
- "declaration specifiers");
+ pedwarn (loc, OPT_pedantic,
+ "ISO C does not support saturating types");
+ if (specs->typespec_word == cts_int128)
+ {
+ error_at (loc,
+ ("both %<_Sat%> and %<__int128%> in "
+ "declaration specifiers"));
+ }
+ else if (specs->typespec_word == cts_void)
+ error_at (loc,
+ ("both %<_Sat%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<_Sat%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_char)
- error ("both %<_Sat%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_int)
- error ("both %<_Sat%> and %<int%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<_Sat%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_double)
- error ("both %<_Sat%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<_Sat%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<_Sat%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<_Sat%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else if (specs->complex_p)
- error ("both %<_Sat%> and %<complex%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<complex%> in "
+ "declaration specifiers"));
else
specs->saturating_p = true;
break;
}
if (dupe)
- error ("duplicate %qE", type);
+ error_at (loc, "duplicate %qE", type);
return specs;
}
else
{
/* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
- "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
+ "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
if (specs->typespec_word != cts_none)
{
- error ("two or more data types in declaration specifiers");
+ error_at (loc,
+ "two or more data types in declaration specifiers");
return specs;
}
switch (i)
{
+ case RID_INT128:
+ if (int128_integer_type_node == NULL_TREE)
+ {
+ error_at (loc, "%<__int128%> is not supported for this target");
+ return specs;
+ }
+ if (!in_system_header)
+ pedwarn (loc, OPT_pedantic,
+ "ISO C does not support %<__int128%> type");
+
+ if (specs->long_p)
+ error_at (loc,
+ ("both %<__int128%> and %<long%> in "
+ "declaration specifiers"));
+ else if (specs->saturating_p)
+ error_at (loc,
+ ("both %<_Sat%> and %<__int128%> in "
+ "declaration specifiers"));
+ else if (specs->short_p)
+ error_at (loc,
+ ("both %<__int128%> and %<short%> in "
+ "declaration specifiers"));
+ else
+ specs->typespec_word = cts_int128;
+ return specs;
case RID_VOID:
if (specs->long_p)
- error ("both %<long%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->signed_p)
- error ("both %<signed%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->complex_p)
- error ("both %<complex%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<void%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_void;
return specs;
case RID_BOOL:
if (specs->long_p)
- error ("both %<long%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->signed_p)
- error ("both %<signed%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->complex_p)
- error ("both %<complex%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_bool;
return specs;
case RID_CHAR:
if (specs->long_p)
- error ("both %<long%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_char;
return specs;
case RID_INT:
if (specs->saturating_p)
- error ("both %<_Sat%> and %<int%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_int;
return specs;
case RID_FLOAT:
if (specs->long_p)
- error ("both %<long%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->signed_p)
- error ("both %<signed%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_float;
return specs;
case RID_DOUBLE:
if (specs->long_long_p)
- error ("both %<long long%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long long%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->signed_p)
- error ("both %<signed%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_double;
return specs;
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
- {
+ {
const char *str;
if (i == RID_DFLOAT32)
str = "_Decimal32";
else
str = "_Decimal128";
if (specs->long_long_p)
- error ("both %<long long%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<long long%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
if (specs->long_p)
- error ("both %<long%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<long%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->short_p)
- error ("both %<short%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<short%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->signed_p)
- error ("both %<signed%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<signed%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<unsigned%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->complex_p)
- error ("both %<complex%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<complex%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<_Sat%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (i == RID_DFLOAT32)
specs->typespec_word = cts_dfloat32;
else if (i == RID_DFLOAT64)
specs->typespec_word = cts_dfloat128;
}
if (!targetm.decimal_float_supported_p ())
- error ("decimal floating point not supported for this target");
- pedwarn (input_location, OPT_pedantic,
+ error_at (loc,
+ ("decimal floating point not supported "
+ "for this target"));
+ pedwarn (loc, OPT_pedantic,
"ISO C does not support decimal floating point");
return specs;
case RID_FRACT:
else
str = "_Accum";
if (specs->complex_p)
- error ("both %<complex%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("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");
- pedwarn (input_location, OPT_pedantic,
+ error_at (loc,
+ "fixed-point types not supported for this target");
+ pedwarn (loc, OPT_pedantic,
"ISO C does not support fixed-point types");
return specs;
default:
if (specs->type || specs->typespec_word != cts_none
|| specs->long_p || specs->short_p || specs->signed_p
|| specs->unsigned_p || specs->complex_p)
- error ("two or more data types in declaration specifiers");
+ error_at (loc, "two or more data types in declaration specifiers");
else if (TREE_CODE (type) == TYPE_DECL)
{
if (TREE_TYPE (type) == error_mark_node)
specs->decl_attr = DECL_ATTRIBUTES (type);
specs->typedef_p = true;
specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+
+ /* If this typedef name is defined in a struct, then a C++
+ lookup would return a different value. */
+ if (warn_cxx_compat
+ && I_SYMBOL_BINDING (DECL_NAME (type))->in_struct)
+ warning_at (loc, OPT_Wc___compat,
+ "C++ lookup of %qD would return a field, not a type",
+ type);
+
+ /* If we are parsing a struct, record that a struct field
+ used a typedef. */
+ if (warn_cxx_compat && struct_parse_info != NULL)
+ VEC_safe_push (tree, heap, struct_parse_info->typedefs_seen, type);
}
}
else if (TREE_CODE (type) == IDENTIFIER_NODE)
{
tree t = lookup_name (type);
if (!t || TREE_CODE (t) != TYPE_DECL)
- error ("%qE fails to be a typedef or built in type", type);
+ error_at (loc, "%qE fails to be a typedef or built in type", type);
else if (TREE_TYPE (t) == error_mark_node)
;
else
&& C_IS_RESERVED_WORD (scspec));
i = C_RID_CODE (scspec);
if (specs->non_sc_seen_p)
- warning (OPT_Wold_style_declaration,
+ warning (OPT_Wold_style_declaration,
"%qE is not at beginning of declaration", scspec);
switch (i)
{
else if (specs->complex_p)
{
specs->typespec_word = cts_double;
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_pedantic,
"ISO C does not support plain %<complex%> meaning "
"%<double complex%>");
}
specs->type = char_type_node;
if (specs->complex_p)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C does not support complex integer types");
+ specs->type = build_complex_type (specs->type);
+ }
+ break;
+ case cts_int128:
+ gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
+ gcc_assert (!(specs->signed_p && specs->unsigned_p));
+ specs->type = (specs->unsigned_p
+ ? int128_unsigned_type_node
+ : int128_integer_type_node);
+ if (specs->complex_p)
+ {
+ pedwarn (input_location, OPT_pedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
: integer_type_node);
if (specs->complex_p)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_pedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
bool reconsider;
/* Process the decls in the order they were written. */
- for (decl = globals; decl; decl = TREE_CHAIN (decl))
+ for (decl = globals; decl; decl = DECL_CHAIN (decl))
{
/* Check for used but undefined static functions using the C
standard's definition of "used", and set TREE_NO_WARNING so
do
{
reconsider = false;
- for (decl = globals; decl; decl = TREE_CHAIN (decl))
+ for (decl = globals; decl; decl = DECL_CHAIN (decl))
reconsider |= wrapup_global_declaration_2 (decl);
}
while (reconsider);
- for (decl = globals; decl; decl = TREE_CHAIN (decl))
+ for (decl = globals; decl; decl = DECL_CHAIN (decl))
check_global_declaration_1 (decl);
}
{
tree decl;
- for (decl = globals; decl ; decl = TREE_CHAIN (decl))
+ for (decl = globals; decl ; decl = DECL_CHAIN (decl))
debug_hooks->global_decl (decl);
}
+/* Callback to collect a source_ref from a DECL. */
+
+static void
+collect_source_ref_cb (tree decl)
+{
+ if (!DECL_IS_BUILTIN (decl))
+ collect_source_ref (LOCATION_FILE (decl_sloc (decl, false)));
+}
+
+/* Collect all references relevant to SOURCE_FILE. */
+
+static void
+collect_all_refs (const char *source_file)
+{
+ tree t;
+
+ for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ collect_ada_nodes (BLOCK_VARS (DECL_INITIAL (t)), source_file);
+}
+
+/* Iterate over all global declarations and call CALLBACK. */
+
+static void
+for_each_global_decl (void (*callback) (tree decl))
+{
+ tree t;
+ tree decls;
+ tree decl;
+
+ for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ {
+ decls = DECL_INITIAL (t);
+ for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl))
+ callback (decl);
+ }
+}
+
/* Preserve the external declarations scope across a garbage collect. */
static GTY(()) tree ext_block;
if (pch_file)
return;
- /* Don't waste time on further processing if -fsyntax-only or we've
- encountered errors. */
- if (flag_syntax_only || errorcount || sorrycount)
- return;
-
/* Close the external scope. */
ext_block = pop_scope ();
external_scope = 0;
gcc_assert (!current_scope);
+ /* Handle -fdump-ada-spec[-slim]. */
+ if (dump_enabled_p (TDI_ada))
+ {
+ /* Build a table of files to generate specs for */
+ if (get_dump_file_info (TDI_ada)->flags & TDF_SLIM)
+ collect_source_ref (main_input_filename);
+ else
+ for_each_global_decl (collect_source_ref_cb);
+
+ dump_ada_specs (collect_all_refs, NULL);
+ }
+
if (ext_block)
{
tree tmp = BLOCK_VARS (ext_block);
/* Process all file scopes in this compilation, and the external_scope,
through wrapup_global_declarations and check_global_declarations. */
- for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ for (t = all_translation_units; t; t = DECL_CHAIN (t))
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_1 (BLOCK_VARS (ext_block));
/* We're done parsing; proceed to optimize and emit assembly.
FIXME: shouldn't be the front end's responsibility to call this. */
- cgraph_optimize ();
+ cgraph_finalize_compilation_unit ();
/* After cgraph has had a chance to emit everything that's going to
be emitted, output debug information for globals. */
- if (errorcount == 0 && sorrycount == 0)
+ if (!seen_error ())
{
timevar_push (TV_SYMOUT);
- for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ for (t = all_translation_units; t; t = DECL_CHAIN (t))
c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_2 (BLOCK_VARS (ext_block));
timevar_pop (TV_SYMOUT);
ext_block = NULL;
}
+/* Register reserved keyword WORD as qualifier for address space AS. */
+
+void
+c_register_addr_space (const char *word, addr_space_t as)
+{
+ int rid = RID_FIRST_ADDR_SPACE + as;
+ tree id;
+
+ /* Address space qualifiers are only supported
+ in C with GNU extensions enabled. */
+ if (c_dialect_objc () || flag_no_asm)
+ return;
+
+ id = get_identifier (word);
+ C_SET_RID_CODE (id, rid);
+ C_IS_RESERVED_WORD (id) = 1;
+ ridpointers [rid] = id;
+}
+
#include "gt-c-decl.h"