static void push_local_name (tree);
static tree grok_reference_init (tree, tree, tree, tree *);
static tree grokfndecl (tree, tree, tree, tree, tree, int,
- enum overload_flags, tree,
+ enum overload_flags, cp_cv_quals,
tree, int, int, int, int, int, int, tree);
-static tree grokvardecl (tree, tree, cp_decl_specifier_seq *, int, int, tree);
+static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
+ int, int, tree);
static void record_unknown_type (tree, const char *);
-static tree builtin_function_1 (const char *, tree, tree, int,
- enum built_in_class, const char *,
+static tree builtin_function_1 (const char *, tree, tree,
+ enum built_in_function code,
+ enum built_in_class cl, const char *,
tree);
static tree build_library_fn_1 (tree, enum tree_code, tree);
static int member_function_or_else (tree, tree, enum overload_flags);
static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
static void save_function_data (tree);
static void check_function_type (tree, tree);
-static void begin_constructor_body (void);
static void finish_constructor_body (void);
static void begin_destructor_body (void);
static void finish_destructor_body (void);
static void end_cleanup_fn (void);
static tree cp_make_fname_decl (tree, int);
static void initialize_predefined_identifiers (void);
-static tree check_special_function_return_type
+static tree check_special_function_return_type
(special_function_kind, tree, tree);
static tree push_cp_library_fn (enum tree_code, tree);
static tree build_cp_library_fn (tree, enum tree_code, tree);
with __attribute__((deprecated)). An object declared as
__attribute__((deprecated)) suppresses warnings of uses of other
deprecated items. */
-
+
enum deprecated_states {
DEPRECATED_NORMAL,
DEPRECATED_SUPPRESS
struct cp_binding_level *b;
/* Scan through the template parameter scopes. */
- for (b = current_binding_level;
- b->kind == sk_template_parms;
+ for (b = current_binding_level;
+ b->kind == sk_template_parms;
b = b->level_chain)
{
/* If we see a specialization scope inside a parameter scope,
location_t location;
cp_error_at ("label `%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));
}
? ((functionbody = 0), tmp) : functionbody);
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
- my_friendly_assert (!current_binding_level->class_shadowed,
+ my_friendly_assert (VEC_length(cp_class_binding,
+ current_binding_level->class_shadowed) == 0,
19990414);
/* We used to use KEEP == 2 to indicate that the new block should go
else
decls = current_binding_level->names;
- /* When not in function-at-a-time mode, expand_end_bindings will
- warn about unused variables. But, in function-at-a-time mode
- expand_end_bindings is not passed the list of variables in the
- current scope, and therefore no warning is emitted. So, we
- explicitly warn here. */
- if (!processing_template_decl)
- warn_about_unused_variables (getdecls ());
-
/* If there were any declarations or structure tags in that level,
or if this level is a function body,
create a BLOCK to record them for the life of this function. */
leaving_for_scope
= current_binding_level->kind == sk_for && flag_new_for_scope == 1;
+ /* Before we remove the declarations first check for unused variables. */
+ if (warn_unused_variable
+ && !processing_template_decl)
+ for (decl = getdecls (); decl; decl = TREE_CHAIN (decl))
+ if (TREE_CODE (decl) == VAR_DECL
+ && ! TREE_USED (decl)
+ && ! DECL_IN_SYSTEM_HEADER (decl)
+ && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
+ warning ("%Junused variable '%D'", decl, decl);
+
/* Remove declarations for all the DECLs in this level. */
for (link = decls; link; link = TREE_CHAIN (link))
{
if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
&& DECL_NAME (link))
{
- cxx_binding *outer_binding
- = IDENTIFIER_BINDING (DECL_NAME (link))->previous;
+ tree name = DECL_NAME (link);
+ cxx_binding *ob;
tree ns_binding;
- if (!outer_binding)
- ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));
+ ob = outer_binding (name,
+ IDENTIFIER_BINDING (name),
+ /*class_p=*/true);
+ if (!ob)
+ ns_binding = IDENTIFIER_NAMESPACE_VALUE (name);
else
ns_binding = NULL_TREE;
- if (outer_binding
- && outer_binding->scope == current_binding_level->level_chain)
+ if (ob && ob->scope == current_binding_level->level_chain)
/* We have something like:
int i;
and we are leaving the `for' scope. There's no reason to
keep the binding of the inner `i' in this case. */
- pop_binding (DECL_NAME (link), link);
- else if ((outer_binding
- && (TREE_CODE (outer_binding->value) == TYPE_DECL))
+ pop_binding (name, link);
+ else if ((ob && (TREE_CODE (ob->value) == TYPE_DECL))
|| (ns_binding && TREE_CODE (ns_binding) == TYPE_DECL))
/* Here, we have something like:
We must pop the for-scope binding so we know what's a
type and what isn't. */
- pop_binding (DECL_NAME (link), link);
+ pop_binding (name, link);
else
{
/* Mark this VAR_DECL as dead so that we can tell we left it
/* Keep track of what should have happened when we
popped the binding. */
- if (outer_binding && outer_binding->value)
- DECL_SHADOWED_FOR_VAR (link) = outer_binding->value;
+ if (ob && ob->value)
+ DECL_SHADOWED_FOR_VAR (link) = ob->value;
/* Add it to the list of dead variables in the next
outermost binding to that we can remove these when we
/* Although we don't pop the cxx_binding, we do clear
its SCOPE since the scope is going away now. */
- IDENTIFIER_BINDING (DECL_NAME (link))->scope = NULL;
+ IDENTIFIER_BINDING (name)->scope
+ = current_binding_level->level_chain;
}
}
else
{
/* Remove the binding. */
decl = link;
+
if (TREE_CODE (decl) == TREE_LIST)
decl = TREE_VALUE (decl);
+
if (DECL_P (decl))
pop_binding (DECL_NAME (decl), decl);
else if (TREE_CODE (decl) == OVERLOAD)
= chainon (current_binding_level->blocks, block);
}
-/* Set the BLOCK node for the innermost scope
- (the one we are currently in). */
-
-void
-set_block (tree block ATTRIBUTE_UNUSED )
-{
- /* The RTL expansion machinery requires us to provide this callback,
- but it is not applicable in function-at-a-time mode. */
-}
-
/* Returns nonzero if T is a virtual function table. */
int
returns a nonzero value, return a nonzero value. */
bool
walk_vtables (walk_globals_pred p, walk_globals_fn f, void *data)
-{
+{
struct walk_globals_data wgd;
- wgd.p = p;
+ wgd.p = p;
wgd.f = f;
wgd.data = data;
walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data)
{
int result = 0;
- tree current = NAMESPACE_LEVEL (namespace)->namespaces;
+ tree current = NAMESPACE_LEVEL (namespace)->namespaces;
result |= (*f) (namespace, data);
/* One of the declarations is a template instantiation, and the
other is not a template at all. That's OK. */
return NULL_TREE;
- else if (TREE_CODE (newdecl) == NAMESPACE_DECL
- && DECL_NAMESPACE_ALIAS (newdecl)
- && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
- /* In [namespace.alias] we have:
-
- In a declarative region, a namespace-alias-definition can be
- used to redefine a namespace-alias declared in that declarative
- region to refer only to the namespace to which it already
- refers.
-
- Therefore, if we encounter a second alias directive for the same
- alias, we can just ignore the second directive. */
- return olddecl;
+ else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
+ {
+ /* In [namespace.alias] we have:
+
+ In a declarative region, a namespace-alias-definition can be
+ used to redefine a namespace-alias declared in that declarative
+ region to refer only to the namespace to which it already
+ refers.
+
+ Therefore, if we encounter a second alias directive for the same
+ alias, we can just ignore the second directive. */
+ if (DECL_NAMESPACE_ALIAS (newdecl)
+ && (DECL_NAMESPACE_ALIAS (newdecl)
+ == DECL_NAMESPACE_ALIAS (olddecl)))
+ return olddecl;
+ /* [namespace.alias]
+
+ A namespace-name or namespace-alias shall not be declared as
+ the name of any other entity in the same declarative region.
+ A namespace-name defined at global scope shall not be
+ declared as the name of any other entity in any glogal scope
+ of the program. */
+ error ("declaration of `namespace %D' conflicts with", newdecl);
+ cp_error_at ("previous declaration of `namespace %D' here", olddecl);
+ return error_mark_node;
+ }
else
{
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
}
}
- if (DECL_DECLARED_INLINE_P (newdecl)
+ if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& TREE_ADDRESSABLE (olddecl) && warn_inline)
{
if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
{
- DECL_SOURCE_LOCATION (olddecl)
+ DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
= DECL_SOURCE_LOCATION (newdecl);
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
{
- DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl))
+ DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl))
|= DECL_INLINE (DECL_TEMPLATE_RESULT (newdecl));
DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (olddecl))
|= DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (newdecl));
TYPE_RAISES_EXCEPTIONS (oldtype));
if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
- && DECL_SOURCE_LINE (olddecl) != 0
+ && ! DECL_IS_BUILTIN (olddecl)
&& flag_exceptions
&& !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
}
- else if (TREE_CODE (newdecl) == VAR_DECL
+ else if (TREE_CODE (newdecl) == VAR_DECL
&& (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
{
/* Keep the old RTL. We cannot keep the old RTL if the old
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
- DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
+ DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
+ DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
|= DECL_INITIALIZED_IN_CLASS_P (olddecl);
DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
- /* If either decl says `inline', this fn is inline, unless
+ /* If either decl says `inline', this fn is inline, unless
its definition was passed already. */
if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
DECL_INLINE (olddecl) = 1;
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
- /* If either declaration has a nondefault visibility, use it. */
- if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
+ /* Warn about conflicting visibility specifications. */
+ if (DECL_VISIBILITY_SPECIFIED (olddecl)
+ && DECL_VISIBILITY_SPECIFIED (newdecl)
+ && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
+ {
+ warning ("%J'%D': visibility attribute ignored because it",
+ newdecl, newdecl);
+ warning ("%Jconflicts with previous declaration here", olddecl);
+ }
+ /* Choose the declaration which specified visibility. */
+ if (DECL_VISIBILITY_SPECIFIED (olddecl))
{
- if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
- && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
- {
- warning ("%J'%D': visibility attribute ignored because it",
- newdecl, newdecl);
- warning ("%Jconflicts with previous declaration here", olddecl);
- }
DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+ DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
olddecl, and not newdecl, is on the list of
instantiations so that if we try to do the instantiation
again we won't get the clobbered declaration. */
- reregister_specialization (newdecl,
- DECL_TI_TEMPLATE (newdecl),
+ reregister_specialization (newdecl,
+ DECL_TI_TEMPLATE (newdecl),
olddecl);
}
else
/* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
so that encode_section_info has a chance to look at the new decl
flags and attributes. */
- if (DECL_RTL_SET_P (olddecl)
+ if (DECL_RTL_SET_P (olddecl)
&& (TREE_CODE (olddecl) == FUNCTION_DECL
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
- make_decl_rtl (olddecl, NULL);
+ make_decl_rtl (olddecl);
return olddecl;
}
}
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL
- || (DECL_TEMPLATE_RESULT (newdecl)
+ || (DECL_TEMPLATE_RESULT (newdecl)
== DECL_TEMPLATE_RESULT (olddecl)))
return NULL;
|| named_label_uses->label_decl != decl)
{
struct named_label_use_list *new_ent;
- new_ent = ggc_alloc (sizeof (struct named_label_use_list));
+ new_ent = GGC_NEW (struct named_label_use_list);
new_ent->label_decl = decl;
new_ent->names_in_scope = current_binding_level->names;
new_ent->binding_level = current_binding_level;
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
IDENTIFIER_LABEL_VALUE before the new label is declared. */
- ent = ggc_alloc_cleared (sizeof (struct named_label_list));
+ ent = GGC_CNEW (struct named_label_list);
ent->old_value = IDENTIFIER_LABEL_VALUE (id);
ent->next = named_labels;
named_labels = ent;
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
- for (p = current_binding_level;
- p->kind != sk_function_parms;
+ for (p = current_binding_level;
+ p->kind != sk_function_parms;
p = p->level_chain)
p->more_cleanups_ok = 0;
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
- r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
+ r = c_add_case_label (switch_stack->cases, cond, TREE_TYPE (cond),
+ low_value, high_value);
check_switch_goto (switch_stack->level);
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
- for (p = current_binding_level;
- p->kind != sk_function_parms;
+ for (p = current_binding_level;
+ p->kind != sk_function_parms;
p = p->level_chain)
p->more_cleanups_ok = 0;
if (typename_htab == NULL)
{
- typename_htab = htab_create_ggc (61, &typename_hash,
+ typename_htab = htab_create_ggc (61, &typename_hash,
&typename_compare, NULL);
}
return error_mark_node;
}
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030802);
-
+
if (TREE_CODE (context) == NAMESPACE_DECL)
{
/* We can get here from typename_sub0 in the explicit_template_type
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
-
+
return t;
}
}
error ("no class template named `%#T' in `%#T'", name, context);
return error_mark_node;
}
-
+
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
type. TYPE is the _TYPE node for the builtin type. */
void
-record_builtin_type (enum rid rid_index,
- const char* name,
+record_builtin_type (enum rid rid_index,
+ const char* name,
tree type)
{
tree rname = NULL_TREE, tname = NULL_TREE;
tree void_ftype;
tree void_ftype_ptr;
+ build_common_tree_nodes (flag_signed_char);
+
/* Create all the identifiers we need. */
initialize_predefined_identifiers ();
/* Initially, C. */
current_lang_name = lang_name_c;
- build_common_tree_nodes (flag_signed_char);
-
error_mark_list = build_tree_list (error_mark_node, error_mark_node);
TREE_TYPE (error_mark_list) = error_mark_node;
java_char_type_node = record_builtin_java_type ("__java_char", -16);
java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1);
- integer_two_node = build_int_2 (2, 0);
- TREE_TYPE (integer_two_node) = integer_type_node;
- integer_three_node = build_int_2 (3, 0);
- TREE_TYPE (integer_three_node) = integer_type_node;
+ integer_two_node = build_int_cst (NULL_TREE, 2, 0);
+ integer_three_node = build_int_cst (NULL_TREE, 3, 0);
record_builtin_type (RID_BOOL, "bool", boolean_type_node);
truthvalue_type_node = boolean_type_node;
void_ftype = build_function_type (void_type_node, void_list_node);
void_ftype_ptr = build_function_type (void_type_node,
tree_cons (NULL_TREE,
- ptr_type_node,
+ ptr_type_node,
void_list_node));
void_ftype_ptr
= build_exception_variant (void_ftype_ptr, empty_except_spec);
bad_alloc_id = get_identifier ("bad_alloc");
bad_alloc_type_node = make_aggr_type (RECORD_TYPE);
TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
- bad_alloc_decl
+ bad_alloc_decl
= create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
DECL_CONTEXT (bad_alloc_decl) = current_namespace;
TYPE_STUB_DECL (bad_alloc_type_node) = bad_alloc_decl;
pop_namespace ();
-
- ptr_ftype_sizetype
+
+ ptr_ftype_sizetype
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
size_type_node,
/* Perform other language dependent initializations. */
init_class_processing ();
- init_search_processing ();
init_rtti_processing ();
if (flag_exceptions)
domain = build_index_type (size_int (length));
init = build_string (length + 1, name);
}
-
+
type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
type = build_cplus_array_type (type, domain);
*type_p = type;
-
+
if (init)
TREE_TYPE (init) = type;
else
init = error_mark_node;
-
+
return init;
}
/* As we're using pushdecl_with_scope, we must set the context. */
DECL_CONTEXT (decl) = current_function_decl;
DECL_PRETTY_FUNCTION_P (decl) = type_dep;
-
+
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = init;
-
+
TREE_USED (decl) = 1;
if (current_function_decl)
}
else
pushdecl_top_level_and_finish (decl, init);
-
+
return decl;
}
builtin_function_1 (const char* name,
tree type,
tree context,
- int code,
+ enum built_in_function code,
enum built_in_class class,
const char* libname,
tree attrs)
builtin_function (const char* name,
tree type,
int code,
- enum built_in_class class,
+ enum built_in_class cl,
const char* libname,
tree attrs)
{
if (name[0] != '_')
{
push_namespace (std_identifier);
- builtin_function_1 (name, type, std_node, code, class, libname, attrs);
+ builtin_function_1 (name, type, std_node, code, cl, libname, attrs);
pop_namespace ();
}
return builtin_function_1 (name, type, NULL_TREE, code,
- class, libname, attrs);
+ cl, libname, attrs);
}
/* Generate a FUNCTION_DECL with the typical flags for a runtime library
TREE_NOTHROW (fn) = 1;
SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
SET_DECL_LANGUAGE (fn, lang_c);
+ /* Runtime library routines are, by definition, available in an
+ external shared object. */
+ DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
+ DECL_VISIBILITY_SPECIFIED (fn) = 1;
return fn;
}
else if (declspecs->redefined_builtin_type)
{
if (!in_system_header)
- pedwarn ("redeclaration of C++ built-in type",
+ pedwarn ("redeclaration of C++ built-in type %qT",
declspecs->redefined_builtin_type);
return NULL_TREE;
}
if (TYPE_P (declspecs->type)
- && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
+ && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
&& IS_AGGR_TYPE (declspecs->type))
|| TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
declared_type = declspecs->type;
/* Anonymous unions are objects, so they can have specifiers. */;
SET_ANON_AGGR_TYPE_P (declared_type);
- if (TREE_CODE (declared_type) != UNION_TYPE && pedantic
+ if (TREE_CODE (declared_type) != UNION_TYPE && pedantic
&& !in_system_header)
pedwarn ("ISO C++ prohibits anonymous structs");
}
{
if (declspecs->specs[(int)ds_inline]
|| declspecs->specs[(int)ds_virtual])
- error ("`%s' can only be specified for functions",
- declspecs->specs[(int)ds_inline]
+ error ("`%s' can only be specified for functions",
+ declspecs->specs[(int)ds_inline]
? "inline" : "virtual");
else if (saw_friend
- && (!current_class_type
+ && (!current_class_type
|| current_scope () != current_class_type))
error ("`friend' can only be specified inside a class");
else if (declspecs->specs[(int)ds_explicit])
Otherwise, it is an error.
C++: may have to grok the declspecs to learn about static,
- complain for anonymous unions.
+ complain for anonymous unions.
Returns the TYPE declared -- or NULL_TREE if none. */
if (TYPE_FIELDS (t))
{
- tree decl = grokdeclarator (/*declarator=*/NULL,
+ tree decl = grokdeclarator (/*declarator=*/NULL,
declspecs, NORMAL, 0, NULL);
finish_anon_union (decl);
}
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
-groktypename (cp_decl_specifier_seq *type_specifiers,
+groktypename (cp_decl_specifier_seq *type_specifiers,
const cp_declarator *declarator)
{
tree attrs;
grokfield and not through here. */
tree
-start_decl (const cp_declarator *declarator,
+start_decl (const cp_declarator *declarator,
cp_decl_specifier_seq *declspecs,
- int initialized,
- tree attributes,
- tree prefix_attributes)
+ int initialized,
+ tree attributes,
+ tree prefix_attributes,
+ bool *pop_scope_p)
{
tree decl;
tree type, tem;
context = DECL_CONTEXT (decl);
- if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
- && context != current_namespace && TREE_CODE (decl) == VAR_DECL)
- {
- /* When parsing the initializer, lookup should use the object's
- namespace. */
- push_decl_namespace (context);
- }
-
+ if (context)
+ *pop_scope_p = push_scope (context);
+ else
+ *pop_scope_p = false;
+
/* We are only interested in class contexts, later. */
if (context && TREE_CODE (context) == NAMESPACE_DECL)
context = NULL_TREE;
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
- push_nested_class (context);
-
if (TREE_CODE (decl) == VAR_DECL)
{
tree field = lookup_field (context, DECL_NAME (decl), 0, false);
`extern X x' for some incomplete type `X'.) */
if (!DECL_EXTERNAL (decl))
complete_type (type);
- if (!DECL_SIZE (decl)
+ if (!DECL_SIZE (decl)
&& TREE_TYPE (decl) != error_mark_node
&& (COMPLETE_TYPE_P (type)
- || (TREE_CODE (type) == ARRAY_TYPE
+ || (TREE_CODE (type) == ARRAY_TYPE
&& !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))))
layout_decl (decl, 0);
&& DECL_FUNCTION_SCOPE_P (decl)
/* Unfortunately, import_export_decl has not always been called
before the function is processed, so we cannot simply check
- DECL_COMDAT. */
+ DECL_COMDAT. */
&& (DECL_COMDAT (DECL_CONTEXT (decl))
|| ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
|| DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
*INITP is one of a list of initializers describing a brace-enclosed
initializer for an entity of the indicated aggregate TYPE. It may
not presently match the shape of the TYPE; for example:
-
+
struct S { int a; int b; };
struct S a[] = { 1, 2, 3, 4 };
else
old_init = error_mark_node;
}
-
+
return old_init;
}
}
else
{
- /* Build a CONSTRUCTOR to hold the contents of the aggregate. */
+ /* Build a CONSTRUCTOR to hold the contents of the aggregate. */
new_init = build_constructor (NULL_TREE, NULL_TREE);
if (CLASS_TYPE_P (type))
if (!field)
{
/* [dcl.init.aggr]
-
+
An initializer for an aggregate member that is an
empty class shall have the form of an empty
initializer-list {}. */
return error_mark_node;
TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
CONSTRUCTOR_ELTS (new_init) = field_init;
- /* [dcl.init.aggr]
+ /* [dcl.init.aggr]
When a union is initialized with a brace-enclosed
initializer, the braces shall only contain an
if (type == error_mark_node)
/* We will have already complained. */
init = NULL_TREE;
- else if (init && COMPLETE_TYPE_P (type)
+ else if (init && COMPLETE_TYPE_P (type)
&& !TREE_CONSTANT (TYPE_SIZE (type)))
{
error ("variable-sized object `%D' may not be initialized", decl);
init = grok_reference_init (decl, type, init, cleanup);
else if (init)
{
- if (TREE_CODE (init) == CONSTRUCTOR
+ if (TREE_CODE (init) == CONSTRUCTOR
&& BRACE_ENCLOSED_INITIALIZER_P (init))
{
/* [dcl.init] paragraph 13,
T x = { a };
is equivalent to
T x = a;
-
+
reshape_init will complain about the extra braces,
and doesn't do anything useful in the case where TYPE is
scalar, so just don't call it. */
check_for_uninitialized_const_var (decl);
if (init && init != error_mark_node)
- init_code = build (INIT_EXPR, type, decl, init);
+ init_code = build2 (INIT_EXPR, type, decl, init);
return init_code;
}
int toplev = toplevel_bindings_p ();
int defer_p;
+ /* Set the DECL_ASSEMBLER_NAME for the object. */
+ if (asmspec)
+ {
+ /* The `register' keyword, when used together with an
+ asm-specification, indicates that the variable should be
+ placed in a particular register. */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+ {
+ change_decl_assembler_name (decl, get_identifier (asmspec));
+ DECL_HARD_REGISTER (decl) = 1;
+ }
+ else
+ set_user_assembler_name (decl, asmspec);
+ }
+
/* Handle non-variables up front. */
if (TREE_CODE (decl) != VAR_DECL)
{
- rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+ rest_of_decl_compilation (decl, toplev, at_eof);
return;
}
my_friendly_assert (DECL_EXTERNAL (decl), 20000723);
}
- /* Set the DECL_ASSEMBLER_NAME for the variable. */
- if (asmspec)
- {
- change_decl_assembler_name (decl, get_identifier (asmspec));
- /* The `register' keyword, when used together with an
- asm-specification, indicates that the variable should be
- placed in a particular register. */
- if (DECL_REGISTER (decl))
- DECL_HARD_REGISTER (decl) = 1;
- }
-
/* We don't create any RTL for local variables. */
if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))
return;
defer_p = 1;
}
/* Likewise for template instantiations. */
- else if (DECL_COMDAT (decl))
+ else if (DECL_LANG_SPECIFIC (decl)
+ && DECL_IMPLICIT_INSTANTIATION (decl))
defer_p = 1;
- /* If we're deferring the variable, we only need to make RTL if
- there's an ASMSPEC. Otherwise, we'll lazily create it later when
- we need it. (There's no way to lazily create RTL for things that
- have assembly specs because the information about the specifier
- isn't stored in the tree, yet) */
- if (defer_p && asmspec)
- make_decl_rtl (decl, asmspec);
/* If we're not deferring, go ahead and assemble the variable. */
- else if (!defer_p)
- rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+ if (!defer_p)
+ rest_of_decl_compilation (decl, toplev, at_eof);
}
/* Generate code to initialize DECL (a local variable). */
tree cleanup;
my_friendly_assert (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == RESULT_DECL,
+ || TREE_CODE (decl) == RESULT_DECL,
20021010);
my_friendly_assert (!TREE_STATIC (decl), 20021010);
/* If a name was specified, get the string. */
if (global_scope_p (current_binding_level))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
- if (asmspec_tree)
+ if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init && TREE_CODE (init) == NAMESPACE_DECL)
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
- if (TREE_CODE (decl) == VAR_DECL
- && DECL_CONTEXT (decl)
- && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
- && DECL_CONTEXT (decl) != current_namespace
- && init)
- {
- /* Leave the namespace of the object. */
- pop_decl_namespace ();
- }
-
type = TREE_TYPE (decl);
if (type == error_mark_node)
- goto finish_end0;
+ goto finish_end;
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
&& !DECL_PRETTY_FUNCTION_P (decl)
&& !dependent_type_p (TREE_TYPE (decl)))
maybe_deduce_size_from_array_init (decl, init);
- goto finish_end0;
+ goto finish_end;
}
/* Parameters are handled by store_parm_decls, not cp_finish_decl. */
&& !COMPLETE_TYPE_P (TREE_TYPE (decl)))
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
- rest_of_decl_compilation (decl, NULL,
- DECL_CONTEXT (decl) == NULL_TREE, at_eof);
+ rest_of_decl_compilation (decl, DECL_CONTEXT (decl) == NULL_TREE,
+ at_eof);
goto finish_end;
}
if (TREE_CODE (decl) != FUNCTION_DECL)
ttype = target_type (type);
-
+
/* Currently, GNU C++ puts constants in text space, making them
impossible to initialize. In the future, one would hope for
an operating system which understood the difference between
if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl))
{
was_readonly = 1;
- if (TYPE_NEEDS_CONSTRUCTING (type)
+ if (TYPE_NEEDS_CONSTRUCTING (type)
|| TREE_CODE (type) == REFERENCE_TYPE)
TREE_READONLY (decl) = 0;
}
init = NULL_TREE;
}
/* Handle:
-
+
[dcl.init]
-
+
The memory occupied by any object of static storage
duration is zero-initialized at program startup before
any other initialization takes place.
-
+
We cannot create an appropriate initializer until after
the type of DECL is finalized. If DECL_INITIAL is set,
then the DECL is statically initialized, and any
/* Remember that the initialization for this variable has
taken place. */
DECL_INITIALIZED_P (decl) = 1;
+ /* The variable is being defined, so determine its
+ visibility. */
+ determine_visibility (decl);
}
/* If the variable has an array type, lay out the type, even if
there is no initializer. It is valid to index through the
make_rtl_for_nonlocal_decl (decl, init, asmspec);
+ /* Check for abstractness of the type. Notice that there is no
+ need to strip array types here since the check for those types
+ is already done within create_array_type_for_decl. */
if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
- abstract_virtuals_error (decl,
- strip_array_types (TREE_TYPE (type)));
- else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
- {
- /* If it's either a pointer or an array type, strip through all
- of them but the last one. If the last is an array type, issue
- an error if the element type is abstract. */
- while (POINTER_TYPE_P (TREE_TYPE (type))
- || TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == ARRAY_TYPE)
- abstract_virtuals_error (decl, TREE_TYPE (type));
- }
+ abstract_virtuals_error (decl, TREE_TYPE (type));
else
abstract_virtuals_error (decl, type);
- if (TREE_CODE (decl) == FUNCTION_DECL
+ if (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_TYPE (decl) == error_mark_node)
/* No initialization required. */
;
/* A variable definition. */
if (DECL_FUNCTION_SCOPE_P (decl))
{
- /* This is a local declaration. */
- maybe_inject_for_scope_var (decl);
/* Initialize the local variable. */
if (processing_template_decl)
{
if (TREE_STATIC (decl))
expand_static_init (decl, init);
}
- finish_end0:
-
- /* Undo call to `pushclass' that was done in `start_decl'
- due to initialization of qualified member variable.
- I.e., Foo::x = 10; */
- {
- tree context = CP_DECL_CONTEXT (decl);
- if (context
- && TYPE_P (context)
- && (TREE_CODE (decl) == VAR_DECL
- /* We also have a pushclass done that we need to undo here
- if we're at top level and declare a method. */
- || TREE_CODE (decl) == FUNCTION_DECL)
- /* If size hasn't been set, we're still defining it,
- and therefore inside the class body; don't pop
- the binding level.. */
- && COMPLETE_TYPE_P (context)
- && context == current_class_type)
- pop_nested_class ();
- }
}
/* If a CLEANUP_STMT was created to destroy a temporary bound to a
to the original function, rather than the anonymous one. That
will make the back-end think that nested functions are in use,
which causes confusion. */
-
+
push_deferring_access_checks (dk_no_check);
fcall = build_cleanup (decl);
pop_deferring_access_checks ();
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
if (flag_use_cxa_atexit)
{
- args = tree_cons (NULL_TREE,
+ args = tree_cons (NULL_TREE,
build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
NULL_TREE);
args = tree_cons (NULL_TREE, null_pointer_node, args);
my_friendly_assert (TREE_STATIC (decl), 20021010);
/* Some variables require no initialization. */
- if (!init
+ if (!init
&& !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
{
int eltsize
= int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
- maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
- / eltsize) - 1, 0);
+ maxindex = build_int_cst (NULL_TREE,
+ (TREE_STRING_LENGTH (initial_value)
+ / eltsize) - 1, 0);
}
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
else
maxindex = size_binop (PLUS_EXPR, maxindex, ssize_int (1));
}
- maxindex = copy_node (maxindex);
}
else
{
initial_value = NULL_TREE;
/* Prevent further error messages. */
- maxindex = build_int_2 (0, 0);
+ maxindex = build_int_cst (NULL_TREE, 0, 0);
}
}
if (!maxindex)
{
if (do_default)
- maxindex = build_int_2 (0, 0);
+ maxindex = build_int_cst (NULL_TREE, 0, 0);
value = 2;
}
domain = build_index_type (maxindex);
TYPE_DOMAIN (type) = domain;
- if (! TREE_TYPE (maxindex))
- TREE_TYPE (maxindex) = domain;
if (initial_value)
itype = TREE_TYPE (initial_value);
else
TYPE_NEEDS_CONSTRUCTING (type)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
- = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
+ = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
}
/* Lay out the type now that we can get the real answer. */
applicable error messages. */
static tree
-grokfndecl (tree ctype,
+grokfndecl (tree ctype,
tree type,
tree declarator,
tree parms,
tree orig_declarator,
int virtualp,
enum overload_flags flags,
- tree quals,
+ cp_cv_quals quals,
tree raises,
- int check,
- int friendp,
- int publicp,
- int inlinep,
- int funcdef_flag,
+ int check,
+ int friendp,
+ int publicp,
+ int inlinep,
+ int funcdef_flag,
int template_count,
tree in_namespace)
{
declare an entity with linkage.
Only check this for public decls for now. See core 319, 389. */
- t = no_linkage_check (TREE_TYPE (decl));
+ t = no_linkage_check (TREE_TYPE (decl),
+ /*relaxed_p=*/false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
DECL_INLINE (decl) = 1;
DECL_EXTERNAL (decl) = 1;
- if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
+ if (quals && TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("%smember function `%D' cannot have `%T' method qualifier",
- (ctype ? "static " : "non-"), decl, TREE_VALUE (quals));
- quals = NULL_TREE;
+ error ("%smember function `%D' cannot have cv-qualifier",
+ (ctype ? "static " : "non-"), decl);
+ quals = TYPE_UNQUALIFIED;
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
return decl;
}
-/* Create a VAR_DECL named NAME with the indicated TYPE.
+/* DECL is a VAR_DECL for a static data member. Set flags to reflect
+ the linkage that DECL will receive in the object file. */
+
+static void
+set_linkage_for_static_data_member (tree decl)
+{
+ /* A static data member always has static storage duration and
+ external linkage. Note that static data members are forbidden in
+ local classes -- the only situation in which a class has
+ non-external linkage. */
+ TREE_PUBLIC (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ /* For non-template classes, static data members are always put
+ out in exactly those files where they are defined, just as
+ with ordinarly namespace-scope variables. */
+ if (!processing_template_decl)
+ DECL_INTERFACE_KNOWN (decl) = 1;
+}
+
+/* Create a VAR_DECL named NAME with the indicated TYPE.
If SCOPE is non-NULL, it is the class type or namespace containing
the variable. If SCOPE is NULL, the variable should is created in
static tree
grokvardecl (tree type,
tree name,
- cp_decl_specifier_seq *declspecs,
+ const cp_decl_specifier_seq *declspecs,
int initialized,
int constp,
tree scope)
{
tree decl;
- my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE,
+ my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE,
20020808);
/* Compute the scope in which to place the variable. */
(TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl)
/* Similarly for namespace-scope variables with language linkage
other than C++. */
- || (TREE_CODE (scope) == NAMESPACE_DECL
+ || (TREE_CODE (scope) == NAMESPACE_DECL
&& current_lang_name != lang_name_cplusplus)
/* Similarly for static data members. */
|| TYPE_P (scope)))
DECL_EXTERNAL (decl) = !initialized;
}
- /* In class context, static means one per class,
- public access, and static storage. */
if (DECL_CLASS_SCOPE_P (decl))
{
- TREE_PUBLIC (decl) = 1;
- TREE_STATIC (decl) = 1;
+ set_linkage_for_static_data_member (decl);
+ /* This function is only called with out-of-class definitions. */
DECL_EXTERNAL (decl) = 0;
}
/* At top level, either `static' or no s.c. makes a definition
declare an entity with linkage.
Only check this for public decls for now. */
- tree t = no_linkage_check (TREE_TYPE (decl));
+ tree t = no_linkage_check (TREE_TYPE (decl),
+ /*relaxed_p=*/false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
= build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
t = make_aggr_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. */
field = build_decl (FIELD_DECL, pfn_identifier, type);
fields = field;
-
+
field = build_decl (FIELD_DECL, delta_identifier, delta_type_node);
TREE_CHAIN (field) = fields;
fields = field;
-
+
finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
/* Zap out the name so that the back-end will give us the debugging
tree arg_types;
arg_types = TYPE_ARG_TYPES (member_type);
- class_type = (cp_build_qualified_type
+ class_type = (cp_build_qualified_type
(class_type,
cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)))));
- member_type
- = build_method_type_directly (class_type,
+ member_type
+ = build_method_type_directly (class_type,
TREE_TYPE (member_type),
TREE_CHAIN (arg_types));
return build_ptrmemfunc_type (build_pointer_type (member_type));
if (size)
itype = compute_array_index_type (name, size);
+ /* [dcl.array]
+ T is called the array element type; this type shall not be [...] an
+ abstract class type. */
+ abstract_virtuals_error (name, type);
+
return build_cplus_array_type (type, itype);
}
/* Check that it's OK to declare a function with the indicated TYPE.
SFK indicates the kind of special function (if any) that this
function is. OPTYPE is the type given in a conversion operator
- declaration. Returns the actual return type of the function; that
+ declaration, or the class type for a constructor/destructor.
+ Returns the actual return type of the function; that
may be different than TYPE if an error occurs, or for certain
special functions. */
if (type)
error ("return type specification for constructor invalid");
- type = void_type_node;
+ if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
+ type = build_pointer_type (optype);
+ else
+ type = void_type_node;
break;
case sfk_destructor:
if (type)
error ("return type specification for destructor invalid");
- type = void_type_node;
+ /* We can't use the proper return type here because we run into
+ problems with abiguous bases and covariant returns.
+ Java classes are left unchanged because (void *) isn't a valid
+ Java type, and we don't want to change the Java ABI. */
+ if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
+ type = build_pointer_type (void_type_node);
+ else
+ type = void_type_node;
break;
case sfk_conversion:
tree
grokdeclarator (const cp_declarator *declarator,
- cp_decl_specifier_seq *declspecs,
+ const cp_decl_specifier_seq *declspecs,
enum decl_context decl_context,
int initialized,
tree* attrlist)
int explicit_char = 0;
int defaulted_int = 0;
tree dependant_name = NULL_TREE;
-
+
tree typedef_decl = NULL_TREE;
const char *name = NULL;
tree typedef_type = NULL_TREE;
tree dname = NULL_TREE;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
- tree quals = NULL_TREE;
+ cp_cv_quals quals = TYPE_UNQUALIFIED;
tree raises = NULL_TREE;
int template_count = 0;
tree returned_attrs = NULL_TREE;
/* The NAMESPACE_DECL for the namespace in which this entity is
located. If an unqualified name is used to declare the entity,
this value will be NULL_TREE, even if the entity is located at
- namespace scope. */
+ namespace scope. */
tree in_namespace = NULL_TREE;
cp_decl_spec ds;
+ cp_storage_class storage_class;
+ bool unsigned_p, signed_p, short_p, long_p, thread_p;
+
+ signed_p = declspecs->specs[(int)ds_signed];
+ unsigned_p = declspecs->specs[(int)ds_unsigned];
+ short_p = declspecs->specs[(int)ds_short];
+ long_p = declspecs->specs[(int)ds_long];
+ thread_p = declspecs->specs[(int)ds_thread];
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
- for (id_declarator = declarator;
- id_declarator;
+ for (id_declarator = declarator;
+ id_declarator;
id_declarator = id_declarator->declarator)
{
if (id_declarator->kind != cdk_id)
Therefore, we do as well. */
if (qualifying_scope && TYPE_P (qualifying_scope))
{
- ctype = TYPE_MAIN_VARIANT (qualifying_scope);
+ ctype = TYPE_MAIN_VARIANT (qualifying_scope);
if (innermost_code != cdk_function
&& current_class_type
- && !UNIQUELY_DERIVED_FROM_P (ctype,
+ && !UNIQUELY_DERIVED_FROM_P (ctype,
current_class_type))
{
error ("type `%T' is not derived from type `%T'",
ctype, current_class_type);
ctype = NULL_TREE;
}
- TREE_OPERAND (decl, 0) = ctype;
+ TREE_OPERAND (decl, 0) = ctype;
}
else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
in_namespace = qualifying_scope;
}
if (TREE_CODE (decl) == BASELINK)
decl = BASELINK_FUNCTIONS (decl);
+ if (decl == error_mark_node)
+ return error_mark_node;
switch (TREE_CODE (decl))
{
case BIT_NOT_EXPR:
}
/* No type at all: default to `int', and set DEFAULTED_INT
because it was not a user-defined typedef. */
- if (type == NULL_TREE
- && (declspecs->specs[(int)ds_signed]
- || declspecs->specs[(int)ds_unsigned]
- || declspecs->specs[(int)ds_long]
- || declspecs->specs[(int)ds_short]))
+ if (type == NULL_TREE && (signed_p || unsigned_p || long_p || short_p))
{
/* These imply 'int'. */
type = integer_type_node;
explicit_char = declspecs->explicit_char_p;
/* Check for repeated decl-specifiers. */
- for (ds = ds_first; ds != ds_last; ++ds)
+ for (ds = ds_first; ds != ds_last; ++ds)
{
unsigned count = declspecs->specs[(int)ds];
if (count < 2)
continue;
- /* The "long" specifier is a special case because of
+ /* The "long" specifier is a special case because of
"long long". */
if (ds == ds_long)
{
pedwarn ("ISO C++ does not support `long long'");
else
longlong = 1;
- }
+ }
else if (declspecs->specs[(int)ds] > 1)
{
- static const char *decl_spec_names[] = {
+ static const char *const decl_spec_names[] = {
"signed",
"unsigned",
"short",
typedef_type = type;
+ if (sfk != sfk_conversion)
+ ctor_return_type = ctype;
+
if (sfk != sfk_none)
type = check_special_function_return_type (sfk, type,
ctor_return_type);
type = integer_type_node;
}
-
+
ctype = NULL_TREE;
/* Now process the modifiers that were specified
and check for invalid combinations. */
/* Long double is a special combination. */
- if (declspecs->specs[(int)ds_long]
- && TYPE_MAIN_VARIANT (type) == double_type_node)
+ if (long_p && TYPE_MAIN_VARIANT (type) == double_type_node)
{
- declspecs->specs[(int)ds_long] = 0;
+ long_p = false;
type = build_qualified_type (long_double_type_node,
cp_type_quals (type));
}
/* Check all other uses of type modifiers. */
- if (declspecs->specs[(int)ds_unsigned]
- || declspecs->specs[(int)ds_signed]
- || declspecs->specs[(int)ds_long]
- || declspecs->specs[(int)ds_short])
+ if (unsigned_p || signed_p || long_p || short_p)
{
int ok = 0;
error ("short, signed or unsigned invalid for `%s'", name);
else if (TREE_CODE (type) != INTEGER_TYPE)
error ("long, short, signed or unsigned invalid for `%s'", name);
- else if (declspecs->specs[(int)ds_long]
- && declspecs->specs[(int)ds_short])
+ else if (long_p && short_p)
error ("long and short specified together for `%s'", name);
- else if ((declspecs->specs[(int)ds_long]
- || declspecs->specs[(int)ds_short])
- && explicit_char)
+ else if ((long_p || short_p) && explicit_char)
error ("long or short specified with char for `%s'", name);
- else if ((declspecs->specs[(int)ds_long]
- || declspecs->specs[(int)ds_short])
- && TREE_CODE (type) == REAL_TYPE)
+ else if ((long_p|| short_p) && TREE_CODE (type) == REAL_TYPE)
error ("long or short specified with floating type for `%s'", name);
- else if (declspecs->specs[(int)ds_signed]
- && declspecs->specs[(int)ds_unsigned])
+ else if (signed_p && unsigned_p)
error ("signed and unsigned given together for `%s'", name);
else
{
/* Discard the type modifiers if they are invalid. */
if (! ok)
{
- declspecs->specs[(int)ds_unsigned] = 0;
- declspecs->specs[(int)ds_signed] = 0;
- declspecs->specs[(int)ds_long] = 0;
- declspecs->specs[(int)ds_short] = 0;
+ unsigned_p = false;
+ signed_p = false;
+ long_p = false;
+ short_p = false;
longlong = 0;
}
}
- if (declspecs->specs[(int)ds_complex]
- && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
- {
- error ("complex invalid for `%s'", name);
- declspecs->specs[(int)ds_complex] = 0;
- }
-
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
- if (declspecs->specs[(int)ds_unsigned]
+ if (unsigned_p
/* [class.bit]
It is implementation-defined whether a plain (neither
Naturally, we extend this to long long as well. Note that
this does not include wchar_t. */
|| (bitfield && !flag_signed_bitfields
- && !declspecs->specs[(int)ds_signed]
+ && !signed_p
/* A typedef for plain `int' without `signed' can be
controlled just like plain `int', but a typedef for
`signed int' cannot be so controlled. */
{
if (longlong)
type = long_long_unsigned_type_node;
- else if (declspecs->specs[(int)ds_long])
+ else if (long_p)
type = long_unsigned_type_node;
- else if (declspecs->specs[(int)ds_short])
+ else if (short_p)
type = short_unsigned_type_node;
else if (type == char_type_node)
type = unsigned_char_type_node;
else
type = unsigned_type_node;
}
- else if (declspecs->specs[(int)ds_signed]
- && type == char_type_node)
+ else if (signed_p && type == char_type_node)
type = signed_char_type_node;
else if (longlong)
type = long_long_integer_type_node;
- else if (declspecs->specs[(int)ds_long])
+ else if (long_p)
type = long_integer_type_node;
- else if (declspecs->specs[(int)ds_short])
+ else if (short_p)
type = short_integer_type_node;
if (declspecs->specs[(int)ds_complex])
{
+ if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
+ error ("complex invalid for `%s'", name);
/* If we just have "complex", it is equivalent to
"complex double", but if any modifiers at all are specified it is
the complex form of TYPE. E.g, "complex short" is
"complex short int". */
- if (defaulted_int && ! longlong
- && ! (declspecs->specs[(int)ds_long]
- || declspecs->specs[(int)ds_short]
- || declspecs->specs[(int)ds_signed]
- || declspecs->specs[(int)ds_unsigned]))
+ else if (defaulted_int && ! longlong
+ && ! (long_p || short_p || signed_p || unsigned_p))
type = complex_double_type_node;
else if (type == integer_type_node)
type = complex_integer_type_node;
? tf_ignore_bad_quals : 0) | tf_error | tf_warning));
/* We might have ignored or rejected some of the qualifiers. */
type_quals = cp_type_quals (type);
-
+
staticp = 0;
inlinep = !! declspecs->specs[(int)ds_inline];
virtualp = !! declspecs->specs[(int)ds_virtual];
explicitp = !! declspecs->specs[(int)ds_explicit];
- if (declspecs->storage_class == sc_static)
+ storage_class = declspecs->storage_class;
+ if (storage_class == sc_static)
staticp = 1 + (decl_context == FIELD);
if (virtualp && staticp == 2)
{
if (declspecs->specs[(int)ds_typedef])
error ("typedef declaration invalid in parameter declaration");
- else if (declspecs->storage_class == sc_static
- || declspecs->storage_class == sc_extern
- || declspecs->specs[(int)ds_thread])
+ else if (storage_class == sc_static
+ || storage_class == sc_extern
+ || thread_p)
error ("storage class specifiers invalid in parameter declarations");
}
kinds of declarations (parameters, typenames, etc.). */
if (declspecs->multiple_storage_classes_p)
error ("multiple storage classes in declaration of `%s'", name);
- else if (declspecs->specs[(int)ds_thread]
- && ((declspecs->storage_class
- && declspecs->storage_class != sc_extern
- && declspecs->storage_class != sc_static)
+ else if (thread_p
+ && ((storage_class
+ && storage_class != sc_extern
+ && storage_class != sc_static)
|| declspecs->specs[(int)ds_typedef]))
{
error ("multiple storage classes in declaration of `%s'", name);
- declspecs->specs[(int)ds_thread] = 0;
+ thread_p = false;
}
- else if (decl_context != NORMAL
- && ((declspecs->storage_class != sc_none
- && declspecs->storage_class != sc_mutable)
- || declspecs->specs[(int)ds_thread]))
+ else if (decl_context != NORMAL
+ && ((storage_class != sc_none
+ && storage_class != sc_mutable)
+ || thread_p))
{
if ((decl_context == PARM || decl_context == CATCHPARM)
- && (declspecs->storage_class == sc_register
- || declspecs->storage_class == sc_auto))
+ && (storage_class == sc_register
+ || storage_class == sc_auto))
;
else if (declspecs->specs[(int)ds_typedef])
;
else if (decl_context == FIELD
/* C++ allows static class elements. */
- && declspecs->storage_class == sc_static)
+ && storage_class == sc_static)
/* C++ also allows inlines and signed and unsigned elements,
but in those cases we don't come in here. */
;
else
error ("storage class specified for typename");
}
- if (declspecs->storage_class == sc_register
- || declspecs->storage_class == sc_auto
- || declspecs->storage_class == sc_extern
- || declspecs->specs[(int)ds_thread])
- declspecs->storage_class = sc_none;
+ if (storage_class == sc_register
+ || storage_class == sc_auto
+ || storage_class == sc_extern
+ || thread_p)
+ storage_class = sc_none;
}
}
- else if (declspecs->storage_class == sc_extern && initialized
+ else if (storage_class == sc_extern && initialized
&& !funcdef_flag)
{
if (toplevel_bindings_p ())
else
error ("`%s' has both `extern' and initializer", name);
}
- else if (declspecs->storage_class == sc_extern && funcdef_flag
+ else if (storage_class == sc_extern && funcdef_flag
&& ! toplevel_bindings_p ())
error ("nested function `%s' declared `extern'", name);
else if (toplevel_bindings_p ())
{
- if (declspecs->storage_class == sc_auto)
+ if (storage_class == sc_auto)
error ("top-level declaration of `%s' specifies `auto'", name);
}
- else if (declspecs->specs[(int)ds_thread]
- && declspecs->storage_class != sc_extern
- && declspecs->storage_class != sc_static)
+ else if (thread_p
+ && storage_class != sc_extern
+ && storage_class != sc_static)
{
error ("function-scope `%s' implicitly auto and declared `__thread'",
name);
- declspecs->specs[(int)ds_thread] = 0;
+ thread_p = false;
}
- if (declspecs->storage_class && friendp)
+ if (storage_class && friendp)
error ("storage class specifiers invalid in friend function declarations");
if (!id_declarator)
switch (TREE_CODE (unqualified_id))
{
case BIT_NOT_EXPR:
- unqualified_id
+ unqualified_id
= constructor_name (TREE_OPERAND (unqualified_id, 0));
break;
-
+
case TYPE_DECL:
- unqualified_id
+ unqualified_id
= constructor_name (TREE_TYPE (unqualified_id));
break;
case IDENTIFIER_NODE:
case TEMPLATE_ID_EXPR:
break;
-
+
default:
abort ();
}
/* Determine the type of the entity declared by recurring on the
declarator. */
- for (;
+ for (;
declarator && declarator->kind != cdk_id;
declarator = declarator->declarator)
{
if (attrs)
{
int attr_flags;
-
+
attr_flags = 0;
if (declarator == NULL || declarator->kind == cdk_id)
attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
switch (declarator->kind)
{
case cdk_array:
- type = create_array_type_for_decl (dname, type,
+ type = create_array_type_for_decl (dname, type,
declarator->u.array.bounds);
if (inner_declarator
&& (inner_declarator->kind == cdk_pointer
error ("destructor cannot be static member function");
if (quals)
{
- error ("destructors may not be `%E'",
- TREE_VALUE (quals));
- quals = NULL_TREE;
+ error ("destructors may not be cv-qualified");
+ quals = TYPE_UNQUALIFIED;
}
if (decl_context == FIELD)
{
}
if (quals)
{
- error ("constructors may not be `%E'",
- TREE_VALUE (quals));
- quals = NULL_TREE;
+ error ("constructors may not be cv-qualified");
+ quals = TYPE_UNQUALIFIED;
}
if (decl_context == FIELD)
{
name);
}
- arg_types = grokparms (declarator->u.function.parameters,
+ arg_types = grokparms (declarator->u.function.parameters,
&parms);
if (inner_declarator
arg_types = void_list_node;
parms = NULL_TREE;
}
-
+
type = build_function_type (type, arg_types);
}
break;
|| (quals && TREE_CODE (type) == METHOD_TYPE)))
{
tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
- grok_method_quals (declarator->u.pointer.class_type,
+ grok_method_quals (declarator->u.pointer.class_type,
dummy, quals);
type = TREE_TYPE (dummy);
- quals = NULL_TREE;
+ quals = TYPE_UNQUALIFIED;
}
if (declarator->kind == cdk_reference)
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
else if (declarator->kind == cdk_ptrmem)
- type = build_ptrmem_type (declarator->u.pointer.class_type,
+ type = build_ptrmem_type (declarator->u.pointer.class_type,
type);
else
type = build_pointer_type (type);
if (declarator->u.pointer.qualifiers)
{
- tree typemodlist;
- int erred = 0;
- int constp = 0;
- int volatilep = 0;
- int restrictp = 0;
-
- for (typemodlist = declarator->u.pointer.qualifiers; typemodlist;
- typemodlist = TREE_CHAIN (typemodlist))
- {
- tree qualifier = TREE_VALUE (typemodlist);
-
- if (qualifier == ridpointers[(int) RID_CONST])
- {
- constp++;
- type_quals |= TYPE_QUAL_CONST;
- }
- else if (qualifier == ridpointers[(int) RID_VOLATILE])
- {
- volatilep++;
- type_quals |= TYPE_QUAL_VOLATILE;
- }
- else if (qualifier == ridpointers[(int) RID_RESTRICT])
- {
- restrictp++;
- type_quals |= TYPE_QUAL_RESTRICT;
- }
- else if (!erred)
- {
- erred = 1;
- error ("invalid type modifier within pointer declarator");
- }
- }
- if (constp > 1)
- pedwarn ("duplicate `const'");
- if (volatilep > 1)
- pedwarn ("duplicate `volatile'");
- if (restrictp > 1)
- pedwarn ("duplicate `restrict'");
- type = cp_build_qualified_type (type, type_quals);
+ type
+ = cp_build_qualified_type (type,
+ declarator->u.pointer.qualifiers);
type_quals = cp_type_quals (type);
}
ctype = NULL_TREE;
abort ();
}
}
-
+
if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
&& TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE)
{
- error ("template-id `%D' used as a declarator",
+ error ("template-id `%D' used as a declarator",
unqualified_id);
unqualified_id = dname;
}
/* If DECLARATOR is non-NULL, we know it is a cdk_id declarator;
otherwise, we would not have exited the loop above. */
- if (declarator
+ if (declarator
&& TREE_CODE (declarator->u.id.name) == SCOPE_REF
/* If the qualifying scope was invalid, it will have been set to
NULL_TREE above. */
are always static functions. */
;
else if (current_class_type == NULL_TREE || friendp)
- type
- = build_method_type_directly (ctype,
+ type
+ = build_method_type_directly (ctype,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
else
}
if ((decl_context == FIELD || decl_context == PARM)
- && !processing_template_decl
- && variably_modified_type_p (type))
+ && !processing_template_decl
+ && variably_modified_type_p (type, NULL_TREE))
{
if (decl_context == FIELD)
error ("data member may not have variably modified type `%T'", type);
explicitp = 0;
}
- if (declspecs->storage_class == sc_mutable)
+ if (storage_class == sc_mutable)
{
if (decl_context != FIELD || friendp)
{
error ("non-member `%s' cannot be declared `mutable'", name);
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
{
error ("non-object member `%s' cannot be declared `mutable'", name);
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
error ("function `%s' cannot be declared `mutable'", name);
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
else if (staticp)
{
error ("static `%s' cannot be declared `mutable'", name);
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
else if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
}
if (!current_function_decl)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
}
-
+
/* If the user declares "typedef struct {...} foo" then the
struct will have an anonymous name. Fill that name in now.
Nothing can refer to it, so nothing needs know about the name
grok_method_quals (ctype, decl, quals);
}
- if (declspecs->specs[(int)ds_signed]
+ if (signed_p
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
- bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
+ bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
return decl;
/* Detect where we're using a typedef of function type to declare a
function. PARMS will not be set, so we must create it now. */
-
+
if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE)
{
tree decls = NULL_TREE;
TREE_CHAIN (decl) = decls;
decls = decl;
}
-
+
parms = nreverse (decls);
}
{
decl = cp_build_parm_decl (unqualified_id, type);
- bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
+ bad_specifiers (decl, "parameter", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
else if (decl_context == FIELD)
}
}
else if (staticp < 2)
- type = build_method_type_directly (ctype,
+ type = build_method_type_directly (ctype,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
}
if (decl == error_mark_node)
return error_mark_node;
}
-
+
decl = do_friend (ctype, unqualified_id, decl,
*attrlist, flags, quals, funcdef_flag);
return decl;
/* C++ allows static class members. All other work
for this is done by grokfield. */
decl = build_lang_decl (VAR_DECL, unqualified_id, type);
- TREE_STATIC (decl) = 1;
- /* In class context, 'static' means public access. */
- TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
+ set_linkage_for_static_data_member (decl);
+ /* Even if there is an in-class initialization, DECL
+ is considered undefined until an out-of-class
+ definition is provided. */
+ DECL_EXTERNAL (decl) = 1;
}
else
{
decl = build_decl (FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
- if (declspecs->storage_class == sc_mutable)
+ if (storage_class == sc_mutable)
{
DECL_MUTABLE_P (decl) = 1;
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
}
- bad_specifiers (decl, "field", virtualp, quals != NULL_TREE,
+ bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
}
else
original_name = unqualified_id;
- if (declspecs->storage_class == sc_auto)
+ if (storage_class == sc_auto)
error ("storage class `auto' invalid for function `%s'", name);
- else if (declspecs->storage_class == sc_register)
+ else if (storage_class == sc_register)
error ("storage class `register' invalid for function `%s'", name);
- else if (declspecs->specs[(int)ds_thread])
+ else if (thread_p)
error ("storage class `__thread' invalid for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
if (! toplevel_bindings_p ()
- && (declspecs->storage_class == sc_static
+ && (storage_class == sc_static
|| declspecs->specs[(int)ds_inline])
&& pedantic)
{
- if (declspecs->storage_class == sc_static)
+ if (storage_class == sc_static)
pedwarn ("`static' specified invalid for function `%s' declared out of global scope", name);
else
pedwarn ("`inline' specifier invalid for function `%s' declared out of global scope", name);
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
&& !NEW_DELETE_OPNAME_P (original_name))
- type = build_method_type_directly (ctype,
+ type = build_method_type_directly (ctype,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
- || declspecs->storage_class == sc_extern
- || declspecs->storage_class != sc_static);
+ || storage_class == sc_extern
+ || storage_class != sc_static);
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, quals, raises,
if (invalid_static)
{
staticp = 0;
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
}
}
/* It's a variable. */
/* An uninitialized decl with `extern' is a reference. */
- decl = grokvardecl (type, unqualified_id,
+ decl = grokvardecl (type, unqualified_id,
declspecs,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
- bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
+ bad_specifiers (decl, "variable", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
if (ctype)
{
pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
staticp = 0;
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
- if (declspecs->storage_class == sc_register && TREE_STATIC (decl))
+ if (storage_class == sc_register && TREE_STATIC (decl))
{
error ("static member `%D' declared `register'", decl);
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
- if (declspecs->storage_class == sc_extern && pedantic)
+ if (storage_class == sc_extern && pedantic)
{
pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
decl);
- declspecs->storage_class = sc_none;
+ storage_class = sc_none;
}
}
}
/* Record `register' declaration for warnings on &
and in case doing stupid register allocation. */
- if (declspecs->storage_class == sc_register)
+ if (storage_class == sc_register)
DECL_REGISTER (decl) = 1;
- else if (declspecs->storage_class == sc_extern)
+ else if (storage_class == sc_extern)
DECL_THIS_EXTERN (decl) = 1;
- else if (declspecs->storage_class == sc_static)
+ else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. There's no need to do this
if (type != error_mark_node)
{
- /* If this type is passed by invisible reference, make the PARM_DECL
- reflect that so that alias analysis knows that the actual object
- is external to the function. */
- if (TREE_ADDRESSABLE (type))
- decl = build_decl (PARM_DECL, DECL_NAME (decl),
- build_reference_type (type));
-
/* Top-level qualifiers on the parameters are
ignored for function types. */
type = cp_build_qualified_type (type, 0);
}
if (!any_error && init)
- init = check_default_argument (type, init);
+ init = check_default_argument (decl, init);
else
init = NULL_TREE;
}
tree args;
tree arg_type;
int result = 1;
-
+
my_friendly_assert (DECL_FUNCTION_MEMBER_P (d), 20011208);
if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (d)))
represented as template functions internally, and we must
accept those as copy functions. */
return 0;
-
+
args = FUNCTION_FIRST_USER_PARMTYPE (d);
if (!args)
return 0;
}
else
return 0;
-
+
args = TREE_CHAIN (args);
if (args && args != void_list_node && !TREE_PURPOSE (args))
else if (DECL_CONSTRUCTOR_P (decl))
{
int ctor = copy_fn_p (decl);
-
+
if (ctor > 0)
{
/* [class.copy]
-
+
A non-template constructor for class X is a copy
constructor if its first parameter is of type X&, const
X&, volatile X& or const volatile X&, and either there
else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
{
/* [class.copy]
-
+
A non-template assignment operator for class X is a copy
assignment operator if its parameter is of type X, X&, const
X&, volatile X& or const volatile X&. */
-
+
int assop = copy_fn_p (decl);
-
+
if (assop)
{
TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
if (assop != 1)
TYPE_HAS_CONST_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
- if (DECL_PURE_VIRTUAL_P (decl))
- TYPE_HAS_ABSTRACT_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
}
}
}
if (ctor_parm < 0)
{
/* [class.copy]
-
+
A declaration of a constructor for a class X is ill-formed if
its first parameter is of type (optionally cv-qualified) X
and either there are no other parameters or else all other
parameters have default arguments.
-
+
We *don't* complain about member template instantiations that
have this form, though; they can occur as we try to decide
what constructor to use during overload resolution. Since
ctype, ctype);
return 0;
}
-
+
return 1;
}
}
}
+ /* [basic.std.dynamic.allocation]/1:
+
+ A program is ill-formed if an allocation function is declared
+ in a namespace scope other than global scope or declared static
+ in global scope.
+
+ The same also holds true for deallocation functions. */
+ if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR
+ || operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
+ {
+ if (DECL_NAMESPACE_SCOPE_P (decl))
+ {
+ if (CP_DECL_CONTEXT (decl) != global_namespace)
+ error ("`%D' may not be declared within a namespace", decl);
+ else if (!TREE_PUBLIC (decl))
+ error ("`%D' may not be declared as static", decl);
+ }
+ }
+
if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
type = TREE_TYPE (decl);
- /* [dcl.type.elab]
+ /* [dcl.type.elab]
If the identifier resolves to a typedef-name or a template
type-parameter, the elaborated-type-specifier is ill-formed.
error ("using typedef-name `%D' after `%s'", decl, tag_name (tag_code));
return IS_AGGR_TYPE (type) ? type : error_mark_node;
}
-
+
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
{
error ("using template type parameter `%T' after `%s'",
{
if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))
redeclare_class_template (t, current_template_parms);
- else if (!processing_template_decl
+ else if (!processing_template_decl
&& CLASS_TYPE_P (t)
&& CLASSTYPE_IS_TEMPLATE (t))
{
return xref_tag (tag_kind, id, globalize, false);
}
-/* REF is a type (named NAME), for which we have just seen some
- baseclasses. BASE_LIST is a list of those baseclasses; the
- TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
- the base-class. TREE_VIA_VIRTUAL indicates virtual
- inheritance. CODE_TYPE_NODE indicates whether REF is a class,
- struct, or union. */
+/* Create the binfo hierarchy for REF with (possibly NULL) base list
+ BASE_LIST. For each element on BASE_LIST the TREE_PURPOSE is an
+ access_* node, and the TREE_VALUE is the type of the base-class.
+ Non-NULL TREE_TYPE indicates virtual inheritance. */
void
xref_basetypes (tree ref, tree base_list)
{
- /* In the declaration `A : X, Y, ... Z' we mark all the types
- (A, X, Y, ..., Z) so we can check for duplicates. */
tree *basep;
-
+ tree binfo, base_binfo;
+ unsigned max_vbases = 0; /* Maxium direct & indirect virtual bases. */
+ unsigned max_bases = 0; /* Maxium direct bases. */
int i;
- enum tag_types tag_code;
+ tree default_access;
+ tree igo_prev; /* Track Inheritance Graph Order. */
if (ref == error_mark_node)
return;
- if (TREE_CODE (ref) == UNION_TYPE)
- {
- error ("derived union `%T' invalid", ref);
- return;
- }
-
- tag_code = (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type);
+ /* The base of a derived class is private by default, all others are
+ public. */
+ default_access = (TREE_CODE (ref) == RECORD_TYPE
+ && CLASSTYPE_DECLARED_CLASS (ref)
+ ? access_private_node : access_public_node);
/* First, make sure that any templates in base-classes are
instantiated. This ensures that if we call ourselves recursively
we do not get confused about which classes are marked and which
are not. */
- basep = &base_list;
- while (*basep)
+ basep = &base_list;
+ while (*basep)
{
tree basetype = TREE_VALUE (*basep);
+
if (!(processing_template_decl && uses_template_parms (basetype))
&& !complete_type_or_else (basetype, NULL))
/* An incomplete type. Remove it from the list. */
*basep = TREE_CHAIN (*basep);
else
- basep = &TREE_CHAIN (*basep);
+ {
+ max_bases++;
+ if (TREE_TYPE (*basep))
+ max_vbases++;
+ if (CLASS_TYPE_P (basetype))
+ max_vbases += VEC_length (tree, CLASSTYPE_VBASECLASSES (basetype));
+ basep = &TREE_CHAIN (*basep);
+ }
}
SET_CLASSTYPE_MARKED (ref);
- i = list_length (base_list);
- if (i)
- {
- tree binfo = TYPE_BINFO (ref);
- tree binfos = make_tree_vec (i);
- tree accesses = make_tree_vec (i);
-
- BINFO_BASETYPES (binfo) = binfos;
- BINFO_BASEACCESSES (binfo) = accesses;
-
- for (i = 0; base_list; base_list = TREE_CHAIN (base_list))
- {
- tree access = TREE_PURPOSE (base_list);
- int via_virtual = TREE_VIA_VIRTUAL (base_list);
- tree basetype = TREE_VALUE (base_list);
- tree base_binfo;
-
- if (access == access_default_node)
- /* The base of a derived struct is public by default. */
- access = (tag_code == class_type
- ? access_private_node : access_public_node);
-
- if (basetype && TREE_CODE (basetype) == TYPE_DECL)
- basetype = TREE_TYPE (basetype);
- if (!basetype
- || (TREE_CODE (basetype) != RECORD_TYPE
- && TREE_CODE (basetype) != TYPENAME_TYPE
- && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
- && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
- {
- error ("base type `%T' fails to be a struct or class type",
- basetype);
- continue;
- }
-
- if (CLASSTYPE_MARKED (basetype))
- {
- if (basetype == ref)
- error ("recursive type `%T' undefined", basetype);
- else
- error ("duplicate base type `%T' invalid", basetype);
- continue;
- }
-
- if (TYPE_FOR_JAVA (basetype)
- && (current_lang_depth () == 0))
- TYPE_FOR_JAVA (ref) = 1;
-
- if (CLASS_TYPE_P (basetype))
- {
- base_binfo = TYPE_BINFO (basetype);
- /* This flag will be in the binfo of the base type, we must
- clear it after copying the base binfos. */
- BINFO_DEPENDENT_BASE_P (base_binfo)
- = dependent_type_p (basetype);
- }
- else
- base_binfo = make_binfo (size_zero_node, basetype,
- NULL_TREE, NULL_TREE);
-
- TREE_VEC_ELT (binfos, i) = base_binfo;
- TREE_VEC_ELT (accesses, i) = access;
- /* This flag will be in the binfo of the base type, we must
- clear it after copying the base binfos. */
- TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
-
- SET_CLASSTYPE_MARKED (basetype);
-
- /* We are free to modify these bits because they are meaningless
- at top level, and BASETYPE is a top-level type. */
- if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
- /* Converting to a virtual base class requires looking
- up the offset of the virtual base. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
- }
-
- if (CLASS_TYPE_P (basetype))
- {
- TYPE_HAS_NEW_OPERATOR (ref)
- |= TYPE_HAS_NEW_OPERATOR (basetype);
- TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
- |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
- TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
- /* If the base-class uses multiple inheritance, so do we. */
- TYPE_USES_MULTIPLE_INHERITANCE (ref)
- |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
- /* Likewise, if converting to a base of the base may require
- code, then we may need to generate code to convert to a
- base as well. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
- |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
- }
- i++;
- }
- if (i)
- TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;
- else
- BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE;
-
- if (i > 1)
- {
- TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
- /* If there is more than one non-empty they cannot be at the same
- address. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
- }
+
+ /* The binfo slot should be empty, unless this is an (ill-formed)
+ redefinition. */
+ my_friendly_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref), 20040706);
+ my_friendly_assert (TYPE_MAIN_VARIANT (ref) == ref, 20040712);
+
+ binfo = make_tree_binfo (max_bases);
+
+ TYPE_BINFO (ref) = binfo;
+ BINFO_OFFSET (binfo) = size_zero_node;
+ BINFO_TYPE (binfo) = ref;
+
+ if (max_bases)
+ {
+ BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, max_bases);
+ /* An aggregate cannot have baseclasses. */
+ CLASSTYPE_NON_AGGREGATE (ref) = 1;
+
+ if (TREE_CODE (ref) == UNION_TYPE)
+ error ("derived union `%T' invalid", ref);
}
-
- /* Copy the base binfos, collect the virtual bases and set the
- inheritance order chain. */
- copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
- CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));
- if (TYPE_FOR_JAVA (ref))
+ if (max_bases > 1)
{
- if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
+ TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
+ /* If there is more than one non-empty they cannot be at the
+ same address. */
+ TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
+
+ if (TYPE_FOR_JAVA (ref))
error ("Java class '%T' cannot have multiple bases", ref);
- if (CLASSTYPE_VBASECLASSES (ref))
+ }
+
+ if (max_vbases)
+ {
+ CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases);
+ TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
+ /* Converting to a virtual base class requires looking up the
+ offset of the virtual base. */
+ TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
+
+ if (TYPE_FOR_JAVA (ref))
error ("Java class '%T' cannot have virtual bases", ref);
}
- /* Unmark all the types. */
- while (i--)
+ for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list))
{
- tree basetype = BINFO_TYPE (BINFO_BASETYPE (TYPE_BINFO (ref), i));
-
- CLEAR_CLASSTYPE_MARKED (basetype);
- if (CLASS_TYPE_P (basetype))
+ tree access = TREE_PURPOSE (base_list);
+ int via_virtual = TREE_TYPE (base_list) != NULL_TREE;
+ tree basetype = TREE_VALUE (base_list);
+
+ if (access == access_default_node)
+ access = default_access;
+
+ if (TREE_CODE (basetype) == TYPE_DECL)
+ basetype = TREE_TYPE (basetype);
+ if (TREE_CODE (basetype) != RECORD_TYPE
+ && TREE_CODE (basetype) != TYPENAME_TYPE
+ && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)
{
- TREE_VIA_VIRTUAL (TYPE_BINFO (basetype)) = 0;
- BINFO_DEPENDENT_BASE_P (TYPE_BINFO (basetype)) = 0;
+ error ("base type `%T' fails to be a struct or class type",
+ basetype);
+ continue;
}
+
+ if (CLASSTYPE_MARKED (basetype))
+ {
+ if (basetype == ref)
+ error ("recursive type `%T' undefined", basetype);
+ else
+ error ("duplicate base type `%T' invalid", basetype);
+ continue;
+ }
+ SET_CLASSTYPE_MARKED (basetype);
+
+ if (TYPE_FOR_JAVA (basetype) && (current_lang_depth () == 0))
+ TYPE_FOR_JAVA (ref) = 1;
+
+ base_binfo = NULL_TREE;
+ if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype))
+ {
+ base_binfo = TYPE_BINFO (basetype);
+ /* The orignal basetype could have been a typedef'd type. */
+ basetype = BINFO_TYPE (base_binfo);
+
+ /* Inherit flags from the base. */
+ TYPE_HAS_NEW_OPERATOR (ref)
+ |= TYPE_HAS_NEW_OPERATOR (basetype);
+ TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
+ |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
+ TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+ TYPE_USES_MULTIPLE_INHERITANCE (ref)
+ |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
+ TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
+ |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
+ TYPE_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype);
+ }
+
+ base_binfo = copy_binfo (base_binfo, basetype, ref,
+ &igo_prev, via_virtual);
+ if (!BINFO_INHERITANCE_CHAIN (base_binfo))
+ BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
+
+ BINFO_BASE_APPEND (binfo, base_binfo);
+ BINFO_BASE_ACCESS_APPEND (binfo, access);
}
+
+ /* Unmark all the types. */
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (base_binfo));
CLEAR_CLASSTYPE_MARKED (ref);
}
tree t;
bool unsignedp;
int lowprec;
- int highprec;
+ int highprec;
int precision;
integer_type_kind itk;
tree underlying_type = NULL_TREE;
works. */
if (processing_template_decl)
{
- for (values = TYPE_VALUES (enumtype);
- values;
+ for (values = TYPE_VALUES (enumtype);
+ values;
values = TREE_CHAIN (values))
TREE_TYPE (TREE_VALUE (values)) = enumtype;
if (at_function_scope_p ())
{
minnode = maxnode = NULL_TREE;
- for (values = TYPE_VALUES (enumtype);
- values;
+ for (values = TYPE_VALUES (enumtype);
+ values;
values = TREE_CHAIN (values))
{
decl = TREE_VALUE (values);
enumeration. It is implementation-defined which integral type is
used as the underlying type for an enumeration except that the
underlying type shall not be larger than int unless the value of
- an enumerator cannot fit in an int or unsigned int.
+ an enumerator cannot fit in an int or unsigned int.
We use "int" or an "unsigned int" as the underlying type, even if
a smaller integral type would work, unless the user has
explicitly requested that we use the smallest possible type. */
- for (itk = (flag_short_enums ? itk_char : itk_int);
- itk != itk_none;
+ for (itk = (flag_short_enums ? itk_char : itk_int);
+ itk != itk_none;
itk++)
{
underlying_type = integer_types[itk];
underlying_type = integer_types[itk_unsigned_long_long];
}
- /* Compute the minium and maximum values for the type.
+ /* Compute the minium and maximum values for the type.
[dcl.enum]
set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
/* [dcl.enum]
-
+
The value of sizeof() applied to an enumeration type, an object
of an enumeration type, or an enumerator, is the value of sizeof()
applied to the underlying type. */
fntype = TREE_TYPE (decl1);
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
-
+
/* ISO C++ 11.4/5. A friend function defined in a class is in
the (lexical) scope of the class in which it is defined. */
if (!ctype && DECL_FRIEND_P (decl1))
{
ctype = DECL_FRIEND_CONTEXT (decl1);
-
+
/* CTYPE could be null here if we're dealing with a template;
for example, `inline friend float foo()' inside a template
will have no CTYPE set. */
restype = type_promotes_to (restype);
if (DECL_RESULT (decl1) == NULL_TREE)
{
- DECL_RESULT (decl1)
- = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
- c_apply_type_quals_to_decl (cp_type_quals (restype),
- DECL_RESULT (decl1));
+ tree resdecl;
+
+ resdecl = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
+ DECL_ARTIFICIAL (resdecl) = 1;
+ DECL_IGNORED_P (resdecl) = 1;
+ DECL_RESULT (decl1) = resdecl;
+
+ c_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
}
/* Initialize RTL machinery. We cannot do this until
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. */
- immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
/* Start the statement-tree, start the tree now. */
{
/* A specialization is not used to guide overload resolution. */
if (!DECL_FUNCTION_MEMBER_P (decl1)
- && !(DECL_USE_TEMPLATE (decl1) &&
+ && !(DECL_USE_TEMPLATE (decl1) &&
PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl1))))
{
tree olddecl = pushdecl (decl1);
fntype = TREE_TYPE (decl1);
}
+ /* Determine the ELF visibility attribute for the function. We must
+ not do this before calling "pushdecl", as we must allow
+ "duplicate_decls" to merge any attributes appropriately. */
+ if (!DECL_CLONED_FUNCTION_P (decl1))
+ determine_visibility (decl1);
+
/* Reset these in case the call to pushdecl changed them. */
current_function_decl = decl1;
cfun->decl = decl1;
else if (interface_unknown == 0
&& ! DECL_TEMPLATE_INSTANTIATION (decl1))
{
- if (DECL_DECLARED_INLINE_P (decl1)
+ if (DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1)
|| processing_template_decl)
{
DECL_EXTERNAL (decl1)
= (interface_only
- || (DECL_DECLARED_INLINE_P (decl1)
+ || (DECL_DECLARED_INLINE_P (decl1)
&& ! flag_implement_inlines
&& !DECL_VINDEX (decl1)));
DECL_EXTERNAL (decl1) = 0;
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
+ /* If this function is in an interface implemented in this file,
+ make sure that the backend knows to emit this function
+ here. */
+ if (!DECL_EXTERNAL (decl1))
+ mark_needed (decl1);
}
else if (interface_unknown && interface_only
&& ! DECL_TEMPLATE_INSTANTIATION (decl1))
So clear DECL_EXTERNAL. */
DECL_EXTERNAL (decl1) = 0;
- if ((DECL_DECLARED_INLINE_P (decl1)
+ if ((DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))
&& ! DECL_INTERFACE_KNOWN (decl1)
/* Don't try to defer nested functions for now. */
++function_depth;
- if (DECL_DESTRUCTOR_P (decl1))
+ if (DECL_DESTRUCTOR_P (decl1)
+ || (DECL_CONSTRUCTOR_P (decl1)
+ && targetm.cxx.cdtor_returns_this ()))
{
- dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- DECL_CONTEXT (dtor_label) = current_function_decl;
+ cdtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ DECL_CONTEXT (cdtor_label) = current_function_decl;
}
start_fname_decls ();
-
+
store_parm_decls (current_function_parms);
}
yyparse to report a parse error. */
int
-start_function (cp_decl_specifier_seq *declspecs,
+start_function (cp_decl_specifier_seq *declspecs,
const cp_declarator *declarator,
tree attrs)
{
/* This should only be done once on the outermost decl. */
have_extern_spec = false;
}
-
+
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
return 0;
-
+
cplus_decl_attributes (&decl1, attrs, 0);
-
+
/* If #pragma weak was used, mark the decl weak now. */
if (global_scope_p (current_binding_level))
maybe_apply_pragma_weak (decl1);
-
+
if (DECL_MAIN_P (decl1))
{
/* If this doesn't return integer_type, or a typedef to
DECL_ARGUMENTS is not modified. */
current_binding_level->names = chainon (nonparms, DECL_ARGUMENTS (fndecl));
- /* Do the starting of the exception specifications, if we have any. */
- if (flag_exceptions && !processing_template_decl
- && flag_enforce_eh_specs
- && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
- current_eh_spec_block = begin_eh_spec_block ();
+ /* For a cloned function, we've already got all the code we need;
+ there's no need to add any extra bits. */
+ if (!DECL_CLONED_FUNCTION_P (fndecl))
+ {
+ /* Do the starting of the exception specifications, if we have any. */
+ if (flag_exceptions && !processing_template_decl
+ && flag_enforce_eh_specs
+ && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
+ current_eh_spec_block = begin_eh_spec_block ();
+ }
}
\f
19990908);
/* Make a copy. */
- f = ggc_alloc (sizeof (struct language_function));
+ f = GGC_NEW (struct language_function);
memcpy (f, cp_function_chain, sizeof (struct language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
f->x_local_names = NULL;
}
-/* Add a note to mark the beginning of the main body of the constructor.
- This is used to set up the data structures for the cleanup regions for
- fully-constructed bases and members. */
-
-static void
-begin_constructor_body (void)
-{
-}
-/* Add a note to mark the end of the main body of the constructor. This is
- used to end the cleanup regions for fully-constructed bases and
- members. */
+/* Set the return value of the constructor (if present). */
static void
finish_constructor_body (void)
{
+ tree val;
+ tree exprstmt;
+
+ if (targetm.cxx.cdtor_returns_this ())
+ {
+ /* Any return from a constructor will end up here. */
+ add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
+
+ val = DECL_ARGUMENTS (current_function_decl);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (val),
+ DECL_RESULT (current_function_decl), val);
+ /* Return the address of the object. */
+ exprstmt = build_stmt (RETURN_EXPR, val);
+ add_stmt (exprstmt);
+ }
}
/* Do all the processing for the beginning of a destructor; set up the
if_stmt = begin_if_stmt ();
/* If it is not safe to avoid setting up the vtables, then
- someone will change the condition to be boolean_true_node.
+ someone will change the condition to be boolean_true_node.
(Actually, for now, we do not have code to set the condition
appropriately, so we just assume that we always need to
initialize the vtables.) */
/* Any return from a destructor will end up here; that way all base
and member cleanups will be run when the function returns. */
- add_stmt (build_stmt (LABEL_EXPR, dtor_label));
+ add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
/* In a virtual destructor, we must call delete. */
if (DECL_VIRTUAL_P (current_function_decl))
be looked up in the scope of the destructor's class and if
found shall be accessible and unambiguous. */
exprstmt = build_op_delete_call
- (DELETE_EXPR, current_class_ptr, virtual_size,
+ (DELETE_EXPR, current_class_ptr, virtual_size,
/*global_p=*/false, NULL_TREE);
if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
- current_in_charge_parm,
- integer_one_node),
+ finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node,
+ current_in_charge_parm,
+ integer_one_node),
if_stmt);
finish_expr_stmt (exprstmt);
finish_then_clause (if_stmt);
finish_if_stmt (if_stmt);
}
+
+ if (targetm.cxx.cdtor_returns_this ())
+ {
+ tree val;
+
+ val = DECL_ARGUMENTS (current_function_decl);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (val),
+ DECL_RESULT (current_function_decl), val);
+ /* Return the address of the object. */
+ exprstmt = build_stmt (RETURN_EXPR, val);
+ add_stmt (exprstmt);
+ }
}
/* Do the necessary processing for the beginning of a function body, which
if (processing_template_decl)
/* Do nothing now. */;
- else if (DECL_CONSTRUCTOR_P (current_function_decl))
- begin_constructor_body ();
else if (DECL_DESTRUCTOR_P (current_function_decl))
begin_destructor_body ();
finish_constructor_body ();
else if (DECL_DESTRUCTOR_P (current_function_decl))
finish_destructor_body ();
-}
+}
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
which then got a warning when stored in a ptr-to-function variable. */
my_friendly_assert (building_stmt_tree (), 20000911);
-
+
/* For a cloned function, we've already got all the code we need;
there's no need to add any extra bits. */
if (!DECL_CLONED_FUNCTION_P (fndecl))
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
this function's blocks. */
-
+
/* If the current binding level isn't the outermost binding level
for this function, either there is a bug, or we have experienced
syntax errors and the statement tree is malformed. */
&& !current_function_returns_value && !current_function_returns_null
/* Don't complain if we abort or throw. */
&& !current_function_returns_abnormally
- && !DECL_NAME (DECL_RESULT (fndecl)))
-#if 0
- /* Enable this for all functions until bug 14107 is fixed properly. */
+ && !DECL_NAME (DECL_RESULT (fndecl))
/* Normally, with -Wreturn-type, flow will complain. Unless we're an
inline function, as we might never be compiled separately. */
- && (DECL_INLINE (fndecl) || processing_template_decl))
-#endif
+ && (DECL_INLINE (fndecl) || processing_template_decl)
+ /* Structor return values (if any) are set by the compiler. */
+ && !DECL_CONSTRUCTOR_P (fndecl)
+ && !DECL_DESTRUCTOR_P (fndecl))
warning ("no return statement in function returning non-void");
/* Store the end of the function, so that we get good line number
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (cp_decl_specifier_seq *declspecs,
+start_method (cp_decl_specifier_seq *declspecs,
const cp_declarator *declarator, tree attrlist)
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406);
/* Keep track of variables with incomplete types. */
- if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
+ if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
&& DECL_EXTERNAL (var))
{
tree inner_type = TREE_TYPE (var);
-
+
while (TREE_CODE (inner_type) == ARRAY_TYPE)
inner_type = TREE_TYPE (inner_type);
inner_type = TYPE_MAIN_VARIANT (inner_type);
-
+
if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type))
/* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (inner_type)
tree *list = &incomplete_vars;
my_friendly_assert (CLASS_TYPE_P (type), 20020406);
- while (*list)
+ while (*list)
{
if (same_type_p (type, TREE_PURPOSE (*list)))
{
else
list = &TREE_CHAIN (*list);
}
+
+ /* Check for pending declarations which may have abstract type. */
+ complete_type_check_abstract (type);
}
/* If DECL is of a type which needs a cleanup, build that cleanup
void
cxx_push_function_context (struct function * f)
{
- struct language_function *p
- = ggc_alloc_cleared (sizeof (struct language_function));
+ struct language_function *p = GGC_CNEW (struct language_function);
f->language = p;
/* Whenever we start a new function, we destroy temporaries in the
/* We don't need the saved data anymore. Unless this is an inline
function; we need the named return value info for
- cp_copy_res_decl_for_inlining. */
+ declare_return_variable. */
if (! DECL_INLINE (fn))
DECL_SAVED_FUNCTION_DATA (fn) = NULL;
}
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;
default: return TS_CP_GENERIC;