/* 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 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Process declarations and symbol lookup for C front end.
Also constructs types; the standard scalar types at initialization,
#include "c-pragma.h"
#include "langhooks.h"
#include "tree-mudflap.h"
-#include "tree-gimple.h"
+#include "gimple.h"
+#include "tree-iterator.h"
#include "diagnostic.h"
#include "tree-dump.h"
#include "cgraph.h"
#include "except.h"
#include "langhooks-def.h"
#include "pointer-set.h"
+#include "gimple.h"
+#include "plugin.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
in all such cases, the binding in the outer scope will have its
invisible bit true. */
-struct c_binding GTY((chain_next ("%h.prev")))
-{
+struct GTY((chain_next ("%h.prev"))) c_binding {
tree decl; /* the decl bound */
tree type; /* the type in this scope */
tree id; /* the identifier it's bound to */
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 */
+ location_t locus; /* location for nested bindings */
};
#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
#define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth)
These describe the values of the identifier in the three different
namespaces defined by the language. */
-struct lang_identifier GTY(())
-{
+struct GTY(()) lang_identifier {
struct c_common_identifier common_id;
struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
struct c_binding *tag_binding; /* struct/union/enum tags */
/* The resulting tree type. */
-union lang_tree_node
- GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
- chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : ((union lang_tree_node *) GENERIC_NEXT (&%h.generic))")))
-{
+union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+ chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : ((union lang_tree_node *) TREE_CHAIN (&%h.generic))"))) lang_tree_node
+ {
union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)")))
generic;
pop_scope relies on this. */
-struct c_scope GTY((chain_next ("%h.outer")))
-{
+struct GTY((chain_next ("%h.outer"))) c_scope {
/* The scope containing this one. */
struct c_scope *outer;
struct c_scope *s_ = (scope); \
tree d_ = (decl); \
if (s_->list##_last) \
- TREE_CHAIN (s_->list##_last) = d_; \
+ BLOCK_CHAIN (s_->list##_last) = d_; \
else \
s_->list = d_; \
s_->list##_last = d_; \
struct c_scope *t_ = (tscope); \
struct c_scope *f_ = (fscope); \
if (t_->to##_last) \
- TREE_CHAIN (t_->to##_last) = f_->from; \
+ BLOCK_CHAIN (t_->to##_last) = f_->from; \
else \
t_->to = f_->from; \
t_->to##_last = f_->from##_last; \
static tree c_make_fname_decl (tree, int);
static tree grokdeclarator (const struct c_declarator *,
struct c_declspecs *,
- enum decl_context, bool, tree *,
- enum deprecated_states);
+ enum decl_context, bool, tree *, tree *, tree *,
+ bool *, enum deprecated_states);
static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
\f
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);
- if (C_IS_RESERVED_WORD (node))
+ if (C_IS_RESERVED_WORD (node) && C_RID_CODE (node) != RID_CXX_COMPAT_WARN)
{
tree rid = ridpointers[C_RID_CODE (node)];
indent_to (file, indent + 4);
which may be any of several kinds of DECL or TYPE or error_mark_node,
in the scope SCOPE. */
static void
-bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
+bind (tree name, tree decl, struct c_scope *scope, bool invisible,
+ bool nested, location_t locus)
{
struct c_binding *b, **here;
b->invisible = invisible;
b->nested = nested;
b->inner_comp = 0;
+ b->locus = locus;
b->type = 0;
TREE_USED (block) = 1;
/* In each subblock, record that this is its superior. */
- for (p = scope->blocks; p; p = TREE_CHAIN (p))
+ for (p = scope->blocks; p; p = BLOCK_CHAIN (p))
BLOCK_SUPERCONTEXT (p) = block;
BLOCK_VARS (block) = 0;
error ("nested function %q+D declared but never defined", p);
undef_nested_function = true;
}
- /* C99 6.7.4p6: "a function with external linkage... declared
- with an inline function specifier ... shall also be defined in the
- same translation unit." */
else if (DECL_DECLARED_INLINE_P (p)
&& TREE_PUBLIC (p)
- && !DECL_INITIAL (p)
- && !flag_gnu89_inline)
- pedwarn ("inline function %q+D declared but never defined", p);
+ && !DECL_INITIAL (p))
+ {
+ /* 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)
+ pedwarn (input_location, 0,
+ "inline function %q+D declared but never defined", p);
+ DECL_EXTERNAL (p) = 1;
+ }
goto common_symbol;
TREE_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
}
+ else if (VAR_OR_FUNCTION_DECL_P (p))
+ {
+ /* For block local externs add a special
+ DECL_EXTERNAL decl for debug info generation. */
+ tree extp = copy_node (p);
+
+ DECL_EXTERNAL (extp) = 1;
+ TREE_STATIC (extp) = 0;
+ TREE_PUBLIC (extp) = 1;
+ DECL_INITIAL (extp) = NULL_TREE;
+ DECL_LANG_SPECIFIC (extp) = NULL;
+ DECL_CONTEXT (extp) = current_function_decl;
+ if (TREE_CODE (p) == FUNCTION_DECL)
+ {
+ DECL_RESULT (extp) = NULL_TREE;
+ DECL_SAVED_TREE (extp) = NULL_TREE;
+ DECL_STRUCT_FUNCTION (extp) = NULL;
+ }
+ if (b->locus != UNKNOWN_LOCATION)
+ DECL_SOURCE_LOCATION (extp) = b->locus;
+ TREE_CHAIN (extp) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = extp;
+ }
/* If this is the file scope, and we are processing more
than one translation unit in this compilation, set
DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
bind (DECL_NAME (decl), decl, file_scope,
- /*invisible=*/false, /*nested=*/true);
+ /*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl));
}
void
cgraph_finalize_compilation_unit ();
}
-/* Insert BLOCK at the end of the list of subblocks of the current
- scope. This is used when a BIND_EXPR is expanded, to handle the
- BLOCK node inside the BIND_EXPR. */
-
-void
-insert_block (tree block)
-{
- TREE_USED (block) = 1;
- SCOPE_LIST_APPEND (current_scope, blocks, block);
-}
\f
/* Push a definition or a declaration of struct, union or enum tag "name".
"type" should be the type node.
/* Record the identifier as the type's name if it has none. */
if (name && !TYPE_NAME (type))
TYPE_NAME (type) = name;
- bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false);
+ bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false,
+ UNKNOWN_LOCATION);
/* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
tagged type we just added to the current scope. This fake
if (TREE_CHAIN (t) == 0
&& TYPE_MAIN_VARIANT (type) != void_type_node)
{
- inform ("a parameter list with an ellipsis can%'t match "
+ inform (input_location, "a parameter list with an ellipsis can%'t match "
"an empty parameter name list declaration");
break;
}
if (c_type_promotes_to (type) != type)
{
- inform ("an argument type that has a default promotion can%'t match "
+ inform (input_location, "an argument type that has a default promotion can%'t match "
"an empty parameter name list declaration");
break;
}
first in a pair of mismatched declarations, using the diagnostic
function DIAG. */
static void
-locate_old_decl (tree decl, void (*diag)(const char *, ...) ATTRIBUTE_GCC_CDIAG(1,2))
+locate_old_decl (tree decl)
{
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
;
else if (DECL_INITIAL (decl))
- diag (G_("previous definition of %q+D was here"), decl);
+ inform (input_location, "previous definition of %q+D was here", decl);
else if (C_DECL_IMPLICIT (decl))
- diag (G_("previous implicit declaration of %q+D was here"), decl);
+ inform (input_location, "previous implicit declaration of %q+D was here", decl);
else
- diag (G_("previous declaration of %q+D was here"), decl);
+ inform (input_location, "previous declaration of %q+D was here", decl);
}
/* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL.
&& !C_DECL_DECLARED_BUILTIN (olddecl)))
{
error ("%q+D redeclared as different kind of symbol", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
}
else if (TREE_PUBLIC (newdecl))
warning (0, "built-in function %q+D declared as non-function",
if (TREE_CODE (olddecl) == CONST_DECL)
{
error ("redeclaration of enumerator %q+D", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
&& TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
&& C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl))
{
- pedwarn ("conflicting types for %q+D", newdecl);
+ pedwarned = pedwarn (input_location, 0,
+ "conflicting types for %q+D", newdecl);
/* Make sure we keep void as the return type. */
TREE_TYPE (newdecl) = *newtypep = newtype = oldtype;
C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
- pedwarned = true;
}
/* Permit void foo (...) to match an earlier call to foo (...) with
no declared type (thus, implicitly int). */
&& TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == integer_type_node
&& C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl))
{
- pedwarn ("conflicting types for %q+D", newdecl);
+ pedwarned = pedwarn (input_location, 0,
+ "conflicting types for %q+D", newdecl);
/* Make sure we keep void as the return type. */
TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype;
- pedwarned = true;
}
else
{
else
error ("conflicting types for %q+D", newdecl);
diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
}
header. (Conflicting redeclarations were handled above.) */
if (TREE_CODE (newdecl) == TYPE_DECL)
{
- if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl))
+ 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, error);
+ locate_old_decl (olddecl);
return false;
}
&& same_translation_unit_p (newdecl, olddecl))
{
error ("redefinition of %q+D", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
}
&& TYPE_ACTUAL_ARG_TYPES (oldtype)
&& !validate_proto_after_old_defn (newdecl, newtype, oldtype))
{
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
/* A non-static declaration (even an "extern") followed by a
{
error ("static declaration of %q+D follows "
"non-static declaration", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
}
return false;
}
{
error ("non-static declaration of %q+D follows "
"static declaration", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
else if (warn_traditional)
{
- warning (OPT_Wtraditional, "non-static declaration of %q+D "
- "follows static declaration", newdecl);
- warned = true;
+ warned |= warning (OPT_Wtraditional,
+ "non-static declaration of %q+D "
+ "follows static declaration", newdecl);
}
}
error ("non-thread-local declaration of %q+D follows "
"thread-local declaration", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
{
error ("redefinition of %q+D", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
{
error ("extern declaration of %q+D follows "
"declaration with no linkage", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
else if (warn_traditional)
{
- warning (OPT_Wtraditional, "non-static declaration of %q+D "
- "follows static declaration", newdecl);
- warned = true;
+ warned |= warning (OPT_Wtraditional,
+ "non-static declaration of %q+D "
+ "follows static declaration", newdecl);
}
}
else
error ("static declaration of %q+D follows "
"non-static declaration", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
}
{
error ("declaration of %q+D with no linkage follows "
"extern declaration", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
}
else
{
error ("redeclaration of %q+D with no linkage", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
}
return false;
&& DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
- warning (0, "redeclaration of %q+D with different visibility "
- "(old visibility preserved)", newdecl);
- warned = true;
+ warned |= warning (0, "redeclaration of %q+D with different visibility "
+ "(old visibility preserved)", newdecl);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
if (DECL_DECLARED_INLINE_P (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warning (OPT_Wattributes, "inline declaration of %qD follows "
- "declaration with attribute noinline", newdecl);
- warned = true;
+ 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)))
{
- warning (OPT_Wattributes, "declaration of %q+D with attribute "
- "noinline follows inline declaration ", newdecl);
- warned = true;
- }
-
- /* Inline declaration after use or definition.
- ??? Should we still warn about this now we have unit-at-a-time
- mode and can get it right?
- Definitely don't complain if the decls are in different translation
- units.
- C99 permits this, so don't warn in that case. (The function
- may not be inlined everywhere in function-at-a-time mode, but
- we still shouldn't warn.) */
- if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl)
- && same_translation_unit_p (olddecl, newdecl)
- && flag_gnu89_inline)
- {
- if (TREE_USED (olddecl))
- {
- warning (0, "%q+D declared inline after being called", olddecl);
- warned = true;
- }
- else if (DECL_INITIAL (olddecl))
- {
- warning (0, "%q+D declared inline after its definition", olddecl);
- warned = true;
- }
+ warned |= warning (OPT_Wattributes,
+ "declaration of %q+D with attribute "
+ "noinline follows inline declaration ", newdecl);
}
}
else /* PARM_DECL, VAR_DECL */
&& (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
{
error ("redefinition of parameter %q+D", newdecl);
- locate_old_decl (olddecl, error);
+ locate_old_decl (olddecl);
return false;
}
}
&& !(TREE_CODE (newdecl) == VAR_DECL
&& DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl)))
{
- warning (OPT_Wredundant_decls, "redundant redeclaration of %q+D",
- newdecl);
- warned = true;
+ warned = warning (OPT_Wredundant_decls, "redundant redeclaration of %q+D",
+ newdecl);
}
- /* Report location of previous decl/defn in a consistent manner. */
+ /* Report location of previous decl/defn. */
if (warned || pedwarned)
- locate_old_decl (olddecl, pedwarned ? pedwarn : warning0);
+ locate_old_decl (olddecl);
#undef DECL_EXTERN_INLINE
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
DECL_MODE (newdecl) = DECL_MODE (olddecl);
- if (TREE_CODE (olddecl) != FUNCTION_DECL)
- if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
- {
- DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
- DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
- }
+ if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
+ {
+ DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+ DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
+ }
}
+ /* Keep the old rtl since we can safely use it. */
+ if (HAS_RTL_P (olddecl))
+ COPY_DECL_RTL (olddecl, newdecl);
/* Merge the type qualifiers. */
if (TREE_READONLY (newdecl))
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
- /* Keep source location of definition rather than declaration and of
- prototype rather than non-prototype unless that prototype is
- built-in. */
- if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
- || (old_is_prototype && !new_is_prototype
- && !C_DECL_BUILTIN_PROTOTYPE (olddecl)))
+ /* If a decl is in a system header and the other isn't, keep the one on the
+ system header. Otherwise, keep source location of definition rather than
+ declaration and of prototype rather than non-prototype unless that
+ prototype is built-in. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)
+ && DECL_IN_SYSTEM_HEADER (olddecl)
+ && !DECL_IN_SYSTEM_HEADER (newdecl) )
+ DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
+ else if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)
+ && DECL_IN_SYSTEM_HEADER (newdecl)
+ && !DECL_IN_SYSTEM_HEADER (olddecl))
+ DECL_SOURCE_LOCATION (olddecl) = DECL_SOURCE_LOCATION (newdecl);
+ else if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
+ || (old_is_prototype && !new_is_prototype
+ && !C_DECL_BUILTIN_PROTOTYPE (olddecl)))
DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
/* Merge the initialization information. */
if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS))
{
- /* Merge the unused-warning information. */
- if (DECL_IN_SYSTEM_HEADER (olddecl))
- DECL_IN_SYSTEM_HEADER (newdecl) = 1;
- else if (DECL_IN_SYSTEM_HEADER (newdecl))
- DECL_IN_SYSTEM_HEADER (olddecl) = 1;
-
/* 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
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
- TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
- DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+ DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
+ TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+ DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
}
|| !DECL_DECLARED_INLINE_P (olddecl)
|| !DECL_EXTERNAL (olddecl))
&& DECL_EXTERNAL (newdecl)
- && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl)))
+ && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl))
+ && !current_function_decl)
DECL_EXTERNAL (newdecl) = 0;
if (DECL_EXTERNAL (newdecl))
throw it away, in case it was inlined into a function that
hasn't been written out yet. */
if (new_is_definition && DECL_INITIAL (olddecl))
- {
- if (TREE_USED (olddecl)
- /* In unit-at-a-time mode we never inline re-defined extern
- inline functions. */
- && !flag_unit_at_a_time
- && cgraph_function_possibly_inlined_p (olddecl))
- (*debug_hooks->outlining_inline_function) (olddecl);
-
- /* The new defn must not be inline. */
- DECL_INLINE (newdecl) = 0;
- DECL_UNINLINABLE (newdecl) = 1;
- }
+ /* The new defn must not be inline. */
+ DECL_UNINLINABLE (newdecl) = 1;
else
{
/* If either decl says `inline', this fn is inline, unless
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+
+ DECL_DISREGARD_INLINE_LIMITS (newdecl)
+ = DECL_DISREGARD_INLINE_LIMITS (olddecl)
+ = (DECL_DISREGARD_INLINE_LIMITS (newdecl)
+ || DECL_DISREGARD_INLINE_LIMITS (olddecl));
}
if (DECL_BUILT_IN (olddecl))
= C_DECL_BUILTIN_PROTOTYPE (olddecl);
}
+ /* Preserve function specific target and optimization options */
+ if (DECL_FUNCTION_SPECIFIC_TARGET (olddecl)
+ && !DECL_FUNCTION_SPECIFIC_TARGET (newdecl))
+ DECL_FUNCTION_SPECIFIC_TARGET (newdecl)
+ = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
+
+ if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl)
+ && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl))
+ DECL_FUNCTION_SPECIFIC_OPTIMIZATION (newdecl)
+ = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (olddecl);
+
/* Also preserve various other info from the definition. */
if (!new_is_definition)
{
+ tree t;
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
- DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
-
- /* Set DECL_INLINE on the declaration if we've got a body
- from which to instantiate. */
- if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl))
- {
- DECL_INLINE (newdecl) = 1;
- DECL_ABSTRACT_ORIGIN (newdecl)
- = DECL_ABSTRACT_ORIGIN (olddecl);
- }
- }
- else
- {
- /* If a previous declaration said inline, mark the
- definition as inlinable. */
- if (DECL_DECLARED_INLINE_P (newdecl)
- && !DECL_UNINLINABLE (newdecl))
- DECL_INLINE (newdecl) = 1;
+ 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))
+ DECL_CONTEXT (t) = newdecl;
+
+ /* See if we've got a function to instantiate from. */
+ if (DECL_SAVED_TREE (olddecl))
+ DECL_ABSTRACT_ORIGIN (newdecl)
+ = DECL_ABSTRACT_ORIGIN (olddecl);
}
}
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;
+
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */
{
unsigned olddecl_uid = DECL_UID (olddecl);
tree olddecl_context = DECL_CONTEXT (olddecl);
+ tree olddecl_arguments = NULL;
+ if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ olddecl_arguments = DECL_ARGUMENTS (olddecl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl_common) - sizeof (struct tree_common));
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:
case RESULT_DECL:
case CONST_DECL:
case TYPE_DECL:
- case FUNCTION_DECL:
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));
}
DECL_UID (olddecl) = olddecl_uid;
DECL_CONTEXT (olddecl) = olddecl_context;
+ if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ DECL_ARGUMENTS (olddecl) = olddecl_arguments;
}
/* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
/* If we changed a function from DECL_EXTERNAL to !DECL_EXTERNAL,
and the definition is coming from the old version, cgraph needs
to be called again. */
- if (extern_changed && !new_is_definition
+ if (extern_changed && !new_is_definition
&& TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl))
- cgraph_finalize_function (olddecl, false);
+ cgraph_mark_if_needed (olddecl);
}
/* Handle when a new declaration NEWDECL has the same name as an old
if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
{
- /* Avoid `unused variable' and other warnings warnings for OLDDECL. */
+ /* Avoid `unused variable' and other warnings for OLDDECL. */
TREE_NO_WARNING (olddecl) = 1;
return false;
}
}
}
-
-/* Subroutine of pushdecl.
-
- X is a TYPE_DECL for a typedef statement. Create a brand new
- ..._TYPE node (which will be just a variant of the existing
- ..._TYPE node with identical properties) and then install X
- as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
-
- The whole point here is to end up with a situation where each
- and every ..._TYPE node the compiler creates will be uniquely
- associated with AT MOST one node representing a typedef name.
- This way, even though the compiler substitutes corresponding
- ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
- early on, later parts of the compiler can always do the reverse
- translation and get back the corresponding typedef name. For
- example, given:
-
- typedef struct S MY_TYPE;
- MY_TYPE object;
-
- Later parts of the compiler might only know that `object' was of
- type `struct S' if it were not for code just below. With this
- code however, later parts of the compiler see something like:
-
- struct S' == struct S
- typedef struct S' MY_TYPE;
- struct S' object;
-
- And they can then deduce (from the node for type struct S') that
- the original object declaration was:
-
- MY_TYPE object;
-
- Being able to do this is important for proper support of protoize,
- and also for generating precise symbolic debugging information
- which takes full account of the programmer's (typedef) vocabulary.
-
- Obviously, we don't want to generate a duplicate ..._TYPE node if
- the TYPE_DECL node that we are now processing really represents a
- standard built-in type.
-
- Since all standard types are effectively declared at line zero
- in the source file, we can easily check to see if we are working
- on a standard type by checking the current value of lineno. */
-
-static void
-clone_underlying_type (tree x)
-{
- if (DECL_IS_BUILTIN (x))
- {
- if (TYPE_NAME (TREE_TYPE (x)) == 0)
- TYPE_NAME (TREE_TYPE (x)) = x;
- }
- else if (TREE_TYPE (x) != error_mark_node
- && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
- {
- tree tt = TREE_TYPE (x);
- DECL_ORIGINAL_TYPE (x) = tt;
- tt = build_variant_type_copy (tt);
- TYPE_NAME (tt) = x;
- TREE_USED (tt) = TREE_USED (x);
- TREE_TYPE (x) = tt;
- }
-}
-
/* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same
name already seen in the same scope).
struct c_scope *scope = current_scope;
struct c_binding *b;
bool nested = false;
-
- /* Functions need the lang_decl data. */
- if (TREE_CODE (x) == FUNCTION_DECL && !DECL_LANG_SPECIFIC (x))
- DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl);
+ location_t locus = DECL_SOURCE_LOCATION (x);
/* Must set DECL_CONTEXT for everything not at file scope or
DECL_FILE_SCOPE_P won't work. Local externs don't count
/* Anonymous decls are just inserted in the scope. */
if (!name)
{
- bind (name, x, scope, /*invisible=*/false, /*nested=*/false);
+ bind (name, x, scope, /*invisible=*/false, /*nested=*/false,
+ locus);
return x;
}
= build_type_attribute_variant (thistype,
TYPE_ATTRIBUTES (b->type));
TREE_TYPE (b->decl) = thistype;
- bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
+ bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
+ locus);
return b->decl;
}
else if (TREE_PUBLIC (x))
else
{
bind (name, x, external_scope, /*invisible=*/true,
- /*nested=*/false);
+ /*nested=*/false, locus);
nested = true;
}
}
skip_external_and_shadow_checks:
if (TREE_CODE (x) == TYPE_DECL)
- clone_underlying_type (x);
+ set_underlying_type (x);
- bind (name, x, scope, /*invisible=*/false, nested);
+ bind (name, x, scope, /*invisible=*/false, nested, locus);
/* If x's type is incomplete because it's based on a
structure or union which has not yet been fully declared,
if (TREE_PUBLIC (x))
{
- bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
+ bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false,
+ UNKNOWN_LOCATION);
nested = true;
}
if (file_scope)
- bind (name, x, file_scope, /*invisible=*/false, nested);
+ bind (name, x, file_scope, /*invisible=*/false, nested, UNKNOWN_LOCATION);
return x;
}
{
if (warn_implicit_function_declaration)
{
+ bool warned;
+
if (flag_isoc99)
- pedwarn (G_("implicit declaration of function %qE"), id);
+ warned = pedwarn (input_location, OPT_Wimplicit_function_declaration,
+ "implicit declaration of function %qE", id);
else
- warning (OPT_Wimplicit_function_declaration,
- G_("implicit declaration of function %qE"), id);
- if (olddecl)
- locate_old_decl (olddecl, inform);
+ warned = warning (OPT_Wimplicit_function_declaration,
+ G_("implicit declaration of function %qE"), id);
+ if (olddecl && warned)
+ locate_old_decl (olddecl);
}
}
if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
{
bind (functionid, decl, file_scope,
- /*invisible=*/false, /*nested=*/true);
+ /*invisible=*/false, /*nested=*/true,
+ DECL_SOURCE_LOCATION (decl));
return decl;
}
else
{
error ("incompatible implicit declaration of function %qD",
decl);
- locate_old_decl (decl, error);
+ locate_old_decl (decl);
}
}
b->type = TREE_TYPE (decl);
TREE_TYPE (decl) = newtype;
bind (functionid, decl, current_scope,
- /*invisible=*/false, /*nested=*/true);
+ /*invisible=*/false, /*nested=*/true,
+ DECL_SOURCE_LOCATION (decl));
return decl;
}
}
will be nonnull but current_function_scope will be null. */
scope = current_function_scope ? current_function_scope : current_scope;
}
- bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false);
+ bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false,
+ UNKNOWN_LOCATION);
}
\f
/* Subroutine of lookup_label, declare_label, define_label: construct a
/* Ordinary labels go in the current function scope. */
bind (name, label, current_function_scope,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
return label;
}
if (b && B_IN_CURRENT_SCOPE (b))
{
error ("duplicate label declaration %qE", name);
- locate_old_decl (b->decl, error);
+ locate_old_decl (b->decl);
/* Just use the previous declaration. */
return b->decl;
/* Declared labels go in the current scope. */
bind (name, label, current_scope,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
return label;
}
&& C_DECLARED_LABEL_FLAG (label))))
{
error ("%Hduplicate label %qD", &location, label);
- locate_old_decl (label, error);
+ locate_old_decl (label);
return 0;
}
else if (label && DECL_CONTEXT (label) == current_function_decl)
/* Ordinary labels go in the current function scope. */
bind (name, label, current_function_scope,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
}
if (!in_system_header && lookup_name (name))
/* Declarations from c_common_nodes_and_builtins must not be associated
with this input file, lest we get differences between using and not
using preprocessed headers. */
-#ifdef USE_MAPPED_LOCATION
input_location = BUILTINS_LOCATION;
-#else
- input_location.file = "<built-in>";
- input_location.line = 0;
-#endif
build_common_tree_nodes (flag_signed_char, false);
DECL_ARTIFICIAL (decl) = 1;
init = build_string (length + 1, name);
- free ((char *) name);
+ free (CONST_CAST (char *, name));
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
{
DECL_CONTEXT (decl) = current_function_decl;
bind (id, decl, current_function_scope,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
}
- finish_decl (decl, init, NULL_TREE);
+ finish_decl (decl, init, NULL_TREE, NULL_TREE);
return decl;
}
tree id = DECL_NAME (decl);
const char *name = IDENTIFIER_POINTER (id);
- DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
/* Should never be called on a symbol with a preexisting meaning. */
gcc_assert (!I_SYMBOL_BINDING (id));
- bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false);
+ bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false,
+ UNKNOWN_LOCATION);
+
+ /* Builtins in the implementation namespace are made visible without
+ needing to be explicitly declared. See push_file_scope. */
+ if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
+ {
+ TREE_CHAIN (decl) = visible_builtins;
+ visible_builtins = decl;
+ }
+
+ return decl;
+}
+
+tree
+c_builtin_function_ext_scope (tree decl)
+{
+ tree type = TREE_TYPE (decl);
+ tree id = DECL_NAME (decl);
+
+ const char *name = IDENTIFIER_POINTER (id);
+ C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
+
+ /* Should never be called on a symbol with a preexisting meaning. */
+ gcc_assert (!I_SYMBOL_BINDING (id));
+
+ 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. */
found_tag = true;
+ if (declspecs->restrict_p)
+ {
+ error ("invalid use of %<restrict%>");
+ warned = 1;
+ }
+
if (name == 0)
{
if (warned != 1 && code != ENUMERAL_TYPE)
/* Empty unnamed enum OK */
{
- pedwarn ("unnamed struct/union that defines no instances");
+ pedwarn (input_location, 0,
+ "unnamed struct/union that defines no instances");
warned = 1;
}
}
&& declspecs->storage_class != csc_none)
{
if (warned != 1)
- pedwarn ("empty declaration with storage class specifier "
+ pedwarn (input_location, 0,
+ "empty declaration with storage class specifier "
"does not redeclare tag");
warned = 1;
pending_xref_error ();
|| declspecs->restrict_p))
{
if (warned != 1)
- pedwarn ("empty declaration with type qualifier "
- "does not redeclare tag");
+ pedwarn (input_location, 0,
+ "empty declaration with type qualifier "
+ "does not redeclare tag");
warned = 1;
pending_xref_error ();
}
{
if (warned != 1 && !in_system_header)
{
- pedwarn ("useless type name in empty declaration");
+ pedwarn (input_location, 0,
+ "useless type name in empty declaration");
warned = 1;
}
}
}
else if (warned != 1 && !in_system_header && declspecs->typedef_p)
{
- pedwarn ("useless type name in empty declaration");
+ pedwarn (input_location, 0, "useless type name in empty declaration");
warned = 1;
}
if (warned != 1)
{
if (!found_tag)
- pedwarn ("empty declaration");
+ pedwarn (input_location, 0, "empty declaration");
}
}
\f
}
declarator->u.array.static_p = static_p;
declarator->u.array.vla_unspec_p = vla_unspec_p;
- if (pedantic && !flag_isoc99)
+ if (!flag_isoc99)
{
if (static_p || quals != NULL)
- pedwarn ("ISO C90 does not support %<static%> or type "
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C90 does not support %<static%> or type "
"qualifiers in parameter array declarators");
if (vla_unspec_p)
- pedwarn ("ISO C90 does not support %<[*]%> array declarators");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C90 does not support %<[*]%> array declarators");
}
if (vla_unspec_p)
{
/* Set the contained declarator of an array declarator. DECL is the
declarator, as constructed by build_array_declarator; INNER is what
- appears on the left of the []. ABSTRACT_P is true if it is an
- abstract declarator, false otherwise; this is used to reject static
- and type qualifiers in abstract declarators, where they are not in
- the C99 grammar (subject to possible change in DR#289). */
+ appears on the left of the []. */
struct c_declarator *
set_array_declarator_inner (struct c_declarator *decl,
- struct c_declarator *inner, bool abstract_p)
+ struct c_declarator *inner)
{
decl->declarator = inner;
- if (abstract_p && (decl->u.array.quals != TYPE_UNQUALIFIED
- || decl->u.array.attrs != NULL_TREE
- || decl->u.array.static_p))
- error ("static or type qualifiers in abstract declarator");
return decl;
}
}
}
\f
-/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
+/* Decode a "typename", such as "int **", returning a ..._TYPE node.
+ Set *EXPR, if EXPR not NULL, to any expression to be evaluated
+ before the type name, and set *EXPR_CONST_OPERANDS, if
+ EXPR_CONST_OPERANDS not NULL, to indicate whether the type name may
+ appear in a constant expression. */
tree
-groktypename (struct c_type_name *type_name)
+groktypename (struct c_type_name *type_name, tree *expr,
+ bool *expr_const_operands)
{
tree type;
tree attrs = type_name->specs->attrs;
type_name->specs->attrs = NULL_TREE;
type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
- false, NULL, DEPRECATED_NORMAL);
+ false, NULL, &attrs, expr, expr_const_operands,
+ DEPRECATED_NORMAL);
/* Apply attributes. */
decl_attributes (&type, attrs, 0);
{
tree decl;
tree tem;
+ tree expr = NULL_TREE;
enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
/* An object declared as __attribute__((deprecated)) suppresses
deprecated_state = DEPRECATED_SUPPRESS;
decl = grokdeclarator (declarator, declspecs,
- NORMAL, initialized, NULL,
+ NORMAL, initialized, NULL, &attributes, &expr, NULL,
deprecated_state);
if (!decl)
return 0;
- if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
- && MAIN_NAME_P (DECL_NAME (decl)))
+ if (expr)
+ add_stmt (expr);
+
+ if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl)))
warning (OPT_Wmain, "%q+D is usually a function", decl);
if (initialized)
if (declspecs->inline_p
&& !flag_gnu89_inline
&& TREE_CODE (decl) == FUNCTION_DECL
- && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl)))
+ && (lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl))
+ || current_function_decl))
{
if (declspecs->storage_class == csc_auto && current_scope != file_scope)
;
if (TREE_CODE (decl) == VAR_DECL
&& current_scope != file_scope
&& TREE_STATIC (decl)
+ && !TREE_READONLY (decl)
&& DECL_DECLARED_INLINE_P (current_function_decl)
&& DECL_EXTERNAL (current_function_decl))
- pedwarn ("%q+D is static but declared in inline function %qD "
+ pedwarn (input_location, 0,
+ "%q+D is static but declared in inline function %qD "
"which is not static", decl, current_function_decl);
/* Add this decl to the current scope.
/* Finish processing of a declaration;
install its initial value.
+ If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
If the length of an array type is not known before,
it must be determined now, from the initial value, or it is an error. */
void
-finish_decl (tree decl, tree init, tree asmspec_tree)
+finish_decl (tree decl, tree init, tree origtype, tree asmspec_tree)
{
tree type;
int was_incomplete = (DECL_SIZE (decl) == 0);
init = 0;
if (init)
- store_init_value (decl, init);
+ store_init_value (decl, init, origtype);
if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
- error ("storage size of %q+D isn%'t constant", decl);
+ {
+ error ("storage size of %q+D isn%'t constant", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
}
if (TREE_USED (type))
}
}
- /* If this was marked 'used', be sure it will be output. */
- if (!flag_unit_at_a_time && lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
- mark_decl_referenced (decl);
-
if (TREE_CODE (decl) == TYPE_DECL)
{
if (!DECL_FILE_SCOPE_P (decl)
tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
tree cleanup_decl = lookup_name (cleanup_id);
tree cleanup;
+ VEC(tree,gc) *vec;
/* Build "cleanup(&decl)" for the destructor. */
- cleanup = build_unary_op (ADDR_EXPR, decl, 0);
- cleanup = build_tree_list (NULL_TREE, cleanup);
- cleanup = build_function_call (cleanup_decl, cleanup);
+ cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
+ vec = VEC_alloc (tree, gc, 1);
+ VEC_quick_push (tree, vec, cleanup);
+ cleanup = build_function_call_vec (cleanup_decl, vec, NULL);
+ VEC_free (tree, gc, vec);
/* Don't warn about decl unused; the cleanup uses it. */
TREE_USED (decl) = 1;
tree
grokparm (const struct c_parm *parm)
{
+ tree attrs = parm->attrs;
tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
- NULL, DEPRECATED_NORMAL);
+ NULL, &attrs, NULL, NULL, DEPRECATED_NORMAL);
- decl_attributes (&decl, parm->attrs, 0);
+ decl_attributes (&decl, attrs, 0);
return decl;
}
void
push_parm_decl (const struct c_parm *parm)
{
+ tree attrs = parm->attrs;
tree decl;
decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
- DEPRECATED_NORMAL);
- decl_attributes (&decl, parm->attrs, 0);
+ &attrs, NULL, NULL, DEPRECATED_NORMAL);
+ decl_attributes (&decl, attrs, 0);
decl = pushdecl (decl);
- finish_decl (decl, NULL_TREE, NULL_TREE);
+ finish_decl (decl, NULL_TREE, NULL_TREE, NULL_TREE);
}
/* Mark all the parameter declarations to date as forward decls.
if (pedantic && !current_scope->warned_forward_parm_decls)
{
- pedwarn ("ISO C forbids forward parameter declarations");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids forward parameter declarations");
current_scope->warned_forward_parm_decls = true;
}
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
literal, which may be an incomplete array type completed by the
initializer; INIT is a CONSTRUCTOR that initializes the compound
- literal. */
+ literal. NON_CONST is true if the initializers contain something
+ that cannot occur in a constant expression. */
tree
-build_compound_literal (tree type, tree init)
+build_compound_literal (tree type, tree init, bool non_const)
{
/* We do not use start_decl here because we have a type, not a declarator;
and do not use finish_decl because the decl should be stored inside
TREE_USED (decl) = 1;
TREE_TYPE (decl) = type;
TREE_READONLY (decl) = TYPE_READONLY (type);
- store_init_value (decl, init);
+ store_init_value (decl, init, NULL_TREE);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
rest_of_decl_compilation (decl, 1, 0);
}
+ if (non_const)
+ {
+ complit = build2 (C_MAYBE_CONST_EXPR, type, NULL, complit);
+ C_MAYBE_CONST_EXPR_NON_CONST (complit) = 1;
+ }
+
return complit;
}
\f
}
type_mv = TYPE_MAIN_VARIANT (*type);
- if (pedantic
- && !in_system_header
+ if (!in_system_header
&& type_mv != integer_type_node
&& type_mv != unsigned_type_node
&& type_mv != boolean_type_node)
- pedwarn ("type of bit-field %qs is a GCC extension", name);
+ pedwarn (input_location, OPT_pedantic,
+ "type of bit-field %qs is a GCC extension", name);
- if (type_mv == boolean_type_node)
- max_width = CHAR_TYPE_SIZE;
- else
- max_width = TYPE_PRECISION (*type);
+ max_width = TYPE_PRECISION (*type);
if (0 < compare_tree_int (*width, max_width))
{
{
struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
if (!lt
- || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
- || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
+ || 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);
}
}
static void
warn_variable_length_array (const char *name, tree size)
{
- int ped = !flag_isoc99 && pedantic && warn_vla != 0;
int const_size = TREE_CONSTANT (size);
- if (ped)
+ if (!flag_isoc99 && pedantic && warn_vla != 0)
{
if (const_size)
{
if (name)
- pedwarn ("ISO C90 forbids array %qs whose size "
+ pedwarn (input_location, OPT_Wvla, "ISO C90 forbids array %qs whose size "
"can%'t be evaluated",
name);
else
- pedwarn ("ISO C90 forbids array whose size "
+ pedwarn (input_location, OPT_Wvla, "ISO C90 forbids array whose size "
"can%'t be evaluated");
}
else
{
if (name)
- pedwarn ("ISO C90 forbids variable length array %qs",
+ pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length array %qs",
name);
else
- pedwarn ("ISO C90 forbids variable length array");
+ pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length array");
}
}
else if (warn_vla > 0)
INITIALIZED is true if the decl has an initializer.
WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
representing the width of the bit-field.
+ DECL_ATTRS points to the list of attributes that should be added to this
+ decl. Any nested attributes that belong on the decl itself will be
+ added to this list.
+ If EXPR is not NULL, any expressions that need to be evaluated as
+ part of evaluating variably modified types will be stored in *EXPR.
+ If EXPR_CONST_OPERANDS is not NULL, *EXPR_CONST_OPERANDS will be
+ set to indicate whether operands in *EXPR can be used in constant
+ expressions.
DEPRECATED_STATE is a deprecated_states value indicating whether
deprecation warnings should be suppressed.
grokdeclarator (const struct c_declarator *declarator,
struct c_declspecs *declspecs,
enum decl_context decl_context, bool initialized, tree *width,
+ tree *decl_attrs, tree *expr, bool *expr_const_operands,
enum deprecated_states deprecated_state)
{
tree type = declspecs->type;
int volatilep;
int type_quals = TYPE_UNQUALIFIED;
const char *name, *orig_name;
- tree typedef_type = 0;
bool funcdef_flag = false;
bool funcdef_syntax = false;
int size_varies = 0;
bool bitfield = width != NULL;
tree element_type;
struct c_arg_info *arg_info = 0;
+ tree expr_dummy;
+ bool expr_const_operands_dummy;
+
+ if (expr == NULL)
+ expr = &expr_dummy;
+ if (expr_const_operands == NULL)
+ expr_const_operands = &expr_const_operands_dummy;
+
+ *expr = declspecs->expr;
+ *expr_const_operands = declspecs->expr_const_operands;
if (decl_context == FUNCDEF)
funcdef_flag = true, decl_context = NORMAL;
type = integer_type_node;
}
- typedef_type = type;
size_varies = C_TYPE_VARIABLE_SIZE (type);
/* Diagnose defaulting to "int". */
if ((warn_implicit_int || warn_return_type || flag_isoc99)
&& funcdef_flag)
warn_about_return_type = 1;
- else if (warn_implicit_int || flag_isoc99)
- pedwarn_c99 ("type defaults to %<int%> in declaration of %qs", name);
+ else
+ pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int,
+ "type defaults to %<int%> in declaration of %qs", name);
}
/* Adjust the type if a bit-field is being declared,
declaration contains the `const'. A third possibility is that
there is a type qualifier on the element type of a typedefed
array type, in which case we should extract that qualifier so
- that c_apply_type_quals_to_decls receives the full list of
+ that c_apply_type_quals_to_decl receives the full list of
qualifiers to work with (C90 is not entirely clear about whether
duplicate qualifiers should be diagnosed in this case, but it
seems most appropriate to do so). */
if (pedantic && !flag_isoc99)
{
if (constp > 1)
- pedwarn ("duplicate %<const%>");
+ pedwarn (input_location, OPT_pedantic, "duplicate %<const%>");
if (restrictp > 1)
- pedwarn ("duplicate %<restrict%>");
+ pedwarn (input_location, OPT_pedantic, "duplicate %<restrict%>");
if (volatilep > 1)
- pedwarn ("duplicate %<volatile%>");
+ pedwarn (input_location, OPT_pedantic, "duplicate %<volatile%>");
}
if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
type = TYPE_MAIN_VARIANT (type);
|| storage_class == csc_register
|| storage_class == csc_typedef))
{
- if (storage_class == csc_auto
- && (pedantic || current_scope == file_scope))
- pedwarn ("function definition declared %<auto%>");
+ if (storage_class == csc_auto)
+ pedwarn (input_location,
+ (current_scope == file_scope) ? 0 : OPT_pedantic,
+ "function definition declared %<auto%>");
if (storage_class == csc_register)
error ("function definition declared %<register%>");
if (storage_class == csc_typedef)
if (storage_class == csc_auto)
error ("file-scope declaration of %qs specifies %<auto%>", name);
if (pedantic && storage_class == csc_register)
- pedwarn ("file-scope declaration of %qs specifies %<register%>", name);
+ pedwarn (input_location, OPT_pedantic,
+ "file-scope declaration of %qs specifies %<register%>", name);
}
else
{
}
if (pedantic && !in_system_header && flexible_array_type_p (type))
- pedwarn ("invalid use of structure with flexible array member");
+ pedwarn (input_location, OPT_pedantic,
+ "invalid use of structure with flexible array member");
if (size == error_mark_node)
type = error_mark_node;
if (size)
{
+ bool size_maybe_const = true;
+ bool size_int_const = (TREE_CODE (size) == INTEGER_CST
+ && !TREE_OVERFLOW (size));
+ bool this_size_varies = false;
+
/* Strip NON_LVALUE_EXPRs since we aren't using as an
lvalue. */
STRIP_TYPE_NOPS (size);
size = integer_one_node;
}
- if (pedantic && integer_zerop (size))
- pedwarn ("ISO C forbids zero-size array %qs", name);
+ size = c_fully_fold (size, false, &size_maybe_const);
+
+ if (pedantic && size_maybe_const && integer_zerop (size))
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids zero-size array %qs", name);
- if (TREE_CODE (size) == INTEGER_CST)
+ if (TREE_CODE (size) == INTEGER_CST && size_maybe_const)
{
constant_expression_warning (size);
if (tree_int_cst_sgn (size) < 0)
error ("size of array %qs is negative", name);
size = integer_one_node;
}
+ /* Handle a size folded to an integer constant but
+ not an integer constant expression. */
+ if (!size_int_const)
+ {
+ /* If this is a file scope declaration of an
+ ordinary identifier, this is invalid code;
+ diagnosing it here and not subsequently
+ treating the type as variable-length avoids
+ more confusing diagnostics later. */
+ if ((decl_context == NORMAL || decl_context == FIELD)
+ && current_scope == file_scope)
+ pedwarn (input_location, 0,
+ "variably modified %qs at file scope", name);
+ else
+ this_size_varies = size_varies = 1;
+ warn_variable_length_array (orig_name, size);
+ }
}
else if ((decl_context == NORMAL || decl_context == FIELD)
&& current_scope == file_scope)
/* Make sure the array size remains visibly
nonconstant even if it is (eg) a const variable
with known value. */
- size_varies = 1;
+ this_size_varies = size_varies = 1;
warn_variable_length_array (orig_name, size);
}
- if (integer_zerop (size))
+ if (integer_zerop (size) && !this_size_varies)
{
/* A zero-length array cannot be represented with
an unsigned index type, which is what we'll
with the +1 that happens when building TYPE_SIZE. */
if (size_varies)
size = variable_size (size);
+ if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
+ size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+ integer_zero_node, size);
/* Compute the maximum valid index, that is, size
- 1. Do the calculation in index_type, so that
itype = build_index_type (itype);
}
+ if (this_size_varies)
+ {
+ if (*expr)
+ *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+ *expr, size);
+ else
+ *expr = size;
+ *expr_const_operands &= size_maybe_const;
+ }
}
else if (decl_context == FIELD)
{
- if (pedantic && !flag_isoc99 && !in_system_header)
- pedwarn ("ISO C90 does not support flexible array members");
+ bool flexible_array_member = false;
+ if (array_parm_vla_unspec_p)
+ /* Field names can in fact have function prototype
+ scope so [*] is disallowed here through making
+ the field variably modified, not through being
+ something other than a declaration with function
+ prototype scope. */
+ size_varies = 1;
+ else
+ {
+ const struct c_declarator *t = declarator;
+ while (t->kind == cdk_attrs)
+ t = t->declarator;
+ flexible_array_member = (t->kind == cdk_id);
+ }
+ if (flexible_array_member
+ && pedantic && !flag_isoc99 && !in_system_header)
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C90 does not support flexible array members");
/* ISO C99 Flexible array members are effectively
identical to GCC's zero-length array extension. */
- itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+ if (flexible_array_member || array_parm_vla_unspec_p)
+ itype = build_range_type (sizetype, size_zero_node,
+ NULL_TREE);
}
else if (decl_context == PARM)
{
if (array_parm_vla_unspec_p)
{
- if (! orig_name)
- {
- /* C99 6.7.5.2p4 */
- error ("%<[*]%> not allowed in other than a declaration");
- }
-
itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
size_varies = 1;
}
{
if (array_parm_vla_unspec_p)
{
- /* The error is printed elsewhere. We use this to
- avoid messing up with incomplete array types of
- the same type, that would otherwise be modified
- below. */
+ /* C99 6.7.5.2p4 */
+ warning (0, "%<[*]%> not in a declaration");
+ /* We use this to avoid messing up with incomplete
+ array types of the same type, that would
+ otherwise be modified below. */
itype = build_range_type (sizetype, size_zero_node,
NULL_TREE);
+ size_varies = 1;
}
}
function definitions in ISO C; GCC used to used
them for noreturn functions. */
if (VOID_TYPE_P (type) && really_funcdef)
- pedwarn ("function definition has qualified void return type");
+ pedwarn (input_location, 0,
+ "function definition has qualified void return type");
else
- warning (OPT_Wreturn_type,
+ warning (OPT_Wignored_qualifiers,
"type qualifiers ignored on function return type");
type = c_build_qualified_type (type, type_quals);
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn ("ISO C forbids qualified function types");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
size_varies = 0;
tree decl = build_decl (TYPE_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (decl) = 1;
pushdecl (decl);
- finish_decl (decl, NULL_TREE, NULL_TREE);
+ finish_decl (decl, NULL_TREE, NULL_TREE, NULL_TREE);
TYPE_NAME (type) = decl;
}
gcc_unreachable ();
}
}
+ *decl_attrs = chainon (returned_attrs, *decl_attrs);
/* Now TYPE has the actual type, apart from any qualifiers in
TYPE_QUALS. */
tree decl;
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn ("ISO C forbids qualified function types");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
decl = build_decl (TYPE_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
if (declspecs->explicit_signed_p)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
- decl_attributes (&decl, returned_attrs, 0);
if (declspecs->inline_p)
- pedwarn ("typedef %q+D declared %<inline%>", decl);
+ pedwarn (input_location, 0,"typedef %q+D declared %<inline%>", decl);
return decl;
}
&& !declspecs->inline_p);
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn ("ISO C forbids const or volatile function types");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- decl_attributes (&type, returned_attrs, 0);
return type;
}
&& variably_modified_type_p (type, NULL_TREE))
{
/* C99 6.7.2.1p8 */
- pedwarn ("a member of a structure or union cannot have a variably modified type");
+ pedwarn (input_location, OPT_pedantic,
+ "a member of a structure or union cannot have a variably modified type");
}
/* Aside from typedefs and type names (handle above),
if (decl_context == PARM)
{
- tree type_as_written;
tree promoted_type;
/* A parameter declared as an array of T is really a pointer to T.
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
type_quals = array_ptr_quals;
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
/* We don't yet implement attributes in this context. */
if (array_ptr_attrs != NULL_TREE)
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- if (pedantic && type_quals)
- pedwarn ("ISO C forbids qualified function types");
+ if (type_quals)
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
else if (type_quals)
type = c_build_qualified_type (type, type_quals);
- type_as_written = type;
-
decl = build_decl (PARM_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
DECL_ARG_TYPE (decl) = promoted_type;
if (declspecs->inline_p)
- pedwarn ("parameter %q+D declared %<inline%>", decl);
+ pedwarn (input_location, 0, "parameter %q+D declared %<inline%>", decl);
}
else if (decl_context == FIELD)
{
}
type = c_build_qualified_type (type, type_quals);
decl = build_decl (FIELD_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (bitfield && !declarator->u.id)
TREE_NO_WARNING (decl) = 1;
GCC allows 'auto', perhaps with 'inline', to support
nested functions. */
if (storage_class == csc_auto)
- {
- if (pedantic)
- pedwarn ("invalid storage class for function %qs", name);
- }
+ pedwarn (input_location, OPT_pedantic, "invalid storage class for function %qs", name);
else if (storage_class == csc_static)
{
error ("invalid storage class for function %qs", name);
}
decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
decl = build_decl_attribute_variant (decl, decl_attr);
- DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
-
if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ISO C forbids qualified function types");
+ pedwarn (input_location, 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 (flag_hosted && MAIN_NAME_P (declarator->u.id))
{
if (declspecs->inline_p)
- pedwarn ("cannot inline function %<main%>");
+ pedwarn (input_location, 0, "cannot inline function %<main%>");
}
else if (declspecs->inline_p)
- {
- /* Record that the function is declared `inline'. */
- DECL_DECLARED_INLINE_P (decl) = 1;
-
- /* Do not mark bare declarations as DECL_INLINE. Doing so
- in the presence of multiple declarations can result in
- the abstract origin pointing between the declarations,
- which will confuse dwarf2out. */
- if (initialized)
- DECL_INLINE (decl) = 1;
- }
- /* If -finline-functions, assume it can be inlined. This does
- two things: let the function be deferred until it is actually
- needed, and let dwarf2 know that the function is inlinable. */
- else if (flag_inline_trees == 2 && initialized)
- DECL_INLINE (decl) = 1;
+ /* Record that the function is declared `inline'. */
+ DECL_DECLARED_INLINE_P (decl) = 1;
}
else
{
C_DECL_VARIABLE_SIZE (decl) = 1;
if (declspecs->inline_p)
- pedwarn ("variable %q+D declared %<inline%>", decl);
+ pedwarn (input_location, 0, "variable %q+D declared %<inline%>", decl);
/* At file scope, an initialized extern declaration may follow
a static declaration. In that case, DECL_EXTERNAL will be
name of a variable. Thus, if it's known before this, die horribly. */
gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
- decl_attributes (&decl, returned_attrs, 0);
-
return decl;
}
}
else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
{
if (!funcdef_flag)
- pedwarn ("parameter names (without types) in function declaration");
+ pedwarn (input_location, 0, "parameter names (without types) in function declaration");
arg_info->parms = arg_info->types;
arg_info->types = 0;
parser_xref_tag (enum tree_code code, tree name)
{
struct c_typespec ret;
+ tree ref;
+
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
+
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
- tree ref = lookup_tag (code, name, 0);
+ ref = lookup_tag (code, name, 0);
/* 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
{
/* Give the type a default layout like unsigned int
to avoid crashing if it does not get defined. */
- TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
+ SET_TYPE_MODE (ref, TYPE_MODE (unsigned_type_node));
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
TYPE_USER_ALIGN (ref) = 0;
TYPE_UNSIGNED (ref) = 1;
error ("redefinition of %<union %E%>", name);
else
error ("redefinition of %<struct %E%>", name);
+ /* Don't create structures using a name already in use. */
+ ref = NULL_TREE;
}
else if (C_TYPE_BEING_DEFINED (ref))
{
/* Process the specs, declarator and width (NULL if omitted)
of a structure component, returning a FIELD_DECL node.
WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
+ DECL_ATTRS is as for grokdeclarator.
+
+ LOC is the location of the structure component.
This is done during the parsing of the struct declaration.
The FIELD_DECL nodes are chained together and the lot of them
are ultimately passed to `build_struct' to make the RECORD_TYPE node. */
tree
-grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs,
- tree width)
+grokfield (location_t loc,
+ struct c_declarator *declarator, struct c_declspecs *declspecs,
+ tree width, tree *decl_attrs)
{
tree value;
}
if (!ok)
{
- pedwarn ("declaration does not declare anything");
+ pedwarn (loc, 0, "declaration does not declare anything");
return NULL_TREE;
}
- if (pedantic)
- pedwarn ("ISO C doesn%'t support unnamed structs/unions");
+ pedwarn (loc, OPT_pedantic, "ISO C doesn%'t support unnamed structs/unions");
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
- width ? &width : NULL, DEPRECATED_NORMAL);
+ width ? &width : NULL, decl_attrs, NULL, NULL,
+ DEPRECATED_NORMAL);
- finish_decl (value, NULL_TREE, NULL_TREE);
+ finish_decl (value, NULL_TREE, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
return value;
if (TREE_CODE (t) == UNION_TYPE)
{
if (fieldlist)
- pedwarn ("union has no named members");
+ pedwarn (input_location, OPT_pedantic, "union has no named members");
else
- pedwarn ("union has no members");
+ pedwarn (input_location, OPT_pedantic, "union has no members");
}
else
{
if (fieldlist)
- pedwarn ("struct has no named members");
+ pedwarn (input_location, OPT_pedantic, "struct has no named members");
else
- pedwarn ("struct has no members");
+ pedwarn (input_location, OPT_pedantic, "struct has no members");
}
}
}
DECL_CONTEXT (x) = t;
- if (TYPE_PACKED (t) && TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
- DECL_PACKED (x) = 1;
-
/* If any field is const, the structure type is pseudo-const. */
if (TREE_READONLY (x))
C_TYPE_FIELDS_READONLY (t) = 1;
SET_DECL_C_BIT_FIELD (x);
}
+ if (TYPE_PACKED (t)
+ && (DECL_BIT_FIELD (x)
+ || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT))
+ DECL_PACKED (x) = 1;
+
/* Detect flexible array member in an invalid context. */
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
if (pedantic && !in_system_header && TREE_CODE (t) == RECORD_TYPE
&& flexible_array_type_p (TREE_TYPE (x)))
- pedwarn ("%Jinvalid use of structure with flexible array member", x);
+ pedwarn (input_location, OPT_pedantic,
+ "%Jinvalid use of structure with flexible array member", x);
if (DECL_NAME (x))
saw_named_field = 1;
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 (min_precision (minnode, unsign),
- min_precision (maxnode, unsign));
+ precision = MAX (tree_int_cst_min_precision (minnode, unsign),
+ tree_int_cst_min_precision (maxnode, unsign));
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
/* The ISO C Standard mandates enumerators to have type int,
even though the underlying type of an enum type is
- unspecified. Here we convert any enumerators that fit in
- an int to type int, to avoid promotions to unsigned types
- when comparing integers with enumerators that fit in the
- int range. When -pedantic is given, build_enumerator()
- would have already taken care of those that don't fit. */
- if (int_fits_type_p (ini, integer_type_node))
- tem = integer_type_node;
- else
- tem = enumtype;
- ini = convert (tem, ini);
+ unspecified. However, GCC allows enumerators of any
+ integer type as an extensions. build_enumerator()
+ converts any enumerators that fit in an int to type int,
+ to avoid promotions to unsigned types when comparing
+ integers with enumerators that fit in the int range.
+ When -pedantic is given, build_enumerator() would have
+ already warned about those that don't fit. Here we
+ convert the rest to the enumerator type. */
+ if (TREE_TYPE (ini) != integer_type_node)
+ ini = convert (enumtype, ini);
DECL_INITIAL (enu) = ini;
TREE_PURPOSE (pair) = DECL_NAME (enu);
TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
- TYPE_MODE (tem) = TYPE_MODE (enumtype);
+ SET_TYPE_MODE (tem, TYPE_MODE (enumtype));
TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
Assignment of sequential values by default is handled here. */
tree
-build_enumerator (struct c_enum_contents *the_enum, tree name, tree value)
+build_enumerator (struct c_enum_contents *the_enum, tree name, tree value,
+ location_t value_loc)
{
tree decl, type;
if (the_enum->enum_overflow)
error ("overflow in enumeration values");
}
-
- if (pedantic && !int_fits_type_p (value, integer_type_node))
- {
- pedwarn ("ISO C restricts enumerator values to range of %<int%>");
- /* XXX This causes -pedantic to change the meaning of the program.
- Remove? -zw 2004-03-15 */
- value = convert (integer_type_node, value);
- }
+ /* Even though the underlying type of an enum is unspecified, the
+ type of enumeration constants is explicitly defined as int
+ (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 (value_loc, OPT_pedantic,
+ "ISO C restricts enumerator values to range of %<int%>");
+
+ /* The ISO C Standard mandates enumerators to have type int, even
+ though the underlying type of an enum type is unspecified.
+ However, GCC allows enumerators of any integer type as an
+ extensions. Here we convert any enumerators that fit in an int
+ to type int, to avoid promotions to unsigned types when comparing
+ integers with enumerators that fit in the int range. When
+ -pedantic is given, we would have already warned about those that
+ don't fit. We have to do this here rather than in finish_enum
+ because this value may be used to define more enumerators. */
+ if (int_fits_type_p (value, integer_type_node))
+ value = convert (integer_type_node, value);
/* Set basis for default for next value. */
- the_enum->enum_next_value = build_binary_op (PLUS_EXPR, value,
- integer_one_node, 0);
+ the_enum->enum_next_value
+ = build_binary_op
+ (EXPR_HAS_LOCATION (value) ? EXPR_LOCATION (value) : input_location,
+ PLUS_EXPR, value, integer_one_node, 0);
the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
/* Now create a declaration for the enum value name. */
c_break_label = c_cont_label = size_zero_node;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
- DEPRECATED_NORMAL);
+ &attributes, NULL, NULL, DEPRECATED_NORMAL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (declspecs->inline_p
&& !flag_gnu89_inline
&& TREE_CODE (decl1) == FUNCTION_DECL
- && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1)))
+ && (lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1))
+ || current_function_decl))
{
if (declspecs->storage_class != csc_static)
DECL_EXTERNAL (decl1) = !DECL_EXTERNAL (decl1);
}
if (warn_about_return_type)
- pedwarn_c99 ("return type defaults to %<int%>");
+ pedwarn_c99 (input_location, flag_isoc99 ? 0
+ : (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. */
maybe_apply_pragma_weak (decl1);
/* Warn for unlikely, improbable, or stupid declarations of `main'. */
- if (warn_main > 0 && MAIN_NAME_P (DECL_NAME (decl1)))
+ if (warn_main && MAIN_NAME_P (DECL_NAME (decl1)))
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
!= integer_type_node)
- pedwarn ("return type of %q+D is not %<int%>", decl1);
+ pedwarn (input_location, OPT_Wmain, "return type of %q+D is not %<int%>", decl1);
- check_main_parameter_types(decl1);
+ check_main_parameter_types (decl1);
if (!TREE_PUBLIC (decl1))
- pedwarn ("%q+D is normally a non-static function", decl1);
+ pedwarn (input_location, OPT_Wmain, "%q+D is normally a non-static function", decl1);
}
/* Record the decl so that the function name is defined.
declare_parm_level ();
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
- /* Promote the value to int before returning it. */
- if (c_promoting_integer_type_p (restype))
- {
- /* It retains unsignedness if not really getting wider. */
- if (TYPE_UNSIGNED (restype)
- && (TYPE_PRECISION (restype)
- == TYPE_PRECISION (integer_type_node)))
- restype = unsigned_type_node;
- else
- restype = integer_type_node;
- }
-
resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
DECL_ARTIFICIAL (resdecl) = 1;
DECL_IGNORED_P (resdecl) = 1;
if (DECL_NAME (decl))
{
bind (DECL_NAME (decl), decl, current_scope,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false,
+ UNKNOWN_LOCATION);
if (!TREE_USED (decl))
warn_if_shadowing (decl);
}
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
bind (DECL_NAME (decl), decl, current_scope,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false, 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,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
}
/* Subroutine of store_parm_decls which handles old-style function
warn_if_shadowing (decl);
if (flag_isoc99)
- pedwarn ("type of %q+D defaults to %<int%>", decl);
+ pedwarn (input_location, 0, "type of %q+D defaults to %<int%>", decl);
else
warning (OPT_Wmissing_parameter_type, "type of %q+D defaults to %<int%>", decl);
}
/* Type for passing arg must be consistent with that
declared for the arg. ISO C says we take the unqualified
type for parameters declared with qualified type. */
- if (!comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
- TYPE_MAIN_VARIANT (TREE_VALUE (type))))
+ if (TREE_TYPE (parm) != error_mark_node
+ && TREE_TYPE (type) != error_mark_node
+ && !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_VALUE (type)))
< TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (parm) = integer_type_node;
- if (pedantic)
+ /* ??? Is it possible to get here with a
+ built-in prototype or will it always have
+ been diagnosed as conflicting with an
+ old-style definition and discarded? */
+ if (current_function_prototype_built_in)
+ warning (OPT_pedantic, "promoted argument %qD "
+ "doesn%'t match built-in prototype", parm);
+ else
{
- /* ??? Is it possible to get here with a
- built-in prototype or will it always have
- been diagnosed as conflicting with an
- old-style definition and discarded? */
- if (current_function_prototype_built_in)
- warning (0, "promoted argument %qD "
- "doesn%'t match built-in prototype", parm);
- else
- {
- pedwarn ("promoted argument %qD "
- "doesn%'t match prototype", parm);
- pedwarn ("%Hprototype declaration",
- ¤t_function_prototype_locus);
- }
+ pedwarn (input_location, OPT_pedantic, "promoted argument %qD "
+ "doesn%'t match prototype", parm);
+ pedwarn (current_function_prototype_locus, OPT_pedantic,
+ "prototype declaration");
}
}
else
gen_aux_info_record (fndecl, 1, 0, proto);
/* Initialize the RTL code for the function. */
- allocate_struct_function (fndecl);
+ allocate_struct_function (fndecl, false);
/* Begin the statement tree for this function. */
DECL_SAVED_TREE (fndecl) = push_stmt_list ();
call expand_expr to calculate the size of a variable-sized array.
We haven't necessarily assigned RTL to all variables yet, so it's
not safe to try to expand expressions involving them. */
- cfun->x_dont_save_pending_sizes_p = 1;
+ cfun->dont_save_pending_sizes_p = 1;
}
\f
/* Emit diagnostics that require gimple input for detection. Operate on
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 (&DECL_SAVED_TREE (fndecl));
+ c_warn_unused_result (body);
/* Notice when OpenMP structured block constraints are violated. */
if (flag_openmp)
if (DECL_RESULT (fndecl) && DECL_RESULT (fndecl) != error_mark_node)
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
- if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
+ if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted
+ && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
+ == integer_type_node && flag_isoc99)
{
- if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
- != integer_type_node)
- {
- /* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
- If warn_main is -1 (-Wno-main) we don't want to be warned. */
- if (!warn_main)
- pedwarn ("return type of %q+D is not %<int%>", fndecl);
- }
- else
- {
- if (flag_isoc99)
- {
- tree stmt = c_finish_return (integer_zero_node);
-#ifdef USE_MAPPED_LOCATION
- /* Hack. We don't want the middle-end to warn that this return
- is unreachable, so we mark its location as special. Using
- UNKNOWN_LOCATION has the problem that it gets clobbered in
- annotate_one_with_locus. A cleaner solution might be to
- ensure ! should_carry_locus_p (stmt), but that needs a flag.
- */
- SET_EXPR_LOCATION (stmt, BUILTINS_LOCATION);
-#else
- /* Hack. We don't want the middle-end to warn that this
- return is unreachable, so put the statement on the
- special line 0. */
- annotate_with_file_line (stmt, input_filename, 0);
-#endif
- }
- }
+ tree stmt = c_finish_return (integer_zero_node, NULL_TREE);
+ /* Hack. We don't want the middle-end to warn that this return
+ is unreachable, so we mark its location as special. Using
+ UNKNOWN_LOCATION has the problem that it gets clobbered in
+ annotate_one_with_locus. A cleaner solution might be to
+ ensure ! should_carry_locus_p (stmt), but that needs a flag.
+ */
+ SET_EXPR_LOCATION (stmt, BUILTINS_LOCATION);
}
/* Tie off the statement tree for this function. */
&& !MAIN_NAME_P (DECL_NAME (fndecl))
/* Or if they didn't actually specify a return type. */
&& !C_FUNCTION_IMPLICIT_INT (fndecl)
- /* Normally, with -Wreturn-type, flow will complain. Unless we're an
- inline function, as we might never be compiled separately. */
- && DECL_INLINE (fndecl))
+ /* Normally, with -Wreturn-type, flow will complain, but we might
+ optimize out static functions. */
+ && !TREE_PUBLIC (fndecl))
{
warning (OPT_Wreturn_type,
"no return statement in function returning non-void");
/* Finalize the ELF visibility for the function. */
c_determine_visibility (fndecl);
+ /* For GNU C extern inline functions disregard inline limits. */
+ if (DECL_EXTERNAL (fndecl)
+ && DECL_DECLARED_INLINE_P (fndecl))
+ DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
+
/* Genericize before inlining. Delay genericizing nested functions
until their parent function is genericized. Since finalizing
requires GENERIC, delay that as well. */
This should be cleaned up later and this conditional removed. */
if (cgraph_global_info_ready)
{
- c_expand_body (fndecl);
+ cgraph_add_new_function (fndecl, false);
return;
}
/* We're leaving the context of this function, so zap cfun.
It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
tree_rest_of_compilation. */
- cfun = NULL;
+ set_cfun (NULL);
current_function_decl = NULL;
}
\f
tree one_decl = NULL_TREE;
int n_decls = 0;
-
if (!flag_isoc99)
{
+ static bool hint = true;
/* If we get here, declarations have been used in a for loop without
the C99 for loop scope. This doesn't make much sense, so don't
allow it. */
- error ("%<for%> loop initial declaration used outside C99 mode");
+ error ("%<for%> loop initial declarations are only allowed in C99 mode");
+ if (hint)
+ {
+ inform (input_location,
+ "use option -std=c99 or -std=gnu99 to compile your code");
+ hint = false;
+ }
return NULL_TREE;
}
/* C99 subclause 6.8.5 paragraph 3:
used during compilation of a C function. */
void
-c_push_function_context (struct function *f)
+c_push_function_context (void)
{
struct language_function *p;
p = GGC_NEW (struct language_function);
- f->language = p;
+ cfun->language = p;
p->base.x_stmt_tree = c_stmt_tree;
p->x_break_label = c_break_label;
p->returns_null = current_function_returns_null;
p->returns_abnormally = current_function_returns_abnormally;
p->warn_about_return_type = warn_about_return_type;
+
+ push_function_context ();
}
/* Restore the variables used during compilation of a C function. */
void
-c_pop_function_context (struct function *f)
+c_pop_function_context (void)
{
- struct language_function *p = f->language;
+ struct language_function *p;
+
+ pop_function_context ();
+ p = cfun->language;
+ cfun->language = NULL;
if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
&& DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
current_function_returns_null = p->returns_null;
current_function_returns_abnormally = p->returns_abnormally;
warn_about_return_type = p->warn_about_return_type;
-
- f->language = NULL;
}
/* Copy the DECL_LANG_SPECIFIC data associated with DECL. */
return &c_stmt_tree;
}
-/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
- C. */
-
-int
-anon_aggr_type_p (tree ARG_UNUSED (node))
-{
- return 0;
-}
-
/* Return the global value of T as a symbol. */
tree
{
struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
ret->type = 0;
+ ret->expr = 0;
ret->decl_attr = 0;
ret->attrs = 0;
ret->typespec_word = cts_none;
ret->storage_class = csc_none;
+ ret->expr_const_operands = true;
ret->declspecs_seen_p = false;
ret->type_seen_p = false;
ret->non_sc_seen_p = false;
ret->const_p = false;
ret->volatile_p = false;
ret->restrict_p = false;
+ ret->saturating_p = false;
return ret;
}
default:
gcc_unreachable ();
}
- if (dupe && pedantic && !flag_isoc99)
- pedwarn ("duplicate %qE", qual);
+ if (dupe && !flag_isoc99)
+ pedwarn (input_location, OPT_pedantic, "duplicate %qE", qual);
return specs;
}
specs->deprecated_p = true;
/* Handle type specifier keywords. */
- if (TREE_CODE (type) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (type))
+ if (TREE_CODE (type) == IDENTIFIER_NODE
+ && C_IS_RESERVED_WORD (type)
+ && C_RID_CODE (type) != RID_CXX_COMPAT_WARN)
{
enum rid i = C_RID_CODE (type);
if (specs->type)
}
if ((int) i <= (int) RID_LAST_MODIFIER)
{
- /* "long", "short", "signed", "unsigned" or "_Complex". */
+ /* "long", "short", "signed", "unsigned", "_Complex" or "_Sat". */
bool dupe = false;
switch (i)
{
"declaration specifiers");
break;
}
- if (pedantic && !flag_isoc99 && !in_system_header
- && warn_long_long)
- pedwarn ("ISO C90 does not support %<long long%>");
+ pedwarn_c90 (input_location, OPT_Wlong_long,
+ "ISO C90 does not support %<long long%>");
specs->long_long_p = 1;
break;
}
break;
case RID_COMPLEX:
dupe = specs->complex_p;
- if (pedantic && !flag_isoc99 && !in_system_header)
- pedwarn ("ISO C90 does not support complex types");
+ if (!flag_isoc99 && !in_system_header)
+ pedwarn (input_location, OPT_pedantic, "ISO C90 does not support complex types");
if (specs->typespec_word == cts_void)
error ("both %<complex%> and %<void%> in "
"declaration specifiers");
else if (specs->typespec_word == cts_dfloat128)
error ("both %<complex%> and %<_Decimal128%> in "
"declaration specifiers");
+ else if (specs->typespec_word == cts_fract)
+ error ("both %<complex%> and %<_Fract%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_accum)
+ error ("both %<complex%> and %<_Accum%> in "
+ "declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<complex%> and %<_Sat%> in "
+ "declaration specifiers");
else
specs->complex_p = true;
break;
+ case RID_SAT:
+ dupe = specs->saturating_p;
+ 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");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_char)
+ error ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_int)
+ error ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat32)
+ error ("both %<_Sat%> and %<_Decimal32%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat64)
+ error ("both %<_Sat%> and %<_Decimal64%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat128)
+ error ("both %<_Sat%> and %<_Decimal128%> in "
+ "declaration specifiers");
+ else if (specs->complex_p)
+ error ("both %<_Sat%> and %<complex%> in "
+ "declaration specifiers");
+ else
+ specs->saturating_p = true;
+ break;
default:
gcc_unreachable ();
}
}
else
{
- /* "void", "_Bool", "char", "int", "float" or "double". */
+ /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
+ "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
if (specs->typespec_word != cts_none)
{
error ("two or more data types in declaration specifiers");
else if (specs->complex_p)
error ("both %<complex%> and %<void%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<void%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_void;
return specs;
else if (specs->complex_p)
error ("both %<complex%> and %<_Bool%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_bool;
return specs;
else if (specs->short_p)
error ("both %<short%> and %<char%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_char;
return specs;
case RID_INT:
- specs->typespec_word = cts_int;
+ if (specs->saturating_p)
+ error ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_int;
return specs;
case RID_FLOAT:
if (specs->long_p)
else if (specs->unsigned_p)
error ("both %<unsigned%> and %<float%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_float;
return specs;
else if (specs->unsigned_p)
error ("both %<unsigned%> and %<double%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_double;
return specs;
else if (specs->complex_p)
error ("both %<complex%> and %<%s%> in "
"declaration specifiers", str);
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<%s%> in "
+ "declaration specifiers", str);
else if (i == RID_DFLOAT32)
specs->typespec_word = cts_dfloat32;
else if (i == RID_DFLOAT64)
}
if (!targetm.decimal_float_supported_p ())
error ("decimal floating point not supported for this target");
- if (pedantic)
- pedwarn ("ISO C does not support decimal floating point");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C does not support decimal floating point");
+ return specs;
+ case RID_FRACT:
+ case RID_ACCUM:
+ {
+ const char *str;
+ if (i == RID_FRACT)
+ str = "_Fract";
+ else
+ str = "_Accum";
+ if (specs->complex_p)
+ error ("both %<complex%> and %<%s%> in "
+ "declaration specifiers", str);
+ else if (i == RID_FRACT)
+ specs->typespec_word = cts_fract;
+ else
+ specs->typespec_word = cts_accum;
+ }
+ if (!targetm.fixed_point_supported_p ())
+ error ("fixed-point types not supported for this target");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C does not support fixed-point types");
return specs;
default:
/* ObjC reserved word "id", handled below. */
if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
specs->tag_defined_p = true;
if (spec.kind == ctsk_typeof)
- specs->typedef_p = true;
+ {
+ specs->typedef_p = true;
+ if (spec.expr)
+ {
+ if (specs->expr)
+ specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr),
+ specs->expr, spec.expr);
+ else
+ specs->expr = spec.expr;
+ specs->expr_const_operands &= spec.expr_const_operands;
+ }
+ }
specs->type = type;
}
"_Complex short" is equivalent to "_Complex short int". */
if (specs->typespec_word == cts_none)
{
- if (specs->long_p || specs->short_p
- || specs->signed_p || specs->unsigned_p)
+ if (specs->saturating_p)
+ {
+ error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+ if (!targetm.fixed_point_supported_p ())
+ error ("fixed-point types not supported for this target");
+ specs->typespec_word = cts_fract;
+ }
+ else if (specs->long_p || specs->short_p
+ || specs->signed_p || specs->unsigned_p)
{
specs->typespec_word = cts_int;
}
else if (specs->complex_p)
{
specs->typespec_word = cts_double;
- if (pedantic)
- pedwarn ("ISO C does not support plain %<complex%> meaning "
- "%<double complex%>");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C does not support plain %<complex%> meaning "
+ "%<double complex%>");
}
else
{
specs->type = char_type_node;
if (specs->complex_p)
{
- if (pedantic)
- pedwarn ("ISO C does not support complex integer types");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
break;
: integer_type_node);
if (specs->complex_p)
{
- if (pedantic)
- pedwarn ("ISO C does not support complex integer types");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
break;
else
specs->type = dfloat128_type_node;
break;
+ case cts_fract:
+ gcc_assert (!specs->complex_p);
+ if (!targetm.fixed_point_supported_p ())
+ specs->type = integer_type_node;
+ else if (specs->saturating_p)
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_long_fract_type_node
+ : sat_long_long_fract_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_fract_type_node
+ : sat_long_fract_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_short_fract_type_node
+ : sat_short_fract_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_fract_type_node
+ : sat_fract_type_node;
+ }
+ else
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_long_fract_type_node
+ : long_long_fract_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_fract_type_node
+ : long_fract_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_short_fract_type_node
+ : short_fract_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? unsigned_fract_type_node
+ : fract_type_node;
+ }
+ break;
+ case cts_accum:
+ gcc_assert (!specs->complex_p);
+ if (!targetm.fixed_point_supported_p ())
+ specs->type = integer_type_node;
+ else if (specs->saturating_p)
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_long_accum_type_node
+ : sat_long_long_accum_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_accum_type_node
+ : sat_long_accum_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_short_accum_type_node
+ : sat_short_accum_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_accum_type_node
+ : sat_accum_type_node;
+ }
+ else
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_long_accum_type_node
+ : long_long_accum_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_accum_type_node
+ : long_accum_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_short_accum_type_node
+ : short_accum_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? unsigned_accum_type_node
+ : accum_type_node;
+ }
+ break;
default:
gcc_unreachable ();
}
&& !TREE_PUBLIC (decl)
&& C_DECL_USED (decl))
{
- pedwarn ("%q+F used but never defined", decl);
+ pedwarn (input_location, 0, "%q+F used but never defined", decl);
TREE_NO_WARNING (decl) = 1;
}
/* Don't waste time on further processing if -fsyntax-only or we've
encountered errors. */
- if (flag_syntax_only || errorcount || sorrycount || cpp_errors (parse_in))
+ if (flag_syntax_only || errorcount || sorrycount)
return;
/* Close the external scope. */