/* 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
+ Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
location_t location;
error ("label %q+D used but not defined", label);
-#ifdef USE_MAPPED_LOCATION
location = input_location; /* FIXME want (input_filename, (line)0) */
-#else
- location.file = input_filename;
- location.line = 0;
-#endif
/* Avoid crashing later. */
define_label (location, DECL_NAME (label));
}
/* In each subblock, record that this is its superior. */
if (keep >= 0)
- for (link = subblocks; link; link = TREE_CHAIN (link))
+ for (link = subblocks; link; link = BLOCK_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
/* We still support the old for-scope rules, whereby the variables
}
}
+#define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn) \
+ && lookup_attribute ("gnu_inline", \
+ DECL_ATTRIBUTES (fn)))
+
/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
If the redeclaration is invalid, a diagnostic is issued, and the
error_mark_node is returned. Otherwise, OLDDECL is returned.
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
}
+ /* If a function is explicitly declared "throw ()", propagate that to
+ the corresponding builtin. */
+ if (DECL_BUILT_IN_CLASS (olddecl) == BUILT_IN_NORMAL
+ && DECL_ANTICIPATED (olddecl)
+ && TREE_NOTHROW (newdecl)
+ && !TREE_NOTHROW (olddecl)
+ && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != NULL_TREE
+ && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != olddecl
+ && types_match)
+ TREE_NOTHROW (built_in_decls [DECL_FUNCTION_CODE (olddecl)]) = 1;
+
/* Whether or not the builtin can throw exceptions has no
bearing on this declarator. */
TREE_NOTHROW (olddecl) = 0;
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
+ DECL_ATTRIBUTES (old_result)
+ = (*targetm.merge_decl_attributes) (old_result, new_result);
+
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
{
- DECL_INLINE (old_result)
- |= DECL_INLINE (new_result);
- DECL_DECLARED_INLINE_P (old_result)
- |= DECL_DECLARED_INLINE_P (new_result);
- check_redeclaration_exception_specification (newdecl, olddecl);
+ if (GNU_INLINE_P (old_result) != GNU_INLINE_P (new_result)
+ && DECL_INITIAL (new_result))
+ {
+ if (DECL_INITIAL (old_result))
+ {
+ DECL_INLINE (old_result) = 0;
+ DECL_UNINLINABLE (old_result) = 1;
+ }
+ else
+ {
+ DECL_INLINE (old_result) = DECL_INLINE (new_result);
+ DECL_UNINLINABLE (old_result) = DECL_UNINLINABLE (new_result);
+ }
+ DECL_EXTERNAL (old_result) = DECL_EXTERNAL (new_result);
+ DECL_NOT_REALLY_EXTERN (old_result)
+ = DECL_NOT_REALLY_EXTERN (new_result);
+ DECL_INTERFACE_KNOWN (old_result)
+ = DECL_INTERFACE_KNOWN (new_result);
+ DECL_DECLARED_INLINE_P (old_result)
+ = DECL_DECLARED_INLINE_P (new_result);
+ DECL_DISREGARD_INLINE_LIMITS (old_result)
+ |= DECL_DISREGARD_INLINE_LIMITS (new_result);
+
+ }
+ else
+ {
+ DECL_INLINE (old_result)
+ |= DECL_INLINE (new_result);
+ DECL_DECLARED_INLINE_P (old_result)
+ |= DECL_DECLARED_INLINE_P (new_result);
+ DECL_DISREGARD_INLINE_LIMITS (old_result)
+ |= DECL_DISREGARD_INLINE_LIMITS (new_result);
+ check_redeclaration_exception_specification (newdecl, olddecl);
+ }
}
/* If the new declaration is a definition, update the file and
line information on the declaration, and also make
the old declaration the same definition. */
- if (DECL_INITIAL (old_result) == NULL_TREE
- && DECL_INITIAL (new_result) != NULL_TREE)
+ if (DECL_INITIAL (new_result) != NULL_TREE)
{
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (old_result)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
- TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
TREE_NOTHROW (newdecl) |= TREE_NOTHROW (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);
+ DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
+ TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+ DECL_LOOPING_CONST_OR_PURE_P (newdecl)
+ |= DECL_LOOPING_CONST_OR_PURE_P (olddecl);
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
}
new_template = NULL_TREE;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
- DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
- DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
- DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+ bool new_redefines_gnu_inline = false;
+
+ if (new_defines_function
+ && ((DECL_INTERFACE_KNOWN (olddecl)
+ && TREE_CODE (olddecl) == FUNCTION_DECL)
+ || (TREE_CODE (olddecl) == TEMPLATE_DECL
+ && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
+ == FUNCTION_DECL))))
+ {
+ tree fn = olddecl;
+
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ fn = DECL_TEMPLATE_RESULT (olddecl);
+
+ new_redefines_gnu_inline = GNU_INLINE_P (fn) && DECL_INITIAL (fn);
+ }
+
+ if (!new_redefines_gnu_inline)
+ {
+ DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
+ DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
+ DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+ }
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
/* [temp.expl.spec/14] We don't inline explicit specialization
just because the primary template says so. */
}
+ else if (new_defines_function && DECL_INITIAL (olddecl))
+ {
+ /* C++ is always in in unit-at-a-time mode, so we never
+ inline re-defined extern inline functions. */
+ DECL_INLINE (newdecl) = 0;
+ DECL_UNINLINABLE (newdecl) = 1;
+ }
else
{
if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
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));
}
/* Preserve abstractness on cloned [cd]tors. */
{
if (DECL_NAME (olddecl) == NULL_TREE)
return "%q#D not declared in class";
- else
+ else if (!GNU_INLINE_P (olddecl)
+ || GNU_INLINE_P (newdecl))
return "redefinition of %q#D";
}
+
+ if (DECL_DECLARED_INLINE_P (olddecl) && DECL_DECLARED_INLINE_P (newdecl))
+ {
+ bool olda = GNU_INLINE_P (olddecl);
+ bool newa = GNU_INLINE_P (newdecl);
+
+ if (olda != newa)
+ {
+ if (newa)
+ return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ else
+ return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ }
+ }
+
return NULL;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
ot = DECL_TEMPLATE_RESULT (olddecl);
if (DECL_TEMPLATE_INFO (ot))
ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
- if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
+ if (DECL_INITIAL (nt) && DECL_INITIAL (ot)
+ && (!GNU_INLINE_P (ot) || GNU_INLINE_P (nt)))
return "redefinition of %q#D";
+ if (DECL_DECLARED_INLINE_P (ot) && DECL_DECLARED_INLINE_P (nt))
+ {
+ bool olda = GNU_INLINE_P (ot);
+ bool newa = GNU_INLINE_P (nt);
+
+ if (olda != newa)
+ {
+ if (newa)
+ return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ else
+ return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ }
+ }
+
/* Core issue #226 (C++0x):
If a friend function template declaration specifies a
else
{
/* Build the TYPENAME_TYPE. */
- t = make_aggr_type (TYPENAME_TYPE);
+ t = cxx_make_type (TYPENAME_TYPE);
TYPE_CONTEXT (t) = ti.scope;
TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
TYPENAME_IS_ENUM_P (t) = ti.enum_p;
if (dependent_type_p (context))
return build_typename_type (context, name, fullname, tag_type);
- if (!IS_AGGR_TYPE (context))
+ if (!MAYBE_CLASS_TYPE_P (context))
{
if (complain & tf_error)
error ("%q#T is not a class", context);
{
tree tmpl = NULL_TREE;
- if (IS_AGGR_TYPE (context))
+ if (MAYBE_CLASS_TYPE_P (context))
tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
}
/* Build the UNBOUND_CLASS_TEMPLATE. */
- t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
+ t = cxx_make_type (UNBOUND_CLASS_TEMPLATE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
TREE_TYPE (t) = NULL_TREE;
SET_TYPE_STRUCTURAL_EQUALITY (t);
push_namespace (std_identifier);
bad_alloc_id = get_identifier ("bad_alloc");
- bad_alloc_type_node = make_aggr_type (RECORD_TYPE);
+ bad_alloc_type_node = make_class_type (RECORD_TYPE);
TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
bad_alloc_decl
= create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
tree decl = build_decl (VAR_DECL, id, type);
if (name)
- free (CONST_CAST (name));
+ free (CONST_CAST (char *, name));
/* As we're using pushdecl_with_scope, we must set the context. */
DECL_CONTEXT (decl) = current_function_decl;
anticipated but not actually declared. */
if (name[0] != '_' || name[1] != '_')
DECL_ANTICIPATED (decl) = 1;
+ else if (strncmp (name + 2, "builtin_", strlen ("builtin_")) != 0)
+ {
+ size_t len = strlen (name);
+
+ /* Treat __*_chk fortification functions as anticipated as well,
+ unless they are __builtin_*. */
+ if (len > strlen ("___chk")
+ && memcmp (name + len - strlen ("_chk"),
+ "_chk", strlen ("_chk") + 1) == 0)
+ DECL_ANTICIPATED (decl) = 1;
+ }
return decl;
}
tree *q;
/* Wipe out memory of synthesized methods. */
- TYPE_HAS_CONSTRUCTOR (t) = 0;
+ TYPE_HAS_USER_CONSTRUCTOR (t) = 0;
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0;
/* ISO C++ 9.5.3. Anonymous unions may not have function members. */
if (TYPE_METHODS (t))
- error ("%Jan anonymous union cannot have function members",
- TYPE_MAIN_DECL (t));
+ {
+ tree decl = TYPE_MAIN_DECL (t);
+
+ if (TREE_CODE (t) != UNION_TYPE)
+ error ("%Jan anonymous struct cannot have function members", decl);
+ else
+ error ("%Jan anonymous union cannot have function members", decl);
+ }
/* Anonymous aggregates cannot have fields with ctors, dtors or complex
assignment operators (because they cannot have these methods themselves).
if (declspecs->type
&& TYPE_P (declspecs->type)
&& ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
- && IS_AGGR_TYPE (declspecs->type))
+ && MAYBE_CLASS_TYPE_P (declspecs->type))
|| TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
declared_type = declspecs->type;
else if (declspecs->type == error_mark_node)
if (declared_type == NULL_TREE && ! saw_friend && !error_p)
pedwarn ("declaration does not declare anything");
/* Check for an anonymous union. */
- else if (declared_type && IS_AGGR_TYPE_CODE (TREE_CODE (declared_type))
+ else if (declared_type && RECORD_OR_UNION_CODE_P (TREE_CODE (declared_type))
&& TYPE_ANONYMOUS_P (declared_type))
{
/* 7/3 In a simple-declaration, the optional init-declarator-list
attrs = type_specifiers->attributes;
type_specifiers->attributes = NULL_TREE;
type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
- if (attrs)
- cplus_decl_attributes (&type, attrs, 0);
+ if (attrs && type != error_mark_node)
+ {
+ if (CLASS_TYPE_P (type))
+ warning (OPT_Wattributes, "ignoring attributes applied to class type %qT "
+ "outside of definition", type);
+ else if (MAYBE_CLASS_TYPE_P (type))
+ /* A template type parameter or other dependent type. */
+ warning (OPT_Wattributes, "ignoring attributes applied to dependent "
+ "type %qT without an associated declaration", type);
+ else
+ cplus_decl_attributes (&type, attrs, 0);
+ }
return type;
}
-/* Decode a declarator in an ordinary declaration or data definition.
- This is called as soon as the type information and variable name
- have been parsed, before parsing the initializer if any.
- Here we create the ..._DECL node, fill in its type,
- and put it on the list of decls for the current context.
- The ..._DECL node is returned as the value.
-
- Exception: for arrays where the length is not specified,
- the type is left null, to be filled in by `cp_finish_decl'.
-
- Function definitions do not come here; they go to start_function
- instead. However, external and forward declarations of functions
- do go through here. Structure field declarations are done by
- grokfield and not through here. */
+/* Process a DECLARATOR for a function-scope variable declaration,
+ namespace-scope variable declaration, or function declaration.
+ (Function definitions go through start_function; class member
+ declarations appearing in the body of the class go through
+ grokfield.) The DECL corresponding to the DECLARATOR is returned.
+ If an error occurs, the error_mark_node is returned instead.
+
+ DECLSPECS are the decl-specifiers for the declaration. INITIALIZED
+ is true if an explicit initializer is present, but false if this is
+ a variable implicitly initialized via a default constructor.
+ ATTRIBUTES and PREFIX_ATTRIBUTES are GNU attributes associated with
+ this declaration. *PUSHED_SCOPE_P is set to the scope entered in
+ this function, if any; if set, the caller is responsible for
+ calling pop_scope. */
tree
start_decl (const cp_declarator *declarator,
tree *pushed_scope_p)
{
tree decl;
- tree type, tem;
+ tree type;
tree context;
bool was_public;
+ int flags;
*pushed_scope_p = NULL_TREE;
TREE_STATIC (decl) = 1;
}
+ /* If this is a typedef that names the class for linkage purposes
+ (7.1.3p8), apply any attributes directly to the type. */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TAGGED_TYPE_P (TREE_TYPE (decl))
+ && decl == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl))))
+ flags = ATTR_FLAG_TYPE_IN_PLACE;
+ else
+ flags = 0;
+
/* Set attributes here so if duplicate decl, will have proper attributes. */
- cplus_decl_attributes (&decl, attributes, 0);
+ cplus_decl_attributes (&decl, attributes, flags);
/* Dllimported symbols cannot be defined. Static data members (which
can be initialized in-class and dllimported) go through grokfield,
was_public = TREE_PUBLIC (decl);
/* Enter this declaration into the symbol table. */
- tem = maybe_push_decl (decl);
+ decl = maybe_push_decl (decl);
if (processing_template_decl)
- tem = push_template_decl (tem);
- if (tem == error_mark_node)
+ decl = push_template_decl (decl);
+ if (decl == error_mark_node)
return error_mark_node;
/* Tell the back end to use or not use .common as appropriate. If we say
produce errors about redefs; to do this we force variables into the
data segment. */
if (flag_conserve_space
- && TREE_CODE (tem) == VAR_DECL
- && TREE_PUBLIC (tem)
- && !DECL_THREAD_LOCAL_P (tem)
+ && TREE_CODE (decl) == VAR_DECL
+ && TREE_PUBLIC (decl)
+ && !DECL_THREAD_LOCAL_P (decl)
&& !have_global_bss_p ())
- DECL_COMMON (tem) = 1;
+ DECL_COMMON (decl) = 1;
- if (TREE_CODE (tem) == VAR_DECL
- && DECL_NAMESPACE_SCOPE_P (tem) && !TREE_PUBLIC (tem) && !was_public
- && !DECL_THIS_STATIC (tem) && !DECL_ARTIFICIAL (tem))
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public
+ && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
{
/* This is a const variable with implicit 'static'. Set
DECL_THIS_STATIC so we can tell it from variables that are
!TREE_PUBLIC because of the anonymous namespace. */
- gcc_assert (cp_type_readonly (TREE_TYPE (tem)));
- DECL_THIS_STATIC (tem) = 1;
+ gcc_assert (cp_type_readonly (TREE_TYPE (decl)));
+ DECL_THIS_STATIC (decl) = 1;
}
- if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
- start_decl_1 (tem, initialized);
+ if (!processing_template_decl && TREE_CODE (decl) == VAR_DECL)
+ start_decl_1 (decl, initialized);
- return tem;
+ return decl;
}
+/* Process the declaration of a variable DECL. INITIALIZED is true
+ iff DECL is explicitly initialized. (INITIALIZED is false if the
+ variable is initialized via an implicitly-called constructor.)
+ This function must be called for ordinary variables (including, for
+ example, implicit instantiations of templates), but must not be
+ called for template declarations. */
+
void
start_decl_1 (tree decl, bool initialized)
{
tree type;
+ bool complete_p;
+ bool aggregate_definition_p;
gcc_assert (!processing_template_decl);
return;
gcc_assert (TREE_CODE (decl) == VAR_DECL);
+
type = TREE_TYPE (decl);
+ complete_p = COMPLETE_TYPE_P (type);
+ aggregate_definition_p = MAYBE_CLASS_TYPE_P (type) && !DECL_EXTERNAL (decl);
+
+ /* If an explicit initializer is present, or if this is a definition
+ of an aggregate, then we need a complete type at this point.
+ (Scalars are always complete types, so there is nothing to
+ check.) This code just sets COMPLETE_P; errors (if necessary)
+ are issued below. */
+ if ((initialized || aggregate_definition_p)
+ && !complete_p
+ && COMPLETE_TYPE_P (complete_type (type)))
+ {
+ complete_p = true;
+ /* We will not yet have set TREE_READONLY on DECL if the type
+ was "const", but incomplete, before this point. But, now, we
+ have a complete type, so we can try again. */
+ cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
+ }
if (initialized)
- /* Is it valid for this decl to have an initializer at all?
- If not, set INITIALIZED to zero, which will indirectly
- tell `cp_finish_decl' to ignore the initializer once it is parsed. */
+ /* Is it valid for this decl to have an initializer at all? */
{
/* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */
- if (COMPLETE_TYPE_P (complete_type (type)))
+ if (complete_p)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
error ("variable %q#D has initializer but incomplete type", decl);
- initialized = 0;
type = TREE_TYPE (decl) = error_mark_node;
}
else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
error ("elements of array %q#D have incomplete type", decl);
/* else we already gave an error in start_decl. */
- initialized = 0;
}
}
- else if (IS_AGGR_TYPE (type)
- && ! DECL_EXTERNAL (decl))
+ else if (aggregate_definition_p && !complete_p)
{
- if (!COMPLETE_TYPE_P (complete_type (type)))
- {
- error ("aggregate %q#D has incomplete type and cannot be defined",
- decl);
- /* Change the type so that assemble_variable will give
- DECL an rtl we can live with: (mem (const_int 0)). */
- type = TREE_TYPE (decl) = error_mark_node;
- }
- else
- {
- /* If any base type in the hierarchy of TYPE needs a constructor,
- then we set initialized to 1. This way any nodes which are
- created for the purposes of initializing this aggregate
- will live as long as it does. This is necessary for global
- aggregates which do not have their initializers processed until
- the end of the file. */
- initialized = TYPE_NEEDS_CONSTRUCTING (type);
- }
+ error ("aggregate %q#D has incomplete type and cannot be defined",
+ decl);
+ /* Change the type so that assemble_variable will give
+ DECL an rtl we can live with: (mem (const_int 0)). */
+ type = TREE_TYPE (decl) = error_mark_node;
}
/* Create a new scope to hold this declaration if necessary.
HOST_WIDE_INT i;
for (i = 0;
VEC_iterate (constructor_elt, v, i, ce);
- ++i)
+ ++i)
if (!check_array_designated_initializer (ce))
failure = 1;
}
/* Keep this code around in case we later want to control debug info
based on whether a type is "used". (jason 1999-11-11) */
- else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
+ else if (!DECL_EXTERNAL (decl) && MAYBE_CLASS_TYPE_P (ttype))
/* Let debugger know it should output info for this type. */
note_debug_info_needed (ttype);
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
- error ("storage size of %qD isn't constant", decl);
+ {
+ error ("storage size of %qD isn't constant", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
}
}
return new_init;
}
+/* Verify array initializer. Returns true if errors have been reported. */
+
+bool
+check_array_initializer (tree decl, tree type, tree init)
+{
+ tree element_type = TREE_TYPE (type);
+
+ /* The array type itself need not be complete, because the
+ initializer may tell us how many elements are in the array.
+ But, the elements of the array must be complete. */
+ if (!COMPLETE_TYPE_P (complete_type (element_type)))
+ {
+ if (decl)
+ error ("elements of array %q#D have incomplete type", decl);
+ else
+ error ("elements of array %q#T have incomplete type", type);
+ return true;
+ }
+ /* It is not valid to initialize a VLA. */
+ if (init
+ && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
+ || !TREE_CONSTANT (TYPE_SIZE (element_type))))
+ {
+ if (decl)
+ error ("variable-sized object %qD may not be initialized", decl);
+ else
+ error ("variable-sized compound literal");
+ return true;
+ }
+ return false;
+}
+
/* Verify INIT (the initializer for DECL), and record the
initialization in DECL_INITIAL, if appropriate. CLEANUP is as for
grok_reference_init.
if (TREE_CODE (type) == ARRAY_TYPE)
{
- tree element_type = TREE_TYPE (type);
-
- /* The array type itself need not be complete, because the
- initializer may tell us how many elements are in the array.
- But, the elements of the array must be complete. */
- if (!COMPLETE_TYPE_P (complete_type (element_type)))
- {
- error ("elements of array %q#D have incomplete type", decl);
- return NULL_TREE;
- }
- /* It is not valid to initialize a VLA. */
- if (init
- && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
- || !TREE_CONSTANT (TYPE_SIZE (element_type))))
- {
- error ("variable-sized object %qD may not be initialized", decl);
- return NULL_TREE;
- }
+ if (check_array_initializer (decl, type, init))
+ return NULL_TREE;
}
else if (!COMPLETE_TYPE_P (type))
{
if (type == error_mark_node)
return NULL_TREE;
- if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
+ if (TREE_CODE (type) == ARRAY_TYPE && TYPE_NEEDS_CONSTRUCTING (type))
+ goto initialize_aggr;
+ else if (CLASS_TYPE_P (type))
{
- if (TREE_CODE (type) == ARRAY_TYPE)
- goto initialize_aggr;
- else if (TREE_CODE (init) == CONSTRUCTOR)
+ if (TREE_CODE (init) == CONSTRUCTOR)
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
}
- init = build_aggr_init (decl, init, flags);
+ init = build_aggr_init (decl, init, flags, tf_warning_or_error);
if (building_stmt_tree ())
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
;
else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
goto initialize_aggr;
- else if (IS_AGGR_TYPE (type))
+ else if (MAYBE_CLASS_TYPE_P (type))
{
tree core_type = strip_array_types (type);
/* An in-class declaration of a static data member should be
external; it is only a declaration, and not a definition. */
if (init == NULL_TREE)
- gcc_assert (DECL_EXTERNAL (decl));
+ gcc_assert (DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl));
}
/* We don't create any RTL for local variables. */
rest_of_decl_compilation (decl, toplev, at_eof);
}
+/* walk_tree helper for wrap_temporary_cleanups, below. */
+
+static tree
+wrap_cleanups_r (tree *stmt_p, int *walk_subtrees, void *data)
+{
+ if (TYPE_P (*stmt_p))
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (*stmt_p) == TARGET_EXPR)
+ {
+ tree guard = (tree)data;
+ tree tcleanup = TARGET_EXPR_CLEANUP (*stmt_p);
+
+ tcleanup = build2 (TRY_CATCH_EXPR, void_type_node, tcleanup, guard);
+ /* Tell honor_protect_cleanup_actions to handle this as a separate
+ cleanup. */
+ TRY_CATCH_IS_CLEANUP (tcleanup) = 1;
+
+ TARGET_EXPR_CLEANUP (*stmt_p) = tcleanup;
+ }
+
+ return NULL_TREE;
+}
+
+/* We're initializing a local variable which has a cleanup GUARD. If there
+ are any temporaries used in the initializer INIT of this variable, we
+ need to wrap their cleanups with TRY_CATCH_EXPR (, GUARD) so that the
+ variable will be cleaned up properly if one of them throws.
+
+ Unfortunately, there's no way to express this properly in terms of
+ nesting, as the regions for the temporaries overlap the region for the
+ variable itself; if there are two temporaries, the variable needs to be
+ the first thing destroyed if either of them throws. However, we only
+ want to run the variable's cleanup if it actually got constructed. So
+ we need to guard the temporary cleanups with the variable's cleanup if
+ they are run on the normal path, but not if they are run on the
+ exceptional path. We implement this by telling
+ honor_protect_cleanup_actions to strip the variable cleanup from the
+ exceptional path. */
+
+static void
+wrap_temporary_cleanups (tree init, tree guard)
+{
+ cp_walk_tree_without_duplicates (&init, wrap_cleanups_r, (void *)guard);
+}
+
/* Generate code to initialize DECL (a local variable). */
static void
{
tree type = TREE_TYPE (decl);
tree cleanup;
+ int already_used;
gcc_assert (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == RESULT_DECL);
/* If we used it already as memory, it must stay in memory. */
DECL_INITIAL (decl) = NULL_TREE;
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
+ return;
}
- if (DECL_SIZE (decl) && type != error_mark_node)
- {
- int already_used;
+ if (type == error_mark_node)
+ return;
- /* Compute and store the initial value. */
- already_used = TREE_USED (decl) || TREE_USED (type);
+ /* Compute and store the initial value. */
+ already_used = TREE_USED (decl) || TREE_USED (type);
- /* Perform the initialization. */
- if (init)
- {
- int saved_stmts_are_full_exprs_p;
+ /* Generate a cleanup, if necessary. */
+ cleanup = cxx_maybe_build_cleanup (decl);
- gcc_assert (building_stmt_tree ());
- saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
- current_stmt_tree ()->stmts_are_full_exprs_p = 1;
- finish_expr_stmt (init);
- current_stmt_tree ()->stmts_are_full_exprs_p =
- saved_stmts_are_full_exprs_p;
- }
+ /* Perform the initialization. */
+ if (init)
+ {
+ int saved_stmts_are_full_exprs_p;
- /* Set this to 0 so we can tell whether an aggregate which was
- initialized was ever used. Don't do this if it has a
- destructor, so we don't complain about the 'resource
- allocation is initialization' idiom. Now set
- attribute((unused)) on types so decls of that type will be
- marked used. (see TREE_USED, above.) */
- if (TYPE_NEEDS_CONSTRUCTING (type)
- && ! already_used
- && TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
- && DECL_NAME (decl))
- TREE_USED (decl) = 0;
- else if (already_used)
- TREE_USED (decl) = 1;
- }
+ /* If we're only initializing a single object, guard the destructors
+ of any temporaries used in its initializer with its destructor.
+ This isn't right for arrays because each element initialization is
+ a full-expression. */
+ if (cleanup && TREE_CODE (type) != ARRAY_TYPE)
+ wrap_temporary_cleanups (init, cleanup);
- /* Generate a cleanup, if necessary. */
- cleanup = cxx_maybe_build_cleanup (decl);
- if (DECL_SIZE (decl) && cleanup)
+ gcc_assert (building_stmt_tree ());
+ saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
+ current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+ finish_expr_stmt (init);
+ current_stmt_tree ()->stmts_are_full_exprs_p =
+ saved_stmts_are_full_exprs_p;
+ }
+
+ /* Set this to 0 so we can tell whether an aggregate which was
+ initialized was ever used. Don't do this if it has a
+ destructor, so we don't complain about the 'resource
+ allocation is initialization' idiom. Now set
+ attribute((unused)) on types so decls of that type will be
+ marked used. (see TREE_USED, above.) */
+ if (TYPE_NEEDS_CONSTRUCTING (type)
+ && ! already_used
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
+ && DECL_NAME (decl))
+ TREE_USED (decl) = 0;
+ else if (already_used)
+ TREE_USED (decl) = 1;
+
+ if (cleanup)
finish_decl_cleanup (decl, cleanup);
}
type_dependent_p = dependent_type_p (type);
+ if (check_for_bare_parameter_packs (init))
+ {
+ init = NULL_TREE;
+ DECL_INITIAL (decl) = NULL_TREE;
+ }
+
if (init && init_const_expr_p)
{
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
goto finish_end;
}
- init = fold_non_dependent_expr (init);
+ if (TREE_CODE (init) == TREE_LIST)
+ {
+ /* If the parenthesized-initializer form was used (e.g.,
+ "int A<N>::i(X)"), then INIT will be a TREE_LIST of initializer
+ arguments. (There is generally only one.) We convert them
+ individually. */
+ tree list = init;
+ for (; list; list = TREE_CHAIN (list))
+ {
+ tree elt = TREE_VALUE (list);
+ TREE_VALUE (list) = fold_non_dependent_expr (elt);
+ }
+ }
+ else
+ init = fold_non_dependent_expr (init);
processing_template_decl = 0;
}
if (TREE_CODE (decl) == TYPE_DECL)
{
if (type != error_mark_node
- && IS_AGGR_TYPE (type) && DECL_NAME (decl))
+ && MAYBE_CLASS_TYPE_P (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
warning (0, "shadowing previous type declaration of %q#D", decl);
require a guard variable, and since the mangled name of the
guard variable will depend on the mangled name of this
variable. */
- if (!processing_template_decl
- && DECL_FUNCTION_SCOPE_P (decl)
+ if (DECL_FUNCTION_SCOPE_P (decl)
&& TREE_STATIC (decl)
&& !DECL_ARTIFICIAL (decl))
push_local_name (decl);
is *not* defined. */
&& (!DECL_EXTERNAL (decl) || init))
{
+ if (TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
+ {
+ tree jclass
+ = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
+ /* Allow libjava/prims.cc define primitive classes. */
+ if (init != NULL_TREE
+ || jclass == NULL_TREE
+ || TREE_CODE (jclass) != TYPE_DECL
+ || !POINTER_TYPE_P (TREE_TYPE (jclass))
+ || !same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (TREE_TYPE (jclass))))
+ error ("Java object %qD not allocated with %<new%>", decl);
+ init = NULL_TREE;
+ }
if (init)
{
DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
else if (TREE_CODE (type) == ARRAY_TYPE)
layout_type (type);
}
+ else if (TREE_CODE (decl) == FIELD_DECL
+ && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
+ error ("non-static data member %qD has Java class type", decl);
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_EXPR for a
maybe_commonize_var (decl);
}
+ /* This needs to happen after the linkage is set. */
+ determine_visibility (decl);
+
+ if (var_definition_p && TREE_STATIC (decl))
+ {
+ /* If a TREE_READONLY variable needs initialization
+ at runtime, it is no longer readonly and we need to
+ avoid MEM_READONLY_P being set on RTL created for it. */
+ if (init)
+ {
+ if (TREE_READONLY (decl))
+ TREE_READONLY (decl) = 0;
+ was_readonly = 0;
+ }
+ else if (was_readonly)
+ TREE_READONLY (decl) = 1;
+ }
+
make_rtl_for_nonlocal_decl (decl, init, asmspec);
/* Check for abstractness of the type. Notice that there is no
else
abstract_virtuals_error (decl, type);
- /* This needs to happen after the linkage is set. */
- determine_visibility (decl);
-
if (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_TYPE (decl) == error_mark_node)
/* No initialization required. */
if (init)
DECL_INITIAL (decl) = init;
}
- else
- {
- /* A variable definition. */
- if (DECL_FUNCTION_SCOPE_P (decl))
- {
- /* Initialize the local variable. */
- if (processing_template_decl)
- DECL_INITIAL (decl) = init;
- else if (!TREE_STATIC (decl))
- initialize_local_var (decl, init);
- }
+ /* A variable definition. */
+ else if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))
+ /* Initialize the local variable. */
+ initialize_local_var (decl, init);
- /* If a variable is defined, and then a subsequent
- definition with external linkage is encountered, we will
- get here twice for the same variable. We want to avoid
- calling expand_static_init more than once. For variables
- that are not static data members, we can call
- expand_static_init only when we actually process the
- initializer. It is not legal to redeclare a static data
- member, so this issue does not arise in that case. */
- if (var_definition_p && TREE_STATIC (decl))
- {
- /* If a TREE_READONLY variable needs initialization
- at runtime, it is no longer readonly and we need to
- avoid MEM_READONLY_P being set on RTL created for it. */
- if (init)
- {
- if (TREE_READONLY (decl))
- TREE_READONLY (decl) = 0;
- was_readonly = 0;
- }
- expand_static_init (decl, init);
- }
- }
+ /* If a variable is defined, and then a subsequent
+ definition with external linkage is encountered, we will
+ get here twice for the same variable. We want to avoid
+ calling expand_static_init more than once. For variables
+ that are not static data members, we can call
+ expand_static_init only when we actually process the
+ initializer. It is not legal to redeclare a static data
+ member, so this issue does not arise in that case. */
+ else if (var_definition_p && TREE_STATIC (decl))
+ expand_static_init (decl, init);
}
/* If a CLEANUP_STMT was created to destroy a temporary bound to a
addr = build_address (decl);
/* The declared type of the parameter to "__cxa_atexit" is
"void *". For plain "T*", we could just let the
- machinery in build_function_call convert it -- but if the
+ machinery in cp_build_function_call convert it -- but if the
type is "cv-qualified T *", then we need to convert it
before passing it in, to avoid spurious errors. */
addr = build_nop (ptr_type_node, addr);
other value. */
addr = null_pointer_node;
args = tree_cons (NULL_TREE,
- build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
+ cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0,
+ tf_warning_or_error),
NULL_TREE);
if (targetm.cxx.use_aeabi_atexit ())
{
}
else
args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
- return build_function_call (get_atexit_node (), args);
+ return cp_build_function_call (get_atexit_node (), args,
+ tf_warning_or_error);
}
/* DECL is a VAR_DECL with static storage duration. INIT, if present,
if (initial_value)
{
+ unsigned HOST_WIDE_INT i;
+ tree value;
+
/* An array of character type can be initialized from a
brace-enclosed string constant.
&& VEC_length (constructor_elt, v) == 1)
initial_value = value;
}
+
+ /* If any of the elements are parameter packs, we can't actually
+ complete this type now because the array size is dependent. */
+ if (TREE_CODE (initial_value) == CONSTRUCTOR)
+ {
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (initial_value),
+ i, value)
+ {
+ if (PACK_EXPANSION_P (value))
+ return 0;
+ }
+ }
}
failure = complete_array_type (ptype, initial_value, do_default);
XXX Isn't this done in start_function, too? */
revert_static_member_fn (decl);
if (DECL_ARTIFICIAL (old_decl))
- error ("definition of implicitly-declared %qD", old_decl);
+ {
+ error ("definition of implicitly-declared %qD", old_decl);
+ return NULL_TREE;
+ }
/* Since we've smashed OLD_DECL to its
DECL_TEMPLATE_RESULT, we must do the same to DECL. */
unqualified_variant
= build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
- t = make_aggr_type (RECORD_TYPE);
+ t = make_class_type (RECORD_TYPE);
xref_basetypes (t, NULL_TREE);
/* Let the front end know this is a pointer to member function... */
TYPE_PTRMEMFUNC_FLAG (t) = 1;
- /* ... and not really an aggregate. */
- SET_IS_AGGR_TYPE (t, 0);
+ /* ... and not really a class type. */
+ SET_CLASS_TYPE_P (t, 0);
field = build_decl (FIELD_DECL, pfn_identifier, type);
fields = field;
{
/* Check to see if the array bound overflowed. Make that an
error, no matter how generous we're being. */
- int old_flag_pedantic_errors = flag_pedantic_errors;
- int old_pedantic = pedantic;
- pedantic = flag_pedantic_errors = 1;
- constant_expression_warning (size);
- pedantic = old_pedantic;
- flag_pedantic_errors = old_flag_pedantic_errors;
+ constant_expression_error (size);
/* An array must have a positive number of elements. */
if (INT_CST_LT (size, integer_zero_node))
processing_template_decl = 0;
itype = cp_build_binary_op (MINUS_EXPR,
cp_convert (ssizetype, size),
- cp_convert (ssizetype, integer_one_node));
+ cp_convert (ssizetype, integer_one_node),
+ tf_warning_or_error);
itype = fold (itype);
processing_template_decl = saved_processing_template_decl;
return error_mark_node;
}
+ if (declspecs->conflicting_specifiers_p)
+ {
+ error ("conflicting specifiers in declaration of %qs", name);
+ return error_mark_node;
+ }
+
/* Extract the basic type from the decl-specifier-seq. */
type = declspecs->type;
if (type == error_mark_node)
{
typedef_decl = type;
type = TREE_TYPE (typedef_decl);
+ if (TREE_DEPRECATED (type)
+ && DECL_ARTIFICIAL (typedef_decl)
+ && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (type);
}
/* No type at all: default to `int', and set DEFAULTED_INT
because it was not a user-defined typedef. */
error ("%<long%> or %<short%> specified with char for %qs", name);
else if (long_p && short_p)
error ("%<long%> and %<short%> specified together for %qs", name);
+ else if (type == char16_type_node || type == char32_type_node)
+ {
+ if (signed_p || unsigned_p)
+ error ("%<signed%> or %<unsigned%> invalid for %qs", name);
+ else if (short_p || long_p)
+ error ("%<short%> or %<long%> invalid for %qs", name);
+ }
else
{
ok = 1;
if (virtualp
&& (current_class_name == NULL_TREE || decl_context != FIELD))
{
- error ("virtual outside class declaration");
+ error ("%<virtual%> outside class declaration");
virtualp = 0;
}
error ("multiple storage classes in declaration of %qs", name);
thread_p = false;
}
- if (declspecs->conflicting_specifiers_p)
- {
- error ("conflicting specifiers in declaration of %qs", name);
- storage_class = sc_none;
- }
- else if (decl_context != NORMAL
- && ((storage_class != sc_none
- && storage_class != sc_mutable)
- || thread_p))
+ if (decl_context != NORMAL
+ && ((storage_class != sc_none
+ && storage_class != sc_mutable)
+ || thread_p))
{
if ((decl_context == PARM || decl_context == CATCHPARM)
&& (storage_class == sc_register
if (type_quals != TYPE_UNQUALIFIED)
{
if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
- warning (OPT_Wreturn_type,
+ warning (OPT_Wignored_qualifiers,
"type qualifiers ignored on function return type");
/* We now know that the TYPE_QUALS don't apply to the
decl, but to its return type. */
type_quals = TYPE_UNQUALIFIED;
if (declarator->kind == cdk_ptrmem
- && (TREE_CODE (type) == FUNCTION_TYPE || memfn_quals))
+ && (TREE_CODE (type) == FUNCTION_TYPE
+ || (memfn_quals && TREE_CODE (type) == METHOD_TYPE)))
{
memfn_quals |= cp_type_quals (type);
type = build_memfn_type (type,
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& TYPE_ANONYMOUS_P (type)
- /* Don't do this if there are attributes. */
- && (!attrlist || !*attrlist)
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
{
tree oldname = TYPE_NAME (type);
return error_mark_node;
}
}
+ else if (sfk == sfk_constructor && friendp)
+ {
+ error ("expected qualified name in friend declaration "
+ "for constructor %qD",
+ id_declarator->u.id.unqualified_name);
+ return error_mark_node;
+ }
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
function_context = (ctype != NULL_TREE) ?
else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
- /* Record constancy and volatility. There's no need to do this
- when processing a template; we'll do this for the instantiated
- declaration based on the type of DECL. */
+ /* Record constancy and volatility on the DECL itself . There's
+ no need to do this when processing a template; we'll do this
+ for the instantiated declaration based on the type of DECL. */
if (!processing_template_decl)
cp_apply_type_quals_to_decl (type_quals, decl);
TREE_TYPE (decl) = error_mark_node;
}
+ if (type != error_mark_node
+ && TYPE_FOR_JAVA (type)
+ && MAYBE_CLASS_TYPE_P (type))
+ {
+ error ("parameter %qD has Java class type", decl);
+ type = error_mark_node;
+ TREE_TYPE (decl) = error_mark_node;
+ init = NULL_TREE;
+ }
+
if (type != error_mark_node)
{
/* Top-level qualifiers on the parameters are
operator. */
int
-copy_fn_p (tree d)
+copy_fn_p (const_tree d)
{
tree args;
tree arg_type;
operator, false otherwise. */
bool
-move_fn_p (tree d)
+move_fn_p (const_tree d)
{
tree args;
tree arg_type;
/* Remember any special properties of member function DECL. */
-void grok_special_member_properties (tree decl)
+void
+grok_special_member_properties (tree decl)
{
tree class_type;
{
int ctor = copy_fn_p (decl);
- TYPE_HAS_CONSTRUCTOR (class_type) = 1;
+ if (!DECL_ARTIFICIAL (decl))
+ TYPE_HAS_USER_CONSTRUCTOR (class_type) = 1;
if (ctor > 0)
{
if the class has a constructor of the form X(X). */
int
-grok_ctor_properties (tree ctype, tree decl)
+grok_ctor_properties (const_tree ctype, const_tree decl)
{
int ctor_parm = copy_fn_p (decl);
}
if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
- TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+ {
+ TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+ DECL_IS_OPERATOR_NEW (decl) = 1;
+ }
else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
else
if (arg == error_mark_node)
return false;
- /* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used
+ /* MAYBE_CLASS_TYPE_P, rather than CLASS_TYPE_P, is used
because these checks are performed even on
template functions. */
- if (IS_AGGR_TYPE (arg) || TREE_CODE (arg) == ENUMERAL_TYPE)
+ if (MAYBE_CLASS_TYPE_P (arg)
+ || TREE_CODE (arg) == ENUMERAL_TYPE)
break;
}
if (t == class_type)
what = "the same type";
/* Don't force t to be complete here. */
- else if (IS_AGGR_TYPE (t)
+ else if (MAYBE_CLASS_TYPE_P (t)
&& COMPLETE_TYPE_P (t)
&& DERIVED_FROM_P (t, class_type))
what = "a base class";
}
else
{
- t = make_aggr_type (code);
+ t = make_class_type (code);
TYPE_CONTEXT (t) = context;
t = pushtag (name, t, scope);
}
}
else
{
- if (template_header_p && IS_AGGR_TYPE (t))
+ if (template_header_p && MAYBE_CLASS_TYPE_P (t))
{
if (!redeclare_class_template (t, current_template_parms))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
saved_location = input_location;
input_location = DECL_SOURCE_LOCATION (decl);
value = perform_implicit_conversion (underlying_type,
- DECL_INITIAL (decl));
+ DECL_INITIAL (decl),
+ tf_warning_or_error);
input_location = saved_location;
/* Do not clobber shared ints. */
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
TREE_CONSTANT (decl) = 1;
- TREE_INVARIANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;
if (dependent_type_p (return_type))
return;
- if (!COMPLETE_OR_VOID_TYPE_P (return_type))
+ if (!COMPLETE_OR_VOID_TYPE_P (return_type)
+ || (TYPE_FOR_JAVA (return_type) && MAYBE_CLASS_TYPE_P (return_type)))
{
tree args = TYPE_ARG_TYPES (fntype);
- error ("return type %q#T is incomplete", return_type);
+ if (!COMPLETE_OR_VOID_TYPE_P (return_type))
+ error ("return type %q#T is incomplete", return_type);
+ else
+ error ("return type has Java class type %q#T", return_type);
/* Make it return void instead. */
if (TREE_CODE (fntype) == METHOD_TYPE)
&& lookup_attribute ("noinline", attrs))
warning (0, "inline function %q+D given attribute noinline", decl1);
+ /* Handle gnu_inline attribute. */
+ if (GNU_INLINE_P (decl1))
+ {
+ DECL_EXTERNAL (decl1) = 1;
+ DECL_NOT_REALLY_EXTERN (decl1) = 0;
+ DECL_INTERFACE_KNOWN (decl1) = 1;
+ DECL_DISREGARD_INLINE_LIMITS (decl1) = 1;
+ }
+
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
/* This is a constructor, we must ensure that any default args
introduced by this definition are propagated to the clones
CFUN set up, and our per-function variables initialized.
FIXME factor out the non-RTL stuff. */
bl = current_binding_level;
- allocate_struct_function (decl1);
+ allocate_struct_function (decl1, processing_template_decl);
+
+ /* Initialize the language data structures. Whenever we start
+ a new function, we destroy temporaries in the usual way. */
+ cfun->language = GGC_CNEW (struct language_function);
+ current_stmt_tree ()->stmts_are_full_exprs_p = 1;
current_binding_level = bl;
/* Even though we're inside a function body, we still don't want to
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;
/* Start the statement-tree, start the tree now. */
DECL_SAVED_TREE (decl1) = push_stmt_list ();
gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
cp_function_chain->x_current_class_ref
- = build_indirect_ref (t, NULL);
+ = cp_build_indirect_ref (t, NULL, tf_warning_or_error);
cp_function_chain->x_current_class_ptr = t;
/* Constructors and destructors need to know whether they're "in
else
{
/* This is a definition, not a reference.
- So clear DECL_EXTERNAL. */
- DECL_EXTERNAL (decl1) = 0;
+ So clear DECL_EXTERNAL, unless this is a GNU extern inline. */
+ if (!GNU_INLINE_P (decl1))
+ DECL_EXTERNAL (decl1) = 0;
if ((DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))
of curly braces, skipping the artificial block created for constructor
initializers. */
-static tree
+tree
outer_curly_brace_block (tree fndecl)
{
tree block = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl));
/* Hack. We don't want the middle-end to warn that this
return is unreachable, so put the statement on the
special line 0. */
-#ifdef USE_MAPPED_LOCATION
- SET_EXPR_LOCATION (stmt, UNKNOWN_LOCATION);
-#else
- annotate_with_file_line (stmt, input_filename, 0);
-#endif
+ {
+ location_t linezero = linemap_line_start (line_table, 0, 1);
+ SET_EXPR_LOCATION (stmt, linezero);
+ }
}
if (use_eh_spec_block (current_function_decl))
/* 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;
/* If this is an in-class inline definition, we may have to pop the
fn = lookup_name (id);
arg = build_address (decl);
mark_used (decl);
- cleanup = build_function_call (fn, build_tree_list (NULL_TREE,
- arg));
+ cleanup = cp_build_function_call (fn, build_tree_list (NULL_TREE,
+ arg),
+ tf_warning_or_error);
}
/* Handle ordinary C++ destructors. */
type = TREE_TYPE (decl);
if (TREE_CODE (type) == ARRAY_TYPE)
addr = decl;
else
- {
- cxx_mark_addressable (decl);
- addr = build_unary_op (ADDR_EXPR, decl, 0);
- }
+ addr = build_address (decl);
/* Optimize for space over speed here. */
if (!has_vbases || flag_expensive_optimizations)
DECL_STATIC_FUNCTION_P (decl) = 1;
}
-/* Initialize the variables used during compilation of a C++
- function. */
-
-void
-cxx_push_function_context (struct function * f)
-{
- struct language_function *p = GGC_CNEW (struct language_function);
- f->language = p;
-
- /* Whenever we start a new function, we destroy temporaries in the
- usual way. */
- current_stmt_tree ()->stmts_are_full_exprs_p = 1;
-
- if (f->decl)
- {
- tree fn = f->decl;
-
- if (DECL_SAVED_FUNCTION_DATA (fn))
- {
- /* If we already parsed this function, and we're just expanding it
- now, restore saved state. */
- *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
-
- /* We don't need the saved data anymore. Unless this is an inline
- function; we need the named return value info for
- declare_return_variable. */
- if (! DECL_INLINE (fn))
- DECL_SAVED_FUNCTION_DATA (fn) = NULL;
- }
- }
-}
-
-/* Free the language-specific parts of F, now that we've finished
- compiling the function. */
-
-void
-cxx_pop_function_context (struct function * f)
-{
- f->language = 0;
-}
-
/* Return which tree structure is used by T, or TS_CP_GENERIC if T is
one of the language-independent trees. */
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
case OVERLOAD: return TS_CP_OVERLOAD;
case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
- case TINST_LEVEL: return TS_CP_TINST_LEVEL;
case PTRMEM_CST: return TS_CP_PTRMEM;
case BASELINK: return TS_CP_BASELINK;
case STATIC_ASSERT: return TS_CP_STATIC_ASSERT;