#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "flags.h"
#include "cp-tree.h"
#include "tree-inline.h"
#include "decl.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "hashtab.h"
#include "tm_p.h"
#include "target.h"
#include "c-common.h"
#include "c-pragma.h"
#include "diagnostic.h"
#include "debug.h"
#include "timevar.h"
#include "tree-flow.h"
static tree grokparms (cp_parameter_declarator *, tree *);
static const char *redeclaration_error_message (tree, tree);
static int decl_jump_unsafe (tree);
static void require_complete_types_for_parms (tree);
static int ambi_op_p (enum tree_code);
static int unary_op_p (enum tree_code);
static void push_local_name (tree);
static tree grok_reference_init (tree, tree, tree, 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,
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 bad_specifiers (tree, const char *, int, int, int, int,
int);
static void check_for_uninitialized_const_var (tree);
static hashval_t typename_hash (const void *);
static int typename_compare (const void *, const void *);
static tree local_variable_p_walkfn (tree *, int *, void *);
static tree record_builtin_java_type (const char *, int);
static const char *tag_name (enum tag_types);
static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool);
static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
static tree make_label_decl (tree, int);
static void use_label (tree);
static void check_previous_goto_1 (tree, struct cp_binding_level *, tree,
const location_t *);
static void check_previous_goto (struct named_label_use_list *);
static void check_switch_goto (struct cp_binding_level *);
static void check_previous_gotos (tree);
static void pop_label (tree, tree);
static void pop_labels (tree);
static void maybe_deduce_size_from_array_init (tree, tree);
static void layout_var_decl (tree);
static void maybe_commonize_var (tree);
static tree check_initializer (tree, tree, int, tree *);
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 finish_constructor_body (void);
static void begin_destructor_body (void);
static void finish_destructor_body (void);
static tree create_array_type_for_decl (tree, tree, tree);
static tree get_atexit_node (void);
static tree get_dso_handle_node (void);
static tree start_cleanup_fn (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
(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);
static void store_parm_decls (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
static tree reshape_init (tree, tree *);
tree error_mark_list;
tree cp_global_trees[CPTI_MAX];
tree global_type_node;
tree global_scope_name;
struct named_label_use_list GTY(())
{
struct cp_binding_level *binding_level;
tree names_in_scope;
tree label_decl;
location_t o_goto_locus;
struct named_label_use_list *next;
};
#define named_label_uses cp_function_chain->x_named_label_uses
#define local_names cp_function_chain->x_local_names
tree static_aggregates;
tree integer_two_node, integer_three_node;
struct named_label_list GTY(())
{
struct cp_binding_level *binding_level;
tree names_in_scope;
tree old_value;
tree label_decl;
tree bad_decls;
struct named_label_list *next;
unsigned int in_try_scope : 1;
unsigned int in_catch_scope : 1;
};
#define named_labels cp_function_chain->x_named_labels
int function_depth;
enum deprecated_states {
DEPRECATED_NORMAL,
DEPRECATED_SUPPRESS
};
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
bool have_extern_spec;
static GTY(()) tree incomplete_vars;
tmpl_spec_kind
current_tmpl_spec_kind (int n_class_scopes)
{
int n_template_parm_scopes = 0;
int seen_specialization_p = 0;
int innermost_specialization_p = 0;
struct cp_binding_level *b;
for (b = current_binding_level;
b->kind == sk_template_parms;
b = b->level_chain)
{
if (b->explicit_spec_p)
{
if (n_template_parm_scopes == 0)
innermost_specialization_p = 1;
else
seen_specialization_p = 1;
}
else if (seen_specialization_p == 1)
return tsk_invalid_member_spec;
++n_template_parm_scopes;
}
if (processing_explicit_instantiation)
{
if (n_template_parm_scopes != 0)
return tsk_invalid_expl_inst;
else
return tsk_expl_inst;
}
if (n_template_parm_scopes < n_class_scopes)
return tsk_insufficient_parms;
else if (n_template_parm_scopes == n_class_scopes)
return tsk_none;
else if (n_template_parm_scopes > n_class_scopes + 1)
return tsk_excessive_parms;
else
return innermost_specialization_p ? tsk_expl_spec : tsk_template;
}
void
finish_scope (void)
{
poplevel (0, 0, 0);
}
static void
pop_label (tree label, tree old_value)
{
if (!processing_template_decl)
{
if (DECL_INITIAL (label) == NULL_TREE)
{
location_t location;
cp_error_at ("label %qD used but not defined", label);
#ifdef USE_MAPPED_LOCATION
location = input_location;
#else
location.file = input_filename;
location.line = 0;
#endif
define_label (location, DECL_NAME (label));
}
else if (warn_unused_label && !TREE_USED (label))
cp_warning_at ("label %qD defined but not used", label);
}
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
}
static void
pop_labels (tree block)
{
struct named_label_list *link;
for (link = named_labels; link; link = link->next)
{
pop_label (link->label_decl, link->old_value);
TREE_CHAIN (link->label_decl) = BLOCK_VARS (block);
BLOCK_VARS (block) = link->label_decl;
}
named_labels = NULL;
}
void *
objc_get_current_scope (void)
{
return current_binding_level;
}
void
objc_mark_locals_volatile (void *enclosing_blk)
{
struct cp_binding_level *scope;
for (scope = current_binding_level;
scope && scope != enclosing_blk && scope->kind == sk_block;
scope = scope->level_chain)
{
tree decl;
for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
{
if (TREE_CODE (decl) == VAR_DECL)
{
DECL_REGISTER (decl) = 0;
TREE_THIS_VOLATILE (decl) = 1;
}
}
}
}
tree
poplevel (int keep, int reverse, int functionbody)
{
tree link;
tree decls;
int tmp = functionbody;
int real_functionbody;
tree subblocks;
tree block;
tree decl;
int leaving_for_scope;
scope_kind kind;
timevar_push (TV_NAME_LOOKUP);
restart:
block = NULL_TREE;
gcc_assert (current_binding_level->kind != sk_class);
real_functionbody = (current_binding_level->kind == sk_cleanup
? ((functionbody = 0), tmp) : functionbody);
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
gcc_assert (!VEC_length(cp_class_binding,
current_binding_level->class_shadowed));
gcc_assert (keep == 0 || keep == 1);
if (current_binding_level->keep)
keep = 1;
if (cfun && !functionbody)
{
struct cp_binding_level *level_chain;
level_chain = current_binding_level->level_chain;
if (level_chain)
{
struct named_label_use_list *uses;
struct named_label_list *labels;
for (labels = named_labels; labels; labels = labels->next)
if (labels->binding_level == current_binding_level)
{
tree decl;
if (current_binding_level->kind == sk_try)
labels->in_try_scope = 1;
if (current_binding_level->kind == sk_catch)
labels->in_catch_scope = 1;
for (decl = labels->names_in_scope; decl;
decl = TREE_CHAIN (decl))
if (decl_jump_unsafe (decl))
labels->bad_decls = tree_cons (NULL_TREE, decl,
labels->bad_decls);
labels->binding_level = level_chain;
labels->names_in_scope = level_chain->names;
}
for (uses = named_label_uses; uses; uses = uses->next)
if (uses->binding_level == current_binding_level)
{
uses->binding_level = level_chain;
uses->names_in_scope = level_chain->names;
}
}
}
if (reverse)
current_binding_level->names
= decls = nreverse (current_binding_level->names);
else
decls = current_binding_level->names;
block = NULL_TREE;
if (keep == 1 || functionbody)
block = make_node (BLOCK);
if (block != NULL_TREE)
{
BLOCK_VARS (block) = decls;
BLOCK_SUBBLOCKS (block) = subblocks;
}
if (keep >= 0)
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
leaving_for_scope
= current_binding_level->kind == sk_for && flag_new_for_scope == 1;
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 %qD", decl, decl);
for (link = decls; link; link = TREE_CHAIN (link))
{
if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
&& DECL_NAME (link))
{
tree name = DECL_NAME (link);
cxx_binding *ob;
tree ns_binding;
ob = outer_binding (name,
IDENTIFIER_BINDING (name),
true);
if (!ob)
ns_binding = IDENTIFIER_NAMESPACE_VALUE (name);
else
ns_binding = NULL_TREE;
if (ob && ob->scope == current_binding_level->level_chain)
pop_binding (name, link);
else if ((ob && (TREE_CODE (ob->value) == TYPE_DECL))
|| (ns_binding && TREE_CODE (ns_binding) == TYPE_DECL))
pop_binding (name, link);
else
{
DECL_DEAD_FOR_LOCAL (link) = 1;
if (ob && ob->value)
DECL_SHADOWED_FOR_VAR (link) = ob->value;
current_binding_level->level_chain->dead_vars_from_for
= tree_cons (NULL_TREE, link,
current_binding_level->level_chain->
dead_vars_from_for);
IDENTIFIER_BINDING (name)->scope
= current_binding_level->level_chain;
}
}
else
{
tree name;
decl = link;
if (TREE_CODE (decl) == TREE_LIST)
decl = TREE_VALUE (decl);
name = decl;
if (TREE_CODE (name) == OVERLOAD)
name = OVL_FUNCTION (name);
gcc_assert (DECL_P (name));
pop_binding (DECL_NAME (name), decl);
}
}
for (link = current_binding_level->dead_vars_from_for;
link; link = TREE_CHAIN (link))
pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
for (link = current_binding_level->shadowed_labels;
link;
link = TREE_CHAIN (link))
pop_label (TREE_VALUE (link), TREE_PURPOSE (link));
if (block)
{
tree* d;
for (d = &BLOCK_VARS (block); *d; )
{
if (TREE_CODE (*d) == TREE_LIST)
*d = TREE_CHAIN (*d);
else
d = &TREE_CHAIN (*d);
}
}
if (functionbody)
{
BLOCK_VARS (block) = 0;
pop_labels (block);
}
kind = current_binding_level->kind;
if (kind == sk_cleanup)
{
tree stmt;
stmt = pop_stmt_list (current_binding_level->statement_list);
stmt = c_build_bind_expr (block, stmt);
add_stmt (stmt);
}
leave_scope ();
if (functionbody)
DECL_INITIAL (current_function_decl) = block;
else if (block)
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
else if (subblocks)
current_binding_level->blocks
= chainon (current_binding_level->blocks, subblocks);
if (block)
TREE_USED (block) = 1;
if (kind == sk_cleanup)
goto restart;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
void
insert_block (tree block)
{
TREE_USED (block) = 1;
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
}
static int
walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data)
{
int result = 0;
tree current = NAMESPACE_LEVEL (namespace)->namespaces;
result |= (*f) (namespace, data);
for (; current; current = TREE_CHAIN (current))
result |= walk_namespaces_r (current, f, data);
return result;
}
int
walk_namespaces (walk_namespaces_fn f, void* data)
{
return walk_namespaces_r (global_namespace, f, data);
}
int
wrapup_globals_for_namespace (tree namespace, void* data)
{
struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
varray_type statics = level->static_decls;
tree *vec = &VARRAY_TREE (statics, 0);
int len = VARRAY_ACTIVE_SIZE (statics);
int last_time = (data != 0);
if (last_time)
{
check_global_declarations (vec, len);
return 0;
}
return wrapup_global_declarations (vec, len);
}
tree
create_implicit_typedef (tree name, tree type)
{
tree decl;
decl = build_decl (TYPE_DECL, name, type);
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_IMPLICIT_TYPEDEF_P (decl);
TYPE_NAME (type) = decl;
return decl;
}
static void
push_local_name (tree decl)
{
size_t i, nelts;
tree t, name;
timevar_push (TV_NAME_LOOKUP);
if (!local_names)
VARRAY_TREE_INIT (local_names, 8, "local_names");
name = DECL_NAME (decl);
nelts = VARRAY_ACTIVE_SIZE (local_names);
for (i = 0; i < nelts; i++)
{
t = VARRAY_TREE (local_names, i);
if (DECL_NAME (t) == name)
{
if (!DECL_LANG_SPECIFIC (decl))
retrofit_lang_decl (decl);
DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1;
if (DECL_LANG_SPECIFIC (t))
DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
else
DECL_DISCRIMINATOR (decl) = 1;
VARRAY_TREE (local_names, i) = decl;
timevar_pop (TV_NAME_LOOKUP);
return;
}
}
VARRAY_PUSH_TREE (local_names, decl);
timevar_pop (TV_NAME_LOOKUP);
}
int
decls_match (tree newdecl, tree olddecl)
{
int types_match;
if (newdecl == olddecl)
return 1;
if (TREE_CODE (newdecl) != TREE_CODE (olddecl))
return 0;
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
tree f2 = TREE_TYPE (olddecl);
tree p1 = TYPE_ARG_TYPES (f1);
tree p2 = TYPE_ARG_TYPES (f2);
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
&& ! (DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl)))
return 0;
if (TREE_CODE (f1) != TREE_CODE (f2))
return 0;
if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
{
if (p2 == NULL_TREE && DECL_EXTERN_C_P (olddecl)
&& (DECL_BUILT_IN (olddecl)
#ifndef NO_IMPLICIT_EXTERN_C
|| (DECL_IN_SYSTEM_HEADER (newdecl) && !DECL_CLASS_SCOPE_P (newdecl))
|| (DECL_IN_SYSTEM_HEADER (olddecl) && !DECL_CLASS_SCOPE_P (olddecl))
#endif
))
{
types_match = self_promoting_args_p (p1);
if (p1 == void_list_node)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
#ifndef NO_IMPLICIT_EXTERN_C
else if (p1 == NULL_TREE
&& (DECL_EXTERN_C_P (olddecl)
&& DECL_IN_SYSTEM_HEADER (olddecl)
&& !DECL_CLASS_SCOPE_P (olddecl))
&& (DECL_EXTERN_C_P (newdecl)
&& DECL_IN_SYSTEM_HEADER (newdecl)
&& !DECL_CLASS_SCOPE_P (newdecl)))
{
types_match = self_promoting_args_p (p2);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
#endif
else
types_match = compparms (p1, p2);
}
else
types_match = 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl))
!= TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)))
return 0;
if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
return 0;
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
types_match = same_type_p (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl)),
TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl)));
else
types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
DECL_TEMPLATE_RESULT (newdecl));
}
else
{
if (TREE_CODE (newdecl) == VAR_DECL
&& CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
return 0;
if (TREE_TYPE (newdecl) == error_mark_node)
types_match = TREE_TYPE (olddecl) == error_mark_node;
else if (TREE_TYPE (olddecl) == NULL_TREE)
types_match = TREE_TYPE (newdecl) == NULL_TREE;
else if (TREE_TYPE (newdecl) == NULL_TREE)
types_match = 0;
else
types_match = comptypes (TREE_TYPE (newdecl),
TREE_TYPE (olddecl),
COMPARE_REDECLARATION);
}
return types_match;
}
void
warn_extern_redeclared_static (tree newdecl, tree olddecl)
{
tree name;
if (TREE_CODE (newdecl) == TYPE_DECL
|| TREE_CODE (newdecl) == TEMPLATE_DECL
|| TREE_CODE (newdecl) == CONST_DECL
|| TREE_CODE (newdecl) == NAMESPACE_DECL)
return;
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_STATIC_FUNCTION_P (newdecl))
return;
if (DECL_THIS_STATIC (olddecl) || !DECL_THIS_STATIC (newdecl))
return;
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
return;
name = DECL_ASSEMBLER_NAME (newdecl);
pedwarn ("%qD was declared %<extern%> and later %<static%>", newdecl);
cp_pedwarn_at ("previous declaration of %qD", olddecl);
}
tree
duplicate_decls (tree newdecl, tree olddecl)
{
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0;
int new_defines_function = 0;
if (newdecl == olddecl)
return olddecl;
types_match = decls_match (newdecl, olddecl);
if (TREE_TYPE (newdecl) == error_mark_node
|| TREE_TYPE (olddecl) == error_mark_node)
types_match = 1;
if (DECL_P (olddecl)
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
{
if (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
;
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
;
else if (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
warning ("%Jfunction %qD redeclared as inline", newdecl, newdecl);
warning ("%Jprevious declaration of %qD with attribute noinline",
olddecl, olddecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
warning ("%Jfunction %qD redeclared with attribute noinline",
newdecl, newdecl);
warning ("%Jprevious declaration of %qD was inline",
olddecl, olddecl);
}
}
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
if (DECL_ANTICIPATED (olddecl))
return NULL_TREE;
if (! TREE_PUBLIC (newdecl))
{
if (warn_shadow)
warning ("shadowing %s function %q#D",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
return NULL_TREE;
}
else if (! DECL_BUILT_IN (olddecl))
warning ("library function %q#D redeclared as non-function %q#D",
olddecl, newdecl);
else
{
error ("declaration of %q#D", newdecl);
error ("conflicts with built-in declaration %q#D",
olddecl);
}
return NULL_TREE;
}
else if (!types_match)
{
if (DECL_ANTICIPATED (olddecl))
{
tree t1, t2;
for (t1 = TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
t2 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
t1 || t2;
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
if (!t1 || !t2)
break;
else if (TREE_VALUE (t2) == fileptr_type_node)
{
tree t = TREE_VALUE (t1);
if (TREE_CODE (t) == POINTER_TYPE
&& TYPE_NAME (TREE_TYPE (t))
&& DECL_NAME (TYPE_NAME (TREE_TYPE (t)))
== get_identifier ("FILE")
&& compparms (TREE_CHAIN (t1), TREE_CHAIN (t2)))
{
tree oldargs = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
TYPE_ARG_TYPES (TREE_TYPE (olddecl))
= TYPE_ARG_TYPES (TREE_TYPE (newdecl));
types_match = decls_match (newdecl, olddecl);
if (types_match)
return duplicate_decls (newdecl, olddecl);
TYPE_ARG_TYPES (TREE_TYPE (olddecl)) = oldargs;
}
}
else if (! same_type_p (TREE_VALUE (t1), TREE_VALUE (t2)))
break;
}
else if ((DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl))
|| compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
if (TREE_PUBLIC (newdecl))
{
warning ("new declaration %q#D", newdecl);
warning ("ambiguates built-in declaration %q#D",
olddecl);
}
else if (warn_shadow)
warning ("shadowing %s function %q#D",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
}
else
return NULL_TREE;
COPY_DECL_RTL (newdecl, olddecl);
}
else if (DECL_ANTICIPATED (olddecl))
{
tree type = TREE_TYPE (newdecl);
tree attribs = (*targetm.merge_type_attributes)
(TREE_TYPE (olddecl), type);
type = cp_build_type_attribute_variant (type, attribs);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
}
TREE_NOTHROW (olddecl) = 0;
if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
{
DECL_THIS_STATIC (olddecl) = 1;
TREE_PUBLIC (olddecl) = 0;
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
COPY_DECL_RTL (newdecl, olddecl);
}
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
&& TREE_CODE (newdecl) != TYPE_DECL
&& ! (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
|| (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
&& TREE_CODE (olddecl) != TYPE_DECL
&& ! (TREE_CODE (olddecl) == TEMPLATE_DECL
&& (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
== TYPE_DECL))))
{
return NULL_TREE;
}
if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
return NULL_TREE;
error ("%q#D redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
cp_error_at ("previous declaration of %q#D", olddecl);
return error_mark_node;
}
else if (!types_match)
{
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
return NULL_TREE;
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
|| TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
{
error ("declaration of template %q#D", newdecl);
cp_error_at ("conflicts with previous declaration %q#D",
olddecl);
}
else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl))
&& same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
TREE_TYPE (TREE_TYPE (olddecl))))
{
error ("new declaration %q#D", newdecl);
cp_error_at ("ambiguates old declaration %q#D", olddecl);
}
return NULL_TREE;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
{
error ("declaration of C function %q#D conflicts with",
newdecl);
cp_error_at ("previous declaration %q#D here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
error ("new declaration %q#D", newdecl);
cp_error_at ("ambiguates old declaration %q#D", olddecl);
}
else
return NULL_TREE;
}
else
{
error ("conflicting declaration %q#D", newdecl);
cp_error_at ("%qD has a previous declaration as %q#D",
olddecl, olddecl);
return error_mark_node;
}
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
&& (!DECL_TEMPLATE_INFO (newdecl)
|| (DECL_TI_TEMPLATE (newdecl)
!= DECL_TI_TEMPLATE (olddecl))))
|| (DECL_TEMPLATE_SPECIALIZATION (newdecl)
&& (!DECL_TEMPLATE_INFO (olddecl)
|| (DECL_TI_TEMPLATE (olddecl)
!= DECL_TI_TEMPLATE (newdecl))))))
return NULL_TREE;
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_USE_TEMPLATE (newdecl))
|| (DECL_TEMPLATE_INSTANTIATION (newdecl)
&& !DECL_USE_TEMPLATE (olddecl))))
return NULL_TREE;
else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
{
if (DECL_NAMESPACE_ALIAS (newdecl)
&& (DECL_NAMESPACE_ALIAS (newdecl)
== DECL_NAMESPACE_ALIAS (olddecl)))
return olddecl;
error ("declaration of namespace %qD conflicts with", newdecl);
cp_error_at ("previous declaration of namespace %qD here", olddecl);
return error_mark_node;
}
else
{
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
error (errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
&& namespace_bindings_p ())
? "%q#D previously defined here"
: "%q#D previously declared here", olddecl);
return error_mark_node;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != NULL_TREE
&& TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
{
cp_warning_at ("prototype for %q#D", newdecl);
warning ("%Jfollows non-prototype definition here", olddecl);
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
{
if (current_lang_depth () == 0)
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
else
{
cp_error_at ("previous declaration of %q#D with %qL linkage",
olddecl, DECL_LANGUAGE (olddecl));
error ("conflicts with new declaration with %qL linkage",
DECL_LANGUAGE (newdecl));
}
}
if (DECL_LANG_SPECIFIC (olddecl) && DECL_USE_TEMPLATE (olddecl))
;
else if (TREE_CODE (olddecl) == FUNCTION_DECL)
{
tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
int i = 1;
if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
for (; t1 && t1 != void_list_node;
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
{
if (1 == simple_cst_equal (TREE_PURPOSE (t1),
TREE_PURPOSE (t2)))
{
pedwarn ("default argument given for parameter %d of %q#D",
i, newdecl);
cp_pedwarn_at ("after previous specification in %q#D",
olddecl);
}
else
{
error ("default argument given for parameter %d of %q#D",
i, newdecl);
cp_error_at ("after previous specification in %q#D",
olddecl);
}
}
if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& TREE_ADDRESSABLE (olddecl) && warn_inline)
{
warning ("%q#D was used before it was declared inline", newdecl);
warning ("%Jprevious non-inline declaration here", olddecl);
}
}
}
if (TREE_CODE (olddecl) == TYPE_DECL
&& (DECL_IMPLICIT_TYPEDEF_P (olddecl)
|| DECL_IMPLICIT_TYPEDEF_P (newdecl)))
return NULL_TREE;
warn_extern_redeclared_static (newdecl, olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_VINDEX (olddecl))
DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl);
if (DECL_CONTEXT (olddecl))
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
SET_OVERLOADED_OPERATOR_CODE
(newdecl, DECL_OVERLOADED_OPERATOR_P (olddecl));
new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
&& ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
{
warning ("redundant redeclaration of %qD in same scope", newdecl);
cp_warning_at ("previous declaration of %qD", olddecl);
}
}
if (TREE_CODE (olddecl) == TYPE_DECL)
{
tree newtype = TREE_TYPE (newdecl);
tree oldtype = TREE_TYPE (olddecl);
if (newtype != error_mark_node && oldtype != error_mark_node
&& TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
CLASSTYPE_FRIEND_CLASSES (newtype)
= CLASSTYPE_FRIEND_CLASSES (oldtype);
DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl);
}
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
{
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
= DECL_SOURCE_LOCATION (newdecl);
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (olddecl))
= DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (newdecl));
}
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
{
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));
}
return olddecl;
}
if (types_match)
{
tree oldtype = TREE_TYPE (olddecl);
tree newtype;
newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
if (TREE_CODE (newdecl) == TYPE_DECL
&& newtype == DECL_ORIGINAL_TYPE (newdecl))
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
{
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
!= TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
{
TREE_TYPE (newdecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
TREE_TYPE (olddecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (oldtype));
if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
&& ! DECL_IS_BUILTIN (olddecl)
&& flag_exceptions
&& !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
{
error ("declaration of %qF throws different exceptions",
newdecl);
cp_error_at ("than previous declaration %qF", olddecl);
}
}
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
if (! same_type_p (newtype, oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
if ((TREE_CODE (newdecl) == VAR_DECL
|| TREE_CODE (newdecl) == PARM_DECL
|| TREE_CODE (newdecl) == RESULT_DECL
|| TREE_CODE (newdecl) == FIELD_DECL
|| TREE_CODE (newdecl) == TYPE_DECL)
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_decl (newdecl, 0);
if (TREE_READONLY (newdecl))
TREE_READONLY (olddecl) = 1;
if (TREE_THIS_VOLATILE (newdecl))
TREE_THIS_VOLATILE (olddecl) = 1;
if (TREE_NOTHROW (newdecl))
TREE_NOTHROW (olddecl) = 1;
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
if (DECL_INITIAL (newdecl) == NULL_TREE
&& DECL_INITIAL (olddecl) != NULL_TREE)
{
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
if (CAN_HAVE_FULL_LANG_DECL_P (newdecl)
&& DECL_LANG_SPECIFIC (newdecl)
&& DECL_LANG_SPECIFIC (olddecl))
{
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
}
}
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= 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);
COPY_DECL_RTL (olddecl, newdecl);
}
else if (TREE_CODE (newdecl) == VAR_DECL
&& (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
{
COPY_DECL_RTL (olddecl, newdecl);
}
}
else
{
tree oldstatic = value_member (olddecl, static_aggregates);
if (oldstatic)
TREE_VALUE (oldstatic) = error_mark_node;
TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
}
merge_weak (newdecl, olddecl);
DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl);
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0;
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);
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
if (DECL_IMPLICIT_INSTANTIATION (olddecl)
&& !DECL_USE_TEMPLATE (newdecl))
SET_DECL_IMPLICIT_INSTANTIATION (newdecl);
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
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);
olddecl_friend = DECL_FRIEND_P (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (newdecl))
{
DECL_BEFRIENDING_CLASSES (newdecl)
= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
DECL_BEFRIENDING_CLASSES (olddecl));
if (DECL_VIRTUAL_P (newdecl))
DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
}
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_TEMPLATE_INSTANTIATION (newdecl))
{
gcc_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl));
if (TREE_USED (olddecl))
error ("explicit specialization of %qD after first use",
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
}
else
{
if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
DECL_INLINE (olddecl) = 1;
DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
}
DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
if (! types_match)
{
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl);
COPY_DECL_RTL (newdecl, olddecl);
}
if (! types_match || new_defines_function)
{
DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
}
if (new_defines_function)
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
else if (types_match)
{
if (DECL_BUILT_IN (olddecl))
{
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
COPY_DECL_RTL (olddecl, newdecl);
}
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
if (DECL_ARGUMENTS (olddecl))
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
}
}
else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl);
TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
if (DECL_VISIBILITY_SPECIFIED (olddecl)
&& DECL_VISIBILITY_SPECIFIED (newdecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
warning ("%J%qD: visibility attribute ignored because it",
newdecl, newdecl);
warning ("%Jconflicts with previous declaration here", olddecl);
}
if (DECL_VISIBILITY_SPECIFIED (olddecl))
{
DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
}
if (DECL_LANG_SPECIFIC (olddecl))
{
gcc_assert (DECL_LANG_SPECIFIC (olddecl)
!= DECL_LANG_SPECIFIC (newdecl));
ggc_free (DECL_LANG_SPECIFIC (olddecl));
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
function_size = sizeof (struct tree_decl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
function_size - sizeof (struct tree_common));
if (DECL_TEMPLATE_INSTANTIATION (newdecl))
reregister_specialization (newdecl,
DECL_TI_TEMPLATE (newdecl),
olddecl);
}
else
{
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common)
+ TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
}
DECL_UID (olddecl) = olddecl_uid;
if (olddecl_friend)
DECL_FRIEND_P (olddecl) = 1;
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
if (DECL_RTL_SET_P (olddecl)
&& (TREE_CODE (olddecl) == FUNCTION_DECL
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl);
ggc_free (newdecl);
return olddecl;
}
static const char *
redeclaration_error_message (tree newdecl, tree olddecl)
{
if (TREE_CODE (newdecl) == TYPE_DECL)
{
if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
return 0;
else
return "redefinition of %q#D";
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl)
&& DECL_INITIAL (olddecl) == NULL_TREE)
return 0;
if (DECL_NAMESPACE_SCOPE_P (olddecl)
&& DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)
&& ! decls_match (olddecl, newdecl))
return "%qD conflicts with used function";
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
if (DECL_NAME (olddecl) == NULL_TREE)
return "%q#D not declared in class";
else
return "redefinition of %q#D";
}
return 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
tree nt, ot;
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
{
if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
&& COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
return "redefinition of %q#D";
return NULL;
}
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL
|| (DECL_TEMPLATE_RESULT (newdecl)
== DECL_TEMPLATE_RESULT (olddecl)))
return NULL;
nt = DECL_TEMPLATE_RESULT (newdecl);
if (DECL_TEMPLATE_INFO (nt))
nt = DECL_TEMPLATE_RESULT (template_for_substitution (nt));
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))
return "redefinition of %q#D";
return NULL;
}
else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
{
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
return "redefinition of %q#D";
}
else
{
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
return "redeclaration of %q#D";
return 0;
}
}
static tree
make_label_decl (tree id, int local_p)
{
tree decl;
decl = build_decl (LABEL_DECL, id, void_type_node);
DECL_CONTEXT (decl) = current_function_decl;
DECL_MODE (decl) = VOIDmode;
C_DECLARED_LABEL_FLAG (decl) = local_p;
DECL_SOURCE_LOCATION (decl) = input_location;
SET_IDENTIFIER_LABEL_VALUE (id, decl);
return decl;
}
static void
use_label (tree decl)
{
if (named_label_uses == NULL
|| named_label_uses->names_in_scope != current_binding_level->names
|| named_label_uses->label_decl != decl)
{
struct named_label_use_list *new_ent;
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;
new_ent->o_goto_locus = input_location;
new_ent->next = named_label_uses;
named_label_uses = new_ent;
}
}
tree
lookup_label (tree id)
{
tree decl;
struct named_label_list *ent;
timevar_push (TV_NAME_LOOKUP);
if (current_function_decl == NULL_TREE)
{
error ("label %qE referenced outside of any function", id);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
decl = IDENTIFIER_LABEL_VALUE (id);
if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
ent = GGC_CNEW (struct named_label_list);
ent->old_value = IDENTIFIER_LABEL_VALUE (id);
ent->next = named_labels;
named_labels = ent;
decl = make_label_decl (id, 0);
ent->label_decl = decl;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
tree
declare_local_label (tree id)
{
tree decl;
current_binding_level->shadowed_labels
= tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
current_binding_level->shadowed_labels);
decl = make_label_decl (id, 1);
TREE_VALUE (current_binding_level->shadowed_labels) = decl;
return decl;
}
static int
decl_jump_unsafe (tree decl)
{
if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
return 0;
if (DECL_INITIAL (decl) == NULL_TREE
&& pod_type_p (TREE_TYPE (decl)))
return 0;
if (DECL_INITIAL (decl)
|| (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
return 2;
return 1;
}
static void
check_previous_goto_1 (tree decl,
struct cp_binding_level* level,
tree names, const location_t *locus)
{
int identified = 0;
int saw_eh = 0;
struct cp_binding_level *b = current_binding_level;
for (; b; b = b->level_chain)
{
tree new_decls = b->names;
tree old_decls = (b == level ? names : NULL_TREE);
for (; new_decls != old_decls;
new_decls = TREE_CHAIN (new_decls))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
continue;
if (! identified)
{
if (decl)
pedwarn ("jump to label %qD", decl);
else
pedwarn ("jump to case label");
if (locus)
pedwarn ("%H from here", locus);
identified = 1;
}
if (problem > 1)
cp_error_at (" crosses initialization of %q#D",
new_decls);
else
cp_pedwarn_at (" enters scope of non-POD %q#D",
new_decls);
}
if (b == level)
break;
if ((b->kind == sk_try || b->kind == sk_catch) && ! saw_eh)
{
if (! identified)
{
if (decl)
pedwarn ("jump to label %qD", decl);
else
pedwarn ("jump to case label");
if (locus)
pedwarn ("%H from here", locus);
identified = 1;
}
if (b->kind == sk_try)
error (" enters try block");
else
error (" enters catch block");
saw_eh = 1;
}
}
}
static void
check_previous_goto (struct named_label_use_list* use)
{
check_previous_goto_1 (use->label_decl, use->binding_level,
use->names_in_scope, &use->o_goto_locus);
}
static void
check_switch_goto (struct cp_binding_level* level)
{
check_previous_goto_1 (NULL_TREE, level, level->names, NULL);
}
static void
check_previous_gotos (tree decl)
{
struct named_label_use_list **usep;
if (! TREE_USED (decl))
return;
for (usep = &named_label_uses; *usep; )
{
struct named_label_use_list *use = *usep;
if (use->label_decl == decl)
{
check_previous_goto (use);
*usep = use->next;
}
else
usep = &(use->next);
}
}
void
check_goto (tree decl)
{
int identified = 0;
tree bad;
struct named_label_list *lab;
if (! DECL_P (decl))
return;
if (! DECL_INITIAL (decl))
{
use_label (decl);
return;
}
for (lab = named_labels; lab; lab = lab->next)
if (decl == lab->label_decl)
break;
if (lab == 0)
return;
if ((lab->in_try_scope || lab->in_catch_scope || lab->bad_decls)
&& !identified)
{
cp_pedwarn_at ("jump to label %qD", decl);
pedwarn (" from here");
identified = 1;
}
for (bad = lab->bad_decls; bad; bad = TREE_CHAIN (bad))
{
tree b = TREE_VALUE (bad);
int u = decl_jump_unsafe (b);
if (u > 1 && DECL_ARTIFICIAL (b))
error ("%J enters catch block", b);
else if (u > 1)
cp_error_at (" skips initialization of %q#D", b);
else
cp_pedwarn_at (" enters scope of non-POD %q#D", b);
}
if (lab->in_try_scope)
error (" enters try block");
else if (lab->in_catch_scope)
error (" enters catch block");
}
tree
define_label (location_t location, tree name)
{
tree decl = lookup_label (name);
struct named_label_list *ent;
struct cp_binding_level *p;
timevar_push (TV_NAME_LOOKUP);
for (ent = named_labels; ent; ent = ent->next)
if (ent->label_decl == decl)
break;
for (p = current_binding_level;
p->kind != sk_function_parms;
p = p->level_chain)
p->more_cleanups_ok = 0;
if (name == get_identifier ("wchar_t"))
pedwarn ("label named wchar_t");
if (DECL_INITIAL (decl) != NULL_TREE)
error ("duplicate label %qD", decl);
else
{
DECL_INITIAL (decl) = error_mark_node;
DECL_SOURCE_LOCATION (decl) = location;
if (ent)
{
ent->names_in_scope = current_binding_level->names;
ent->binding_level = current_binding_level;
}
check_previous_gotos (decl);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
struct cp_switch
{
struct cp_binding_level *level;
struct cp_switch *next;
tree switch_stmt;
splay_tree cases;
};
static struct cp_switch *switch_stack;
void
push_switch (tree switch_stmt)
{
struct cp_switch *p = xmalloc (sizeof (struct cp_switch));
p->level = current_binding_level;
p->next = switch_stack;
p->switch_stmt = switch_stmt;
p->cases = splay_tree_new (case_compare, NULL, NULL);
switch_stack = p;
}
void
pop_switch (void)
{
struct cp_switch *cs = switch_stack;
c_do_switch_warnings (cs->cases, cs->switch_stmt);
splay_tree_delete (cs->cases);
switch_stack = switch_stack->next;
free (cs);
}
tree
finish_case_label (tree low_value, tree high_value)
{
tree cond, r;
struct cp_binding_level *p;
if (processing_template_decl)
{
tree label;
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
return add_stmt (build_case_label (low_value, high_value, label));
}
cond = SWITCH_STMT_COND (switch_stack->switch_stmt);
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
r = c_add_case_label (switch_stack->cases, cond, TREE_TYPE (cond),
low_value, high_value);
check_switch_goto (switch_stack->level);
for (p = current_binding_level;
p->kind != sk_function_parms;
p = p->level_chain)
p->more_cleanups_ok = 0;
return r;
}
static hashval_t
typename_hash (const void* k)
{
hashval_t hash;
tree t = (tree) k;
hash = (htab_hash_pointer (TYPE_CONTEXT (t))
^ htab_hash_pointer (DECL_NAME (TYPE_NAME (t))));
return hash;
}
typedef struct typename_info {
tree scope;
tree name;
tree template_id;
bool enum_p;
bool class_p;
} typename_info;
static int
typename_compare (const void * k1, const void * k2)
{
tree t1;
const typename_info *t2;
t1 = (tree) k1;
t2 = (const typename_info *) k2;
return (DECL_NAME (TYPE_NAME (t1)) == t2->name
&& TYPE_CONTEXT (t1) == t2->scope
&& TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
&& TYPENAME_IS_ENUM_P (t1) == t2->enum_p
&& TYPENAME_IS_CLASS_P (t1) == t2->class_p);
}
static GTY ((param_is (union tree_node))) htab_t typename_htab;
static tree
build_typename_type (tree context, tree name, tree fullname,
enum tag_types tag_type)
{
tree t;
tree d;
typename_info ti;
void **e;
hashval_t hash;
if (typename_htab == NULL)
typename_htab = htab_create_ggc (61, &typename_hash,
&typename_compare, NULL);
ti.scope = FROB_CONTEXT (context);
ti.name = name;
ti.template_id = fullname;
ti.enum_p = tag_type == enum_type;
ti.class_p = (tag_type == class_type
|| tag_type == record_type
|| tag_type == union_type);
hash = (htab_hash_pointer (ti.scope)
^ htab_hash_pointer (ti.name));
e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT);
if (*e)
t = (tree) *e;
else
{
t = make_aggr_type (TYPENAME_TYPE);
TYPE_CONTEXT (t) = ti.scope;
TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
TYPENAME_IS_ENUM_P (t) = ti.enum_p;
TYPENAME_IS_CLASS_P (t) = ti.class_p;
d = build_decl (TYPE_DECL, name, t);
TYPE_NAME (TREE_TYPE (d)) = d;
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
DECL_ARTIFICIAL (d) = 1;
*e = t;
}
return t;
}
tree
make_typename_type (tree context, tree name, enum tag_types tag_type,
tsubst_flags_t complain)
{
tree fullname;
if (name == error_mark_node
|| context == NULL_TREE
|| context == error_mark_node)
return error_mark_node;
if (TYPE_P (name))
{
if (!(TYPE_LANG_SPECIFIC (name)
&& (CLASSTYPE_IS_TEMPLATE (name)
|| CLASSTYPE_USE_TEMPLATE (name))))
name = TYPE_IDENTIFIER (name);
else
name = build_nt (TEMPLATE_ID_EXPR,
CLASSTYPE_TI_TEMPLATE (name),
CLASSTYPE_TI_ARGS (name));
}
else if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
fullname = name;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
name = TREE_OPERAND (name, 0);
if (TREE_CODE (name) == TEMPLATE_DECL)
name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);
}
if (TREE_CODE (name) == TEMPLATE_DECL)
{
error ("%qD used without template parameters", name);
return error_mark_node;
}
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
gcc_assert (TYPE_P (context));
if (!dependent_type_p (context)
|| currently_open_class (context))
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
{
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
error ("no class template named %q#T in %q#T",
name, context);
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
NULL_TREE, context,
0,
tf_error | tf_warning | tf_user);
}
else
{
tree t;
if (!IS_AGGR_TYPE (context))
{
if (complain & tf_error)
error ("no type named %q#T in %q#T", name, context);
return error_mark_node;
}
t = lookup_field (context, name, 0, true);
if (t)
{
if (TREE_CODE (t) != TYPE_DECL)
{
if (complain & tf_error)
error ("no type named %q#T in %q#T", name, context);
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), t);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
return t;
}
}
}
if (!dependent_type_p (context))
{
if (complain & tf_error)
error ("no type named %q#T in %q#T", name, context);
return error_mark_node;
}
return build_typename_type (context, name, fullname, tag_type);
}
tree
make_unbound_class_template (tree context, tree name, tree parm_list,
tsubst_flags_t complain)
{
tree t;
tree d;
if (TYPE_P (name))
name = TYPE_IDENTIFIER (name);
else if (DECL_P (name))
name = DECL_NAME (name);
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
if (!dependent_type_p (context)
|| currently_open_class (context))
{
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
error ("no class template named %q#T in %q#T", name, context);
return error_mark_node;
}
if (parm_list
&& !comp_template_parms (DECL_TEMPLATE_PARMS (tmpl), parm_list))
{
if (complain & tf_error)
{
error ("template parameters do not match template");
cp_error_at ("%qD declared here", tmpl);
}
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
return tmpl;
}
t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
TREE_TYPE (t) = NULL_TREE;
d = build_decl (TEMPLATE_DECL, name, t);
TYPE_NAME (TREE_TYPE (d)) = d;
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
DECL_ARTIFICIAL (d) = 1;
DECL_TEMPLATE_PARMS (d) = parm_list;
return t;
}
void
record_builtin_type (enum rid rid_index,
const char* name,
tree type)
{
tree rname = NULL_TREE, tname = NULL_TREE;
tree tdecl = NULL_TREE;
if ((int) rid_index < (int) RID_MAX)
rname = ridpointers[(int) rid_index];
if (name)
tname = get_identifier (name);
if (tname)
{
tdecl = build_decl (TYPE_DECL, tname, type);
DECL_ARTIFICIAL (tdecl) = 1;
SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
}
if (rname)
{
if (!tdecl)
{
tdecl = build_decl (TYPE_DECL, rname, type);
DECL_ARTIFICIAL (tdecl) = 1;
}
SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl);
}
if (!TYPE_NAME (type))
TYPE_NAME (type) = tdecl;
if (tdecl)
debug_hooks->type_decl (tdecl, 0);
}
static tree
record_builtin_java_type (const char* name, int size)
{
tree type, decl;
if (size > 0)
type = make_signed_type (size);
else if (size > -32)
{
type = make_unsigned_type (-size);
}
else
{
type = make_node (REAL_TYPE);
TYPE_PRECISION (type) = - size;
layout_type (type);
}
record_builtin_type (RID_MAX, name, type);
decl = TYPE_NAME (type);
DECL_IGNORED_P (decl) = 1;
TYPE_FOR_JAVA (type) = 1;
return type;
}
static void
record_unknown_type (tree type, const char* name)
{
tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
DECL_IGNORED_P (decl) = 1;
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
TYPE_SIZE (type) = TYPE_SIZE (void_type_node);
TYPE_ALIGN (type) = 1;
TYPE_USER_ALIGN (type) = 0;
TYPE_MODE (type) = TYPE_MODE (void_type_node);
}
typedef struct predefined_identifier
{
const char *const name;
tree *const node;
const int ctor_or_dtor_p;
} predefined_identifier;
static void
initialize_predefined_identifiers (void)
{
const predefined_identifier *pid;
static const predefined_identifier predefined_identifiers[] = {
{ "C++", &lang_name_cplusplus, 0 },
{ "C", &lang_name_c, 0 },
{ "Java", &lang_name_java, 0 },
{ "__ct ", &ctor_identifier, 1 },
{ "__base_ctor ", &base_ctor_identifier, 1 },
{ "__comp_ctor ", &complete_ctor_identifier, 1 },
{ "__dt ", &dtor_identifier, 1 },
{ "__comp_dtor ", &complete_dtor_identifier, 1 },
{ "__base_dtor ", &base_dtor_identifier, 1 },
{ "__deleting_dtor ", &deleting_dtor_identifier, 1 },
{ IN_CHARGE_NAME, &in_charge_identifier, 0 },
{ "nelts", &nelts_identifier, 0 },
{ THIS_NAME, &this_identifier, 0 },
{ VTABLE_DELTA_NAME, &delta_identifier, 0 },
{ VTABLE_PFN_NAME, &pfn_identifier, 0 },
{ "_vptr", &vptr_identifier, 0 },
{ "__vtt_parm", &vtt_parm_identifier, 0 },
{ "::", &global_scope_name, 0 },
{ "std", &std_identifier, 0 },
{ NULL, NULL, 0 }
};
for (pid = predefined_identifiers; pid->name; ++pid)
{
*pid->node = get_identifier (pid->name);
if (pid->ctor_or_dtor_p)
IDENTIFIER_CTOR_OR_DTOR_P (*pid->node) = 1;
}
}
void
cxx_init_decl_processing (void)
{
tree void_ftype;
tree void_ftype_ptr;
build_common_tree_nodes (flag_signed_char, false);
initialize_predefined_identifiers ();
push_to_top_level ();
current_function_decl = NULL_TREE;
current_binding_level = NULL;
gcc_assert (global_namespace == NULL_TREE);
global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
void_type_node);
begin_scope (sk_namespace, global_namespace);
current_lang_name = NULL_TREE;
if (!flag_permissive)
flag_pedantic_errors = 1;
if (!flag_no_inline)
{
flag_inline_trees = 1;
flag_no_inline = 1;
}
if (flag_inline_functions)
flag_inline_trees = 2;
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
&& force_align_functions_log < 1)
force_align_functions_log = 1;
current_lang_name = lang_name_c;
error_mark_list = build_tree_list (error_mark_node, error_mark_node);
TREE_TYPE (error_mark_list) = error_mark_node;
push_namespace (std_identifier);
std_node = current_namespace;
pop_namespace ();
c_common_nodes_and_builtins ();
java_byte_type_node = record_builtin_java_type ("__java_byte", 8);
java_short_type_node = record_builtin_java_type ("__java_short", 16);
java_int_type_node = record_builtin_java_type ("__java_int", 32);
java_long_type_node = record_builtin_java_type ("__java_long", 64);
java_float_type_node = record_builtin_java_type ("__java_float", -32);
java_double_type_node = record_builtin_java_type ("__java_double", -64);
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_cst (NULL_TREE, 2);
integer_three_node = build_int_cst (NULL_TREE, 3);
record_builtin_type (RID_BOOL, "bool", boolean_type_node);
truthvalue_type_node = boolean_type_node;
truthvalue_false_node = boolean_false_node;
truthvalue_true_node = boolean_true_node;
empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
#if 0
record_builtin_type (RID_MAX, NULL, string_type_node);
#endif
delta_type_node = ptrdiff_type_node;
vtable_index_type = ptrdiff_type_node;
vtt_parm_type = build_pointer_type (const_ptr_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,
void_list_node));
void_ftype_ptr
= build_exception_variant (void_ftype_ptr, empty_except_spec);
unknown_type_node = make_node (UNKNOWN_TYPE);
record_unknown_type (unknown_type_node, "unknown type");
TREE_TYPE (unknown_type_node) = unknown_type_node;
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
{
tree vfunc_type = make_node (FUNCTION_TYPE);
TREE_TYPE (vfunc_type) = integer_type_node;
TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
layout_type (vfunc_type);
vtable_entry_type = build_pointer_type (vfunc_type);
}
record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
vtbl_type_node
= build_cplus_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node);
vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, NULL, vtbl_type_node);
vtbl_ptr_type_node = build_pointer_type (vtable_entry_type);
layout_type (vtbl_ptr_type_node);
record_builtin_type (RID_MAX, NULL, vtbl_ptr_type_node);
push_namespace (get_identifier ("__cxxabiv1"));
abi_node = current_namespace;
pop_namespace ();
global_type_node = make_node (LANG_TYPE);
record_unknown_type (global_type_node, "global type");
current_lang_name = lang_name_cplusplus;
{
tree bad_alloc_id;
tree bad_alloc_type_node;
tree bad_alloc_decl;
tree newtype, deltype;
tree ptr_ftype_sizetype;
push_namespace (std_identifier);
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
= 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
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
size_type_node,
void_list_node));
newtype = build_exception_variant
(ptr_ftype_sizetype, add_exception_specifier
(NULL_TREE, bad_alloc_type_node, -1));
deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
push_cp_library_fn (NEW_EXPR, newtype);
push_cp_library_fn (VEC_NEW_EXPR, newtype);
global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
push_cp_library_fn (VEC_DELETE_EXPR, deltype);
}
abort_fndecl
= build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
init_class_processing ();
init_rtti_processing ();
if (flag_exceptions)
init_exception_processing ();
if (! supports_one_only ())
flag_weak = 0;
make_fname_decl = cp_make_fname_decl;
start_fname_decls ();
if (flag_exceptions)
using_eh_for_cleanups ();
}
tree
cp_fname_init (const char* name, tree *type_p)
{
tree domain = NULL_TREE;
tree type;
tree init = NULL_TREE;
size_t length = 0;
if (name)
{
length = strlen (name);
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;
}
static tree
cp_make_fname_decl (tree id, int type_dep)
{
const char *const name = (type_dep && processing_template_decl
? NULL : fname_as_string (type_dep));
tree type;
tree init = cp_fname_init (name, &type);
tree decl = build_decl (VAR_DECL, id, type);
if (name)
free ((char *) name);
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)
{
struct cp_binding_level *b = current_binding_level;
while (b->level_chain->kind != sk_function_parms)
b = b->level_chain;
pushdecl_with_scope (decl, b);
cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
}
else
pushdecl_top_level_and_finish (decl, init);
return decl;
}
static tree
builtin_function_1 (const char* name,
tree type,
tree context,
enum built_in_function code,
enum built_in_class class,
const char* libname,
tree attrs)
{
tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = code;
DECL_CONTEXT (decl) = context;
pushdecl (decl);
if (libname)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname));
if (name[0] != '_' || name[1] != '_')
DECL_ANTICIPATED (decl) = 1;
if (attrs)
decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
else
decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
tree
builtin_function (const char* name,
tree type,
int code,
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, cl, libname, attrs);
pop_namespace ();
}
return builtin_function_1 (name, type, NULL_TREE, code,
cl, libname, attrs);
}
static tree
build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
{
tree fn = build_lang_decl (FUNCTION_DECL, name, type);
DECL_EXTERNAL (fn) = 1;
TREE_PUBLIC (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
TREE_NOTHROW (fn) = 1;
SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
SET_DECL_LANGUAGE (fn, lang_c);
DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
DECL_VISIBILITY_SPECIFIED (fn) = 1;
return fn;
}
tree
build_library_fn (tree name, tree type)
{
return build_library_fn_1 (name, ERROR_MARK, type);
}
static tree
build_cp_library_fn (tree name, enum tree_code operator_code, tree type)
{
tree fn = build_library_fn_1 (name, operator_code, type);
TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);
SET_DECL_LANGUAGE (fn, lang_cplusplus);
return fn;
}
tree
build_library_fn_ptr (const char* name, tree type)
{
return build_library_fn (get_identifier (name), type);
}
tree
build_cp_library_fn_ptr (const char* name, tree type)
{
return build_cp_library_fn (get_identifier (name), ERROR_MARK, type);
}
tree
push_library_fn (tree name, tree type)
{
tree fn = build_library_fn (name, type);
pushdecl_top_level (fn);
return fn;
}
static tree
push_cp_library_fn (enum tree_code operator_code, tree type)
{
tree fn = build_cp_library_fn (ansi_opname (operator_code),
operator_code,
type);
pushdecl (fn);
return fn;
}
tree
push_void_library_fn (tree name, tree parmtypes)
{
tree type = build_function_type (void_type_node, parmtypes);
return push_library_fn (name, type);
}
tree
push_throw_library_fn (tree name, tree type)
{
tree fn = push_library_fn (name, type);
TREE_THIS_VOLATILE (fn) = 1;
TREE_NOTHROW (fn) = 0;
return fn;
}
void
fixup_anonymous_aggr (tree t)
{
tree *q;
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0;
TYPE_HAS_ASSIGN_REF (t) = 0;
TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
q = &TYPE_METHODS (t);
while (*q)
{
if (DECL_ARTIFICIAL (*q))
*q = TREE_CHAIN (*q);
else
q = &TREE_CHAIN (*q);
}
if (TYPE_METHODS (t))
error ("%Jan anonymous union cannot have function members",
TYPE_MAIN_DECL (t));
if (TREE_CODE (t) != UNION_TYPE)
{
tree field, type;
for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
type = TREE_TYPE (field);
if (CLASS_TYPE_P (type))
{
if (TYPE_NEEDS_CONSTRUCTING (type))
cp_error_at ("member %q#D with constructor not allowed "
"in anonymous aggregate",
field);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
cp_error_at ("member %q#D with destructor not allowed "
"in anonymous aggregate",
field);
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
cp_error_at ("member %q#D with copy assignment operator "
"not allowed in anonymous aggregate",
field);
}
}
}
}
tree
check_tag_decl (cp_decl_specifier_seq *declspecs)
{
int saw_friend = declspecs->specs[(int)ds_friend] != 0;
int saw_typedef = declspecs->specs[(int)ds_typedef] != 0;
tree declared_type = NULL_TREE;
bool error_p = false;
if (declspecs->multiple_types_p)
error ("multiple types in one declaration");
else if (declspecs->redefined_builtin_type)
{
if (!in_system_header)
pedwarn ("redeclaration of C++ built-in type %qT",
declspecs->redefined_builtin_type);
return NULL_TREE;
}
if (declspecs->type
&& TYPE_P (declspecs->type)
&& ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
&& IS_AGGR_TYPE (declspecs->type))
|| TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
declared_type = declspecs->type;
else if (declspecs->type == error_mark_node)
error_p = true;
if (declared_type == NULL_TREE && ! saw_friend && !error_p)
pedwarn ("declaration does not declare anything");
else if (declared_type && IS_AGGR_TYPE_CODE (TREE_CODE (declared_type))
&& TYPE_ANONYMOUS_P (declared_type))
{
if (saw_typedef)
{
error ("missing type-name in typedef-declaration");
return NULL_TREE;
}
;
SET_ANON_AGGR_TYPE_P (declared_type);
if (TREE_CODE (declared_type) != UNION_TYPE && pedantic
&& !in_system_header)
pedwarn ("ISO C++ prohibits anonymous structs");
}
else
{
if (declspecs->specs[(int)ds_inline]
|| declspecs->specs[(int)ds_virtual])
error ("%qs can only be specified for functions",
declspecs->specs[(int)ds_inline]
? "inline" : "virtual");
else if (saw_friend
&& (!current_class_type
|| current_scope () != current_class_type))
error ("%<friend%> can only be specified inside a class");
else if (declspecs->specs[(int)ds_explicit])
error ("%<explicit%> can only be specified for constructors");
else if (declspecs->storage_class)
error ("a storage class can only be specified for objects "
"and functions");
else if (declspecs->specs[(int)ds_const]
|| declspecs->specs[(int)ds_volatile]
|| declspecs->specs[(int)ds_restrict]
|| declspecs->specs[(int)ds_thread])
error ("qualifiers can only be specified for objects "
"and functions");
}
return declared_type;
}
tree
shadow_tag (cp_decl_specifier_seq *declspecs)
{
tree t = check_tag_decl (declspecs);
if (!t)
return NULL_TREE;
if (declspecs->attributes)
{
cp_warning_at ("attribute ignored in declaration of %q#T", t);
cp_warning_at ("attribute for %q#T must follow the %qs keyword",
t,
class_key_or_enum_as_string (t));
}
maybe_process_partial_specialization (t);
if (ANON_AGGR_TYPE_P (t))
{
fixup_anonymous_aggr (t);
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (NULL,
declspecs, NORMAL, 0, NULL);
finish_anon_union (decl);
}
}
return t;
}
tree
groktypename (cp_decl_specifier_seq *type_specifiers,
const cp_declarator *declarator)
{
tree attrs;
tree type;
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);
return type;
}
tree
start_decl (const cp_declarator *declarator,
cp_decl_specifier_seq *declspecs,
int initialized,
tree attributes,
tree prefix_attributes,
tree *pushed_scope_p)
{
tree decl;
tree type, tem;
tree context;
*pushed_scope_p = NULL_TREE;
if (have_extern_spec)
{
declspecs->storage_class = sc_extern;
have_extern_spec = false;
}
if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
attributes = chainon (attributes, prefix_attributes);
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
&attributes);
deprecated_state = DEPRECATED_NORMAL;
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return error_mark_node;
type = TREE_TYPE (decl);
if (type == error_mark_node)
return error_mark_node;
context = DECL_CONTEXT (decl);
if (context)
{
*pushed_scope_p = push_scope (context);
if (TREE_CODE (context) == NAMESPACE_DECL)
context = NULL_TREE;
}
if (initialized)
switch (TREE_CODE (decl))
{
case TYPE_DECL:
error ("typedef %qD is initialized (use __typeof__ instead)", decl);
initialized = 0;
break;
case FUNCTION_DECL:
error ("function %q#D is initialized like a variable", decl);
initialized = 0;
break;
default:
break;
}
if (initialized)
{
if (! toplevel_bindings_p ()
&& DECL_EXTERNAL (decl))
warning ("declaration of %q#D has %<extern%> and is initialized",
decl);
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
DECL_INITIAL (decl) = error_mark_node;
}
cplus_decl_attributes (&decl, attributes, 0);
maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
warning ("%Jinline function %qD given attribute noinline", decl, decl);
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
if (TREE_CODE (decl) == VAR_DECL)
{
tree field = lookup_field (context, DECL_NAME (decl), 0, false);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
error ("%q#D is not a static member of %q#T", decl, context);
else
{
if (DECL_CONTEXT (field) != context)
{
if (!same_type_p (DECL_CONTEXT (field), context))
pedwarn ("ISO C++ does not permit %<%T::%D%> "
"to be defined as %<%T::%D%>",
DECL_CONTEXT (field), DECL_NAME (decl),
context, DECL_NAME (decl));
DECL_CONTEXT (decl) = DECL_CONTEXT (field);
}
if (processing_specialization
&& template_class_depth (context) == 0
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (context))
error ("template header not allowed in member definition "
"of explicitly specialized class");
if (DECL_INITIAL (decl) && DECL_INITIAL (field))
error ("duplicate initialization of %qD", decl);
if (duplicate_decls (decl, field))
decl = field;
}
}
else
{
tree field = check_classfn (context, decl,
(processing_template_decl
> template_class_depth (context))
? current_template_parms
: NULL_TREE);
if (field && duplicate_decls (decl, field))
decl = field;
}
DECL_IN_AGGR_P (decl) = 0;
if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
|| CLASSTYPE_TEMPLATE_INSTANTIATION (context))
{
if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
if (DECL_INITIAL (decl) == NULL_TREE && processing_specialization)
DECL_EXTERNAL (decl) = 1;
}
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
pedwarn ("declaration of %q#D outside of class is not definition",
decl);
}
tem = maybe_push_decl (decl);
if (processing_template_decl)
tem = push_template_decl (tem);
if (tem == error_mark_node)
return error_mark_node;
#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
DECL_COMMON (tem) = ((TREE_CODE (tem) != VAR_DECL
|| !DECL_THREAD_LOCAL (tem))
&& (flag_conserve_space || ! TREE_PUBLIC (tem)));
#endif
if (! processing_template_decl)
start_decl_1 (tem);
return tem;
}
void
start_decl_1 (tree decl)
{
tree type = TREE_TYPE (decl);
int initialized = (DECL_INITIAL (decl) != NULL_TREE);
if (type == error_mark_node)
return;
if (initialized)
{
if (COMPLETE_TYPE_P (complete_type (type)))
;
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);
initialized = 0;
}
}
if (!initialized
&& TREE_CODE (decl) != TYPE_DECL
&& TREE_CODE (decl) != TEMPLATE_DECL
&& type != error_mark_node
&& IS_AGGR_TYPE (type)
&& ! DECL_EXTERNAL (decl))
{
if ((! processing_template_decl || ! uses_template_parms (type))
&& !COMPLETE_TYPE_P (complete_type (type)))
{
error ("aggregate %q#D has incomplete type and cannot be defined",
decl);
type = TREE_TYPE (decl) = error_mark_node;
}
else
{
initialized = TYPE_NEEDS_CONSTRUCTING (type);
}
}
if (! initialized)
DECL_INITIAL (decl) = NULL_TREE;
maybe_push_cleanup_level (type);
}
static tree
grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
{
tree tmp;
if (init == NULL_TREE)
{
if ((DECL_LANG_SPECIFIC (decl) == 0
|| DECL_IN_AGGR_P (decl) == 0)
&& ! DECL_THIS_EXTERN (decl))
error ("%qD declared as reference but not initialized", decl);
return NULL_TREE;
}
if (TREE_CODE (init) == CONSTRUCTOR)
{
error ("ISO C++ forbids use of initializer list to "
"initialize reference %qD", decl);
return NULL_TREE;
}
if (TREE_CODE (init) == TREE_LIST)
init = build_x_compound_expr_from_list (init, "initializer");
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
init = decay_conversion (init);
tmp = initialize_reference (type, init, decl, cleanup);
if (tmp == error_mark_node)
return NULL_TREE;
else if (tmp == NULL_TREE)
{
error ("cannot initialize %qT from %qT", type, TREE_TYPE (init));
return NULL_TREE;
}
if (TREE_STATIC (decl) && !TREE_CONSTANT (tmp))
return tmp;
DECL_INITIAL (decl) = tmp;
return NULL_TREE;
}
static void
maybe_deduce_size_from_array_init (tree decl, tree init)
{
tree type = TREE_TYPE (decl);
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE
&& TREE_CODE (decl) != TYPE_DECL)
{
int do_default = !DECL_EXTERNAL (decl);
tree initializer = init ? init : DECL_INITIAL (decl);
int failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
do_default);
if (failure == 1)
error ("initializer fails to determine size of %qD", decl);
if (failure == 2)
{
if (do_default)
error ("array size missing in %qD", decl);
else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
DECL_EXTERNAL (decl) = 1;
}
if (failure == 3)
error ("zero-size array %qD", decl);
layout_decl (decl, 0);
}
}
static void
layout_var_decl (tree decl)
{
tree type = TREE_TYPE (decl);
#if 0
tree ttype = target_type (type);
#endif
if (!DECL_EXTERNAL (decl))
complete_type (type);
if (!DECL_SIZE (decl)
&& TREE_TYPE (decl) != error_mark_node
&& (COMPLETE_TYPE_P (type)
|| (TREE_CODE (type) == ARRAY_TYPE
&& !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))))
layout_decl (decl, 0);
if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
{
error ("storage size of %qD isn't known", decl);
TREE_TYPE (decl) = error_mark_node;
}
#if 0
else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
note_debug_info_needed (ttype);
if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl))
note_debug_info_needed (DECL_CONTEXT (decl));
#endif
if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
&& DECL_SIZE (decl) != NULL_TREE
&& ! TREE_CONSTANT (DECL_SIZE (decl)))
{
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
error ("storage size of %qD isn't constant", decl);
}
if (TREE_STATIC (decl)
&& !DECL_ARTIFICIAL (decl)
&& current_function_decl
&& DECL_CONTEXT (decl) == current_function_decl)
push_local_name (decl);
}
static void
maybe_commonize_var (tree decl)
{
if (TREE_STATIC (decl)
&& ! DECL_ARTIFICIAL (decl)
&& DECL_FUNCTION_SCOPE_P (decl)
&& (DECL_COMDAT (DECL_CONTEXT (decl))
|| ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
|| DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
&& TREE_PUBLIC (DECL_CONTEXT (decl)))))
{
if (flag_weak)
{
comdat_linkage (decl);
}
else
{
if (DECL_INITIAL (decl) == NULL_TREE
|| DECL_INITIAL (decl) == error_mark_node)
{
TREE_PUBLIC (decl) = 1;
DECL_COMMON (decl) = 1;
}
else
{
TREE_PUBLIC (decl) = 0;
DECL_COMMON (decl) = 0;
cp_warning_at ("sorry: semantics of inline function static "
"data %q#D are wrong (you'll wind up "
"with multiple copies)", decl);
warning ("%J you can work around this by removing "
"the initializer",
decl);
}
}
}
else if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
comdat_linkage (decl);
}
static void
check_for_uninitialized_const_var (tree decl)
{
tree type = TREE_TYPE (decl);
if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
&& !TYPE_NEEDS_CONSTRUCTING (type)
&& !DECL_INITIAL (decl))
error ("uninitialized const %qD", decl);
}
static tree
next_initializable_field (tree field)
{
while (field
&& (TREE_CODE (field) != FIELD_DECL
|| (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
|| DECL_ARTIFICIAL (field)))
field = TREE_CHAIN (field);
return field;
}
static bool
reshape_init_array (tree elt_type, tree max_index,
tree *initp, tree new_init)
{
bool sized_array_p = (max_index != NULL_TREE);
unsigned HOST_WIDE_INT max_index_cst = 0;
unsigned HOST_WIDE_INT index;
if (sized_array_p)
{
if (host_integerp (max_index, 1))
max_index_cst = tree_low_cst (max_index, 1);
else
max_index_cst = tree_low_cst (fold_convert (size_type_node, max_index),
1);
}
for (index = 0;
*initp && (!sized_array_p || index <= max_index_cst);
++index)
{
tree element_init;
tree designated_index;
element_init = reshape_init (elt_type, initp);
if (element_init == error_mark_node)
return false;
TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
CONSTRUCTOR_ELTS (new_init) = element_init;
designated_index = TREE_PURPOSE (element_init);
if (designated_index)
{
if (TREE_CODE (designated_index) == IDENTIFIER_NODE)
{
error ("name %qD used in a GNU-style designated "
"initializer for an array", designated_index);
TREE_PURPOSE (element_init) = NULL_TREE;
}
else
gcc_unreachable ();
}
}
return true;
}
static tree
reshape_init (tree type, tree *initp)
{
tree inits;
tree old_init;
tree old_init_value;
tree new_init;
bool brace_enclosed_p;
bool string_init_p;
old_init = *initp;
old_init_value = (TREE_CODE (*initp) == TREE_LIST
? TREE_VALUE (*initp) : old_init);
gcc_assert (old_init_value);
if (TREE_CODE (old_init_value) == CONSTRUCTOR
&& BRACE_ENCLOSED_INITIALIZER_P (old_init_value))
{
*initp = TREE_CHAIN (old_init);
TREE_CHAIN (old_init) = NULL_TREE;
inits = CONSTRUCTOR_ELTS (old_init_value);
initp = &inits;
brace_enclosed_p = true;
}
else
{
inits = NULL_TREE;
brace_enclosed_p = false;
}
if (!CP_AGGREGATE_TYPE_P (type))
{
*initp = TREE_CHAIN (old_init);
TREE_CHAIN (old_init) = NULL_TREE;
if (brace_enclosed_p)
{
error ("brace-enclosed initializer used to initialize %qT",
type);
if (TREE_CODE (old_init) == TREE_LIST)
TREE_VALUE (old_init) = error_mark_node;
else
old_init = error_mark_node;
}
return old_init;
}
if (!brace_enclosed_p
&& can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value))
{
*initp = TREE_CHAIN (old_init);
TREE_CHAIN (old_init) = NULL_TREE;
return old_init;
}
string_init_p = false;
if (TREE_CODE (old_init_value) == STRING_CST
&& TREE_CODE (type) == ARRAY_TYPE
&& char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
{
new_init = old_init;
*initp = TREE_CHAIN (old_init);
TREE_CHAIN (old_init) = NULL_TREE;
string_init_p = true;
}
else
{
new_init = build_constructor (NULL_TREE, NULL_TREE);
if (CLASS_TYPE_P (type))
{
tree field;
field = next_initializable_field (TYPE_FIELDS (type));
if (!field)
{
if (!brace_enclosed_p)
{
error ("initializer for %qT must be brace-enclosed", type);
return error_mark_node;
}
}
else
{
while (*initp)
{
tree field_init;
if (TREE_PURPOSE (*initp))
{
if (pedantic)
pedwarn ("ISO C++ does not allow designated initializers");
field = lookup_field_1 (type, TREE_PURPOSE (*initp),
false);
if (!field || TREE_CODE (field) != FIELD_DECL)
error ("%qT has no non-static data member named %qD",
type, TREE_PURPOSE (*initp));
}
if (!field)
break;
field_init = reshape_init (TREE_TYPE (field), initp);
if (field_init == error_mark_node)
return error_mark_node;
TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
CONSTRUCTOR_ELTS (new_init) = field_init;
if (TREE_CODE (type) == UNION_TYPE)
break;
field = next_initializable_field (TREE_CHAIN (field));
}
}
}
else if (TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == VECTOR_TYPE)
{
tree max_index = NULL_TREE;
if (TREE_CODE (type) == ARRAY_TYPE)
{
if (TYPE_DOMAIN (type))
max_index = array_type_nelts (type);
}
else
{
tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS
(rtype)));
}
if (!reshape_init_array (TREE_TYPE (type), max_index,
initp, new_init))
return error_mark_node;
}
else
gcc_unreachable ();
CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));
if (TREE_CODE (old_init) == TREE_LIST)
new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
}
if (*initp)
{
if (brace_enclosed_p)
error ("too many initializers for %qT", type);
else if (warn_missing_braces && !string_init_p)
warning ("missing braces around initializer");
}
return new_init;
}
static tree
check_initializer (tree decl, tree init, int flags, tree *cleanup)
{
tree type = TREE_TYPE (decl);
tree init_code = NULL;
if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
init = NULL_TREE;
DECL_INITIAL (decl) = NULL_TREE;
TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
if (type == error_mark_node)
init = NULL_TREE;
else if (init && COMPLETE_TYPE_P (type)
&& !TREE_CONSTANT (TYPE_SIZE (type)))
{
error ("variable-sized object %qD may not be initialized", decl);
init = NULL_TREE;
}
else if (TREE_CODE (type) == ARRAY_TYPE
&& !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
{
error ("elements of array %q#D have incomplete type", decl);
init = NULL_TREE;
}
else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
error ("%qD has incomplete type", decl);
TREE_TYPE (decl) = error_mark_node;
init = NULL_TREE;
}
if (TREE_CODE (decl) == CONST_DECL)
{
gcc_assert (TREE_CODE (decl) != REFERENCE_TYPE);
DECL_INITIAL (decl) = init;
gcc_assert (init != NULL_TREE);
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
init = grok_reference_init (decl, type, init, cleanup);
else if (init)
{
if (TREE_CODE (init) == CONSTRUCTOR
&& BRACE_ENCLOSED_INITIALIZER_P (init))
{
if (CP_AGGREGATE_TYPE_P (type))
init = reshape_init (type, &init);
if ((*targetm.vector_opaque_p) (type))
{
error ("opaque vector types cannot be initialized");
init = error_mark_node;
}
}
maybe_deduce_size_from_array_init (decl, init);
type = TREE_TYPE (decl);
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
goto initialize_aggr;
else if (TREE_CODE (init) == CONSTRUCTOR
&& BRACE_ENCLOSED_INITIALIZER_P (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
error ("%qD must be initialized by constructor, "
"not by %<{...}%>",
decl);
init = error_mark_node;
}
else
goto dont_use_constructor;
}
else
{
int saved_stmts_are_full_exprs_p;
initialize_aggr:
saved_stmts_are_full_exprs_p = 0;
if (building_stmt_tree ())
{
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);
if (building_stmt_tree ())
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
return init;
}
}
else
{
dont_use_constructor:
if (TREE_CODE (init) != TREE_VEC)
{
init_code = store_init_value (decl, init);
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
&& PAREN_STRING_LITERAL_P (DECL_INITIAL (decl)))
warning ("array %qD initialized by parenthesized string literal %qE",
decl, DECL_INITIAL (decl));
init = NULL;
}
}
}
else if (DECL_EXTERNAL (decl))
;
else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
goto initialize_aggr;
else if (IS_AGGR_TYPE (type))
{
tree core_type = strip_array_types (type);
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
error ("structure %qD with uninitialized const members", decl);
if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
error ("structure %qD with uninitialized reference members", decl);
check_for_uninitialized_const_var (decl);
}
else
check_for_uninitialized_const_var (decl);
if (init && init != error_mark_node)
init_code = build2 (INIT_EXPR, type, decl, init);
return init_code;
}
static void
make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
{
int toplev = toplevel_bindings_p ();
int defer_p;
if (asmspec)
{
if (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
{
change_decl_assembler_name (decl, get_identifier (asmspec));
DECL_HARD_REGISTER (decl) = 1;
}
else
{
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
set_builtin_user_assembler_name (decl, asmspec);
set_user_assembler_name (decl, asmspec);
}
}
if (TREE_CODE (decl) != VAR_DECL)
{
rest_of_decl_compilation (decl, toplev, at_eof);
return;
}
if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl))
{
gcc_assert (TREE_STATIC (decl));
if (init == NULL_TREE)
gcc_assert (DECL_EXTERNAL (decl));
}
if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))
return;
defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl);
if (!DECL_VIRTUAL_P (decl)
&& TREE_READONLY (decl)
&& DECL_INITIAL (decl) != NULL_TREE
&& DECL_INITIAL (decl) != error_mark_node
&& ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))
&& toplev
&& !TREE_PUBLIC (decl))
{
struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
if (!finfo->interface_unknown && !TREE_PUBLIC (decl))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = finfo->interface_only;
}
defer_p = 1;
}
else if (DECL_LANG_SPECIFIC (decl)
&& DECL_IMPLICIT_INSTANTIATION (decl))
defer_p = 1;
if (!defer_p)
rest_of_decl_compilation (decl, toplev, at_eof);
}
static void
initialize_local_var (tree decl, tree init)
{
tree type = TREE_TYPE (decl);
tree cleanup;
gcc_assert (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == RESULT_DECL);
gcc_assert (!TREE_STATIC (decl));
if (DECL_SIZE (decl) == NULL_TREE)
{
DECL_INITIAL (decl) = NULL_TREE;
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
}
if (DECL_SIZE (decl) && type != error_mark_node)
{
int already_used;
already_used = TREE_USED (decl) || TREE_USED (type);
if (init)
{
int saved_stmts_are_full_exprs_p;
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;
}
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;
}
cleanup = cxx_maybe_build_cleanup (decl);
if (DECL_SIZE (decl) && cleanup)
finish_decl_cleanup (decl, cleanup);
}
void
initialize_artificial_var (tree decl, tree init)
{
DECL_INITIAL (decl) = build_constructor (NULL_TREE, init);
DECL_INITIALIZED_P (decl) = 1;
determine_visibility (decl);
layout_var_decl (decl);
maybe_commonize_var (decl);
make_rtl_for_nonlocal_decl (decl, init, NULL);
}
void
cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
{
tree type;
tree ttype = NULL_TREE;
tree cleanup;
const char *asmspec = NULL;
int was_readonly = 0;
bool var_definition_p = false;
if (decl == error_mark_node)
return;
else if (! decl)
{
if (init)
error ("assignment (not initialization) in declaration");
return;
}
gcc_assert (TREE_CODE (decl) != RESULT_DECL);
cleanup = NULL_TREE;
if (global_scope_p (current_binding_level))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init && TREE_CODE (init) == NAMESPACE_DECL)
{
error ("cannot initialize %qD to namespace %qD", decl, init);
init = NULL_TREE;
}
if (current_class_type
&& CP_DECL_CONTEXT (decl) == current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
type = TREE_TYPE (decl);
if (type == error_mark_node)
goto finish_end;
if (processing_template_decl)
{
if (at_function_scope_p ())
add_decl_expr (decl);
if (init && DECL_INITIAL (decl))
DECL_INITIAL (decl) = init;
if (TREE_CODE (decl) == VAR_DECL
&& !DECL_PRETTY_FUNCTION_P (decl)
&& !dependent_type_p (TREE_TYPE (decl)))
maybe_deduce_size_from_array_init (decl, init);
goto finish_end;
}
gcc_assert (TREE_CODE (decl) != PARM_DECL);
if (TREE_CODE (decl) == TYPE_DECL)
{
if (type != error_mark_node
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
warning ("shadowing previous type declaration of %q#D", decl);
set_identifier_type_value (DECL_NAME (decl), decl);
}
if (TYPE_MAIN_DECL (TREE_TYPE (decl)) == decl
&& !COMPLETE_TYPE_P (TREE_TYPE (decl)))
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
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);
if (! DECL_EXTERNAL (decl)
&& TREE_READONLY (decl)
&& TREE_CODE (type) == REFERENCE_TYPE)
{
was_readonly = 1;
TREE_READONLY (decl) = 0;
}
if (TREE_CODE (decl) == VAR_DECL)
{
if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
error ("%qD cannot be thread-local because it has non-POD type %qT",
decl, TREE_TYPE (decl));
if (!DECL_INITIALIZED_P (decl)
&& (!DECL_EXTERNAL (decl) || init))
{
init = check_initializer (decl, init, flags, &cleanup);
if (DECL_THREAD_LOCAL (decl) && init)
{
error ("%qD is thread-local and so cannot be dynamically "
"initialized", decl);
init = NULL_TREE;
}
if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
NULL_TREE,
true);
DECL_INITIALIZED_P (decl) = 1;
if (!DECL_EXTERNAL (decl))
var_definition_p = true;
determine_visibility (decl);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
layout_type (type);
}
if (at_function_scope_p ())
add_decl_expr (decl);
if (TREE_CODE (decl) == VAR_DECL)
layout_var_decl (decl);
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
if (TREE_CODE (decl) == VAR_DECL)
maybe_commonize_var (decl);
make_rtl_for_nonlocal_decl (decl, init, asmspec);
if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
abstract_virtuals_error (decl, TREE_TYPE (type));
else
abstract_virtuals_error (decl, type);
if (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_TYPE (decl) == error_mark_node)
;
else if (DECL_EXTERNAL (decl)
&& ! (DECL_LANG_SPECIFIC (decl)
&& DECL_NOT_REALLY_EXTERN (decl)))
{
if (init)
DECL_INITIAL (decl) = init;
}
else
{
if (DECL_FUNCTION_SCOPE_P (decl))
{
if (processing_template_decl)
{
if (init || DECL_INITIAL (decl) == error_mark_node)
DECL_INITIAL (decl) = init;
}
else if (!TREE_STATIC (decl))
initialize_local_var (decl, init);
}
if (var_definition_p && TREE_STATIC (decl))
expand_static_init (decl, init);
}
}
if (cleanup)
push_cleanup (decl, cleanup, false);
finish_end:
if (was_readonly)
TREE_READONLY (decl) = 1;
if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
mark_decl_referenced (decl);
}
void
finish_decl (tree decl, tree init, tree asmspec_tree)
{
cp_finish_decl (decl, init, asmspec_tree, 0);
}
tree
declare_global_var (tree name, tree type)
{
tree decl;
push_to_top_level ();
decl = build_decl (VAR_DECL, name, type);
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
decl = pushdecl (decl);
cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
pop_from_top_level ();
return decl;
}
static tree
get_atexit_node (void)
{
tree atexit_fndecl;
tree arg_types;
tree fn_type;
tree fn_ptr_type;
const char *name;
if (atexit_node)
return atexit_node;
if (flag_use_cxa_atexit)
{
arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
fn_type = build_function_type (void_type_node, arg_types);
fn_ptr_type = build_pointer_type (fn_type);
arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
fn_type = build_function_type (integer_type_node, arg_types);
fn_ptr_type = build_pointer_type (fn_type);
name = "__cxa_atexit";
}
else
{
fn_type = build_function_type (void_type_node, void_list_node);
fn_ptr_type = build_pointer_type (fn_type);
arg_types = tree_cons (NULL_TREE, fn_ptr_type, void_list_node);
fn_type = build_function_type (integer_type_node, arg_types);
name = "atexit";
}
push_lang_context (lang_name_c);
atexit_fndecl = build_library_fn_ptr (name, fn_type);
mark_used (atexit_fndecl);
pop_lang_context ();
atexit_node = decay_conversion (atexit_fndecl);
return atexit_node;
}
static tree
get_dso_handle_node (void)
{
if (dso_handle_node)
return dso_handle_node;
dso_handle_node = declare_global_var (get_identifier ("__dso_handle"),
ptr_type_node);
return dso_handle_node;
}
static GTY(()) int start_cleanup_cnt;
static tree
start_cleanup_fn (void)
{
char name[32];
tree parmtypes;
tree fntype;
tree fndecl;
push_to_top_level ();
push_lang_context (lang_name_c);
parmtypes = void_list_node;
if (flag_use_cxa_atexit)
parmtypes = tree_cons (NULL_TREE, ptr_type_node, parmtypes);
fntype = build_function_type (void_type_node, parmtypes);
sprintf (name, "__tcf_%d", start_cleanup_cnt++);
fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
TREE_PUBLIC (fndecl) = 0;
DECL_ARTIFICIAL (fndecl) = 1;
DECL_INLINE (fndecl) = 1;
DECL_DECLARED_INLINE_P (fndecl) = 1;
DECL_INTERFACE_KNOWN (fndecl) = 1;
if (flag_use_cxa_atexit)
{
tree parmdecl;
parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node);
DECL_CONTEXT (parmdecl) = fndecl;
TREE_USED (parmdecl) = 1;
DECL_ARGUMENTS (fndecl) = parmdecl;
}
pushdecl (fndecl);
start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
pop_lang_context ();
return current_function_decl;
}
static void
end_cleanup_fn (void)
{
expand_or_defer_fn (finish_function (0));
pop_from_top_level ();
}
tree
register_dtor_fn (tree decl)
{
tree cleanup;
tree compound_stmt;
tree args;
tree fcall;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return void_zero_node;
build_cleanup (decl);
cleanup = start_cleanup_fn ();
push_deferring_access_checks (dk_no_check);
fcall = build_cleanup (decl);
pop_deferring_access_checks ();
compound_stmt = begin_compound_stmt (BCS_FN_BODY);
finish_expr_stmt (fcall);
finish_compound_stmt (compound_stmt);
end_cleanup_fn ();
cxx_mark_addressable (cleanup);
mark_used (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
if (flag_use_cxa_atexit)
{
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);
args = tree_cons (NULL_TREE, cleanup, args);
}
else
args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
return build_function_call (get_atexit_node (), args);
}
static void
expand_static_init (tree decl, tree init)
{
gcc_assert (TREE_CODE (decl) == VAR_DECL);
gcc_assert (TREE_STATIC (decl));
if (!init
&& !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
if (DECL_FUNCTION_SCOPE_P (decl))
{
tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE;
tree guard, guard_addr, guard_addr_list;
tree acquire_fn, release_fn, abort_fn;
tree flag, begin;
guard = get_guard (decl);
if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
{
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
then_clause = begin_compound_stmt (BCS_NO_SCOPE);
}
if (flag_threadsafe_statics)
{
guard_addr = build_address (guard);
guard_addr_list = build_tree_list (NULL_TREE, guard_addr);
acquire_fn = get_identifier ("__cxa_guard_acquire");
release_fn = get_identifier ("__cxa_guard_release");
abort_fn = get_identifier ("__cxa_guard_abort");
if (!get_global_value_if_present (acquire_fn, &acquire_fn))
{
tree argtypes = tree_cons (NULL_TREE, TREE_TYPE (guard_addr),
void_list_node);
tree vfntype = build_function_type (void_type_node, argtypes);
acquire_fn = push_library_fn
(acquire_fn, build_function_type (integer_type_node, argtypes));
release_fn = push_library_fn (release_fn, vfntype);
abort_fn = push_library_fn (abort_fn, vfntype);
}
else
{
release_fn = identifier_global_value (release_fn);
abort_fn = identifier_global_value (abort_fn);
}
inner_if_stmt = begin_if_stmt ();
finish_if_stmt_cond (build_call (acquire_fn, guard_addr_list),
inner_if_stmt);
inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE);
begin = get_target_expr (boolean_false_node);
flag = TARGET_EXPR_SLOT (begin);
TARGET_EXPR_CLEANUP (begin)
= build (COND_EXPR, void_type_node, flag,
void_zero_node,
build_call (abort_fn, guard_addr_list));
CLEANUP_EH_ONLY (begin) = 1;
init = add_stmt_to_compound (begin, init);
init = add_stmt_to_compound
(init, build (MODIFY_EXPR, void_type_node, flag, boolean_true_node));
init = add_stmt_to_compound
(init, build_call (release_fn, guard_addr_list));
}
else
init = add_stmt_to_compound (init, set_guard (guard));
init = add_stmt_to_compound (init, register_dtor_fn (decl));
finish_expr_stmt (init);
if (flag_threadsafe_statics)
{
finish_compound_stmt (inner_then_clause);
finish_then_clause (inner_if_stmt);
finish_if_stmt (inner_if_stmt);
}
if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
{
finish_compound_stmt (then_clause);
finish_then_clause (if_stmt);
finish_if_stmt (if_stmt);
}
}
else
static_aggregates = tree_cons (init, decl, static_aggregates);
}
int
cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
{
int failure;
tree type, elt_type;
if (initial_value)
{
if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype)))
&& TREE_CODE (initial_value) == CONSTRUCTOR
&& CONSTRUCTOR_ELTS (initial_value)
&& (TREE_CODE (TREE_VALUE (CONSTRUCTOR_ELTS (initial_value)))
== STRING_CST)
&& TREE_CHAIN (CONSTRUCTOR_ELTS (initial_value)) == NULL_TREE)
initial_value = TREE_VALUE (CONSTRUCTOR_ELTS (initial_value));
}
failure = complete_array_type (ptype, initial_value, do_default);
type = *ptype;
if (TYPE_DOMAIN (type))
{
elt_type = TREE_TYPE (type);
TYPE_NEEDS_CONSTRUCTING (type) = TYPE_NEEDS_CONSTRUCTING (elt_type);
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (elt_type);
}
return failure;
}
static int
member_function_or_else (tree ctype, tree cur_type, enum overload_flags flags)
{
if (ctype && ctype != cur_type)
{
if (flags == DTOR_FLAG)
error ("destructor for alien class %qT cannot be a member", ctype);
else
error ("constructor for alien class %qT cannot be a member", ctype);
return 0;
}
return 1;
}
static void
bad_specifiers (tree object,
const char* type,
int virtualp,
int quals,
int inlinep,
int friendp,
int raises)
{
if (virtualp)
error ("%qD declared as a %<virtual%> %s", object, type);
if (inlinep)
error ("%qD declared as an %<inline%> %s", object, type);
if (quals)
error ("%<const%> and %<volatile%> function specifiers on "
"%qD invalid in %s declaration",
object, type);
if (friendp)
cp_error_at ("%qD declared as a friend", object);
if (raises
&& (TREE_CODE (object) == TYPE_DECL
|| (!TYPE_PTRFN_P (TREE_TYPE (object))
&& !TYPE_REFFN_P (TREE_TYPE (object))
&& !TYPE_PTRMEMFUNC_P (TREE_TYPE (object)))))
cp_error_at ("%qD declared with an exception specification", object);
}
static tree
grokfndecl (tree ctype,
tree type,
tree declarator,
tree parms,
tree orig_declarator,
int virtualp,
enum overload_flags flags,
cp_cv_quals quals,
tree raises,
int check,
int friendp,
int publicp,
int inlinep,
special_function_kind sfk,
int funcdef_flag,
int template_count,
tree in_namespace,
tree* attrlist)
{
tree decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
int has_default_arg = 0;
tree t;
if (raises)
type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
DECL_ARGUMENTS (decl) = parms;
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
if (in_namespace)
set_decl_namespace (decl, in_namespace, friendp);
else if (!ctype)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
if ((MAIN_NAME_P (declarator)
|| (IDENTIFIER_LENGTH (declarator) > 10
&& IDENTIFIER_POINTER (declarator)[0] == '_'
&& IDENTIFIER_POINTER (declarator)[1] == '_'
&& strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
&& current_lang_name == lang_name_cplusplus
&& ctype == NULL_TREE
&& DECL_CONTEXT (decl) == NULL_TREE)
SET_DECL_LANGUAGE (decl, lang_c);
if (staticp)
{
DECL_STATIC_FUNCTION_P (decl) = 1;
DECL_CONTEXT (decl) = ctype;
}
if (ctype)
DECL_CONTEXT (decl) = ctype;
if (ctype == NULL_TREE && DECL_MAIN_P (decl))
{
if (processing_template_decl)
error ("cannot declare %<::main%> to be a template");
if (inlinep)
error ("cannot declare %<::main%> to be inline");
if (!publicp)
error ("cannot declare %<::main%> to be static");
if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
integer_type_node))
{
error ("%<::main%> must return %<int%>");
TREE_TYPE (TREE_TYPE (decl)) = integer_type_node;
}
inlinep = 0;
publicp = 1;
}
if (ctype && (TYPE_ANONYMOUS_P (ctype)
|| decl_function_context (TYPE_MAIN_DECL (ctype))))
publicp = 0;
if (publicp)
{
t = no_linkage_check (TREE_TYPE (decl),
false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
{
if (DECL_EXTERN_C_P (decl))
;
else
{
pedwarn ("non-local function %q#D uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
cp_pedwarn_at ("%q#D does not refer to the unqualified "
"type, so it is not used for linkage",
TYPE_NAME (t));
}
}
else
pedwarn ("non-local function %q#D uses local type %qT", decl, t);
}
}
TREE_PUBLIC (decl) = publicp;
if (! publicp)
{
DECL_INTERFACE_KNOWN (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 1;
}
if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1;
if (DECL_DECLARED_INLINE_P (decl)
|| (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag))
DECL_INLINE (decl) = 1;
DECL_EXTERNAL (decl) = 1;
if (quals && TREE_CODE (type) == FUNCTION_TYPE)
{
error ("%smember function %qD cannot have cv-qualifier",
(ctype ? "static " : "non-"), decl);
quals = TYPE_UNQUALIFIED;
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
grok_op_properties (decl, friendp, true);
if (ctype && decl_function_context (decl))
DECL_NO_STATIC_CHAIN (decl) = 1;
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t)
&& TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
{
has_default_arg = 1;
break;
}
if (friendp
&& TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
{
if (funcdef_flag)
error
("defining explicit specialization %qD in friend declaration",
orig_declarator);
else
{
tree fns = TREE_OPERAND (orig_declarator, 0);
tree args = TREE_OPERAND (orig_declarator, 1);
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
{
error ("invalid use of template-id %qD in declaration "
"of primary template",
orig_declarator);
return NULL_TREE;
}
SET_DECL_IMPLICIT_INSTANTIATION (decl);
if (TREE_CODE (fns) == COMPONENT_REF)
{
gcc_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
== current_class_type);
fns = TREE_OPERAND (fns, 1);
}
gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
|| TREE_CODE (fns) == OVERLOAD);
DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
if (has_default_arg)
{
error ("default arguments are not allowed in declaration "
"of friend template specialization %qD",
decl);
return NULL_TREE;
}
if (inlinep)
{
error ("%<inline%> is not allowed in declaration of friend "
"template specialization %qD",
decl);
return NULL_TREE;
}
}
}
if (funcdef_flag)
DECL_INITIAL (decl) = error_mark_node;
if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
TREE_NOTHROW (decl) = 1;
if (check < 0)
return decl;
if (ctype != NULL_TREE)
{
if (sfk == sfk_constructor)
DECL_CONSTRUCTOR_P (decl) = 1;
grokclassfn (ctype, decl, flags, quals);
}
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
if (decl == error_mark_node)
return NULL_TREE;
if (attrlist)
{
cplus_decl_attributes (&decl, *attrlist, 0);
*attrlist = NULL_TREE;
}
if (ctype != NULL_TREE
&& (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
{
tree old_decl;
old_decl = check_classfn (ctype, decl,
(processing_template_decl
> template_class_depth (ctype))
? current_template_parms
: NULL_TREE);
if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
old_decl = DECL_TEMPLATE_RESULT (old_decl);
if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
revert_static_member_fn (decl);
if (old_decl && DECL_ARTIFICIAL (old_decl))
error ("definition of implicitly-declared %qD", old_decl);
if (old_decl)
{
tree ok;
tree pushed_scope;
if (TREE_CODE (decl) == TEMPLATE_DECL)
decl = DECL_TEMPLATE_RESULT (decl);
pushed_scope = push_scope (ctype);
ok = duplicate_decls (decl, old_decl);
if (pushed_scope)
pop_scope (pushed_scope);
if (!ok)
{
error ("no %q#D member function declared in class %qT",
decl, ctype);
return NULL_TREE;
}
return old_decl;
}
}
if (DECL_CONSTRUCTOR_P (decl) && !grok_ctor_properties (ctype, decl))
return NULL_TREE;
if (ctype == NULL_TREE || check)
return decl;
if (virtualp)
DECL_VIRTUAL_P (decl) = 1;
return decl;
}
static void
set_linkage_for_static_data_member (tree decl)
{
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
if (!processing_template_decl)
DECL_INTERFACE_KNOWN (decl) = 1;
}
static tree
grokvardecl (tree type,
tree name,
const cp_decl_specifier_seq *declspecs,
int initialized,
int constp,
tree scope)
{
tree decl;
tree explicit_scope;
gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE);
explicit_scope = scope;
if (!scope)
{
if (declspecs->storage_class == sc_extern)
scope = current_namespace;
else if (!at_function_scope_p ())
scope = current_scope ();
}
if (scope
&& (
(TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl)
|| (TREE_CODE (scope) == NAMESPACE_DECL
&& current_lang_name != lang_name_cplusplus)
|| TYPE_P (scope)))
decl = build_lang_decl (VAR_DECL, name, type);
else
decl = build_decl (VAR_DECL, name, type);
if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL)
set_decl_namespace (decl, explicit_scope, 0);
else
DECL_CONTEXT (decl) = scope;
if (declspecs->storage_class == sc_extern)
{
DECL_THIS_EXTERN (decl) = 1;
DECL_EXTERNAL (decl) = !initialized;
}
if (DECL_CLASS_SCOPE_P (decl))
{
set_linkage_for_static_data_member (decl);
DECL_EXTERNAL (decl) = 0;
}
else if (toplevel_bindings_p ())
{
TREE_PUBLIC (decl) = (declspecs->storage_class != sc_static
&& (DECL_THIS_EXTERN (decl) || ! constp));
TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
}
else
{
TREE_STATIC (decl) = declspecs->storage_class == sc_static;
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
if (declspecs->specs[(int)ds_thread])
{
if (targetm.have_tls)
DECL_THREAD_LOCAL (decl) = 1;
else
error ("thread-local storage not supported for this target");
}
if (TREE_PUBLIC (decl))
{
tree t = no_linkage_check (TREE_TYPE (decl), false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
{
if (DECL_EXTERN_C_P (decl))
;
else
{
warning ("non-local variable %q#D uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
cp_warning_at ("%q#D does not refer to the unqualified "
"type, so it is not used for linkage",
TYPE_NAME (t));
}
}
else
warning ("non-local variable %q#D uses local type %qT", decl, t);
}
}
else
DECL_INTERFACE_KNOWN (decl) = 1;
return decl;
}
tree
build_ptrmemfunc_type (tree type)
{
tree field, fields;
tree t;
tree unqualified_variant = NULL_TREE;
if (type == error_mark_node)
return type;
if ((t = TYPE_GET_PTRMEMFUNC_TYPE (type)))
return t;
if (cp_type_quals (type) != TYPE_UNQUALIFIED)
unqualified_variant
= build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
t = make_aggr_type (RECORD_TYPE);
xref_basetypes (t, NULL_TREE);
TYPE_PTRMEMFUNC_FLAG (t) = 1;
SET_IS_AGGR_TYPE (t, 0);
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);
TYPE_NAME (t) = NULL_TREE;
if (cp_type_quals (type) != TYPE_UNQUALIFIED)
{
t = build_qualified_type (t, cp_type_quals (type));
TYPE_MAIN_VARIANT (t) = unqualified_variant;
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
TYPE_NEXT_VARIANT (unqualified_variant) = t;
}
TYPE_SET_PTRMEMFUNC_TYPE (type, t);
return t;
}
tree
build_ptrmem_type (tree class_type, tree member_type)
{
if (TREE_CODE (member_type) == METHOD_TYPE)
{
tree arg_types;
arg_types = TYPE_ARG_TYPES (member_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,
TREE_TYPE (member_type),
TREE_CHAIN (arg_types));
return build_ptrmemfunc_type (build_pointer_type (member_type));
}
else
{
gcc_assert (TREE_CODE (member_type) != FUNCTION_TYPE);
return build_offset_type (class_type, member_type);
}
}
int
check_static_variable_definition (tree decl, tree type)
{
if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)
{
error ("invalid in-class initialization of static data member "
"of non-integral type %qT",
type);
return 1;
}
else if (!CP_TYPE_CONST_P (type))
error ("ISO C++ forbids in-class initialization of non-const "
"static member %qD",
decl);
else if (pedantic && !INTEGRAL_TYPE_P (type))
pedwarn ("ISO C++ forbids initialization of member constant "
"%qD of non-integral type %qT", decl, type);
return 0;
}
tree
compute_array_index_type (tree name, tree size)
{
tree type = TREE_TYPE (size);
tree itype;
if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type))
{
if (name)
error ("size of array %qD has non-integral type %qT", name, type);
else
error ("size of array has non-integral type %qT", type);
size = integer_one_node;
type = TREE_TYPE (size);
}
if (abi_version_at_least (2)
? value_dependent_expression_p (size)
: processing_template_decl)
return build_index_type (build_min (MINUS_EXPR, sizetype,
size, integer_one_node));
STRIP_TYPE_NOPS (size);
size = integral_constant_value (size);
if (TREE_CODE (size) == INTEGER_CST)
{
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;
if (INT_CST_LT (size, integer_zero_node))
{
if (name)
error ("size of array %qD is negative", name);
else
error ("size of array is negative");
size = integer_one_node;
}
else if (integer_zerop (size) && pedantic && !in_system_header)
{
if (name)
pedwarn ("ISO C++ forbids zero-size array %qD", name);
else
pedwarn ("ISO C++ forbids zero-size array");
}
}
else if (TREE_CONSTANT (size))
{
if (name)
error ("size of array %qD is not an integral constant-expression",
name);
else
error ("size of array is not an integral constant-expression");
}
else if (pedantic)
{
if (name)
pedwarn ("ISO C++ forbids variable-size array %qD", name);
else
pedwarn ("ISO C++ forbids variable-size array");
}
if (processing_template_decl && !TREE_CONSTANT (size))
itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node);
else
{
HOST_WIDE_INT saved_processing_template_decl;
saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
itype = cp_build_binary_op (MINUS_EXPR,
cp_convert (ssizetype, size),
cp_convert (ssizetype, integer_one_node));
itype = fold (itype);
processing_template_decl = saved_processing_template_decl;
if (!TREE_CONSTANT (itype))
itype = variable_size (itype);
else if (TREE_OVERFLOW (itype))
{
error ("overflow in array dimension");
TREE_OVERFLOW (itype) = 0;
}
}
return build_index_type (itype);
}
tree
get_scope_of_declarator (const cp_declarator *declarator)
{
while (declarator && declarator->kind != cdk_id)
declarator = declarator->declarator;
if (declarator
&& declarator->u.id.qualifying_scope)
return declarator->u.id.qualifying_scope;
return NULL_TREE;
}
static tree
create_array_type_for_decl (tree name, tree type, tree size)
{
tree itype = NULL_TREE;
const char* error_msg;
if (type == error_mark_node || size == error_mark_node)
return error_mark_node;
error_msg = NULL;
switch (TREE_CODE (type))
{
case VOID_TYPE:
error_msg = "array of void";
break;
case FUNCTION_TYPE:
error_msg = "array of functions";
break;
case REFERENCE_TYPE:
error_msg = "array of references";
break;
case METHOD_TYPE:
error_msg = "array of function members";
break;
default:
break;
}
if (error_msg)
{
if (name)
error ("declaration of %qD as %s", name, error_msg);
else
error ("creating %s", error_msg);
return error_mark_node;
}
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
{
if (name)
error ("declaration of %qD as multidimensional array must "
"have bounds for all dimensions except the first",
name);
else
error ("multidimensional array must have bounds for all "
"dimensions except the first");
return error_mark_node;
}
if (size)
itype = compute_array_index_type (name, size);
abstract_virtuals_error (name, type);
return build_cplus_array_type (type, itype);
}
static tree
check_special_function_return_type (special_function_kind sfk,
tree type,
tree optype)
{
switch (sfk)
{
case sfk_constructor:
if (type)
error ("return type specification for constructor invalid");
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");
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:
if (type && !same_type_p (type, optype))
error ("operator %qT declared to return %qT", optype, type);
else if (type)
pedwarn ("return type specified for %<operator %T%>", optype);
type = optype;
break;
default:
gcc_unreachable ();
}
return type;
}
tree
check_var_type (tree identifier, tree type)
{
if (VOID_TYPE_P (type))
{
if (!identifier)
error ("unnamed variable or field declared void");
else if (TREE_CODE (identifier) == IDENTIFIER_NODE)
{
gcc_assert (!IDENTIFIER_OPNAME_P (identifier));
error ("variable or field %qE declared void", identifier);
}
else
error ("variable or field declared void");
type = integer_type_node;
}
return type;
}
tree
grokdeclarator (const cp_declarator *declarator,
const cp_decl_specifier_seq *declspecs,
enum decl_context decl_context,
int initialized,
tree* attrlist)
{
tree type = NULL_TREE;
int longlong = 0;
int type_quals;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
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;
int funcdef_flag = 0;
cp_declarator_kind innermost_code = cdk_error;
int bitfield = 0;
#if 0
tree decl_attr = NULL_TREE;
#endif
special_function_kind sfk = sfk_none;
tree dname = NULL_TREE;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
cp_cv_quals quals = TYPE_UNQUALIFIED;
tree raises = NULL_TREE;
int template_count = 0;
tree returned_attrs = NULL_TREE;
tree parms = NULL_TREE;
const cp_declarator *id_declarator;
tree unqualified_id;
tree ctype = current_class_type;
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;
bool type_was_error_mark_node = false;
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;
else if (decl_context == MEMFUNCDEF)
funcdef_flag = -1, decl_context = FIELD;
else if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
for (id_declarator = declarator;
id_declarator;
id_declarator = id_declarator->declarator)
{
if (id_declarator->kind != cdk_id)
innermost_code = id_declarator->kind;
switch (id_declarator->kind)
{
case cdk_function:
if (id_declarator->declarator
&& id_declarator->declarator->kind == cdk_id)
{
sfk = id_declarator->declarator->u.id.sfk;
if (sfk == sfk_destructor)
flags = DTOR_FLAG;
}
break;
case cdk_id:
{
tree qualifying_scope = id_declarator->u.id.qualifying_scope;
tree decl = id_declarator->u.id.unqualified_name;
if (!decl)
break;
if (qualifying_scope)
{
if (TYPE_P (qualifying_scope))
{
ctype = qualifying_scope;
if (innermost_code != cdk_function
&& current_class_type
&& !UNIQUELY_DERIVED_FROM_P (ctype,
current_class_type))
{
error ("type %qT is not derived from type %qT",
ctype, current_class_type);
return error_mark_node;
}
}
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:
{
tree type;
if (innermost_code != cdk_function)
{
error ("declaration of %qD as non-function", decl);
return error_mark_node;
}
else if (!qualifying_scope
&& !(current_class_type && at_class_scope_p ()))
{
error ("declaration of %qD as non-member", decl);
return error_mark_node;
}
type = TREE_OPERAND (decl, 0);
name = IDENTIFIER_POINTER (constructor_name (type));
}
break;
case TEMPLATE_ID_EXPR:
{
tree fns = TREE_OPERAND (decl, 0);
dname = fns;
if (TREE_CODE (dname) == COMPONENT_REF)
dname = TREE_OPERAND (dname, 1);
if (TREE_CODE (dname) != IDENTIFIER_NODE)
{
gcc_assert (is_overloaded_fn (dname));
dname = DECL_NAME (get_first_fn (dname));
}
}
case IDENTIFIER_NODE:
if (TREE_CODE (decl) == IDENTIFIER_NODE)
dname = decl;
if (C_IS_RESERVED_WORD (dname))
{
error ("declarator-id missing; using reserved word %qD",
dname);
name = IDENTIFIER_POINTER (dname);
}
else if (!IDENTIFIER_TYPENAME_P (dname))
name = IDENTIFIER_POINTER (dname);
else
{
gcc_assert (flags == NO_SPECIAL);
flags = TYPENAME_FLAG;
ctor_return_type = TREE_TYPE (dname);
sfk = sfk_conversion;
if (is_typename_at_global_scope (dname))
name = IDENTIFIER_POINTER (dname);
else
name = "<invalid operator>";
}
break;
case TYPE_DECL:
dname = constructor_name (TREE_TYPE (decl));
name = IDENTIFIER_POINTER (dname);
break;
default:
gcc_unreachable ();
}
break;
case cdk_array:
case cdk_pointer:
case cdk_reference:
case cdk_ptrmem:
break;
case cdk_error:
break;
default:
gcc_unreachable ();
}
}
if (id_declarator->kind == cdk_id)
break;
}
if (funcdef_flag && innermost_code != cdk_function)
return 0;
if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
&& innermost_code != cdk_function
&& ! (ctype && !declspecs->any_specifiers_p))
{
error ("declaration of %qD as non-function", dname);
return error_mark_node;
}
if (decl_context == NORMAL && !toplevel_bindings_p ())
{
struct cp_binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
if (current_binding_level != 0 && toplevel_bindings_p ())
decl_context = PARM;
current_binding_level = b;
}
if (name == NULL)
name = decl_context == PARM ? "parameter" : "type name";
if (declspecs->multiple_types_p)
error ("two or more data types in declaration of %qs", name);
type = declspecs->type;
if (type == error_mark_node)
{
type = NULL_TREE;
type_was_error_mark_node = true;
}
if (type && TREE_DEPRECATED (type)
&& deprecated_state != DEPRECATED_SUPPRESS)
warn_deprecated_use (type);
if (type && TREE_CODE (type) == TYPE_DECL)
{
typedef_decl = type;
type = TREE_TYPE (typedef_decl);
}
if (type == NULL_TREE && (signed_p || unsigned_p || long_p || short_p))
{
type = integer_type_node;
defaulted_int = 1;
}
explicit_int = declspecs->explicit_int_p;
explicit_char = declspecs->explicit_char_p;
for (ds = ds_first; ds != ds_last; ++ds)
{
unsigned count = declspecs->specs[(int)ds];
if (count < 2)
continue;
if (ds == ds_long)
{
if (count > 2)
error ("%<long long long%> is too long for GCC");
else if (pedantic && !in_system_header && warn_long_long)
pedwarn ("ISO C++ does not support %<long long%>");
else
longlong = 1;
}
else if (declspecs->specs[(int)ds] > 1)
{
static const char *const decl_spec_names[] = {
"signed",
"unsigned",
"short",
"long",
"const",
"volatile",
"restrict",
"inline",
"virtual",
"explicit",
"friend",
"typedef",
"__complex",
"__thread"
};
error ("duplicate %qs", decl_spec_names[(int)ds]);
}
}
#if 0
if (typedef_decl)
decl_attr = DECL_ATTRIBUTES (typedef_decl);
#endif
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);
else if (type == NULL_TREE)
{
int is_main;
explicit_int = -1;
is_main = (funcdef_flag
&& dname && MAIN_NAME_P (dname)
&& ctype == NULL_TREE
&& in_namespace == NULL_TREE
&& current_namespace == global_namespace);
if (type_was_error_mark_node)
;
else if (in_system_header || flag_ms_extensions)
;
else if (pedantic || ! is_main)
pedwarn ("ISO C++ forbids declaration of %qs with no type", name);
else if (warn_return_type)
warning ("ISO C++ forbids declaration of %qs with no type", name);
type = integer_type_node;
}
ctype = NULL_TREE;
if (long_p && TYPE_MAIN_VARIANT (type) == double_type_node)
{
long_p = false;
type = build_qualified_type (long_double_type_node,
cp_type_quals (type));
}
if (unsigned_p || signed_p || long_p || short_p)
{
int ok = 0;
if (TREE_CODE (type) == REAL_TYPE)
error ("short, signed or unsigned invalid for %qs", name);
else if (TREE_CODE (type) != INTEGER_TYPE)
error ("long, short, signed or unsigned invalid for %qs", name);
else if (long_p && short_p)
error ("long and short specified together for %qs", name);
else if ((long_p || short_p) && explicit_char)
error ("long or short specified with char for %qs", name);
else if ((long_p|| short_p) && TREE_CODE (type) == REAL_TYPE)
error ("long or short specified with floating type for %qs", name);
else if (signed_p && unsigned_p)
error ("signed and unsigned given together for %qs", name);
else
{
ok = 1;
if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
{
pedwarn ("long, short, signed or unsigned used invalidly for %qs",
name);
if (flag_pedantic_errors)
ok = 0;
}
}
if (! ok)
{
unsigned_p = false;
signed_p = false;
long_p = false;
short_p = false;
longlong = 0;
}
}
if (unsigned_p
|| (bitfield && !flag_signed_bitfields
&& !signed_p
&& !(typedef_decl
&& C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
&& (TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == CHAR_TYPE)
&& !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
{
if (longlong)
type = long_long_unsigned_type_node;
else if (long_p)
type = long_unsigned_type_node;
else if (short_p)
type = short_unsigned_type_node;
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
type = c_common_unsigned_type (type);
else
type = unsigned_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 (long_p)
type = long_integer_type_node;
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 %qs", name);
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;
else if (type == float_type_node)
type = complex_float_type_node;
else if (type == double_type_node)
type = complex_double_type_node;
else if (type == long_double_type_node)
type = complex_long_double_type_node;
else
type = build_complex_type (type);
}
type_quals = TYPE_UNQUALIFIED;
if (declspecs->specs[(int)ds_const])
type_quals |= TYPE_QUAL_CONST;
if (declspecs->specs[(int)ds_volatile])
type_quals |= TYPE_QUAL_VOLATILE;
if (declspecs->specs[(int)ds_restrict])
type_quals |= TYPE_QUAL_RESTRICT;
if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
error ("qualifiers are not allowed on declaration of %<operator %T%>",
ctor_return_type);
if (TREE_CODE (type) == FUNCTION_TYPE
&& type_quals != TYPE_UNQUALIFIED)
{
if (pedantic)
{
tree bad_type = build_qualified_type (type, type_quals);
pedwarn ("ignoring %qV qualifiers added to function type %qT",
bad_type, type);
}
type_quals = TYPE_UNQUALIFIED;
}
type_quals |= cp_type_quals (type);
type = cp_build_qualified_type_real
(type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
? tf_ignore_bad_quals : 0) | tf_error | tf_warning));
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];
storage_class = declspecs->storage_class;
if (storage_class == sc_static)
staticp = 1 + (decl_context == FIELD);
if (virtualp && staticp == 2)
{
error ("member %qD cannot be declared both virtual and static", dname);
staticp = 0;
}
friendp = !! declspecs->specs[(int)ds_friend];
if (dependant_name && !friendp)
{
error ("%<%T::%D%> is not a valid declarator", ctype, dependant_name);
return void_type_node;
}
if (decl_context == PARM)
{
if (declspecs->specs[(int)ds_typedef])
error ("typedef declaration invalid in parameter declaration");
else if (storage_class == sc_static
|| storage_class == sc_extern
|| thread_p)
error ("storage class specifiers invalid in parameter declarations");
}
if (virtualp
&& (current_class_name == NULL_TREE || decl_context != FIELD))
{
error ("virtual outside class declaration");
virtualp = 0;
}
if (staticp && decl_context == TYPENAME
&& declspecs->type
&& ANON_AGGR_TYPE_P (declspecs->type))
decl_context = FIELD;
if (declspecs->multiple_storage_classes_p)
error ("multiple storage classes in declaration of %qs", name);
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 %qs", name);
thread_p = false;
}
else 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
|| storage_class == sc_auto))
;
else if (declspecs->specs[(int)ds_typedef])
;
else if (decl_context == FIELD
&& storage_class == sc_static)
;
else
{
if (decl_context == FIELD)
{
tree tmp = NULL_TREE;
int op = 0;
if (declarator)
{
if (declarator->kind != cdk_id)
tmp = declarator->declarator->u.id.unqualified_name;
else
tmp = declarator->u.id.unqualified_name;
op = IDENTIFIER_OPNAME_P (tmp);
if (IDENTIFIER_TYPENAME_P (tmp))
{
if (is_typename_at_global_scope (tmp))
name = IDENTIFIER_POINTER (tmp);
else
name = "<invalid operator>";
}
}
error ("storage class specified for %s %qs",
op ? "member operator" : "field",
name);
}
else
{
if (decl_context == PARM || decl_context == CATCHPARM)
error ("storage class specified for parameter %qs", name);
else
error ("storage class specified for typename");
}
if (storage_class == sc_register
|| storage_class == sc_auto
|| storage_class == sc_extern
|| thread_p)
storage_class = sc_none;
}
}
else if (storage_class == sc_extern && initialized
&& !funcdef_flag)
{
if (toplevel_bindings_p ())
{
if (!(type_quals & TYPE_QUAL_CONST))
warning ("%qs initialized and declared %<extern%>", name);
}
else
error ("%qs has both %<extern%> and initializer", name);
}
else if (storage_class == sc_extern && funcdef_flag
&& ! toplevel_bindings_p ())
error ("nested function %qs declared %<extern%>", name);
else if (toplevel_bindings_p ())
{
if (storage_class == sc_auto)
error ("top-level declaration of %qs specifies %<auto%>", name);
}
else if (thread_p
&& storage_class != sc_extern
&& storage_class != sc_static)
{
error ("function-scope %qs implicitly auto and declared %<__thread%>",
name);
thread_p = false;
}
if (storage_class && friendp)
error ("storage class specifiers invalid in friend function declarations");
if (!id_declarator)
unqualified_id = NULL_TREE;
else
{
unqualified_id = id_declarator->u.id.unqualified_name;
if (TREE_CODE (unqualified_id) == BASELINK)
unqualified_id = BASELINK_FUNCTIONS (unqualified_id);
switch (TREE_CODE (unqualified_id))
{
case BIT_NOT_EXPR:
unqualified_id
= constructor_name (TREE_OPERAND (unqualified_id, 0));
break;
case TYPE_DECL:
unqualified_id
= constructor_name (TREE_TYPE (unqualified_id));
break;
case IDENTIFIER_NODE:
case TEMPLATE_ID_EXPR:
break;
default:
gcc_unreachable ();
}
}
for (; declarator; declarator = declarator->declarator)
{
const cp_declarator *inner_declarator;
tree attrs;
if (type == error_mark_node)
return error_mark_node;
attrs = declarator->attributes;
if (attrs)
{
int attr_flags;
attr_flags = 0;
if (declarator == NULL || declarator->kind == cdk_id)
attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
if (declarator->kind == cdk_function)
attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
if (declarator->kind == cdk_array)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
returned_attrs = decl_attributes (&type,
chainon (returned_attrs, attrs),
attr_flags);
}
if (declarator->kind == cdk_id)
break;
inner_declarator = declarator->declarator;
switch (declarator->kind)
{
case cdk_array:
type = create_array_type_for_decl (dname, type,
declarator->u.array.bounds);
break;
case cdk_function:
{
tree arg_types;
int funcdecl_p;
type_quals = TYPE_UNQUALIFIED;
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error ("%qs declared as function returning a function", name);
type = integer_type_node;
}
if (TREE_CODE (type) == ARRAY_TYPE)
{
error ("%qs declared as function returning an array", name);
type = integer_type_node;
}
quals = declarator->u.function.qualifiers;
raises = declarator->u.function.exception_specification;
funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id;
if (ctype == NULL_TREE
&& decl_context == FIELD
&& funcdecl_p
&& (friendp == 0 || dname == current_class_name))
ctype = current_class_type;
if (ctype && sfk == sfk_conversion)
TYPE_HAS_CONVERSION (ctype) = 1;
if (ctype && (sfk == sfk_constructor
|| sfk == sfk_destructor))
{
if (flags == DTOR_FLAG)
{
if (staticp == 2)
error ("destructor cannot be static member function");
if (quals)
{
error ("destructors may not be cv-qualified");
quals = TYPE_UNQUALIFIED;
}
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
current_class_type,
flags))
return void_type_node;
}
}
else
{
if (explicitp == 1)
explicitp = 2;
if (staticp == 2)
error ("constructor cannot be static member function");
if (virtualp)
{
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
if (quals)
{
error ("constructors may not be cv-qualified");
quals = TYPE_UNQUALIFIED;
}
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
current_class_type,
flags))
return void_type_node;
TYPE_HAS_CONSTRUCTOR (ctype) = 1;
if (sfk != sfk_constructor)
return NULL_TREE;
}
}
if (decl_context == FIELD)
staticp = 0;
}
else if (friendp)
{
if (initialized)
error ("can't initialize friend function %qs", name);
if (virtualp)
{
error ("virtual functions cannot be friends");
friendp = 0;
}
if (decl_context == NORMAL)
error ("friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
error ("can't define friend function %qs in a local "
"class definition",
name);
}
arg_types = grokparms (declarator->u.function.parameters,
&parms);
if (inner_declarator
&& inner_declarator->kind == cdk_id
&& inner_declarator->u.id.sfk == sfk_destructor
&& arg_types != void_list_node)
{
error ("destructors may not have parameters");
arg_types = void_list_node;
parms = NULL_TREE;
}
type = build_function_type (type, arg_types);
type = cp_build_qualified_type (type, quals);
}
break;
case cdk_pointer:
case cdk_reference:
case cdk_ptrmem:
if (TREE_CODE (type) == REFERENCE_TYPE)
{
error (declarator->kind == cdk_reference
? "cannot declare reference to %q#T"
: "cannot declare pointer to %q#T", type);
type = TREE_TYPE (type);
}
else if (VOID_TYPE_P (type))
{
if (declarator->kind == cdk_reference)
error ("cannot declare reference to %q#T", type);
else if (declarator->kind == cdk_ptrmem)
error ("cannot declare pointer to %q#T member", type);
}
type_quals = TYPE_UNQUALIFIED;
if (declarator->kind == cdk_ptrmem
&& (TREE_CODE (type) == FUNCTION_TYPE
|| (quals && TREE_CODE (type) == METHOD_TYPE)))
{
tree dummy;
if (TREE_CODE (type) == FUNCTION_TYPE)
quals = cp_type_quals (type);
dummy = build_decl (TYPE_DECL, NULL_TREE, type);
grok_method_quals (declarator->u.pointer.class_type,
dummy, quals);
type = TREE_TYPE (dummy);
quals = TYPE_UNQUALIFIED;
}
if (declarator->kind == cdk_reference)
{
if (!VOID_TYPE_P (type))
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
else if (declarator->kind == cdk_ptrmem)
{
if (TREE_CODE (declarator->u.pointer.class_type)
== NAMESPACE_DECL)
{
error ("%qD is a namespace",
declarator->u.pointer.class_type);
type = build_pointer_type (type);
}
else if (declarator->u.pointer.class_type == error_mark_node)
type = error_mark_node;
else
type = build_ptrmem_type (declarator->u.pointer.class_type,
type);
}
else
type = build_pointer_type (type);
if (declarator->u.pointer.qualifiers)
{
type
= cp_build_qualified_type (type,
declarator->u.pointer.qualifiers);
type_quals = cp_type_quals (type);
}
ctype = NULL_TREE;
break;
case cdk_error:
break;
default:
gcc_unreachable ();
}
}
if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
&& TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE)
{
error ("template-id %qD used as a declarator",
unqualified_id);
unqualified_id = dname;
}
if (declarator
&& declarator->u.id.qualifying_scope
&& TYPE_P (declarator->u.id.qualifying_scope))
{
tree t;
ctype = declarator->u.id.qualifying_scope;
ctype = TYPE_MAIN_VARIANT (ctype);
t = ctype;
while (t != NULL_TREE && CLASS_TYPE_P (t))
{
if (CLASSTYPE_TEMPLATE_INFO (t)
&& (CLASSTYPE_TEMPLATE_INSTANTIATION (t)
|| uses_template_parms (CLASSTYPE_TI_ARGS (t)))
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
template_count += 1;
t = TYPE_MAIN_DECL (t);
t = DECL_CONTEXT (t);
}
if (ctype == current_class_type)
{
if (pedantic)
pedwarn ("extra qualification %<%T::%> on member %qs ignored",
ctype, name);
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
tree sname = declarator->u.id.unqualified_name;
if (TREE_CODE (sname) == IDENTIFIER_NODE
&& NEW_DELETE_OPNAME_P (sname))
;
else if (current_class_type == NULL_TREE || friendp)
type
= build_method_type_directly (ctype,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
else
{
error ("cannot declare member function %<%T::%s%> within %<%T%>",
ctype, name, current_class_type);
return error_mark_node;
}
}
else if (declspecs->specs[(int)ds_typedef]
|| COMPLETE_TYPE_P (complete_type (ctype)))
{
if (current_class_type)
{
error ("cannot declare member %<%T::%s%> within %qT",
ctype, name, current_class_type);
return void_type_node;
}
}
else
{
cxx_incomplete_type_error (NULL_TREE, ctype);
return error_mark_node;
}
}
if (returned_attrs)
{
if (attrlist)
*attrlist = chainon (returned_attrs, *attrlist);
else
attrlist = &returned_attrs;
}
if (TREE_CODE (type) == ARRAY_TYPE
&& COMPLETE_TYPE_P (type)
&& TREE_OVERFLOW (TYPE_SIZE (type)))
{
error ("size of array %qs is too large", name);
type = error_mark_node;
}
if ((decl_context == FIELD || decl_context == PARM)
&& !processing_template_decl
&& variably_modified_type_p (type, NULL_TREE))
{
if (decl_context == FIELD)
error ("data member may not have variably modified type %qT", type);
else
error ("parameter may not have variably modified type %qT", type);
type = error_mark_node;
}
if (explicitp == 1 || (explicitp && friendp))
{
error ("only declarations of constructors can be %<explicit%>");
explicitp = 0;
}
if (storage_class == sc_mutable)
{
if (decl_context != FIELD || friendp)
{
error ("non-member %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
{
error ("non-object member %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
error ("function %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
else if (staticp)
{
error ("static %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
else if (type_quals & TYPE_QUAL_CONST)
{
error ("const %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
}
if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME)
{
tree decl;
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
if (decl_context == FIELD)
decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else
decl = build_decl (TYPE_DECL, unqualified_id, type);
if (id_declarator && declarator->u.id.qualifying_scope)
error ("%Jtypedef name may not be a nested-name-specifier", decl);
if (decl_context != FIELD)
{
if (!current_function_decl)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl)
|| (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P
(current_function_decl)))
DECL_ABSTRACT (decl) = 1;
}
else if (constructor_name_p (unqualified_id, current_class_type))
pedwarn ("ISO C++ forbids nested type %qD with same name "
"as enclosing class",
unqualified_id);
if (type != error_mark_node
&& unqualified_id
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& TYPE_ANONYMOUS_P (type)
&& (!attrlist || !*attrlist)
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
{
tree oldname = TYPE_NAME (type);
tree t;
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
if (TYPE_NAME (t) == oldname)
TYPE_NAME (t) = decl;
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_ANONYMOUS (type) = 1;
if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_TEMPLATE_INFO (type))
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
= TYPE_IDENTIFIER (type);
}
if (quals)
{
if (ctype == NULL_TREE)
{
if (TREE_CODE (type) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (type);
else if (TREE_CODE (type) == FUNCTION_TYPE)
quals = TYPE_UNQUALIFIED;
}
if (ctype != NULL_TREE)
grok_method_quals (ctype, decl, quals);
}
if (signed_p
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
return decl;
}
if (type && typedef_type
&& TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE)
{
tree decls = NULL_TREE;
tree args;
for (args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args))
{
tree decl = cp_build_parm_decl (NULL_TREE, TREE_VALUE (args));
TREE_CHAIN (decl) = decls;
decls = decl;
}
parms = nreverse (decls);
if (decl_context != TYPENAME)
{
if (cp_type_quals (type) != TYPE_UNQUALIFIED
&& (current_class_type == NULL_TREE || staticp) )
{
error ("qualified function types cannot be used to declare %s functions",
(staticp? "static member" : "free"));
type = TYPE_MAIN_VARIANT (type);
}
quals |= cp_type_quals (type);
}
}
if (decl_context == TYPENAME)
{
if (type_quals != TYPE_UNQUALIFIED)
type_quals = TYPE_UNQUALIFIED;
if (friendp)
{
if (type_quals != TYPE_UNQUALIFIED)
{
error ("type qualifiers specified for friend class declaration");
type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
error ("%<inline%> specified for friend class declaration");
inlinep = 0;
}
if (!current_aggr)
{
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
pedwarn ("template parameters cannot be friends");
else if (TREE_CODE (type) == TYPENAME_TYPE)
pedwarn ("friend declaration requires class-key, "
"i.e. %<friend class %T::%D%>",
TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
else
pedwarn ("friend declaration requires class-key, "
"i.e. %<friend %#T%>",
type);
}
if (type != integer_type_node)
{
if (current_class_type)
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type),
true);
else
error ("trying to make class %qT a friend of global scope",
type);
type = void_type_node;
}
}
else if (quals)
{
if (ctype == NULL_TREE)
{
if (TREE_CODE (type) != METHOD_TYPE)
error ("invalid qualifiers on non-member function type");
else
ctype = TYPE_METHOD_BASETYPE (type);
}
if (ctype)
{
tree dummy = build_decl (TYPE_DECL, unqualified_id, type);
grok_method_quals (ctype, dummy, quals);
type = TREE_TYPE (dummy);
}
}
return type;
}
else if (unqualified_id == NULL_TREE && decl_context != PARM
&& decl_context != CATCHPARM
&& TREE_CODE (type) != UNION_TYPE
&& ! bitfield)
{
error ("abstract declarator %qT used as declaration", type);
return error_mark_node;
}
if (unqualified_id
&& IDENTIFIER_OPNAME_P (unqualified_id)
&& TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE)
{
error ("declaration of %qD as non-function", unqualified_id);
return error_mark_node;
}
if (decl_context != PARM)
type = check_var_type (unqualified_id, type);
if (decl_context == PARM || decl_context == CATCHPARM)
{
if (ctype || in_namespace)
error ("cannot use %<::%> in parameter declaration");
if (TREE_CODE (type) == ARRAY_TYPE)
{
type = build_pointer_type (TREE_TYPE (type));
type_quals = TYPE_UNQUALIFIED;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
type = build_pointer_type (type);
}
{
tree decl;
if (decl_context == PARM)
{
decl = cp_build_parm_decl (unqualified_id, type);
bad_specifiers (decl, "parameter", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
else if (decl_context == FIELD)
{
if (!staticp && TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
{
tree itype = compute_array_index_type (dname, integer_zero_node);
type = build_cplus_array_type (TREE_TYPE (type), itype);
}
if (type == error_mark_node)
{
decl = NULL_TREE;
}
else if (in_namespace && !friendp)
{
error ("invalid use of %<::%>");
decl = NULL_TREE;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
int publicp = 0;
tree function_context;
if (friendp == 0)
{
if (ctype == NULL_TREE)
ctype = current_class_type;
if (ctype == NULL_TREE)
{
error ("can't make %qD into a method -- not in a class",
unqualified_id);
return void_type_node;
}
if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
{
error ("function %qD declared virtual inside a union",
unqualified_id);
return void_type_node;
}
if (NEW_DELETE_OPNAME_P (unqualified_id))
{
if (virtualp)
{
error ("%qD cannot be declared virtual, since it "
"is always static",
unqualified_id);
virtualp = 0;
}
}
else if (staticp < 2)
type = build_method_type_directly (ctype,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
}
if (sfk == sfk_destructor
&& !same_type_p (TREE_OPERAND
(id_declarator->u.id.unqualified_name, 0),
ctype))
{
error ("declaration of %qD as member of %qT",
id_declarator->u.id.unqualified_name,
ctype);
return error_mark_node;
}
function_context = (ctype != NULL_TREE) ?
decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
publicp = (! friendp || ! staticp)
&& function_context == NULL_TREE;
decl = grokfndecl (ctype, type,
TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
? unqualified_id : dname,
parms,
unqualified_id,
virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
sfk,
funcdef_flag, template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
return decl;
#if 0
decl = build_decl_attribute_variant (decl, decl_attr);
#endif
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
else if (DECL_CONSTRUCTOR_P (decl))
{
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl);
if (arg_types == void_list_node
|| (arg_types
&& TREE_CHAIN (arg_types)
&& TREE_CHAIN (arg_types) != void_list_node
&& !TREE_PURPOSE (TREE_CHAIN (arg_types))))
DECL_NONCONVERTING_P (decl) = 1;
}
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
decl = grokfndecl (ctype, type,
TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
? unqualified_id : dname,
parms,
unqualified_id,
virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, 1, 0, sfk,
funcdef_flag, template_count, in_namespace,
attrlist);
if (decl == NULL_TREE)
return NULL_TREE;
}
else if (!staticp && !dependent_type_p (type)
&& !COMPLETE_TYPE_P (complete_type (type))
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
if (unqualified_id)
error ("field %qD has incomplete type", unqualified_id);
else
error ("name %qT has incomplete type", type);
if (current_class_type
&& TYPE_NAME (current_class_type)
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))
&& declspecs->type
&& declspecs->type == type)
error (" in instantiation of template %qT",
current_class_type);
type = error_mark_node;
decl = NULL_TREE;
}
else
{
if (friendp)
{
error ("%qE is neither function nor member function; "
"cannot be declared friend", unqualified_id);
friendp = 0;
}
decl = NULL_TREE;
}
if (friendp)
{
if (ctype == current_class_type)
warning ("member functions are implicitly friends of their class");
else if (decl && DECL_NAME (decl))
{
if (template_class_depth (current_class_type) == 0)
{
decl = check_explicit_specialization
(unqualified_id, decl, template_count,
2 * (funcdef_flag != 0) + 4);
if (decl == error_mark_node)
return error_mark_node;
}
decl = do_friend (ctype, unqualified_id, decl,
*attrlist, flags, quals, funcdef_flag);
return decl;
}
else
return void_type_node;
}
if (decl == NULL_TREE)
{
if (initialized)
{
if (!staticp)
{
pedwarn ("ISO C++ forbids initialization of member %qD",
unqualified_id);
pedwarn ("making %qD static", unqualified_id);
staticp = 1;
}
if (uses_template_parms (type))
;
else if (check_static_variable_definition (unqualified_id,
type))
return void_type_node;
}
if (staticp)
{
decl = build_lang_decl (VAR_DECL, unqualified_id, type);
set_linkage_for_static_data_member (decl);
DECL_EXTERNAL (decl) = 1;
}
else
{
decl = build_decl (FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (storage_class == sc_mutable)
{
DECL_MUTABLE_P (decl) = 1;
storage_class = sc_none;
}
}
bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
}
}
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
tree original_name;
int publicp = 0;
if (!unqualified_id)
return NULL_TREE;
if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
original_name = dname;
else
original_name = unqualified_id;
if (storage_class == sc_auto)
error ("storage class %<auto%> invalid for function %qs", name);
else if (storage_class == sc_register)
error ("storage class %<register%> invalid for function %qs", name);
else if (thread_p)
error ("storage class %<__thread%> invalid for function %qs", name);
if (! toplevel_bindings_p ()
&& (storage_class == sc_static
|| declspecs->specs[(int)ds_inline])
&& pedantic)
{
if (storage_class == sc_static)
pedwarn ("%<static%> specified invalid for function %qs "
"declared out of global scope", name);
else
pedwarn ("%<inline%> specifier invalid for function %qs "
"declared out of global scope", name);
}
if (ctype == NULL_TREE)
{
if (virtualp)
{
error ("virtual non-class function %qs", name);
virtualp = 0;
}
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
&& !NEW_DELETE_OPNAME_P (original_name))
type = build_method_type_directly (ctype,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
publicp = (ctype != NULL_TREE
|| storage_class == sc_extern
|| storage_class != sc_static);
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, quals, raises,
1, friendp,
publicp, inlinep, sfk, funcdef_flag,
template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
return NULL_TREE;
if (staticp == 1)
{
int invalid_static = 0;
if (TREE_CODE (type) == METHOD_TYPE)
{
pedwarn ("cannot declare member function %qD to have "
"static linkage", decl);
invalid_static = 1;
}
else if (current_function_decl)
{
error ("cannot declare static function inside another function");
invalid_static = 1;
}
if (invalid_static)
{
staticp = 0;
storage_class = sc_none;
}
}
}
else
{
decl = grokvardecl (type, unqualified_id,
declspecs,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
if (ctype)
{
DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
pedwarn ("%<static%> may not be used when defining "
"(as opposed to declaring) a static data member");
staticp = 0;
storage_class = sc_none;
}
if (storage_class == sc_register && TREE_STATIC (decl))
{
error ("static member %qD declared %<register%>", decl);
storage_class = sc_none;
}
if (storage_class == sc_extern && pedantic)
{
pedwarn ("cannot explicitly declare member %q#D to have "
"extern linkage",
decl);
storage_class = sc_none;
}
}
}
if (storage_class == sc_register)
DECL_REGISTER (decl) = 1;
else if (storage_class == sc_extern)
DECL_THIS_EXTERN (decl) = 1;
else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
if (!processing_template_decl)
cp_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
}
static void
require_complete_types_for_parms (tree parms)
{
for (; parms; parms = TREE_CHAIN (parms))
{
if (dependent_type_p (TREE_TYPE (parms)))
continue;
if (VOID_TYPE_P (TREE_TYPE (parms)))
TREE_TYPE (parms) = error_mark_node;
else if (complete_type_or_else (TREE_TYPE (parms), parms))
{
layout_decl (parms, 0);
DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
}
}
}
int
local_variable_p (tree t)
{
if ((TREE_CODE (t) == VAR_DECL
&& !TYPE_P (CP_DECL_CONTEXT (t))
&& !DECL_NAMESPACE_SCOPE_P (t))
|| (TREE_CODE (t) == PARM_DECL))
return 1;
return 0;
}
int
nonstatic_local_decl_p (tree t)
{
return ((local_variable_p (t) && !TREE_STATIC (t))
|| TREE_CODE (t) == LABEL_DECL
|| TREE_CODE (t) == RESULT_DECL);
}
static tree
local_variable_p_walkfn (tree *tp, int *walk_subtrees,
void *data ATTRIBUTE_UNUSED)
{
if (local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp))
return *tp;
else if (TYPE_P (*tp))
*walk_subtrees = 0;
return NULL_TREE;
}
tree
check_default_argument (tree decl, tree arg)
{
tree var;
tree decl_type;
if (TREE_CODE (arg) == DEFAULT_ARG)
return arg;
if (processing_template_decl || uses_template_parms (arg))
return arg;
if (TYPE_P (decl))
{
decl_type = decl;
decl = NULL_TREE;
}
else
decl_type = TREE_TYPE (decl);
if (arg == error_mark_node
|| decl == error_mark_node
|| TREE_TYPE (arg) == error_mark_node
|| decl_type == error_mark_node)
return error_mark_node;
if (!TREE_TYPE (arg)
|| !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
{
if (decl)
error ("default argument for %q#D has type %qT",
decl, TREE_TYPE (arg));
else
error ("default argument for parameter of type %qT has type %qT",
decl_type, TREE_TYPE (arg));
return error_mark_node;
}
var = walk_tree_without_duplicates (&arg, local_variable_p_walkfn,
NULL);
if (var)
{
error ("default argument %qE uses local variable %qD", arg, var);
return error_mark_node;
}
return arg;
}
static tree
grokparms (cp_parameter_declarator *first_parm, tree *parms)
{
tree result = NULL_TREE;
tree decls = NULL_TREE;
int ellipsis = !first_parm || first_parm->ellipsis_p;
cp_parameter_declarator *parm;
int any_error = 0;
for (parm = first_parm; parm != NULL; parm = parm->next)
{
tree type = NULL_TREE;
tree init = parm->default_argument;
tree attrs;
tree decl;
if (parm == no_parameters)
break;
attrs = parm->decl_specifiers.attributes;
parm->decl_specifiers.attributes = NULL_TREE;
decl = grokdeclarator (parm->declarator, &parm->decl_specifiers,
PARM, init != NULL_TREE, &attrs);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
if (attrs)
cplus_decl_attributes (&decl, attrs, 0);
type = TREE_TYPE (decl);
if (VOID_TYPE_P (type))
{
if (same_type_p (type, void_type_node)
&& !DECL_NAME (decl) && !result && !parm->next && !ellipsis)
break;
cxx_incomplete_type_error (decl, type);
type = error_mark_node;
TREE_TYPE (decl) = error_mark_node;
}
if (type != error_mark_node)
{
type = cp_build_qualified_type (type, 0);
if (TREE_CODE (type) == METHOD_TYPE)
{
error ("parameter %qD invalidly declared method type", decl);
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
else if (abstract_virtuals_error (decl, type))
any_error = 1;
else if (POINTER_TYPE_P (type))
{
tree t = TREE_TYPE (type);
int ptr = TYPE_PTR_P (type);
while (1)
{
if (TYPE_PTR_P (t))
ptr = 1;
else if (TREE_CODE (t) != ARRAY_TYPE)
break;
else if (!TYPE_DOMAIN (t))
break;
t = TREE_TYPE (t);
}
if (TREE_CODE (t) == ARRAY_TYPE)
error ("parameter %qD includes %s to array of unknown "
"bound %qT",
decl, ptr ? "pointer" : "reference", t);
}
if (!any_error && init)
init = check_default_argument (decl, init);
else
init = NULL_TREE;
}
TREE_CHAIN (decl) = decls;
decls = decl;
result = tree_cons (init, type, result);
}
decls = nreverse (decls);
result = nreverse (result);
if (!ellipsis)
result = chainon (result, void_list_node);
*parms = decls;
return result;
}
int
copy_fn_p (tree d)
{
tree args;
tree arg_type;
int result = 1;
gcc_assert (DECL_FUNCTION_MEMBER_P (d));
if (DECL_TEMPLATE_INFO (d)
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d)))
return 0;
args = FUNCTION_FIRST_USER_PARMTYPE (d);
if (!args)
return 0;
arg_type = TREE_VALUE (args);
if (TYPE_MAIN_VARIANT (arg_type) == DECL_CONTEXT (d))
{
result = -1;
}
else if (TREE_CODE (arg_type) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
{
if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
result = 2;
}
else
return 0;
args = TREE_CHAIN (args);
if (args && args != void_list_node && !TREE_PURPOSE (args))
return 0;
return result;
}
void grok_special_member_properties (tree decl)
{
if (!DECL_NONSTATIC_MEMBER_FUNCTION_P(decl))
;
else if (DECL_CONSTRUCTOR_P (decl))
{
int ctor = copy_fn_p (decl);
if (ctor > 0)
{
TYPE_HAS_INIT_REF (DECL_CONTEXT (decl)) = 1;
if (ctor > 1)
TYPE_HAS_CONST_INIT_REF (DECL_CONTEXT (decl)) = 1;
}
else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
TYPE_HAS_DEFAULT_CONSTRUCTOR (DECL_CONTEXT (decl)) = 1;
}
else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
{
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;
}
}
}
int
grok_ctor_properties (tree ctype, tree decl)
{
int ctor_parm = copy_fn_p (decl);
if (ctor_parm < 0)
{
error ("invalid constructor; you probably meant %<%T (const %T&)%>",
ctype, ctype);
return 0;
}
return 1;
}
static int
ambi_op_p (enum tree_code code)
{
return (code == INDIRECT_REF
|| code == ADDR_EXPR
|| code == CONVERT_EXPR
|| code == NEGATE_EXPR
|| code == PREINCREMENT_EXPR
|| code == PREDECREMENT_EXPR);
}
static int
unary_op_p (enum tree_code code)
{
return (code == TRUTH_NOT_EXPR
|| code == BIT_NOT_EXPR
|| code == COMPONENT_REF
|| code == TYPE_EXPR);
}
bool
grok_op_properties (tree decl, int friendp, bool complain)
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree argtype;
int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
tree name = DECL_NAME (decl);
enum tree_code operator_code;
int arity;
bool ok;
ok = true;
for (argtype = argtypes, arity = 0;
argtype && argtype != void_list_node;
argtype = TREE_CHAIN (argtype))
++arity;
if (current_class_type == NULL_TREE)
friendp = 1;
if (DECL_CONV_FN_P (decl))
operator_code = TYPE_EXPR;
else
do
{
#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \
if (ansi_opname (CODE) == name) \
{ \
operator_code = (CODE); \
break; \
} \
else if (ansi_assopname (CODE) == name) \
{ \
operator_code = (CODE); \
DECL_ASSIGNMENT_OPERATOR_P (decl) = 1; \
break; \
}
#include "operators.def"
#undef DEF_OPERATOR
gcc_unreachable ();
}
while (0);
gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
if (! friendp)
{
switch (operator_code)
{
case NEW_EXPR:
TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
break;
case DELETE_EXPR:
TYPE_GETS_DELETE (current_class_type) |= 1;
break;
case VEC_NEW_EXPR:
TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
break;
case VEC_DELETE_EXPR:
TYPE_GETS_DELETE (current_class_type) |= 2;
break;
default:
break;
}
}
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 ("%qD may not be declared within a namespace", decl);
else if (!TREE_PUBLIC (decl))
error ("%qD 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)
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
else
{
if (! methodp || DECL_STATIC_FUNCTION_P (decl))
{
if (operator_code == TYPE_EXPR
|| operator_code == CALL_EXPR
|| operator_code == COMPONENT_REF
|| operator_code == ARRAY_REF
|| operator_code == NOP_EXPR)
error ("%qD must be a nonstatic member function", decl);
else
{
tree p;
if (DECL_STATIC_FUNCTION_P (decl))
error ("%qD must be either a non-static member "
"function or a non-member function", decl);
for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
{
tree arg = non_reference (TREE_VALUE (p));
if (IS_AGGR_TYPE (arg) || TREE_CODE (arg) == ENUMERAL_TYPE)
break;
}
if (!p || p == void_list_node)
{
if (!complain)
return false;
error ("%qD must have an argument of class or "
"enumerated type",
decl);
ok = false;
}
}
}
if (operator_code == CALL_EXPR)
return ok;
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
tree t = TREE_TYPE (name);
if (! friendp)
{
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
const char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
if (TREE_CODE (t) == VOID_TYPE)
what = "void";
else if (t == current_class_type)
what = "the same type";
else if (IS_AGGR_TYPE (t)
&& COMPLETE_TYPE_P (t)
&& DERIVED_FROM_P (t, current_class_type))
what = "a base class";
if (what && warn_conversion)
warning ("conversion to %s%s will never use a type "
"conversion operator",
ref ? "a reference to " : "", what);
}
}
if (operator_code == COND_EXPR)
{
error ("ISO C++ prohibits overloading operator ?:");
}
else if (ambi_op_p (operator_code))
{
if (arity == 1)
;
else if (arity == 2)
{
switch (operator_code)
{
case INDIRECT_REF:
operator_code = MULT_EXPR;
break;
case ADDR_EXPR:
operator_code = BIT_AND_EXPR;
break;
case CONVERT_EXPR:
operator_code = PLUS_EXPR;
break;
case NEGATE_EXPR:
operator_code = MINUS_EXPR;
break;
case PREINCREMENT_EXPR:
operator_code = POSTINCREMENT_EXPR;
break;
case PREDECREMENT_EXPR:
operator_code = POSTDECREMENT_EXPR;
break;
default:
gcc_unreachable ();
}
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
if ((operator_code == POSTINCREMENT_EXPR
|| operator_code == POSTDECREMENT_EXPR)
&& ! processing_template_decl
&& ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
if (methodp)
error ("postfix %qD must take %<int%> as its argument",
decl);
else
error
("postfix %qD must take %<int%> as its second argument",
decl);
}
}
else
{
if (methodp)
error ("%qD must take either zero or one argument", decl);
else
error ("%qD must take either one or two arguments", decl);
}
if (warn_ecpp
&& (operator_code == POSTINCREMENT_EXPR
|| operator_code == POSTDECREMENT_EXPR
|| operator_code == PREINCREMENT_EXPR
|| operator_code == PREDECREMENT_EXPR))
{
tree arg = TREE_VALUE (argtypes);
tree ret = TREE_TYPE (TREE_TYPE (decl));
if (methodp || TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
arg = TYPE_MAIN_VARIANT (arg);
if (operator_code == PREINCREMENT_EXPR
|| operator_code == PREDECREMENT_EXPR)
{
if (TREE_CODE (ret) != REFERENCE_TYPE
|| !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
arg))
warning ("prefix %qD should return %qT", decl,
build_reference_type (arg));
}
else
{
if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
warning ("postfix %qD should return %qT", decl, arg);
}
}
}
else if (unary_op_p (operator_code))
{
if (arity != 1)
{
if (methodp)
error ("%qD must take %<void%>", decl);
else
error ("%qD must take exactly one argument", decl);
}
}
else
{
if (arity != 2)
{
if (methodp)
error ("%qD must take exactly one argument", decl);
else
error ("%qD must take exactly two arguments", decl);
}
if (warn_ecpp
&& (operator_code == TRUTH_ANDIF_EXPR
|| operator_code == TRUTH_ORIF_EXPR
|| operator_code == COMPOUND_EXPR))
warning ("user-defined %qD always evaluates both arguments",
decl);
}
if (warn_ecpp
&& arity == 2
&& !DECL_ASSIGNMENT_OPERATOR_P (decl)
&& (operator_code == PLUS_EXPR
|| operator_code == MINUS_EXPR
|| operator_code == TRUNC_DIV_EXPR
|| operator_code == MULT_EXPR
|| operator_code == TRUNC_MOD_EXPR)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
warning ("%qD should return by value", decl);
for (; argtypes && argtypes != void_list_node;
argtypes = TREE_CHAIN (argtypes))
if (TREE_PURPOSE (argtypes))
{
TREE_PURPOSE (argtypes) = NULL_TREE;
if (operator_code == POSTINCREMENT_EXPR
|| operator_code == POSTDECREMENT_EXPR)
{
if (pedantic)
pedwarn ("%qD cannot have default arguments", decl);
}
else
error ("%qD cannot have default arguments", decl);
}
}
return ok;
}
static const char *
tag_name (enum tag_types code)
{
switch (code)
{
case record_type:
return "struct";
case class_type:
return "class";
case union_type:
return "union";
case enum_type:
return "enum";
case typename_type:
return "typename";
default:
gcc_unreachable ();
}
}
tree
check_elaborated_type_specifier (enum tag_types tag_code,
tree decl,
bool allow_template_p)
{
tree type;
if (DECL_SELF_REFERENCE_P (decl))
decl = TYPE_NAME (TREE_TYPE (decl));
type = TREE_TYPE (decl);
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
{
error ("using template type parameter %qT after %qs",
type, tag_name (tag_code));
return error_mark_node;
}
else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
&& tag_code != typename_type)
{
error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
cp_error_at ("%qD has a previous declaration here", decl);
return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE
&& tag_code != enum_type
&& tag_code != typename_type)
{
error ("%qT referred to as %qs", type, tag_name (tag_code));
cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
&& tag_code == enum_type
&& tag_code != typename_type)
{
error ("%qT referred to as enum", type);
cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node;
}
else if (!allow_template_p
&& TREE_CODE (type) == RECORD_TYPE
&& CLASSTYPE_IS_TEMPLATE (type))
{
error ("template argument required for %<%s %T%>",
tag_name (tag_code),
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
return error_mark_node;
}
return type;
}
static tree
lookup_and_check_tag (enum tag_types tag_code, tree name,
tag_scope scope, bool template_header_p)
{
tree t;
tree decl;
if (scope == ts_global)
decl = lookup_name (name, 2);
else
decl = lookup_type_scope (name, scope);
if (decl && DECL_CLASS_TEMPLATE_P (decl))
decl = DECL_TEMPLATE_RESULT (decl);
if (decl && TREE_CODE (decl) == TYPE_DECL)
{
if (scope == ts_current && DECL_SELF_REFERENCE_P (decl))
{
error ("%qD has the same name as the class in which it is "
"declared",
decl);
return error_mark_node;
}
t = check_elaborated_type_specifier (tag_code,
decl,
template_header_p
| DECL_SELF_REFERENCE_P (decl));
return t;
}
else
return NULL_TREE;
}
tree
xref_tag (enum tag_types tag_code, tree name,
tag_scope scope, bool template_header_p)
{
enum tree_code code;
tree t;
tree context = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
switch (tag_code)
{
case record_type:
case class_type:
code = RECORD_TYPE;
break;
case union_type:
code = UNION_TYPE;
break;
case enum_type:
code = ENUMERAL_TYPE;
break;
default:
gcc_unreachable ();
}
if (ANON_AGGRNAME_P (name))
t = NULL_TREE;
else
t = lookup_and_check_tag (tag_code, name,
scope, template_header_p);
if (t == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (scope != ts_current && t && current_class_type
&& template_class_depth (current_class_type)
&& template_header_p)
{
context = TYPE_CONTEXT (t);
t = NULL_TREE;
}
if (! t)
{
if (code == ENUMERAL_TYPE)
{
error ("use of enum %q#D without previous declaration", name);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
{
t = make_aggr_type (code);
TYPE_CONTEXT (t) = context;
t = pushtag (name, t, scope != ts_current);
}
}
else
{
if (template_header_p && IS_AGGR_TYPE (t))
redeclare_class_template (t, current_template_parms);
else if (!processing_template_decl
&& CLASS_TYPE_P (t)
&& CLASSTYPE_IS_TEMPLATE (t))
{
error ("redeclaration of %qT as a non-template", t);
t = error_mark_node;
}
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
tree
xref_tag_from_type (tree old, tree id, tag_scope scope)
{
enum tag_types tag_kind;
if (TREE_CODE (old) == RECORD_TYPE)
tag_kind = (CLASSTYPE_DECLARED_CLASS (old) ? class_type : record_type);
else
tag_kind = union_type;
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
return xref_tag (tag_kind, id, scope, false);
}
void
xref_basetypes (tree ref, tree base_list)
{
tree *basep;
tree binfo, base_binfo;
unsigned max_vbases = 0;
unsigned max_bases = 0;
int i;
tree default_access;
tree igo_prev;
if (ref == error_mark_node)
return;
default_access = (TREE_CODE (ref) == RECORD_TYPE
&& CLASSTYPE_DECLARED_CLASS (ref)
? access_private_node : access_public_node);
basep = &base_list;
while (*basep)
{
tree basetype = TREE_VALUE (*basep);
if (!(processing_template_decl && uses_template_parms (basetype))
&& !complete_type_or_else (basetype, NULL))
*basep = TREE_CHAIN (*basep);
else
{
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);
}
}
TYPE_MARKED_P (ref) = 1;
gcc_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref));
gcc_assert (TYPE_MAIN_VARIANT (ref) == ref);
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);
CLASSTYPE_NON_AGGREGATE (ref) = 1;
if (TREE_CODE (ref) == UNION_TYPE)
error ("derived union %qT invalid", ref);
}
if (max_bases > 1)
{
if (TYPE_FOR_JAVA (ref))
error ("Java class %qT cannot have multiple bases", ref);
}
if (max_vbases)
{
CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases);
if (TYPE_FOR_JAVA (ref))
error ("Java class %qT cannot have virtual bases", ref);
}
for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list))
{
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)
{
error ("base type %qT fails to be a struct or class type",
basetype);
continue;
}
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);
basetype = BINFO_TYPE (base_binfo);
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_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype);
CLASSTYPE_DIAMOND_SHAPED_P (ref)
|= CLASSTYPE_DIAMOND_SHAPED_P (basetype);
CLASSTYPE_REPEATED_BASE_P (ref)
|= CLASSTYPE_REPEATED_BASE_P (basetype);
}
if (TYPE_MARKED_P (basetype))
{
if (basetype == ref)
error ("recursive type %qT undefined", basetype);
else
error ("duplicate base type %qT invalid", basetype);
continue;
}
TYPE_MARKED_P (basetype) = 1;
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);
}
if (VEC_space (tree, CLASSTYPE_VBASECLASSES (ref), 1))
CLASSTYPE_DIAMOND_SHAPED_P (ref) = 1;
for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0;
TYPE_MARKED_P (ref) = 0;
if (!CLASSTYPE_REPEATED_BASE_P (ref))
{
for (base_binfo = binfo; base_binfo;
base_binfo = TREE_CHAIN (base_binfo))
{
if (TYPE_MARKED_P (BINFO_TYPE (base_binfo)))
{
CLASSTYPE_REPEATED_BASE_P (ref) = 1;
break;
}
TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 1;
}
for (base_binfo = binfo; base_binfo;
base_binfo = TREE_CHAIN (base_binfo))
if (TYPE_MARKED_P (BINFO_TYPE (base_binfo)))
TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0;
else
break;
}
}
tree
start_enum (tree name)
{
tree enumtype;
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
enumtype = lookup_and_check_tag (enum_type, name,
ts_current,
false);
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
{
error ("multiple definition of %q#T", enumtype);
error ("%Jprevious definition here", TYPE_MAIN_DECL (enumtype));
TYPE_VALUES (enumtype) = NULL_TREE;
}
else
{
if (enumtype == error_mark_node)
name = make_anon_name ();
enumtype = make_node (ENUMERAL_TYPE);
enumtype = pushtag (name, enumtype, 0);
}
return enumtype;
}
void
finish_enum (tree enumtype)
{
tree values;
tree decl;
tree value;
tree minnode;
tree maxnode;
tree t;
bool unsignedp;
bool use_short_enum;
int lowprec;
int highprec;
int precision;
integer_type_kind itk;
tree underlying_type = NULL_TREE;
TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
if (processing_template_decl)
{
for (values = TYPE_VALUES (enumtype);
values;
values = TREE_CHAIN (values))
TREE_TYPE (TREE_VALUE (values)) = enumtype;
if (at_function_scope_p ())
add_stmt (build_min (TAG_DEFN, enumtype));
return;
}
if (TYPE_VALUES (enumtype))
{
minnode = maxnode = NULL_TREE;
for (values = TYPE_VALUES (enumtype);
values;
values = TREE_CHAIN (values))
{
decl = TREE_VALUE (values);
TREE_TYPE (decl) = enumtype;
value = DECL_INITIAL (decl);
if (!minnode)
minnode = maxnode = value;
else if (tree_int_cst_lt (maxnode, value))
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
}
}
else
minnode = maxnode = integer_zero_node;
unsignedp = tree_int_cst_sgn (minnode) >= 0;
lowprec = min_precision (minnode, unsignedp);
highprec = min_precision (maxnode, unsignedp);
precision = MAX (lowprec, highprec);
use_short_enum = flag_short_enums
|| lookup_attribute ("packed", TYPE_ATTRIBUTES (enumtype));
for (itk = (use_short_enum ? itk_char : itk_int);
itk != itk_none;
itk++)
{
underlying_type = integer_types[itk];
if (TYPE_PRECISION (underlying_type) >= precision
&& TYPE_UNSIGNED (underlying_type) == unsignedp)
break;
}
if (itk == itk_none)
{
error ("no integral type can represent all of the enumerator values "
"for %qT", enumtype);
precision = TYPE_PRECISION (long_long_integer_type_node);
underlying_type = integer_types[itk_unsigned_long_long];
}
TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
TYPE_SIZE (enumtype) = TYPE_SIZE (underlying_type);
TYPE_SIZE_UNIT (enumtype) = TYPE_SIZE_UNIT (underlying_type);
TYPE_MODE (enumtype) = TYPE_MODE (underlying_type);
TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type);
TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type);
TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (underlying_type);
for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
{
decl = TREE_VALUE (values);
value = perform_implicit_conversion (underlying_type,
DECL_INITIAL (decl));
value = copy_node (value);
TREE_TYPE (value) = enumtype;
DECL_INITIAL (decl) = value;
TREE_VALUE (values) = value;
}
for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t))
{
TYPE_VALUES (t) = TYPE_VALUES (enumtype);
TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (enumtype);
TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (enumtype);
TYPE_SIZE (t) = TYPE_SIZE (enumtype);
TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (enumtype);
TYPE_MODE (t) = TYPE_MODE (enumtype);
TYPE_PRECISION (t) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (t) = TYPE_ALIGN (enumtype);
TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (enumtype);
TYPE_UNSIGNED (t) = TYPE_UNSIGNED (enumtype);
}
rest_of_type_compilation (enumtype, namespace_bindings_p ());
}
void
build_enumerator (tree name, tree value, tree enumtype)
{
tree decl;
tree context;
tree type;
if (value == error_mark_node)
value = NULL_TREE;
if (value)
STRIP_TYPE_NOPS (value);
if (! processing_template_decl)
{
if (value != NULL_TREE)
{
value = integral_constant_value (value);
if (TREE_CODE (value) == INTEGER_CST)
{
value = perform_integral_promotions (value);
constant_expression_warning (value);
}
else
{
error ("enumerator value for %qD not integer constant", name);
value = NULL_TREE;
}
}
if (value == NULL_TREE)
{
if (TYPE_VALUES (enumtype))
{
HOST_WIDE_INT hi;
unsigned HOST_WIDE_INT lo;
tree prev_value;
bool overflowed;
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
overflowed = add_double (TREE_INT_CST_LOW (prev_value),
TREE_INT_CST_HIGH (prev_value),
1, 0, &lo, &hi);
value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
overflowed |= !int_fits_type_p (value, TREE_TYPE (prev_value));
if (overflowed)
error ("overflow in enumeration values at %qD", name);
}
else
value = integer_zero_node;
}
STRIP_TYPE_NOPS (value);
}
context = current_scope ();
type = value ? TREE_TYPE (value) : NULL_TREE;
if (context && context == current_class_type)
decl = build_lang_decl (CONST_DECL, name, type);
else
decl = build_decl (CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
TREE_CONSTANT (decl) = 1;
TREE_INVARIANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;
if (context && context == current_class_type)
finish_member_declaration (decl);
else
pushdecl (decl);
TYPE_VALUES (enumtype) = tree_cons (name, decl, TYPE_VALUES (enumtype));
}
static void
check_function_type (tree decl, tree current_function_parms)
{
tree fntype = TREE_TYPE (decl);
tree return_type = complete_type (TREE_TYPE (fntype));
require_complete_types_for_parms (current_function_parms);
if (dependent_type_p (return_type))
return;
if (!COMPLETE_OR_VOID_TYPE_P (return_type))
{
error ("return type %q#T is incomplete", TREE_TYPE (fntype));
if (TREE_CODE (fntype) == METHOD_TYPE)
{
tree ctype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype)));
TREE_TYPE (decl)
= build_method_type_directly (ctype,
void_type_node,
FUNCTION_ARG_CHAIN (decl));
}
else
TREE_TYPE (decl)
= build_function_type (void_type_node,
TYPE_ARG_TYPES (TREE_TYPE (decl)));
TREE_TYPE (decl)
= build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (fntype));
}
else
abstract_virtuals_error (decl, TREE_TYPE (fntype));
}
void
start_preparsed_function (tree decl1, tree attrs, int flags)
{
tree ctype = NULL_TREE;
tree fntype;
tree restype;
int doing_friend = 0;
struct cp_binding_level *bl;
tree current_function_parms;
struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE);
fntype = TREE_TYPE (decl1);
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
if (!ctype && DECL_FRIEND_P (decl1))
{
ctype = DECL_FRIEND_CONTEXT (decl1);
if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
ctype = NULL_TREE;
else
doing_friend = 1;
}
if (DECL_DECLARED_INLINE_P (decl1)
&& lookup_attribute ("noinline", attrs))
warning ("%Jinline function %qD given attribute noinline", decl1, decl1);
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
adjust_clone_args (decl1);
if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)
&& TREE_CODE (TREE_TYPE (decl1)) == METHOD_TYPE)
{
revert_static_member_fn (decl1);
ctype = NULL_TREE;
}
if (ctype)
push_nested_class (ctype);
else if (DECL_STATIC_FUNCTION_P (decl1))
push_nested_class (DECL_CONTEXT (decl1));
if (flags & SF_INCLASS_INLINE)
maybe_begin_member_template_processing (decl1);
if (warn_ecpp
&& DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
&& TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
warning ("%<operator=%> should return a reference to %<*this%>");
if (!DECL_INITIAL (decl1))
DECL_INITIAL (decl1) = error_mark_node;
TREE_STATIC (decl1) = 1;
if (processing_template_decl)
{
tree newdecl1 = push_template_decl (decl1);
if (newdecl1 != error_mark_node)
decl1 = newdecl1;
}
current_function_decl = decl1;
current_function_parms = DECL_ARGUMENTS (decl1);
check_function_type (decl1, current_function_parms);
restype = TREE_TYPE (fntype);
if (c_promoting_integer_type_p (restype))
restype = type_promotes_to (restype);
if (DECL_RESULT (decl1) == NULL_TREE)
{
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;
cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
}
bl = current_binding_level;
allocate_struct_function (decl1);
current_binding_level = bl;
cfun->x_dont_save_pending_sizes_p = 1;
DECL_SAVED_TREE (decl1) = push_stmt_list ();
announce_function (decl1);
if (!processing_template_decl && !(flags & SF_PRE_PARSED))
{
if (!DECL_FUNCTION_MEMBER_P (decl1)
&& !(DECL_USE_TEMPLATE (decl1) &&
PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl1))))
{
tree olddecl = pushdecl (decl1);
if (olddecl == error_mark_node)
;
else
decl1 = olddecl;
}
else
{
if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
check_default_args (decl1);
}
fntype = TREE_TYPE (decl1);
}
if (!DECL_CLONED_FUNCTION_P (decl1))
determine_visibility (decl1);
current_function_decl = decl1;
cfun->decl = decl1;
if (!DECL_PENDING_INLINE_P (decl1))
DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
{
tree t = DECL_ARGUMENTS (decl1);
gcc_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL);
gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
cp_function_chain->x_current_class_ref
= build_indirect_ref (t, NULL);
cp_function_chain->x_current_class_ptr = t;
t = TREE_CHAIN (t);
if (DECL_HAS_IN_CHARGE_PARM_P (decl1))
{
current_in_charge_parm = t;
t = TREE_CHAIN (t);
}
if (DECL_HAS_VTT_PARM_P (decl1))
{
gcc_assert (DECL_NAME (t) == vtt_parm_identifier);
current_vtt_parm = t;
}
}
if (DECL_INTERFACE_KNOWN (decl1))
{
tree ctx = decl_function_context (decl1);
if (DECL_NOT_REALLY_EXTERN (decl1))
DECL_EXTERNAL (decl1) = 0;
if (ctx != NULL_TREE && DECL_DECLARED_INLINE_P (ctx)
&& TREE_PUBLIC (ctx))
comdat_linkage (decl1);
}
else if (finfo->interface_unknown == 0
&& ! DECL_TEMPLATE_INSTANTIATION (decl1))
{
if (DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1)
|| processing_template_decl)
{
DECL_EXTERNAL (decl1)
= (finfo->interface_only
|| (DECL_DECLARED_INLINE_P (decl1)
&& ! flag_implement_inlines
&& !DECL_VINDEX (decl1)));
maybe_make_one_only (decl1);
}
else
DECL_EXTERNAL (decl1) = 0;
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
if (!DECL_EXTERNAL (decl1))
mark_needed (decl1);
}
else if (finfo->interface_unknown && finfo->interface_only
&& ! DECL_TEMPLATE_INSTANTIATION (decl1))
{
comdat_linkage (decl1);
DECL_EXTERNAL (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
DECL_DEFER_OUTPUT (decl1) = 1;
}
else
{
DECL_EXTERNAL (decl1) = 0;
if ((DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))
&& ! DECL_INTERFACE_KNOWN (decl1)
&& ! decl_function_context (decl1))
DECL_DEFER_OUTPUT (decl1) = 1;
else
DECL_INTERFACE_KNOWN (decl1) = 1;
}
begin_scope (sk_function_parms, decl1);
++function_depth;
if (DECL_DESTRUCTOR_P (decl1)
|| (DECL_CONSTRUCTOR_P (decl1)
&& targetm.cxx.cdtor_returns_this ()))
{
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);
}
int
start_function (cp_decl_specifier_seq *declspecs,
const cp_declarator *declarator,
tree attrs)
{
tree decl1;
if (have_extern_spec)
{
declspecs->storage_class = sc_extern;
have_extern_spec = false;
}
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
return 0;
if (global_scope_p (current_binding_level))
maybe_apply_pragma_weak (decl1);
if (DECL_MAIN_P (decl1))
gcc_assert (same_type_p (TREE_TYPE (TREE_TYPE (decl1)),
integer_type_node));
start_preparsed_function (decl1, attrs, SF_DEFAULT);
return 1;
}
static void
store_parm_decls (tree current_function_parms)
{
tree fndecl = current_function_decl;
tree parm;
tree nonparms = NULL_TREE;
if (current_function_parms)
{
tree specparms = current_function_parms;
tree next;
current_binding_level->names = NULL;
specparms = nreverse (specparms);
for (parm = specparms; parm; parm = next)
{
next = TREE_CHAIN (parm);
if (TREE_CODE (parm) == PARM_DECL)
{
if (DECL_NAME (parm) == NULL_TREE
|| TREE_CODE (parm) != VOID_TYPE)
pushdecl (parm);
else
error ("parameter %qD declared void", parm);
}
else
{
TREE_CHAIN (parm) = NULL_TREE;
nonparms = chainon (nonparms, parm);
}
}
DECL_ARGUMENTS (fndecl) = getdecls ();
}
else
DECL_ARGUMENTS (fndecl) = NULL_TREE;
current_binding_level->names = chainon (nonparms, DECL_ARGUMENTS (fndecl));
if (!DECL_CLONED_FUNCTION_P (fndecl))
{
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 ();
}
}
static void
save_function_data (tree decl)
{
struct language_function *f;
gcc_assert (!DECL_PENDING_INLINE_P (decl));
f = GGC_NEW (struct language_function);
memcpy (f, cp_function_chain, sizeof (struct language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
f->base.x_stmt_tree.x_cur_stmt_list = NULL_TREE;
f->x_named_label_uses = NULL;
f->bindings = NULL;
f->x_local_names = NULL;
}
static void
finish_constructor_body (void)
{
tree val;
tree exprstmt;
if (targetm.cxx.cdtor_returns_this ())
{
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);
exprstmt = build_stmt (RETURN_EXPR, val);
add_stmt (exprstmt);
}
}
static void
begin_destructor_body (void)
{
tree if_stmt;
tree compound_stmt;
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (boolean_true_node, if_stmt);
compound_stmt = begin_compound_stmt (0);
initialize_vtbl_ptrs (current_class_ptr);
finish_compound_stmt (compound_stmt);
finish_then_clause (if_stmt);
finish_if_stmt (if_stmt);
push_base_cleanups ();
}
static void
finish_destructor_body (void)
{
tree exprstmt;
add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
if (DECL_VIRTUAL_P (current_function_decl))
{
tree if_stmt;
tree virtual_size = cxx_sizeof (current_class_type);
exprstmt = build_op_delete_call
(DELETE_EXPR, current_class_ptr, virtual_size,
false, NULL_TREE);
if_stmt = begin_if_stmt ();
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);
exprstmt = build_stmt (RETURN_EXPR, val);
add_stmt (exprstmt);
}
}
tree
begin_function_body (void)
{
tree stmt;
if (processing_template_decl)
;
else
keep_next_level (true);
stmt = begin_compound_stmt (BCS_FN_BODY);
if (processing_template_decl)
;
else if (DECL_DESTRUCTOR_P (current_function_decl))
begin_destructor_body ();
return stmt;
}
void
finish_function_body (tree compstmt)
{
finish_compound_stmt (compstmt);
if (processing_template_decl)
;
else if (DECL_CONSTRUCTOR_P (current_function_decl))
finish_constructor_body ();
else if (DECL_DESTRUCTOR_P (current_function_decl))
finish_destructor_body ();
}
tree
finish_function (int flags)
{
tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE;
int inclass_inline = (flags & 2) != 0;
int nested;
if (fndecl == NULL_TREE)
return error_mark_node;
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
&& DECL_VIRTUAL_P (fndecl)
&& !processing_template_decl)
{
tree fnclass = DECL_CONTEXT (fndecl);
if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
}
nested = function_depth > 1;
fntype = TREE_TYPE (fndecl);
gcc_assert (building_stmt_tree ());
if (!DECL_CLONED_FUNCTION_P (fndecl))
{
if (DECL_MAIN_P (current_function_decl))
{
tree stmt;
#if VMS_TARGET
stmt = finish_return_stmt (integer_one_node);
#else
stmt = finish_return_stmt (integer_zero_node);
#endif
annotate_with_file_line (stmt, input_filename, 0);
}
if (flag_exceptions && !processing_template_decl
&& flag_enforce_eh_specs
&& TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
finish_eh_spec_block (TYPE_RAISES_EXCEPTIONS
(TREE_TYPE (current_function_decl)),
current_eh_spec_block);
}
DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
finish_fname_decls ();
if (!processing_template_decl
&& !cp_function_chain->can_throw
&& !flag_non_call_exceptions)
TREE_NOTHROW (fndecl) = 1;
if (current_binding_level->kind != sk_function_parms)
{
gcc_assert (errorcount);
DECL_SAVED_TREE (fndecl) = alloc_stmt_list ();
while (current_binding_level->kind != sk_function_parms)
{
if (current_binding_level->kind == sk_class)
pop_nested_class ();
else
poplevel (0, 0, 0);
}
}
poplevel (1, 0, 1);
gcc_assert (stmts_are_full_exprs_p ());
if (current_function_return_value)
{
tree r = current_function_return_value;
tree outer;
if (r != error_mark_node
&& aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)), fndecl)
&& (outer = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl)))
&& (outer = BLOCK_SUBBLOCKS (outer))
&& chain_member (r, BLOCK_VARS (outer)))
finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl));
current_function_return_value = NULL_TREE;
}
if (current_class_name)
ctype = current_class_type;
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
if (!processing_template_decl)
save_function_data (fndecl);
if (warn_return_type
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
&& !dependent_type_p (TREE_TYPE (fntype))
&& !current_function_returns_value && !current_function_returns_null
&& !current_function_returns_abnormally
&& !DECL_NAME (DECL_RESULT (fndecl))
&& (DECL_INLINE (fndecl) || processing_template_decl)
&& !DECL_CONSTRUCTOR_P (fndecl)
&& !DECL_DESTRUCTOR_P (fndecl))
warning ("no return statement in function returning non-void");
cfun->function_end_locus = input_location;
if (!processing_template_decl)
{
struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
cp_genericize (fndecl);
f->x_current_class_ptr = NULL;
f->x_current_class_ref = NULL;
f->x_eh_spec_block = NULL;
f->x_in_charge_parm = NULL;
f->x_vtt_parm = NULL;
f->x_return_value = NULL;
f->bindings = NULL;
c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
}
local_names = NULL;
named_label_uses = NULL;
cfun = NULL;
current_function_decl = NULL;
if (inclass_inline)
maybe_end_member_template_processing ();
if (ctype)
pop_nested_class ();
--function_depth;
if (! nested)
current_function_decl = NULL_TREE;
return fndecl;
}
tree
start_method (cp_decl_specifier_seq *declspecs,
const cp_declarator *declarator, tree attrlist)
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
&attrlist);
if (fndecl == error_mark_node)
return error_mark_node;
if (fndecl == NULL || TREE_CODE (fndecl) != FUNCTION_DECL)
{
error ("invalid member function declaration");
return error_mark_node;
}
if (attrlist)
cplus_decl_attributes (&fndecl, attrlist, 0);
if (fndecl == void_type_node)
return fndecl;
if (DECL_IN_AGGR_P (fndecl))
{
if (DECL_CONTEXT (fndecl)
&& TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
error ("%qD is already defined in class %qT", fndecl,
DECL_CONTEXT (fndecl));
return void_type_node;
}
check_template_shadow (fndecl);
DECL_DECLARED_INLINE_P (fndecl) = 1;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
{
fndecl = push_template_decl (fndecl);
if (fndecl == error_mark_node)
return fndecl;
}
if (! DECL_FRIEND_P (fndecl))
{
if (TREE_CHAIN (fndecl))
{
fndecl = copy_node (fndecl);
TREE_CHAIN (fndecl) = NULL_TREE;
}
grok_special_member_properties (fndecl);
}
cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
begin_scope (sk_function_parms, fndecl);
DECL_IN_AGGR_P (fndecl) = 1;
return fndecl;
}
tree
finish_method (tree decl)
{
tree fndecl = decl;
tree old_initial;
tree link;
if (decl == void_type_node)
return decl;
old_initial = DECL_INITIAL (fndecl);
for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != NULL_TREE)
pop_binding (DECL_NAME (link), link);
gcc_assert (TREE_CODE (link) != FUNCTION_DECL);
DECL_CONTEXT (link) = NULL_TREE;
}
poplevel (0, 0, 0);
DECL_INITIAL (fndecl) = old_initial;
if (DECL_FRIEND_P (fndecl))
{
VEC_safe_push (tree, CLASSTYPE_INLINE_FRIENDS (current_class_type),
fndecl);
decl = void_type_node;
}
return decl;
}
void
maybe_register_incomplete_var (tree var)
{
gcc_assert (TREE_CODE (var) == VAR_DECL);
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))
|| (TYPE_LANG_SPECIFIC (inner_type)
&& TYPE_BEING_DEFINED (inner_type)))
incomplete_vars = tree_cons (inner_type, var, incomplete_vars);
}
}
void
complete_vars (tree type)
{
tree *list = &incomplete_vars;
gcc_assert (CLASS_TYPE_P (type));
while (*list)
{
if (same_type_p (type, TREE_PURPOSE (*list)))
{
tree var = TREE_VALUE (*list);
tree type = TREE_TYPE (var);
complete_type (type);
cp_apply_type_quals_to_decl (cp_type_quals (type), var);
*list = TREE_CHAIN (*list);
}
else
list = &TREE_CHAIN (*list);
}
complete_type_check_abstract (type);
}
tree
cxx_maybe_build_cleanup (tree decl)
{
tree type = TREE_TYPE (decl);
if (type != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
&& CLASSTYPE_VBASECLASSES (type));
if (TREE_CODE (type) == ARRAY_TYPE)
rval = decl;
else
{
cxx_mark_addressable (decl);
rval = build_unary_op (ADDR_EXPR, decl, 0);
}
if (!has_vbases || flag_expensive_optimizations)
flags |= LOOKUP_NONVIRTUAL;
rval = build_delete (TREE_TYPE (rval), rval,
sfk_complete_destructor, flags, 0);
return rval;
}
return NULL_TREE;
}
void
finish_stmt (void)
{
}
void
revert_static_member_fn (tree decl)
{
tree tmp;
tree function = TREE_TYPE (decl);
tree args = TYPE_ARG_TYPES (function);
if (cp_type_quals (TREE_TYPE (TREE_VALUE (args)))
!= TYPE_UNQUALIFIED)
error ("static member function %q#D declared with type qualifiers", decl);
args = TREE_CHAIN (args);
tmp = build_function_type (TREE_TYPE (function), args);
tmp = build_qualified_type (tmp, cp_type_quals (function));
tmp = build_exception_variant (tmp,
TYPE_RAISES_EXCEPTIONS (function));
TREE_TYPE (decl) = tmp;
if (DECL_ARGUMENTS (decl))
DECL_ARGUMENTS (decl) = TREE_CHAIN (DECL_ARGUMENTS (decl));
DECL_STATIC_FUNCTION_P (decl) = 1;
}
void
cxx_push_function_context (struct function * f)
{
struct language_function *p = GGC_CNEW (struct language_function);
f->language = p;
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
if (f->decl)
{
tree fn = f->decl;
if (DECL_SAVED_FUNCTION_DATA (fn))
{
*cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
if (! DECL_INLINE (fn))
DECL_SAVED_FUNCTION_DATA (fn) = NULL;
}
}
}
void
cxx_pop_function_context (struct function * f)
{
f->language = 0;
}
enum cp_tree_node_structure_enum
cp_tree_node_structure (union lang_tree_node * t)
{
switch (TREE_CODE (&t->generic))
{
case DEFAULT_ARG: return TS_CP_DEFAULT_ARG;
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;
}
}
tree
build_void_list_node (void)
{
tree t = build_tree_list (NULL_TREE, void_type_node);
return t;
}
bool
cp_missing_noreturn_ok_p (tree decl)
{
return DECL_MAIN_P (decl);
}
const char *
cxx_comdat_group (tree decl)
{
tree name;
if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl))
name = DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (DECL_CONTEXT (decl)));
else
{
while (DECL_THUNK_P (decl))
{
tree target = THUNK_TARGET (decl);
if (TARGET_USE_LOCAL_THUNK_ALIAS_P (target)
&& DECL_SECTION_NAME (target) != NULL
&& DECL_ONE_ONLY (target))
decl = target;
else
break;
}
name = DECL_ASSEMBLER_NAME (decl);
}
return IDENTIFIER_POINTER (name);
}
#include "gt-cp-decl.h"