/* Process declarations and variables for C compiler.
- Copyright (C) 1988-2013 Free Software Foundation, Inc.
+ Copyright (C) 1988-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "input.h"
-#include "tm.h"
-#include "intl.h"
+#include "target.h"
+#include "function.h"
#include "tree.h"
+#include "c-family/c-common.h"
+#include "c-tree.h"
+#include "timevar.h"
+#include "tm_p.h"
+#include "stringpool.h"
+#include "cgraph.h"
+#include "intl.h"
+#include "print-tree.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "attribs.h"
#include "tree-inline.h"
#include "flags.h"
-#include "function.h"
-#include "c-tree.h"
#include "toplev.h"
-#include "tm_p.h"
-#include "cpplib.h"
-#include "target.h"
#include "debug.h"
#include "opts.h"
-#include "timevar.h"
-#include "c-family/c-common.h"
#include "c-family/c-objc.h"
#include "c-family/c-pragma.h"
#include "c-family/c-ubsan.h"
#include "c-lang.h"
#include "langhooks.h"
#include "tree-iterator.h"
-#include "diagnostic-core.h"
#include "dumpfile.h"
-#include "cgraph.h"
-#include "hash-table.h"
#include "langhooks-def.h"
-#include "pointer-set.h"
#include "plugin.h"
#include "c-family/c-ada-spec.h"
#include "cilk.h"
+#include "builtins.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
static bool undef_nested_function;
-/* Mode used to build pointers (VOIDmode means ptr_mode). */
-
-enum machine_mode c_default_pointer_mode = VOIDmode;
-
/* If non-zero, implicit "omp declare target" attribute is added into the
attribute lists. */
int current_omp_declare_target_attribute;
#define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/)
#define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/)
-#define I_SYMBOL_BINDING(node) \
- (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->symbol_binding)
-#define I_SYMBOL_DECL(node) \
- (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
-
-#define I_TAG_BINDING(node) \
- (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->tag_binding)
-#define I_TAG_DECL(node) \
- (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
-
-#define I_LABEL_BINDING(node) \
- (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding)
-#define I_LABEL_DECL(node) \
- (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
-
/* Each C symbol points to three linked lists of c_binding structures.
These describe the values of the identifier in the three different
namespaces defined by the language. */
extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
[(sizeof(struct lang_identifier) == C_SIZEOF_STRUCT_LANG_IDENTIFIER) ? 1 : -1];
+/* The binding oracle; see c-tree.h. */
+void (*c_binding_oracle) (enum c_oracle_request, tree identifier);
+
+/* This flag is set on an identifier if we have previously asked the
+ binding oracle for this identifier's symbol binding. */
+#define I_SYMBOL_CHECKED(node) \
+ (TREE_LANG_FLAG_4 (IDENTIFIER_NODE_CHECK (node)))
+
+static inline struct c_binding* *
+i_symbol_binding (tree node)
+{
+ struct lang_identifier *lid
+ = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node);
+
+ if (lid->symbol_binding == NULL
+ && c_binding_oracle != NULL
+ && !I_SYMBOL_CHECKED (node))
+ {
+ /* Set the "checked" flag first, to avoid infinite recursion
+ when the binding oracle calls back into gcc. */
+ I_SYMBOL_CHECKED (node) = 1;
+ c_binding_oracle (C_ORACLE_SYMBOL, node);
+ }
+
+ return &lid->symbol_binding;
+}
+
+#define I_SYMBOL_BINDING(node) (*i_symbol_binding (node))
+
+#define I_SYMBOL_DECL(node) \
+ (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
+
+/* This flag is set on an identifier if we have previously asked the
+ binding oracle for this identifier's tag binding. */
+#define I_TAG_CHECKED(node) \
+ (TREE_LANG_FLAG_5 (IDENTIFIER_NODE_CHECK (node)))
+
+static inline struct c_binding **
+i_tag_binding (tree node)
+{
+ struct lang_identifier *lid
+ = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node);
+
+ if (lid->tag_binding == NULL
+ && c_binding_oracle != NULL
+ && !I_TAG_CHECKED (node))
+ {
+ /* Set the "checked" flag first, to avoid infinite recursion
+ when the binding oracle calls back into gcc. */
+ I_TAG_CHECKED (node) = 1;
+ c_binding_oracle (C_ORACLE_TAG, node);
+ }
+
+ return &lid->tag_binding;
+}
+
+#define I_TAG_BINDING(node) (*i_tag_binding (node))
+
+#define I_TAG_DECL(node) \
+ (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
+
+/* This flag is set on an identifier if we have previously asked the
+ binding oracle for this identifier's label binding. */
+#define I_LABEL_CHECKED(node) \
+ (TREE_LANG_FLAG_6 (IDENTIFIER_NODE_CHECK (node)))
+
+static inline struct c_binding **
+i_label_binding (tree node)
+{
+ struct lang_identifier *lid
+ = (struct lang_identifier *) IDENTIFIER_NODE_CHECK (node);
+
+ if (lid->label_binding == NULL
+ && c_binding_oracle != NULL
+ && !I_LABEL_CHECKED (node))
+ {
+ /* Set the "checked" flag first, to avoid infinite recursion
+ when the binding oracle calls back into gcc. */
+ I_LABEL_CHECKED (node) = 1;
+ c_binding_oracle (C_ORACLE_LABEL, node);
+ }
+
+ return &lid->label_binding;
+}
+
+#define I_LABEL_BINDING(node) (*i_label_binding (node))
+
+#define I_LABEL_DECL(node) \
+ (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
+
/* The resulting tree type. */
union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
bool *, enum deprecated_states);
static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
+static void warn_defaults_to (location_t, int, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
\f
/* T is a statement. Add it to the statement-tree. This is the
C/ObjC version--C++ has a slightly different version of this
{
addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
: TYPE_ADDR_SPACE (to_type);
- enum machine_mode pointer_mode;
+ machine_mode pointer_mode;
if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode)
pointer_mode = targetm.addr_space.pointer_mode (as);
return false;
/* Always warn about crossing variably modified types. */
- if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL)
+ if ((VAR_P (decl) || TREE_CODE (decl) == TYPE_DECL)
&& variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
return true;
/* Otherwise, only warn if -Wgoto-misses-init and this is an
initialized automatic decl. */
if (warn_jump_misses_init
- && TREE_CODE (decl) == VAR_DECL
+ && VAR_P (decl)
&& !TREE_STATIC (decl)
&& DECL_INITIAL (decl) != NULL_TREE)
return true;
void
c_print_identifier (FILE *file, tree node, int indent)
{
+ void (*save) (enum c_oracle_request, tree identifier);
+
+ /* Temporarily hide any binding oracle. Without this, calls to
+ debug_tree from the debugger will end up calling into the oracle,
+ making for a confusing debug session. As the oracle isn't needed
+ here for normal operation, it's simplest to suppress it. */
+ save = c_binding_oracle;
+ c_binding_oracle = NULL;
+
print_node (file, "symbol", I_SYMBOL_DECL (node), indent + 4);
print_node (file, "tag", I_TAG_DECL (node), indent + 4);
print_node (file, "label", I_LABEL_DECL (node), indent + 4);
fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
(void *) rid, IDENTIFIER_POINTER (rid));
}
+
+ c_binding_oracle = save;
}
/* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL,
binding_freelist = b->prev;
}
else
- b = ggc_alloc_c_binding ();
+ b = ggc_alloc<c_binding> ();
b->shadowed = 0;
b->decl = decl;
void
c_finish_incomplete_decl (tree decl)
{
- if (TREE_CODE (decl) == VAR_DECL)
+ if (VAR_P (decl))
{
tree type = TREE_TYPE (decl);
if (type != error_mark_node
record_inline_static (location_t loc, tree func, tree decl,
enum c_inline_static_type type)
{
- struct c_inline_static *csi = ggc_alloc_c_inline_static ();
+ 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_alloc_cleared_c_scope ();
+ scope = ggc_cleared_alloc<c_scope> ();
/* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes. */
if (current_scope)
{
tree file_decl = build_translation_unit_decl (NULL_TREE);
context = file_decl;
+ debug_hooks->register_main_translation_unit (file_decl);
}
else
context = block;
/* C99 6.7.4p6: "a function with external linkage... declared
with an inline function specifier ... shall also be defined
in the same translation unit." */
- if (!flag_gnu89_inline)
+ if (!flag_gnu89_inline
+ && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (p))
+ && scope != external_scope)
pedwarn (input_location, 0,
"inline function %q+D declared but never defined", p);
DECL_EXTERNAL (p) = 1;
}
}
}
+
+/* An exported interface to pushtag. This is used by the gdb plugin's
+ binding oracle to introduce a new tag binding. */
+
+void
+c_pushtag (location_t loc, tree name, tree type)
+{
+ pushtag (loc, name, type);
+}
+
+/* An exported interface to bind a declaration. LOC is the location
+ to use. DECL is the declaration to bind. The decl's name is used
+ to determine how it is bound. If DECL is a VAR_DECL, then
+ IS_GLOBAL determines whether the decl is put into the global (file
+ and external) scope or the current function's scope; if DECL is not
+ a VAR_DECL then it is always put into the file scope. */
+
+void
+c_bind (location_t loc, tree decl, bool is_global)
+{
+ struct c_scope *scope;
+ bool nested = false;
+
+ if (!VAR_P (decl) || current_function_scope == NULL)
+ {
+ /* Types and functions are always considered to be global. */
+ scope = file_scope;
+ DECL_EXTERNAL (decl) = 1;
+ TREE_PUBLIC (decl) = 1;
+ }
+ else if (is_global)
+ {
+ /* Also bind it into the external scope. */
+ bind (DECL_NAME (decl), decl, external_scope, true, false, loc);
+ nested = true;
+ scope = file_scope;
+ DECL_EXTERNAL (decl) = 1;
+ TREE_PUBLIC (decl) = 1;
+ }
+ else
+ {
+ DECL_CONTEXT (decl) = current_function_decl;
+ TREE_PUBLIC (decl) = 0;
+ scope = current_function_scope;
+ }
+
+ bind (DECL_NAME (decl), decl, scope, false, nested, loc);
+}
\f
/* Subroutine of compare_decls. Allow harmless mismatches in return
and argument types provided that the type modes match. This function
}
trytype = build_function_type (newrettype, tryargs);
- return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype));
+
+ /* Allow declaration to change transaction_safe attribute. */
+ tree oldattrs = TYPE_ATTRIBUTES (oldtype);
+ tree oldtsafe = lookup_attribute ("transaction_safe", oldattrs);
+ tree newattrs = TYPE_ATTRIBUTES (newtype);
+ tree newtsafe = lookup_attribute ("transaction_safe", newattrs);
+ if (oldtsafe && !newtsafe)
+ oldattrs = remove_attribute ("transaction_safe", oldattrs);
+ else if (newtsafe && !oldtsafe)
+ oldattrs = tree_cons (get_identifier ("transaction_safe"),
+ NULL_TREE, oldattrs);
+
+ return build_type_attribute_variant (trytype, oldattrs);
}
/* Subroutine of diagnose_mismatched_decls. Check for function type
newdecl);
locate_old_decl (olddecl);
}
- else if (pedantic && !flag_isoc11)
- {
- pedwarn (input_location, OPT_Wpedantic,
- "redefinition of typedef %q+D", newdecl);
- locate_old_decl (olddecl);
- }
+ else if (pedwarn_c99 (input_location, OPT_Wpedantic,
+ "redefinition of typedef %q+D", newdecl))
+ locate_old_decl (olddecl);
return true;
}
}
}
}
- else if (TREE_CODE (newdecl) == VAR_DECL)
+ else if (VAR_P (newdecl))
{
/* Only variables can be thread-local, and all declarations must
agree on this property. */
/* Diagnose inline __attribute__ ((noinline)) which is silly. */
if (DECL_DECLARED_INLINE_P (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
- {
- warned |= warning (OPT_Wattributes,
- "inline declaration of %qD follows "
- "declaration with attribute noinline", newdecl);
- }
+ 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,
- "declaration of %q+D with attribute "
- "noinline follows inline declaration ", newdecl);
- }
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute "
+ "noinline follows inline declaration ", newdecl);
+ else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))
+ && lookup_attribute ("always_inline", DECL_ATTRIBUTES (olddecl)))
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute "
+ "%qs follows declaration with attribute %qs",
+ newdecl, "noinline", "always_inline");
+ else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (newdecl))
+ && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute "
+ "%qs follows declaration with attribute %qs",
+ newdecl, "always_inline", "noinline");
+ else if (lookup_attribute ("cold", DECL_ATTRIBUTES (newdecl))
+ && lookup_attribute ("hot", DECL_ATTRIBUTES (olddecl)))
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute %qs follows "
+ "declaration with attribute %qs", newdecl, "cold",
+ "hot");
+ else if (lookup_attribute ("hot", DECL_ATTRIBUTES (newdecl))
+ && lookup_attribute ("cold", DECL_ATTRIBUTES (olddecl)))
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute %qs follows "
+ "declaration with attribute %qs", newdecl, "hot",
+ "cold");
}
else /* PARM_DECL, VAR_DECL */
{
&& !(TREE_CODE (newdecl) == PARM_DECL
&& TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
/* Don't warn about a variable definition following a declaration. */
- && !(TREE_CODE (newdecl) == VAR_DECL
+ && !(VAR_P (newdecl)
&& DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl)))
{
warned = warning (OPT_Wredundant_decls, "redundant redeclaration of %q+D",
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
/* Merge the threadprivate attribute. */
- if (TREE_CODE (olddecl) == VAR_DECL && C_DECL_THREADPRIVATE_P (olddecl))
- {
- DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl);
- C_DECL_THREADPRIVATE_P (newdecl) = 1;
- }
+ if (VAR_P (olddecl) && C_DECL_THREADPRIVATE_P (olddecl))
+ C_DECL_THREADPRIVATE_P (newdecl) = 1;
if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS))
{
- /* Merge the section attribute.
- We want to issue an error if the sections conflict but that
- must be done later in decl_attributes since we are called
- before attributes are assigned. */
- if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
- DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
-
/* Copy the assembler name.
Currently, it can only be defined in the prototype. */
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
&& !current_function_decl)
DECL_EXTERNAL (newdecl) = 0;
+ /* An inline definition following a static declaration is not
+ DECL_EXTERNAL. */
+ if (new_is_definition
+ && (DECL_DECLARED_INLINE_P (newdecl)
+ || DECL_DECLARED_INLINE_P (olddecl))
+ && !TREE_PUBLIC (olddecl))
+ DECL_EXTERNAL (newdecl) = 0;
+
if (DECL_EXTERNAL (newdecl))
{
TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
set_builtin_decl_implicit_p (fncode, true);
break;
default:
+ if (builtin_decl_explicit_p (fncode))
+ set_builtin_decl_declared_p (fncode, true);
break;
}
}
TREE_USED (newdecl) = 1;
else if (TREE_USED (newdecl))
TREE_USED (olddecl) = 1;
- if (TREE_CODE (olddecl) == VAR_DECL || TREE_CODE (olddecl) == PARM_DECL)
+ if (VAR_P (olddecl) || 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;
+ /* Merge DECL_COMMON */
+ if (VAR_P (olddecl) && VAR_P (newdecl)
+ && !lookup_attribute ("common", DECL_ATTRIBUTES (newdecl))
+ && !lookup_attribute ("nocommon", DECL_ATTRIBUTES (newdecl)))
+ DECL_COMMON (newdecl) = DECL_COMMON (newdecl) && DECL_COMMON (olddecl);
+
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
DECL_ARGUMENTS (if appropriate). */
switch (TREE_CODE (olddecl))
{
case FUNCTION_DECL:
- case FIELD_DECL:
case VAR_DECL:
+ {
+ struct symtab_node *snode = olddecl->decl_with_vis.symtab_node;
+
+ memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
+ (char *) newdecl + sizeof (struct tree_decl_common),
+ tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common));
+ olddecl->decl_with_vis.symtab_node = snode;
+
+ if ((DECL_EXTERNAL (olddecl)
+ || TREE_PUBLIC (olddecl)
+ || TREE_STATIC (olddecl))
+ && DECL_SECTION_NAME (newdecl) != NULL)
+ set_decl_section_name (olddecl, DECL_SECTION_NAME (newdecl));
+
+ /* This isn't quite correct for something like
+ int __thread x attribute ((tls_model ("local-exec")));
+ extern int __thread x;
+ as we'll lose the "local-exec" model. */
+ if (VAR_P (olddecl) && DECL_THREAD_LOCAL_P (newdecl))
+ set_decl_tls_model (olddecl, DECL_TLS_MODEL (newdecl));
+ break;
+ }
+
+ case FIELD_DECL:
case PARM_DECL:
case LABEL_DECL:
case RESULT_DECL:
flags and attributes. */
if (DECL_RTL_SET_P (olddecl)
&& (TREE_CODE (olddecl) == FUNCTION_DECL
- || (TREE_CODE (olddecl) == VAR_DECL
- && TREE_STATIC (olddecl))))
+ || (VAR_P (olddecl) && TREE_STATIC (olddecl))))
make_decl_rtl (olddecl);
}
}
merge_decls (newdecl, olddecl, newtype, oldtype);
+
+ /* The NEWDECL will no longer be needed.
+
+ Before releasing the node, be sure to remove function from symbol
+ table that might have been inserted there to record comdat group.
+ Be sure to however do not free DECL_STRUCT_FUNCTION because this
+ structure is shared in between NEWDECL and OLDECL. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ DECL_STRUCT_FUNCTION (newdecl) = NULL;
+ if (VAR_OR_FUNCTION_DECL_P (newdecl))
+ {
+ struct symtab_node *snode = symtab_node::get (newdecl);
+ if (snode)
+ snode->remove ();
+ }
+ ggc_free (newdecl);
return true;
}
DECL_SOURCE_LOCATION (b->decl))))
{
tree old_decl = b->decl;
+ bool warned = false;
if (old_decl == error_mark_node)
{
break;
}
else if (TREE_CODE (old_decl) == PARM_DECL)
- warning (OPT_Wshadow, "declaration of %q+D shadows a parameter",
- new_decl);
+ warned = warning (OPT_Wshadow,
+ "declaration of %q+D shadows a parameter",
+ new_decl);
else if (DECL_FILE_SCOPE_P (old_decl))
{
/* Do not warn if a variable shadows a function, unless
&& !FUNCTION_POINTER_TYPE_P (TREE_TYPE (new_decl)))
continue;
- warning_at (DECL_SOURCE_LOCATION (new_decl), OPT_Wshadow,
- "declaration of %qD shadows a global declaration",
- new_decl);
+ warned = warning_at (DECL_SOURCE_LOCATION (new_decl), OPT_Wshadow,
+ "declaration of %qD shadows a global "
+ "declaration",
+ new_decl);
}
else if (TREE_CODE (old_decl) == FUNCTION_DECL
&& DECL_BUILT_IN (old_decl))
break;
}
else
- warning (OPT_Wshadow, "declaration of %q+D shadows a previous local",
- new_decl);
+ warned = warning (OPT_Wshadow, "declaration of %q+D shadows a "
+ "previous local", new_decl);
- warning_at (DECL_SOURCE_LOCATION (old_decl), OPT_Wshadow,
- "shadowed declaration is here");
+ if (warned)
+ inform (DECL_SOURCE_LOCATION (old_decl),
+ "shadowed declaration is here");
break;
}
DECL_FILE_SCOPE_P won't work. Local externs don't count
unless they have initializers (which generate code). */
if (current_function_decl
- && ((TREE_CODE (x) != FUNCTION_DECL && TREE_CODE (x) != VAR_DECL)
+ && (!VAR_OR_FUNCTION_DECL_P (x)
|| DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
DECL_CONTEXT (x) = current_function_decl;
tree visdecl = 0;
bool type_saved = false;
if (b && !B_IN_EXTERNAL_SCOPE (b)
- && (TREE_CODE (b->decl) == FUNCTION_DECL
- || TREE_CODE (b->decl) == VAR_DECL)
+ && VAR_OR_FUNCTION_DECL_P (b->decl)
&& DECL_FILE_SCOPE_P (b->decl))
{
visdecl = b->decl;
type_saved = true;
}
if (B_IN_FILE_SCOPE (b)
- && TREE_CODE (b->decl) == VAR_DECL
+ && VAR_P (b->decl)
&& TREE_STATIC (b->decl)
&& TREE_CODE (TREE_TYPE (b->decl)) == ARRAY_TYPE
&& !TYPE_DOMAIN (TREE_TYPE (b->decl))
{
tree name;
bool nested = false;
- gcc_assert (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == CONST_DECL);
+ gcc_assert (VAR_P (x) || TREE_CODE (x) == CONST_DECL);
name = DECL_NAME (x);
}
\f
static void
-implicit_decl_warning (tree id, tree olddecl)
+implicit_decl_warning (location_t loc, tree id, tree olddecl)
{
if (warn_implicit_function_declaration)
{
bool warned;
if (flag_isoc99)
- warned = pedwarn (input_location, OPT_Wimplicit_function_declaration,
+ warned = pedwarn (loc, OPT_Wimplicit_function_declaration,
"implicit declaration of function %qE", id);
else
- warned = warning (OPT_Wimplicit_function_declaration,
- G_("implicit declaration of function %qE"), id);
+ warned = warning_at (loc, OPT_Wimplicit_function_declaration,
+ G_("implicit declaration of function %qE"), id);
if (olddecl && warned)
locate_old_decl (olddecl);
}
}
+/* This function represents mapping of a function code FCODE
+ to its respective header. */
+
+static const char *
+header_for_builtin_fn (enum built_in_function fcode)
+{
+ switch (fcode)
+ {
+ CASE_FLT_FN (BUILT_IN_ACOS):
+ CASE_FLT_FN (BUILT_IN_ACOSH):
+ CASE_FLT_FN (BUILT_IN_ASIN):
+ CASE_FLT_FN (BUILT_IN_ASINH):
+ CASE_FLT_FN (BUILT_IN_ATAN):
+ CASE_FLT_FN (BUILT_IN_ATANH):
+ CASE_FLT_FN (BUILT_IN_ATAN2):
+ CASE_FLT_FN (BUILT_IN_CBRT):
+ CASE_FLT_FN (BUILT_IN_CEIL):
+ CASE_FLT_FN (BUILT_IN_COPYSIGN):
+ CASE_FLT_FN (BUILT_IN_COS):
+ CASE_FLT_FN (BUILT_IN_COSH):
+ CASE_FLT_FN (BUILT_IN_ERF):
+ CASE_FLT_FN (BUILT_IN_ERFC):
+ CASE_FLT_FN (BUILT_IN_EXP):
+ CASE_FLT_FN (BUILT_IN_EXP2):
+ CASE_FLT_FN (BUILT_IN_EXPM1):
+ CASE_FLT_FN (BUILT_IN_FABS):
+ CASE_FLT_FN (BUILT_IN_FDIM):
+ CASE_FLT_FN (BUILT_IN_FLOOR):
+ CASE_FLT_FN (BUILT_IN_FMA):
+ CASE_FLT_FN (BUILT_IN_FMAX):
+ CASE_FLT_FN (BUILT_IN_FMIN):
+ CASE_FLT_FN (BUILT_IN_FMOD):
+ CASE_FLT_FN (BUILT_IN_FREXP):
+ CASE_FLT_FN (BUILT_IN_HYPOT):
+ CASE_FLT_FN (BUILT_IN_ILOGB):
+ CASE_FLT_FN (BUILT_IN_LDEXP):
+ CASE_FLT_FN (BUILT_IN_LGAMMA):
+ CASE_FLT_FN (BUILT_IN_LLRINT):
+ CASE_FLT_FN (BUILT_IN_LLROUND):
+ CASE_FLT_FN (BUILT_IN_LOG):
+ CASE_FLT_FN (BUILT_IN_LOG10):
+ CASE_FLT_FN (BUILT_IN_LOG1P):
+ CASE_FLT_FN (BUILT_IN_LOG2):
+ CASE_FLT_FN (BUILT_IN_LOGB):
+ CASE_FLT_FN (BUILT_IN_LRINT):
+ CASE_FLT_FN (BUILT_IN_LROUND):
+ CASE_FLT_FN (BUILT_IN_MODF):
+ CASE_FLT_FN (BUILT_IN_NAN):
+ CASE_FLT_FN (BUILT_IN_NEARBYINT):
+ CASE_FLT_FN (BUILT_IN_NEXTAFTER):
+ CASE_FLT_FN (BUILT_IN_NEXTTOWARD):
+ CASE_FLT_FN (BUILT_IN_POW):
+ CASE_FLT_FN (BUILT_IN_REMAINDER):
+ CASE_FLT_FN (BUILT_IN_REMQUO):
+ CASE_FLT_FN (BUILT_IN_RINT):
+ CASE_FLT_FN (BUILT_IN_ROUND):
+ CASE_FLT_FN (BUILT_IN_SCALBLN):
+ CASE_FLT_FN (BUILT_IN_SCALBN):
+ CASE_FLT_FN (BUILT_IN_SIN):
+ CASE_FLT_FN (BUILT_IN_SINH):
+ CASE_FLT_FN (BUILT_IN_SINCOS):
+ CASE_FLT_FN (BUILT_IN_SQRT):
+ CASE_FLT_FN (BUILT_IN_TAN):
+ CASE_FLT_FN (BUILT_IN_TANH):
+ CASE_FLT_FN (BUILT_IN_TGAMMA):
+ CASE_FLT_FN (BUILT_IN_TRUNC):
+ case BUILT_IN_ISINF:
+ case BUILT_IN_ISNAN:
+ return "<math.h>";
+ CASE_FLT_FN (BUILT_IN_CABS):
+ CASE_FLT_FN (BUILT_IN_CACOS):
+ CASE_FLT_FN (BUILT_IN_CACOSH):
+ CASE_FLT_FN (BUILT_IN_CARG):
+ CASE_FLT_FN (BUILT_IN_CASIN):
+ CASE_FLT_FN (BUILT_IN_CASINH):
+ CASE_FLT_FN (BUILT_IN_CATAN):
+ CASE_FLT_FN (BUILT_IN_CATANH):
+ CASE_FLT_FN (BUILT_IN_CCOS):
+ CASE_FLT_FN (BUILT_IN_CCOSH):
+ CASE_FLT_FN (BUILT_IN_CEXP):
+ CASE_FLT_FN (BUILT_IN_CIMAG):
+ CASE_FLT_FN (BUILT_IN_CLOG):
+ CASE_FLT_FN (BUILT_IN_CONJ):
+ CASE_FLT_FN (BUILT_IN_CPOW):
+ CASE_FLT_FN (BUILT_IN_CPROJ):
+ CASE_FLT_FN (BUILT_IN_CREAL):
+ CASE_FLT_FN (BUILT_IN_CSIN):
+ CASE_FLT_FN (BUILT_IN_CSINH):
+ CASE_FLT_FN (BUILT_IN_CSQRT):
+ CASE_FLT_FN (BUILT_IN_CTAN):
+ CASE_FLT_FN (BUILT_IN_CTANH):
+ return "<complex.h>";
+ case BUILT_IN_MEMCHR:
+ case BUILT_IN_MEMCMP:
+ case BUILT_IN_MEMCPY:
+ case BUILT_IN_MEMMOVE:
+ case BUILT_IN_MEMSET:
+ case BUILT_IN_STRCAT:
+ case BUILT_IN_STRCHR:
+ case BUILT_IN_STRCMP:
+ case BUILT_IN_STRCPY:
+ case BUILT_IN_STRCSPN:
+ case BUILT_IN_STRLEN:
+ case BUILT_IN_STRNCAT:
+ case BUILT_IN_STRNCMP:
+ case BUILT_IN_STRNCPY:
+ case BUILT_IN_STRPBRK:
+ case BUILT_IN_STRRCHR:
+ case BUILT_IN_STRSPN:
+ case BUILT_IN_STRSTR:
+ return "<string.h>";
+ case BUILT_IN_FPRINTF:
+ case BUILT_IN_PUTC:
+ case BUILT_IN_FPUTC:
+ case BUILT_IN_FPUTS:
+ case BUILT_IN_FSCANF:
+ case BUILT_IN_FWRITE:
+ case BUILT_IN_PRINTF:
+ case BUILT_IN_PUTCHAR:
+ case BUILT_IN_PUTS:
+ case BUILT_IN_SCANF:
+ case BUILT_IN_SNPRINTF:
+ case BUILT_IN_SPRINTF:
+ case BUILT_IN_SSCANF:
+ case BUILT_IN_VFPRINTF:
+ case BUILT_IN_VFSCANF:
+ case BUILT_IN_VPRINTF:
+ case BUILT_IN_VSCANF:
+ case BUILT_IN_VSNPRINTF:
+ case BUILT_IN_VSPRINTF:
+ case BUILT_IN_VSSCANF:
+ return "<stdio.h>";
+ case BUILT_IN_ISALNUM:
+ case BUILT_IN_ISALPHA:
+ case BUILT_IN_ISBLANK:
+ case BUILT_IN_ISCNTRL:
+ case BUILT_IN_ISDIGIT:
+ case BUILT_IN_ISGRAPH:
+ case BUILT_IN_ISLOWER:
+ case BUILT_IN_ISPRINT:
+ case BUILT_IN_ISPUNCT:
+ case BUILT_IN_ISSPACE:
+ case BUILT_IN_ISUPPER:
+ case BUILT_IN_ISXDIGIT:
+ case BUILT_IN_TOLOWER:
+ case BUILT_IN_TOUPPER:
+ return "<ctype.h>";
+ case BUILT_IN_ISWALNUM:
+ case BUILT_IN_ISWALPHA:
+ case BUILT_IN_ISWBLANK:
+ case BUILT_IN_ISWCNTRL:
+ case BUILT_IN_ISWDIGIT:
+ case BUILT_IN_ISWGRAPH:
+ case BUILT_IN_ISWLOWER:
+ case BUILT_IN_ISWPRINT:
+ case BUILT_IN_ISWPUNCT:
+ case BUILT_IN_ISWSPACE:
+ case BUILT_IN_ISWUPPER:
+ case BUILT_IN_ISWXDIGIT:
+ case BUILT_IN_TOWLOWER:
+ case BUILT_IN_TOWUPPER:
+ return "<wctype.h>";
+ case BUILT_IN_ABORT:
+ case BUILT_IN_ABS:
+ case BUILT_IN_CALLOC:
+ case BUILT_IN_EXIT:
+ case BUILT_IN_FREE:
+ case BUILT_IN_LABS:
+ case BUILT_IN_LLABS:
+ case BUILT_IN_MALLOC:
+ case BUILT_IN_REALLOC:
+ case BUILT_IN__EXIT2:
+ case BUILT_IN_ALIGNED_ALLOC:
+ return "<stdlib.h>";
+ case BUILT_IN_IMAXABS:
+ return "<inttypes.h>";
+ case BUILT_IN_STRFTIME:
+ return "<time.h>";
+ default:
+ return NULL;
+ }
+}
+
/* Generate an implicit declaration for identifier FUNCTIONID at LOC as a
function of type int (). */
then recycle the old declaration but with the new type. */
if (!C_DECL_IMPLICIT (decl))
{
- implicit_decl_warning (functionid, decl);
+ implicit_decl_warning (loc, functionid, decl);
C_DECL_IMPLICIT (decl) = 1;
}
if (DECL_BUILT_IN (decl))
(TREE_TYPE (decl)));
if (!comptypes (newtype, TREE_TYPE (decl)))
{
- warning_at (loc, 0, "incompatible implicit declaration of "
- "built-in function %qD", decl);
+ bool warned = warning_at (loc, 0, "incompatible implicit "
+ "declaration of built-in "
+ "function %qD", decl);
+ /* See if we can hint which header to include. */
+ const char *header
+ = header_for_builtin_fn (DECL_FUNCTION_CODE (decl));
+ if (header != NULL && warned)
+ inform (loc, "include %qs or provide a declaration of %qD",
+ header, decl);
newtype = TREE_TYPE (decl);
}
}
{
if (!comptypes (newtype, TREE_TYPE (decl)))
{
- error_at (loc, "incompatible implicit declaration of function %qD", decl);
+ error_at (loc, "incompatible implicit declaration of "
+ "function %qD", decl);
locate_old_decl (decl);
}
}
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
C_DECL_IMPLICIT (decl) = 1;
- implicit_decl_warning (functionid, 0);
+ implicit_decl_warning (loc, functionid, 0);
asmspec_tree = maybe_apply_renaming_pragma (decl, /*asmname=*/NULL);
if (asmspec_tree)
set_user_assembler_name (decl, TREE_STRING_POINTER (asmspec_tree));
struct c_label_vars **p_label_vars)
{
tree label = build_decl (location, LABEL_DECL, name, void_type_node);
- struct c_label_vars *label_vars;
-
DECL_CONTEXT (label) = current_function_decl;
DECL_MODE (label) = VOIDmode;
- label_vars = ggc_alloc_c_label_vars ();
+ 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 ();
if (current_function_scope == 0)
{
error ("label %qE referenced outside of any function", name);
- return 0;
+ return NULL_TREE;
}
/* Use a label already defined or ref'd with this name, but not if
list for possible later warnings. */
if (label_vars->label_bindings.scope == NULL)
{
- struct c_goto_bindings *g;
+ c_goto_bindings *g = ggc_alloc<c_goto_bindings> ();
- g = ggc_alloc_c_goto_bindings ();
g->loc = loc;
set_spot_bindings (&g->goto_bindings, true);
vec_safe_push (label_vars->gotos, g);
bind_label (name, label, current_function_scope, label_vars);
}
- if (!in_system_header && lookup_name (name))
+ if (!in_system_header_at (input_location) && lookup_name (name))
warning_at (location, OPT_Wtraditional,
"traditional C lacks a separate namespace "
"for labels, identifier %qE conflicts", name);
If the wrong kind of type is found, an error is reported. */
static tree
-lookup_tag (enum tree_code code, tree name, int thislevel_only,
+lookup_tag (enum tree_code code, tree name, bool thislevel_only,
location_t *ploc)
{
struct c_binding *b = I_TAG_BINDING (name);
- int thislevel = 0;
+ bool thislevel = false;
if (!b || !b->decl)
- return 0;
+ return NULL_TREE;
/* We only care about whether it's in this level if
thislevel_only was set or it might be a type clash. */
file scope is created.) */
if (B_IN_CURRENT_SCOPE (b)
|| (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
- thislevel = 1;
+ thislevel = true;
}
if (thislevel_only && !thislevel)
- return 0;
+ return NULL_TREE;
if (TREE_CODE (b->decl) != code)
{
return b->decl;
}
+/* Return true if a definition exists for NAME with code CODE. */
+
+bool
+tag_exists_p (enum tree_code code, tree name)
+{
+ struct c_binding *b = I_TAG_BINDING (name);
+
+ if (b == NULL || b->decl == NULL_TREE)
+ return false;
+ return TREE_CODE (b->decl) == code;
+}
+
/* Print an error message now
for a recent invalid struct, union or enum cross reference.
We don't print them immediately because they are not invalid
maybe_record_typedef_use (b->decl);
return b->decl;
}
- return 0;
+ return NULL_TREE;
}
/* Similar to `lookup_name' but look only at the indicated scope. */
for (b = I_SYMBOL_BINDING (name); b; b = b->shadowed)
if (B_IN_SCOPE (b, scope))
return b->decl;
- return 0;
+ return NULL_TREE;
}
\f
/* Create the predefined scalar types of C,
input_location = save_loc;
- pedantic_lvalues = true;
-
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
}
const char *name = IDENTIFIER_POINTER (id);
C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type);
- bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false,
- UNKNOWN_LOCATION);
+ if (external_scope)
+ bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false,
+ UNKNOWN_LOCATION);
/* Builtins in the implementation namespace are made visible without
needing to be explicitly declared. See push_file_scope. */
else
{
pending_invalid_xref = 0;
- t = lookup_tag (code, name, 1, NULL);
+ t = lookup_tag (code, name, true, NULL);
- if (t == 0)
+ if (t == NULL_TREE)
{
t = make_node (code);
pushtag (input_location, name, t);
}
else
{
- if (warned != 1 && !in_system_header)
+ if (warned != 1 && !in_system_header_at (input_location))
{
pedwarn (input_location, 0,
"useless type name in empty declaration");
}
}
}
- else if (warned != 1 && !in_system_header && declspecs->typedef_p)
+ else if (warned != 1 && !in_system_header_at (input_location)
+ && declspecs->typedef_p)
{
pedwarn (input_location, 0, "useless type name in empty declaration");
warned = 1;
warned = 1;
}
- if (!warned && !in_system_header && declspecs->storage_class != csc_none)
+ if (!warned && !in_system_header_at (input_location)
+ && declspecs->storage_class != csc_none)
{
warning (0, "useless storage class specifier in empty declaration");
warned = 2;
}
- if (!warned && !in_system_header && declspecs->thread_p)
+ if (!warned && !in_system_header_at (input_location) && declspecs->thread_p)
{
warning (0, "useless %qs in empty declaration",
declspecs->thread_gnu_p ? "__thread" : "_Thread_local");
warned = 2;
}
- if (!warned && !in_system_header && (declspecs->const_p
- || declspecs->volatile_p
- || declspecs->atomic_p
- || declspecs->restrict_p
- || declspecs->address_space))
+ if (!warned
+ && !in_system_header_at (input_location)
+ && (declspecs->const_p
+ || declspecs->volatile_p
+ || declspecs->atomic_p
+ || declspecs->restrict_p
+ || declspecs->address_space))
{
warning (0, "useless type qualifier in empty declaration");
warned = 2;
}
- if (!warned && !in_system_header && declspecs->alignas_p)
+ if (!warned && !in_system_header_at (input_location)
+ && declspecs->alignas_p)
{
warning (0, "useless %<_Alignas%> in empty declaration");
warned = 2;
}
declarator->u.array.static_p = static_p;
declarator->u.array.vla_unspec_p = vla_unspec_p;
- if (!flag_isoc99)
- {
- if (static_p || quals != NULL)
- pedwarn (loc, OPT_Wpedantic,
+ if (static_p || quals != NULL)
+ pedwarn_c90 (loc, OPT_Wpedantic,
"ISO C90 does not support %<static%> or type "
"qualifiers in parameter array declarators");
- if (vla_unspec_p)
- pedwarn (loc, OPT_Wpedantic,
+ if (vla_unspec_p)
+ pedwarn_c90 (loc, OPT_Wpedantic,
"ISO C90 does not support %<[*]%> array declarators");
- }
if (vla_unspec_p)
{
if (!current_scope->parm_flag)
{
/* Add implicit "omp declare target" attribute if requested. */
if (current_omp_declare_target_attribute
- && ((TREE_CODE (*node) == VAR_DECL && TREE_STATIC (*node))
+ && ((VAR_P (*node) && is_global_var (*node))
|| TREE_CODE (*node) == FUNCTION_DECL))
{
- if (TREE_CODE (*node) == VAR_DECL
- && ((DECL_CONTEXT (*node)
- && TREE_CODE (DECL_CONTEXT (*node)) == FUNCTION_DECL)
- || (current_function_decl && !DECL_EXTERNAL (*node))))
- error ("%q+D in block scope inside of declare target directive",
- *node);
- else if (TREE_CODE (*node) == VAR_DECL
- && !COMPLETE_TYPE_P (TREE_TYPE (*node)))
+ if (VAR_P (*node)
+ && !lang_hooks.types.omp_mappable_type (TREE_TYPE (*node)))
error ("%q+D in declare target directive does not have mappable type",
*node);
else
decl = grokdeclarator (declarator, declspecs,
NORMAL, initialized, NULL, &attributes, &expr, NULL,
deprecated_state);
- if (!decl)
- return 0;
+ if (!decl || decl == error_mark_node)
+ return NULL_TREE;
if (expr)
add_stmt (fold_convert (void_type_node, expr));
body of code to break, and it allows more efficient variable references
in the presence of dynamic linking. */
- if (TREE_CODE (decl) == VAR_DECL
+ if (VAR_P (decl)
&& !initialized
&& TREE_PUBLIC (decl)
&& !DECL_THREAD_LOCAL_P (decl)
/* C99 6.7.4p3: An inline definition of a function with external
linkage shall not contain a definition of a modifiable object
with static storage duration... */
- if (TREE_CODE (decl) == VAR_DECL
+ if (VAR_P (decl)
&& current_scope != file_scope
&& TREE_STATIC (decl)
&& !TREE_READONLY (decl)
record_inline_static (input_location, current_function_decl,
decl, csi_modifiable);
- if (c_dialect_objc ()
- && (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL))
+ if (c_dialect_objc ()
+ && VAR_OR_FUNCTION_DECL_P (decl))
objc_check_global_decl (decl);
/* Add this decl to the current scope.
void
finish_decl (tree decl, location_t init_loc, tree init,
- tree origtype, tree asmspec_tree)
+ tree origtype, tree asmspec_tree)
{
tree type;
bool was_incomplete = (DECL_SIZE (decl) == 0);
const char *asmspec = 0;
/* If a name was specified, get the string. */
- if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
+ if (VAR_OR_FUNCTION_DECL_P (decl)
&& DECL_FILE_SCOPE_P (decl))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
- if (TREE_CODE (decl) == VAR_DECL
+ if (VAR_P (decl)
&& TREE_STATIC (decl)
&& global_bindings_p ())
/* So decl is a global variable. Record the types it uses
if (init)
store_init_value (init_loc, decl, init, origtype);
- if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL
+ if (c_dialect_objc () && (VAR_OR_FUNCTION_DECL_P (decl)
|| TREE_CODE (decl) == FIELD_DECL))
objc_check_decl (decl);
relayout_decl (decl);
}
- if (TREE_CODE (decl) == VAR_DECL)
+ if (VAR_P (decl))
{
if (init && TREE_CODE (init) == CONSTRUCTOR)
add_flexible_array_elts_to_size (decl, init);
TREE_TYPE (decl) = error_mark_node;
}
- if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
- && DECL_SIZE (decl) != 0)
+ if (is_global_var (decl) && DECL_SIZE (decl) != 0)
{
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
unless the type is an undefined structure or union.
If not, it will get done when the type is completed. */
- if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+ if (VAR_OR_FUNCTION_DECL_P (decl))
{
/* Determine the ELF visibility. */
if (TREE_PUBLIC (decl))
GCC has accepted -- but ignored -- the ASMSPEC in
this case. */
if (!DECL_FILE_SCOPE_P (decl)
- && TREE_CODE (decl) == VAR_DECL
+ && VAR_P (decl)
&& !C_DECL_REGISTER (decl)
&& !TREE_STATIC (decl))
warning (0, "ignoring asm-specifier for non-static local "
{
/* Recompute the RTL of a local array now
if it used to be an incomplete type. */
- if (was_incomplete
- && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+ if (was_incomplete && !is_global_var (decl))
{
/* If we used it already as memory, it must stay in memory. */
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
}
/* Install a cleanup (aka destructor) if one was given. */
- if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+ if (VAR_P (decl) && !TREE_STATIC (decl))
{
tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
if (attr)
cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
vec_alloc (v, 1);
v->quick_push (cleanup);
- cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl),
- cleanup_decl, v, NULL);
+ cleanup = c_build_function_call_vec (DECL_SOURCE_LOCATION (decl),
+ vNULL, cleanup_decl, v, NULL);
vec_free (v);
/* Don't warn about decl unused; the cleanup uses it. */
}
if (warn_cxx_compat
- && TREE_CODE (decl) == VAR_DECL
+ && VAR_P (decl)
&& !DECL_EXTERNAL (decl)
&& DECL_INITIAL (decl) == NULL_TREE)
{
{
int failure = complete_array_type (&TREE_TYPE (decl),
DECL_INITIAL (decl), true);
- gcc_assert (!failure);
+ /* If complete_array_type returns 3, it means that the
+ initial value of the compound literal is empty. Allow it. */
+ gcc_assert (failure == 0 || failure == 3);
type = TREE_TYPE (decl);
TREE_TYPE (DECL_INITIAL (decl)) = type;
\f
/* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
replacing with appropriate values if they are invalid. */
+
static void
-check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
+check_bitfield_type_and_width (location_t loc, tree *type, tree *width,
+ tree orig_name)
{
tree type_mv;
unsigned int max_width;
field widths. */
if (!INTEGRAL_TYPE_P (TREE_TYPE (*width)))
{
- error ("bit-field %qs width not an integer constant", name);
+ error_at (loc, "bit-field %qs width not an integer constant", name);
*width = integer_one_node;
}
else
{
*width = c_fully_fold (*width, false, NULL);
if (TREE_CODE (*width) == INTEGER_CST)
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (loc, OPT_Wpedantic,
"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);
+ error_at (loc, "bit-field %qs width not an integer constant", name);
*width = integer_one_node;
}
constant_expression_warning (*width);
if (tree_int_cst_sgn (*width) < 0)
{
- error ("negative width in bit-field %qs", name);
+ error_at (loc, "negative width in bit-field %qs", name);
*width = integer_one_node;
}
else if (integer_zerop (*width) && orig_name)
{
- error ("zero width for bit-field %qs", name);
+ error_at (loc, "zero width for bit-field %qs", name);
*width = integer_one_node;
}
}
&& TREE_CODE (*type) != BOOLEAN_TYPE
&& TREE_CODE (*type) != ENUMERAL_TYPE)
{
- error ("bit-field %qs has invalid type", name);
+ error_at (loc, "bit-field %qs has invalid type", name);
*type = unsigned_type_node;
}
type_mv = TYPE_MAIN_VARIANT (*type);
- if (!in_system_header
+ if (!in_system_header_at (input_location)
&& type_mv != integer_type_node
&& type_mv != unsigned_type_node
&& type_mv != boolean_type_node)
- pedwarn (input_location, OPT_Wpedantic,
- "type of bit-field %qs is a GCC extension", name);
+ pedwarn_c90 (loc, OPT_Wpedantic,
+ "type of bit-field %qs is a GCC extension", name);
max_width = TYPE_PRECISION (*type);
if (0 < compare_tree_int (*width, max_width))
{
- error ("width of %qs exceeds its type", name);
+ error_at (loc, "width of %qs exceeds its type", name);
w = max_width;
*width = build_int_cst (integer_type_node, w);
}
else
- w = tree_low_cst (*width, 1);
+ w = tree_to_uhwi (*width);
if (TREE_CODE (*type) == ENUMERAL_TYPE)
{
struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
if (!lt
- || w < tree_int_cst_min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
- || w < tree_int_cst_min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
- warning (0, "%qs is narrower than values of its type", name);
+ || w < tree_int_cst_min_precision (lt->enum_min, TYPE_SIGN (*type))
+ || w < tree_int_cst_min_precision (lt->enum_max, TYPE_SIGN (*type)))
+ warning_at (loc, 0, "%qs is narrower than values of its type", name);
}
}
static void
warn_variable_length_array (tree name, tree size)
{
- int const_size = TREE_CONSTANT (size);
-
- if (!flag_isoc99 && pedantic && warn_vla != 0)
+ if (TREE_CONSTANT (size))
{
- if (const_size)
- {
- if (name)
- pedwarn (input_location, OPT_Wvla,
+ if (name)
+ pedwarn_c90 (input_location, OPT_Wvla,
"ISO C90 forbids array %qE whose size "
- "can%'t be evaluated",
- name);
- else
- pedwarn (input_location, OPT_Wvla, "ISO C90 forbids array whose size "
- "can%'t be evaluated");
- }
+ "can%'t be evaluated", name);
else
- {
- if (name)
- pedwarn (input_location, OPT_Wvla,
- "ISO C90 forbids variable length array %qE",
- name);
- else
- pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length array");
- }
+ pedwarn_c90 (input_location, OPT_Wvla, "ISO C90 forbids array "
+ "whose size can%'t be evaluated");
}
- else if (warn_vla > 0)
+ else
{
- if (const_size)
- {
- if (name)
- warning (OPT_Wvla,
- "the size of array %qE can"
- "%'t be evaluated", name);
- else
- warning (OPT_Wvla,
- "the size of array can %'t be evaluated");
- }
+ if (name)
+ pedwarn_c90 (input_location, OPT_Wvla,
+ "ISO C90 forbids variable length array %qE", name);
else
- {
- if (name)
- warning (OPT_Wvla,
- "variable length array %qE is used",
- name);
- else
- warning (OPT_Wvla,
- "variable length array is used");
- }
+ pedwarn_c90 (input_location, OPT_Wvla, "ISO C90 forbids variable "
+ "length array");
}
}
+/* Print warning about defaulting to int if necessary. */
+
+static void
+warn_defaults_to (location_t location, int opt, const char *gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+ rich_location richloc (location);
+
+ va_start (ap, gmsgid);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ flag_isoc99 ? DK_PEDWARN : DK_WARNING);
+ diagnostic.option_index = opt;
+ report_diagnostic (&diagnostic);
+ va_end (ap);
+}
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
/* Diagnose defaulting to "int". */
- if (declspecs->default_int_p && !in_system_header)
+ if (declspecs->default_int_p && !in_system_header_at (input_location))
{
/* Issue a warning if this is an ISO C 99 program or if
-Wreturn-type and this is a function, or if -Wimplicit;
else
{
if (name)
- pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wimplicit_int,
- "type defaults to %<int%> in declaration of %qE",
- name);
+ warn_defaults_to (loc, OPT_Wimplicit_int,
+ "type defaults to %<int%> in declaration "
+ "of %qE", name);
else
- pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int,
- "type defaults to %<int%> in type name");
+ warn_defaults_to (loc, OPT_Wimplicit_int,
+ "type defaults to %<int%> in type name");
}
}
as2 = TYPE_ADDR_SPACE (element_type);
address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
- if (pedantic && !flag_isoc99)
- {
- if (constp > 1)
- pedwarn (loc, OPT_Wpedantic, "duplicate %<const%>");
- if (restrictp > 1)
- pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>");
- if (volatilep > 1)
- pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>");
- if (atomicp > 1)
- pedwarn (loc, OPT_Wpedantic, "duplicate %<_Atomic%>");
-
- }
+ if (constp > 1)
+ pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<const%>");
+ if (restrictp > 1)
+ pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<restrict%>");
+ if (volatilep > 1)
+ pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<volatile%>");
+ if (atomicp > 1)
+ pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<_Atomic%>");
if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
error_at (loc, "conflicting named address spaces (%s vs %s)",
type = error_mark_node;
}
- if (pedantic && !in_system_header && flexible_array_type_p (type))
+ if (pedantic && !in_system_header_at (input_location)
+ && flexible_array_type_p (type))
pedwarn (loc, OPT_Wpedantic,
"invalid use of structure with flexible array member");
this_size_varies = size_varies = true;
warn_variable_length_array (name, size);
if (flag_sanitize & SANITIZE_VLA
- && decl_context == NORMAL)
+ && decl_context == NORMAL
+ && do_ubsan_in_current_function ())
{
/* Evaluate the array size only once. */
size = c_save_expr (size);
flexible_array_member = (t->kind == cdk_id);
}
if (flexible_array_member
- && pedantic && !flag_isoc99 && !in_system_header)
- pedwarn (loc, OPT_Wpedantic,
- "ISO C90 does not support flexible array members");
+ && !in_system_header_at (input_location))
+ pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not "
+ "support flexible array members");
/* ISO C99 Flexible array members are effectively
identical to GCC's zero-length array extension. */
/* Complain about arrays of incomplete types. */
if (!COMPLETE_TYPE_P (type))
{
- error_at (loc, "array type has incomplete element type");
+ error_at (loc, "array type has incomplete element type %qT",
+ type);
type = error_mark_node;
}
else
/* Check the type and width of a bit-field. */
if (bitfield)
{
- check_bitfield_type_and_width (&type, width, name);
+ check_bitfield_type_and_width (loc, &type, width, name);
/* C11 makes it implementation-defined (6.7.2.1#5) whether
atomic types are permitted for bit-fields; we have no code to
make bit-field accesses atomic, so disallow them. */
if (type_quals & TYPE_QUAL_ATOMIC)
{
if (name)
- error ("bit-field %qE has atomic type", name);
+ error_at (loc, "bit-field %qE has atomic type", name);
else
- error ("bit-field has atomic type");
+ error_at (loc, "bit-field has atomic type");
type_quals &= ~TYPE_QUAL_ATOMIC;
}
}
else if (declspecs->align_log != -1)
{
alignas_align = 1U << declspecs->align_log;
- if (alignas_align < TYPE_ALIGN_UNIT (type))
+ if (alignas_align < min_align_of_type (type))
{
if (name)
error_at (loc, "%<_Alignas%> specifiers cannot reduce "
else
error_at (loc, "size of unnamed array is too large");
/* If we proceed with the array type as it is, we'll eventually
- crash in tree_low_cst(). */
+ crash in tree_to_[su]hwi(). */
type = error_mark_node;
}
if (decl_context == PARM)
{
tree promoted_type;
+ bool array_parameter_p = false;
/* A parameter declared as an array of T is really a pointer to T.
One declared as a function is really a pointer to a function. */
"attributes in parameter array declarator ignored");
size_varies = false;
+ array_parameter_p = true;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
PARM_DECL, declarator->u.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
+ C_ARRAY_PARAMETER (decl) = array_parameter_p;
/* Compute the type actually passed in the parmlist,
for the case where there is no prototype.
error_at (loc, "unnamed field has incomplete type");
type = error_mark_node;
}
+ else if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type) == NULL_TREE)
+ {
+ /* We have a flexible array member through a typedef.
+ Set suitable range. Whether this is a correct position
+ for a flexible array member will be determined elsewhere. */
+ if (!in_system_header_at (input_location))
+ pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not "
+ "support flexible array members");
+ type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+ TYPE_DOMAIN (type) = build_range_type (sizetype, size_zero_node,
+ NULL_TREE);
+ }
type = c_build_qualified_type (type, type_quals);
decl = build_decl (declarator->id_loc,
FIELD_DECL, declarator->u.id, type);
DECL_DECLARED_INLINE_P (decl) = 1;
if (declspecs->noreturn_p)
{
- if (!flag_isoc11)
- {
- if (flag_isoc99)
- pedwarn (loc, OPT_Wpedantic,
+ if (flag_isoc99)
+ pedwarn_c99 (loc, OPT_Wpedantic,
"ISO C99 does not support %<_Noreturn%>");
- else
- pedwarn (loc, OPT_Wpedantic,
+ else
+ pedwarn_c99 (loc, OPT_Wpedantic,
"ISO C90 does not support %<_Noreturn%>");
- }
TREE_THIS_VOLATILE (decl) = 1;
}
}
if (global_decl
&& global_decl != visible_decl
- && TREE_CODE (global_decl) == VAR_DECL
+ && VAR_P (global_decl)
&& !TREE_PUBLIC (global_decl))
error_at (loc, "variable previously declared %<static%> "
"redeclared %<extern%>");
}
if (threadp)
- DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
+ set_decl_tls_model (decl, decl_default_tls_model (decl));
}
if ((storage_class == csc_extern
will be ignored, and would even crash the compiler.
Of course, this only makes sense on VAR,PARM, and RESULT decl's. */
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl))
- && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
+ && (VAR_P (decl) || TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL))
{
/* It is not an error for a structure with volatile fields to
gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
if (warn_cxx_compat
- && TREE_CODE (decl) == VAR_DECL
+ && VAR_P (decl)
&& TREE_PUBLIC (decl)
&& TREE_STATIC (decl)
&& (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
error ("%<[*]%> not allowed in other than function prototype scope");
}
- if (arg_types == 0 && !funcdef_flag && !in_system_header)
+ if (arg_types == 0 && !funcdef_flag
+ && !in_system_header_at (input_location))
warning (OPT_Wstrict_prototypes,
"function declaration isn%'t a prototype");
tree types = 0;
tree others = 0;
- static bool explained_incomplete_types = false;
bool gave_void_only_once_err = false;
arg_info->had_vla_unspec = current_scope->had_vla_unspec;
{
if (b->id)
/* The %s will be one of 'struct', 'union', or 'enum'. */
- warning (0, "%<%s %E%> declared inside parameter list",
- keyword, b->id);
+ warning_at (input_location, 0,
+ "%<%s %E%> declared inside parameter list"
+ " will not be visible outside of this definition or"
+ " declaration", keyword, b->id);
else
/* The %s will be one of 'struct', 'union', or 'enum'. */
- warning (0, "anonymous %s declared inside parameter list",
- keyword);
-
- if (!explained_incomplete_types)
- {
- warning (0, "its scope is only this definition or declaration,"
- " which is probably not what you want");
- explained_incomplete_types = true;
- }
+ warning_at (input_location, 0,
+ "anonymous %s declared inside parameter list"
+ " will not be visible outside of this definition or"
+ " declaration", keyword);
}
tag.id = b->id;
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
- ref = lookup_tag (code, name, 0, &refloc);
+ ref = lookup_tag (code, name, false, &refloc);
/* If this is the right type of tag, return what we found.
(This reference will be shadowed by shadow_tag later if appropriate.)
If this is the wrong type of tag, do not return it. If it was the
location_t refloc = UNKNOWN_LOCATION;
if (name != NULL_TREE)
- ref = lookup_tag (code, name, 1, &refloc);
+ ref = lookup_tag (code, name, true, &refloc);
if (ref && TREE_CODE (ref) == code)
{
if (TYPE_SIZE (ref))
pedwarn (loc, 0, "declaration does not declare anything");
return NULL_TREE;
}
- if (!flag_isoc11)
- {
- if (flag_isoc99)
- pedwarn (loc, OPT_Wpedantic,
+ if (flag_isoc99)
+ pedwarn_c99 (loc, OPT_Wpedantic,
"ISO C99 doesn%'t support unnamed structs/unions");
- else
- pedwarn (loc, OPT_Wpedantic,
+ else
+ pedwarn_c99 (loc, OPT_Wpedantic,
"ISO C90 doesn%'t support unnamed structs/unions");
- }
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
static void
detect_field_duplicates_hash (tree fieldlist,
- hash_table <pointer_hash <tree_node> > htab)
+ hash_table<nofree_ptr_hash <tree_node> > *htab)
{
tree x, y;
tree_node **slot;
for (x = fieldlist; x ; x = DECL_CHAIN (x))
if ((y = DECL_NAME (x)) != 0)
{
- slot = htab.find_slot (y, INSERT);
+ slot = htab->find_slot (y, INSERT);
if (*slot)
{
error ("duplicate member %q+D", x);
&& TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)
{
tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x)));
- slot = htab.find_slot (xn, INSERT);
+ slot = htab->find_slot (xn, INSERT);
if (*slot)
error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x)));
*slot = xn;
}
else
{
- hash_table <pointer_hash <tree_node> > htab;
- htab.create (37);
-
- detect_field_duplicates_hash (fieldlist, htab);
- htab.dispose ();
+ hash_table<nofree_ptr_hash <tree_node> > htab (37);
+ detect_field_duplicates_hash (fieldlist, &htab);
}
}
/* Finish up struct info used by -Wc++-compat. */
static void
-warn_cxx_compat_finish_struct (tree fieldlist)
+warn_cxx_compat_finish_struct (tree fieldlist, enum tree_code code,
+ location_t record_loc)
{
unsigned int ix;
tree x;
struct c_binding *b;
+ if (fieldlist == NULL_TREE)
+ {
+ if (code == RECORD_TYPE)
+ warning_at (record_loc, OPT_Wc___compat,
+ "empty struct has size 0 in C, size 1 in C++");
+ else
+ warning_at (record_loc, OPT_Wc___compat,
+ "empty union has size 0 in C, size 1 in C++");
+ }
+
/* 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
if (!struct_parse_info->typedefs_seen.is_empty ()
&& 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 ();
+ /* Use a hash_set<tree> using the name of the typedef. We can use
+ a hash_set<tree> because identifiers are interned. */
+ hash_set<tree> tset;
FOR_EACH_VEC_ELT (struct_parse_info->typedefs_seen, ix, x)
- pointer_set_insert (tset, DECL_NAME (x));
+ tset.add (DECL_NAME (x));
for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
{
if (DECL_NAME (x) != NULL_TREE
- && pointer_set_contains (tset, DECL_NAME (x)))
+ && tset.contains (DECL_NAME (x)))
{
warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
("using %qD as both field and typedef name is "
the typedef name is used. */
}
}
-
- pointer_set_destroy (tset);
}
/* For each field which has a binding and which was not defined in
if (DECL_INITIAL (x))
{
- unsigned HOST_WIDE_INT width = tree_low_cst (DECL_INITIAL (x), 1);
+ unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (x));
DECL_SIZE (x) = bitsize_int (width);
DECL_BIT_FIELD (x) = 1;
SET_DECL_C_BIT_FIELD (x);
&& TREE_TYPE (*fieldlistp) != error_mark_node)
{
unsigned HOST_WIDE_INT width
- = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
+ = tree_to_uhwi (DECL_INITIAL (*fieldlistp));
tree type = TREE_TYPE (*fieldlistp);
if (width != TYPE_PRECISION (type))
{
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_alloc_cleared_lang_type (sizeof (struct lang_type));
- space2 = ggc_alloc_sorted_fields_type
+ space = ggc_cleared_alloc<struct lang_type> ();
+ space2 = (sorted_fields_type *) ggc_internal_alloc
(sizeof (struct sorted_fields_type) + len * sizeof (tree));
len = 0;
}
/* If this structure or union completes the type of any previous
- variable declaration, lay it out and output its rtl. */
- for (x = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
- x;
- x = TREE_CHAIN (x))
+ variable declaration, lay it out and output its rtl.
+
+ Note: C_TYPE_INCOMPLETE_VARS overloads TYPE_VFIELD which is used
+ in dwarf2out via rest_of_decl_compilation below and means
+ something totally different. Since we will be clearing
+ C_TYPE_INCOMPLETE_VARS shortly after we iterate through them,
+ clear it ahead of time and avoid problems in dwarf2out. Ideally,
+ C_TYPE_INCOMPLETE_VARS should use some language specific
+ node. */
+ tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
+ C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
+ for (x = incomplete_vars; x; x = TREE_CHAIN (x))
{
tree decl = TREE_VALUE (x);
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
rest_of_decl_compilation (decl, toplevel, 0);
}
}
- 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. */
DECL_EXPR, build_decl (loc, TYPE_DECL, NULL, t)));
if (warn_cxx_compat)
- warn_cxx_compat_finish_struct (fieldlist);
+ warn_cxx_compat_finish_struct (fieldlist, TREE_CODE (t), loc);
struct_parse_info->struct_types.release ();
struct_parse_info->fields.release ();
forward reference. */
if (name != NULL_TREE)
- enumtype = lookup_tag (ENUMERAL_TYPE, name, 1, &enumloc);
+ enumtype = lookup_tag (ENUMERAL_TYPE, name, true, &enumloc);
- if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
+ if (enumtype == NULL_TREE || TREE_CODE (enumtype) != ENUMERAL_TYPE)
{
enumtype = make_node (ENUMERAL_TYPE);
pushtag (loc, name, enumtype);
the_enum->enum_overflow = 0;
if (flag_short_enums)
- TYPE_PACKED (enumtype) = 1;
+ for (tree v = TYPE_MAIN_VARIANT (enumtype); v; v = TYPE_NEXT_VARIANT (v))
+ TYPE_PACKED (v) = 1;
/* FIXME: This will issue a warning for a use of a type defined
within sizeof in a statement expr. This is not terribly serious
{
tree pair, tem;
tree minnode = 0, maxnode = 0;
- int precision, unsign;
+ int precision;
+ signop sign;
bool toplevel = (file_scope == current_scope);
struct lang_type *lt;
as one of the integral types - the narrowest one that fits, except
that normally we only go as narrow as int - and signed iff any of
the values are negative. */
- unsign = (tree_int_cst_sgn (minnode) >= 0);
- precision = MAX (tree_int_cst_min_precision (minnode, unsign),
- tree_int_cst_min_precision (maxnode, unsign));
+ sign = (tree_int_cst_sgn (minnode) >= 0) ? UNSIGNED : SIGNED;
+ precision = MAX (tree_int_cst_min_precision (minnode, sign),
+ tree_int_cst_min_precision (maxnode, sign));
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
- tem = c_common_type_for_size (precision, unsign);
+ tem = c_common_type_for_size (precision, sign == UNSIGNED ? 1 : 0);
if (tem == NULL)
{
warning (0, "enumeration values exceed range of largest integer");
}
}
else
- tem = unsign ? unsigned_type_node : integer_type_node;
+ tem = sign == UNSIGNED ? unsigned_type_node : integer_type_node;
TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem);
+ TYPE_ALIGN (enumtype) = TYPE_ALIGN (tem);
TYPE_SIZE (enumtype) = 0;
- /* If the precision of the type was specific with an attribute and it
+ /* If the precision of the type was specified with an attribute and it
was too small, give an error. Otherwise, use it. */
- if (TYPE_PRECISION (enumtype))
+ if (TYPE_PRECISION (enumtype)
+ && lookup_attribute ("mode", attributes))
{
if (precision > TYPE_PRECISION (enumtype))
error ("specified mode too small for enumeral values");
/* Record the min/max values so that we can warn about bit-field
enumerations that are too small for the values. */
- lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+ lt = ggc_cleared_alloc<struct lang_type> ();
lt->enum_min = minnode;
lt->enum_max = maxnode;
TYPE_LANG_SPECIFIC (enumtype) = lt;
/* Set basis for default for next value. */
the_enum->enum_next_value
- = build_binary_op (EXPR_LOC_OR_HERE (value),
+ = build_binary_op (EXPR_LOC_OR_LOC (value, input_location),
PLUS_EXPR, value, integer_one_node, 0);
the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
&attributes, NULL, NULL, DEPRECATED_NORMAL);
+ invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
}
if (warn_about_return_type)
- pedwarn_c99 (loc, flag_isoc99 ? 0
- : (warn_return_type ? OPT_Wreturn_type : OPT_Wimplicit_int),
- "return type defaults to %<int%>");
+ warn_defaults_to (loc, flag_isoc99 ? OPT_Wimplicit_int
+ : (warn_return_type ? OPT_Wreturn_type
+ : OPT_Wimplicit_int),
+ "return type defaults to %<int%>");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in pop_scope) with the BLOCK. */
&& comptypes (TREE_TYPE (TREE_TYPE (decl1)),
TREE_TYPE (TREE_TYPE (old_decl))))
{
+ if (stdarg_p (TREE_TYPE (old_decl)))
+ {
+ warning_at (loc, 0, "%q+D defined as variadic function "
+ "without prototype", decl1);
+ locate_old_decl (old_decl);
+ }
TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
TREE_TYPE (decl1));
current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
&& old_decl != error_mark_node
&& TREE_PUBLIC (decl1)
&& !MAIN_NAME_P (DECL_NAME (decl1))
- && C_DECL_ISNT_PROTOTYPE (old_decl))
+ && C_DECL_ISNT_PROTOTYPE (old_decl)
+ && !DECL_DECLARED_INLINE_P (decl1))
warning_at (loc, OPT_Wmissing_prototypes,
"no previous prototype for %qD", decl1);
/* Optionally warn of any def with no previous prototype
else if (warn_missing_declarations
&& TREE_PUBLIC (decl1)
&& old_decl == 0
- && !MAIN_NAME_P (DECL_NAME (decl1)))
+ && !MAIN_NAME_P (DECL_NAME (decl1))
+ && !DECL_DECLARED_INLINE_P (decl1))
warning_at (loc, OPT_Wmissing_declarations,
"no previous declaration for %qD",
decl1);
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
!= integer_type_node)
pedwarn (loc, OPT_Wmain, "return type of %qD is not %<int%>", decl1);
+ else if (TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (decl1))))
+ pedwarn (loc, OPT_Wmain, "%<_Atomic%>-qualified return type of %qD",
+ decl1);
check_main_parameter_types (decl1);
warning if we got here because ARG_INFO_TYPES was error_mark_node
(this happens when a function definition has just an ellipsis in
its parameter list). */
- else if (!in_system_header && !current_function_scope
+ else if (!in_system_header_at (input_location)
+ && !current_function_scope
&& arg_info->types != error_mark_node)
warning_at (DECL_SOURCE_LOCATION (fndecl), OPT_Wtraditional,
"traditional C rejects ISO C style function definitions");
struct c_binding *b;
tree parm, decl, last;
tree parmids = arg_info->parms;
- struct pointer_set_t *seen_args = pointer_set_create ();
+ hash_set<tree> seen_args;
- if (!in_system_header)
+ if (!in_system_header_at (input_location))
warning_at (DECL_SOURCE_LOCATION (fndecl),
OPT_Wold_style_definition, "old-style function definition");
"%qD declared as a non-parameter", decl);
/* If the declaration is already marked, we have a duplicate
name. Complain and ignore the duplicate. */
- else if (pointer_set_contains (seen_args, decl))
+ else if (seen_args.contains (decl))
{
error_at (DECL_SOURCE_LOCATION (decl),
"multiple parameters named %qD", decl);
if (flag_isoc99)
pedwarn (DECL_SOURCE_LOCATION (decl),
- 0, "type of %qD defaults to %<int%>", decl);
+ OPT_Wimplicit_int, "type of %qD defaults to %<int%>",
+ decl);
else
warning_at (DECL_SOURCE_LOCATION (decl),
OPT_Wmissing_parameter_type,
}
TREE_PURPOSE (parm) = decl;
- pointer_set_insert (seen_args, decl);
+ seen_args.add (decl);
}
/* Now examine the parms chain for incomplete declarations
TREE_TYPE (parm) = error_mark_node;
}
- if (!pointer_set_contains (seen_args, parm))
+ if (!seen_args.contains (parm))
{
error_at (DECL_SOURCE_LOCATION (parm),
"declaration for parameter %qD but no such parameter",
DECL_CHAIN (last) = 0;
}
- pointer_set_destroy (seen_args);
-
/* If there was a previous prototype,
set the DECL_ARG_TYPE of each argument according to
the type previously specified, and report any mismatches. */
store_parm_decls ();
}
+/* Called by walk_tree to look for and update context-less labels. */
+
+static tree
+set_labels_context_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (TREE_CODE (*tp) == LABEL_EXPR
+ && DECL_CONTEXT (LABEL_EXPR_LABEL (*tp)) == NULL_TREE)
+ {
+ DECL_CONTEXT (LABEL_EXPR_LABEL (*tp)) = static_cast<tree>(data);
+ *walk_subtrees = 0;
+ }
+
+ return NULL_TREE;
+}
+
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
digesting the body of the function.
allocate_struct_function (fndecl, false);
if (warn_unused_local_typedefs)
- cfun->language = ggc_alloc_cleared_language_function ();
+ cfun->language = ggc_cleared_alloc<language_function> ();
/* Begin the statement tree for this function. */
DECL_SAVED_TREE (fndecl) = push_stmt_list ();
thus won't naturally see the SAVE_EXPR containing the increment. All
other pending sizes would be handled by gimplify_parameters. */
if (arg_info->pending_sizes)
- add_stmt (arg_info->pending_sizes);
+ {
+ /* In very special circumstances, e.g. for code like
+ _Atomic int i = 5;
+ void f (int a[i += 2]) {}
+ we need to execute the atomic assignment on function entry.
+ But in this case, it is not just a straight store, it has the
+ op= form, which means that build_atomic_assign has generated
+ gotos, labels, etc. Because at that time the function decl
+ for F has not been created yet, those labels do not have any
+ function context. But we have the fndecl now, so update the
+ labels accordingly. gimplify_expr would crash otherwise. */
+ walk_tree_without_duplicates (&arg_info->pending_sizes,
+ set_labels_context_r, fndecl);
+ add_stmt (arg_info->pending_sizes);
+ }
}
/* Store PARM_DECLs in PARMS into scope temporarily. Used for
current_scope->bindings = NULL;
for (; b; b = free_binding_and_advance (b))
{
- gcc_assert (TREE_CODE (b->decl) == PARM_DECL);
+ gcc_assert (TREE_CODE (b->decl) == PARM_DECL
+ || b->decl == error_mark_node);
gcc_assert (I_SYMBOL_BINDING (b->id) == b);
I_SYMBOL_BINDING (b->id) = b->shadowed;
if (b->shadowed && b->shadowed->u.type)
function. */
maybe_warn_unused_local_typedefs ();
+ /* Possibly warn about unused parameters. */
+ if (warn_unused_parameter)
+ do_warn_unused_parameter (fndecl);
+
/* Store the end of the function, so that we get good line number
info for the epilogue. */
cfun->function_end_locus = input_location;
/* ??? Objc emits functions after finalizing the compilation unit.
This should be cleaned up later and this conditional removed. */
- if (cgraph_global_info_ready)
+ if (symtab->global_info_ready)
{
- cgraph_add_new_function (fndecl, false);
+ cgraph_node::add_new_function (fndecl, false);
return;
}
- cgraph_finalize_function (fndecl, false);
+ cgraph_node::finalize_function (fndecl, false);
}
else
{
/* Register this function with cgraph just far enough to get it
added to our parent's nested function list. Handy, since the
C front end doesn't have such a list. */
- (void) cgraph_get_create_node (fndecl);
+ (void) cgraph_node::get_create (fndecl);
}
}
It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
tree_rest_of_compilation. */
set_cfun (NULL);
+ invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, current_function_decl);
current_function_decl = NULL;
}
\f
/* cfun->language might have been already allocated by the use of
-Wunused-local-typedefs. In that case, just re-use it. */
if (p == NULL)
- cfun->language = p = ggc_alloc_cleared_language_function ();
+ cfun->language = p = ggc_cleared_alloc<language_function> ();
p->base.x_stmt_tree = c_stmt_tree;
c_stmt_tree.x_cur_stmt_list = vec_safe_copy (c_stmt_tree.x_cur_stmt_list);
default:
gcc_unreachable ();
}
- if (dupe && !flag_isoc99)
- pedwarn (loc, OPT_Wpedantic, "duplicate %qE", qual);
+ if (dupe)
+ pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %qE", qual);
return specs;
}
error_at (loc,
("both %<long%> and %<short%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<long%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<long%> and %<void%> in "
"declaration specifiers"));
- else if (specs->typespec_word == cts_int128)
+ else if (specs->typespec_word == cts_int_n)
error_at (loc,
- ("both %<long%> and %<__int128%> in "
- "declaration specifiers"));
+ ("both %<long%> and %<__int%d%> in "
+ "declaration specifiers"),
+ int_n_data[specs->int_n_idx].bitsize);
else if (specs->typespec_word == cts_bool)
error_at (loc,
("both %<long%> and %<_Bool%> in "
error_at (loc,
("both %<long%> and %<short%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<short%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<short%> and %<void%> in "
"declaration specifiers"));
- else if (specs->typespec_word == cts_int128)
+ else if (specs->typespec_word == cts_int_n)
error_at (loc,
- ("both %<short%> and %<__int128%> in "
- "declaration specifiers"));
+ ("both %<short%> and %<__int%d%> in "
+ "declaration specifiers"),
+ int_n_data[specs->int_n_idx].bitsize);
else if (specs->typespec_word == cts_bool)
error_at (loc,
("both %<short%> and %<_Bool%> in "
error_at (loc,
("both %<signed%> and %<unsigned%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<signed%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<signed%> and %<void%> in "
error_at (loc,
("both %<signed%> and %<unsigned%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<unsigned%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<unsigned%> and %<void%> in "
break;
case RID_COMPLEX:
dupe = specs->complex_p;
- if (!flag_isoc99 && !in_system_header_at (loc))
- pedwarn (loc, OPT_Wpedantic,
- "ISO C90 does not support complex types");
- if (specs->typespec_word == cts_void)
+ if (!in_system_header_at (loc))
+ pedwarn_c90 (loc, OPT_Wpedantic,
+ "ISO C90 does not support complex types");
+ if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<complex%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<complex%> and %<void%> in "
"declaration specifiers"));
dupe = specs->saturating_p;
pedwarn (loc, OPT_Wpedantic,
"ISO C does not support saturating types");
- if (specs->typespec_word == cts_int128)
+ if (specs->typespec_word == cts_int_n)
{
error_at (loc,
- ("both %<_Sat%> and %<__int128%> in "
- "declaration specifiers"));
+ ("both %<_Sat%> and %<__int%d%> in "
+ "declaration specifiers"),
+ int_n_data[specs->int_n_idx].bitsize);
}
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<_Sat%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<_Sat%> and %<void%> in "
else
{
/* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
- "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
+ "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+ "__auto_type". */
if (specs->typespec_word != cts_none)
{
error_at (loc,
}
switch (i)
{
- case RID_INT128:
- if (int128_integer_type_node == NULL_TREE)
+ case RID_AUTO_TYPE:
+ if (specs->long_p)
+ error_at (loc,
+ ("both %<long%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->short_p)
+ error_at (loc,
+ ("both %<short%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->signed_p)
+ error_at (loc,
+ ("both %<signed%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->unsigned_p)
+ error_at (loc,
+ ("both %<unsigned%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->complex_p)
+ error_at (loc,
+ ("both %<complex%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->saturating_p)
+ error_at (loc,
+ ("both %<_Sat%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else
{
- error_at (loc, "%<__int128%> is not supported for this target");
- return specs;
+ specs->typespec_word = cts_auto_type;
+ specs->locations[cdw_typespec] = loc;
}
- if (!in_system_header)
+ return specs;
+ case RID_INT_N_0:
+ case RID_INT_N_1:
+ case RID_INT_N_2:
+ case RID_INT_N_3:
+ specs->int_n_idx = i - RID_INT_N_0;
+ if (!in_system_header_at (input_location))
pedwarn (loc, OPT_Wpedantic,
- "ISO C does not support %<__int128%> type");
+ "ISO C does not support %<__int%d%> types",
+ int_n_data[specs->int_n_idx].bitsize);
if (specs->long_p)
error_at (loc,
- ("both %<__int128%> and %<long%> in "
- "declaration specifiers"));
+ ("both %<__int%d%> and %<long%> in "
+ "declaration specifiers"),
+ int_n_data[specs->int_n_idx].bitsize);
else if (specs->saturating_p)
error_at (loc,
- ("both %<_Sat%> and %<__int128%> in "
- "declaration specifiers"));
+ ("both %<_Sat%> and %<__int%d%> in "
+ "declaration specifiers"),
+ int_n_data[specs->int_n_idx].bitsize);
else if (specs->short_p)
error_at (loc,
- ("both %<__int128%> and %<short%> in "
- "declaration specifiers"));
+ ("both %<__int%d%> and %<short%> in "
+ "declaration specifiers"),
+ int_n_data[specs->int_n_idx].bitsize);
+ else if (! int_n_enabled_p [specs->int_n_idx])
+ error_at (loc,
+ "%<__int%d%> is not supported on this target",
+ int_n_data[specs->int_n_idx].bitsize);
else
{
- specs->typespec_word = cts_int128;
+ specs->typespec_word = cts_int_n;
specs->locations[cdw_typespec] = loc;
}
return specs;
}
return specs;
case RID_BOOL:
+ if (!in_system_header_at (loc))
+ pedwarn_c90 (loc, OPT_Wpedantic,
+ "ISO C90 does not support boolean types");
if (specs->long_p)
error_at (loc,
("both %<long%> and %<_Bool%> in "
identifier in the implementation namespace; only diagnose
it for the C11 spelling because of existing code using
the other spelling. */
- if (!flag_isoc11 && !specs->thread_gnu_p)
+ if (!specs->thread_gnu_p)
{
if (flag_isoc99)
- pedwarn (loc, OPT_Wpedantic,
- "ISO C99 does not support %qE", scspec);
+ pedwarn_c99 (loc, OPT_Wpedantic,
+ "ISO C99 does not support %qE", scspec);
else
- pedwarn (loc, OPT_Wpedantic,
- "ISO C90 does not support %qE", scspec);
+ pedwarn_c99 (loc, OPT_Wpedantic,
+ "ISO C90 does not support %qE", scspec);
}
specs->locations[cdw_thread] = loc;
}
/* Now compute the actual type. */
switch (specs->typespec_word)
{
+ case cts_auto_type:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p
+ && !specs->complex_p);
+ /* Type to be filled in later. */
+ break;
case cts_void:
gcc_assert (!specs->long_p && !specs->short_p
&& !specs->signed_p && !specs->unsigned_p
specs->type = build_complex_type (specs->type);
}
break;
- case cts_int128:
+ case cts_int_n:
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);
+ ? int_n_trees[specs->int_n_idx].unsigned_type
+ : int_n_trees[specs->int_n_idx].signed_type);
if (specs->complex_p)
{
pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
return specs;
}
-/* A subroutine of c_write_global_declarations. Perform final processing
- on one file scope's declarations (or the external scope's declarations),
- GLOBALS. */
+/* Perform final processing on one file scope's declarations (or the
+ external scope's declarations), GLOBALS. */
static void
c_write_global_declarations_1 (tree globals)
{
/* Check for used but undefined static functions using the C
standard's definition of "used", and set TREE_NO_WARNING so
- that check_global_declarations doesn't repeat the check. */
+ that check_global_declaration doesn't repeat the check. */
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_INITIAL (decl) == 0
&& DECL_EXTERNAL (decl)
reconsider |= wrapup_global_declaration_2 (decl);
}
while (reconsider);
-
- for (decl = globals; decl; decl = DECL_CHAIN (decl))
- check_global_declaration_1 (decl);
-}
-
-/* A subroutine of c_write_global_declarations Emit debug information for each
- of the declarations in GLOBALS. */
-
-static void
-c_write_global_declarations_2 (tree globals)
-{
- tree decl;
-
- for (decl = globals; decl ; decl = DECL_CHAIN (decl))
- debug_hooks->global_decl (decl);
}
/* Callback to collect a source_ref from a DECL. */
callback (decl);
}
+/* Perform any final parser cleanups and generate initial debugging
+ information. */
+
void
-c_write_global_declarations (void)
+c_parse_final_cleanups (void)
{
tree t;
unsigned i;
if (pch_file)
return;
+ timevar_stop (TV_PHASE_PARSING);
timevar_start (TV_PHASE_DEFERRED);
/* Do the Objective-C stuff. This is where all the Objective-C
}
/* Process all file scopes in this compilation, and the external_scope,
- through wrapup_global_declarations and check_global_declarations. */
+ through wrapup_global_declarations. */
FOR_EACH_VEC_ELT (*all_translation_units, i, t)
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_1 (BLOCK_VARS (ext_block));
timevar_stop (TV_PHASE_DEFERRED);
- timevar_start (TV_PHASE_OPT_GEN);
-
- /* We're done parsing; proceed to optimize and emit assembly.
- FIXME: shouldn't be the front end's responsibility to call this. */
- finalize_compilation_unit ();
-
- timevar_stop (TV_PHASE_OPT_GEN);
- timevar_start (TV_PHASE_DBGINFO);
-
- /* After cgraph has had a chance to emit everything that's going to
- be emitted, output debug information for globals. */
- if (!seen_error ())
- {
- timevar_push (TV_SYMOUT);
- FOR_EACH_VEC_ELT (*all_translation_units, i, t)
- c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
- c_write_global_declarations_2 (BLOCK_VARS (ext_block));
- timevar_pop (TV_SYMOUT);
- }
+ timevar_start (TV_PHASE_PARSING);
ext_block = NULL;
- timevar_stop (TV_PHASE_DBGINFO);
}
/* Register reserved keyword WORD as qualifier for address space AS. */