#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"
#include "opts.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 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);
tree cp_global_trees[CPTI_MAX];
tree global_type_node;
tree global_scope_name;
#define local_names cp_function_chain->x_local_names
tree static_aggregates;
tree integer_two_node, integer_three_node;
struct named_label_use_entry GTY(())
{
struct named_label_use_entry *next;
struct cp_binding_level *binding_level;
tree names_in_scope;
location_t o_goto_locus;
bool in_omp_scope;
};
struct named_label_entry GTY(())
{
tree label_decl;
struct cp_binding_level *binding_level;
tree names_in_scope;
tree bad_decls;
struct named_label_use_entry *uses;
bool in_try_scope;
bool in_catch_scope;
bool in_omp_scope;
};
#define named_labels cp_function_chain->x_named_labels
int function_depth;
enum deprecated_states {
DEPRECATED_NORMAL,
DEPRECATED_SUPPRESS
, DEPRECATED_UNAVAILABLE_SUPPRESS
};
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
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;
error ("label %q+D 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 (!TREE_USED (label))
warning (OPT_Wunused_label, "label %q+D defined but not used", label);
}
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
}
static int
pop_labels_1 (void **slot, void *data)
{
struct named_label_entry *ent = (struct named_label_entry *) *slot;
tree block = (tree) data;
pop_label (ent->label_decl, NULL_TREE);
TREE_CHAIN (ent->label_decl) = BLOCK_VARS (block);
BLOCK_VARS (block) = ent->label_decl;
htab_clear_slot (named_labels, slot);
return 1;
}
static void
pop_labels (tree block)
{
if (named_labels)
{
htab_traverse (named_labels, pop_labels_1, block);
named_labels = NULL;
}
}
static void
pop_local_label (tree label, tree old_value)
{
struct named_label_entry dummy;
void **slot;
pop_label (label, old_value);
dummy.label_decl = label;
slot = htab_find_slot (named_labels, &dummy, NO_INSERT);
htab_clear_slot (named_labels, slot);
}
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 = scope->level_chain)
{
tree decl;
for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
objc_volatilize_decl (decl);
if (scope->kind == sk_function_parms)
break;
}
}
static int
poplevel_named_label_1 (void **slot, void *data)
{
struct named_label_entry *ent = (struct named_label_entry *) *slot;
struct cp_binding_level *bl = (struct cp_binding_level *) data;
struct cp_binding_level *obl = bl->level_chain;
if (ent->binding_level == bl)
{
tree decl;
for (decl = ent->names_in_scope; decl; decl = TREE_CHAIN (decl))
if (decl_jump_unsafe (decl))
ent->bad_decls = tree_cons (NULL, decl, ent->bad_decls);
ent->binding_level = obl;
ent->names_in_scope = obl->names;
switch (bl->kind)
{
case sk_try:
ent->in_try_scope = true;
break;
case sk_catch:
ent->in_catch_scope = true;
break;
case sk_omp:
ent->in_omp_scope = true;
break;
default:
break;
}
}
else if (ent->uses)
{
struct named_label_use_entry *use;
for (use = ent->uses; use ; use = use->next)
if (use->binding_level == bl)
{
use->binding_level = obl;
use->names_in_scope = obl->names;
if (bl->kind == sk_omp)
use->in_omp_scope = true;
}
}
return 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 && named_labels)
htab_traverse (named_labels, poplevel_named_label_1,
current_binding_level);
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 (OPT_Wunused_variable, "unused variable %q+D", 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)
{
SET_DECL_SHADOWED_FOR_VAR (link, ob->value);
DECL_HAS_SHADOWED_FOR_VAR_P (link) = 1;
}
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_local_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)
\
{
gcc_assert (DECL_INITIAL (current_function_decl) == error_mark_node);
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);
VEC(tree,gc) *statics = level->static_decls;
tree *vec = VEC_address (tree, statics);
int len = VEC_length (tree, statics);
int last_time = (data != 0);
if (last_time)
{
check_global_declarations (vec, len);
emit_debug_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);
name = DECL_NAME (decl);
nelts = VEC_length (tree, local_names);
for (i = 0; i < nelts; i++)
{
t = VEC_index (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;
VEC_replace (tree, local_names, i, decl);
timevar_pop (TV_NAME_LOOKUP);
return;
}
}
VEC_safe_push (tree, gc, 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)
&& !(DECL_EXTERN_C_P (olddecl) && DECL_EXTERN_C_P (newdecl)))
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);
pedwarn ("previous declaration of %q+D", olddecl);
}
static void
check_redeclaration_exception_specification (tree new_decl,
tree old_decl)
{
tree new_type;
tree old_type;
tree new_exceptions;
tree old_exceptions;
new_type = TREE_TYPE (new_decl);
new_exceptions = TYPE_RAISES_EXCEPTIONS (new_type);
old_type = TREE_TYPE (old_decl);
old_exceptions = TYPE_RAISES_EXCEPTIONS (old_type);
if ((pedantic || ! DECL_IN_SYSTEM_HEADER (old_decl))
&& ! DECL_IS_BUILTIN (old_decl)
&& flag_exceptions
&& !comp_except_specs (new_exceptions, old_exceptions,
true))
{
error ("declaration of %qF throws different exceptions", new_decl);
error ("from previous declaration %q+F", old_decl);
}
}
tree
duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
{
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
int new_defines_function = 0;
tree new_template;
if (newdecl == olddecl)
return olddecl;
types_match = decls_match (newdecl, olddecl);
if (TREE_TYPE (newdecl) == error_mark_node
|| TREE_TYPE (olddecl) == error_mark_node)
return error_mark_node;
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 (OPT_Wattributes, "function %q+D redeclared as inline",
newdecl);
warning (OPT_Wattributes, "previous declaration of %q+D "
"with attribute noinline", olddecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
warning (OPT_Wattributes, "function %q+D redeclared with "
"attribute noinline", newdecl);
warning (OPT_Wattributes, "previous declaration of %q+D was inline",
olddecl);
}
}
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
{
gcc_assert (!DECL_HIDDEN_FRIEND_P (olddecl));
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
if (DECL_ANTICIPATED (olddecl))
return NULL_TREE;
if (! TREE_PUBLIC (newdecl))
{
warning (OPT_Wshadow, "shadowing %s function %q#D",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
return NULL_TREE;
}
else if (! DECL_BUILT_IN (olddecl))
warning (0, "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,
newdecl_is_friend);
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 (0, "new declaration %q#D", newdecl);
warning (0, "ambiguates built-in declaration %q#D",
olddecl);
}
else
warning (OPT_Wshadow, "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 (c_dialect_objc () && DECL_P (newdecl))
objc_check_global_decl (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);
error ("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);
error ("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);
error ("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);
error ("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);
error ("ambiguates old declaration %q+#D", olddecl);
return error_mark_node;
}
else
return NULL_TREE;
}
else
{
error ("conflicting declaration %q#D", newdecl);
error ("%q+D 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);
error ("previous declaration of namespace %q+D 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)
error ((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)
{
warning (0, "prototype for %q+#D", newdecl);
warning (0, "%Jfollows non-prototype definition here", olddecl);
}
else if ((TREE_CODE (olddecl) == FUNCTION_DECL
|| TREE_CODE (olddecl) == VAR_DECL)
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
{
if (current_lang_depth () == 0)
{
if (!DECL_LANG_SPECIFIC (newdecl))
retrofit_lang_decl (newdecl);
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
}
else
{
error ("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);
pedwarn ("after previous specification in %q+#D", olddecl);
}
else
{
error ("default argument given for parameter %d of %q#D",
i, newdecl);
error ("after previous specification in %q+#D",
olddecl);
}
}
if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& TREE_ADDRESSABLE (olddecl) && warn_inline)
{
warning (0, "%q#D was used before it was declared inline", newdecl);
warning (0, "%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_INVALID_OVERRIDER_P (newdecl) |= DECL_INVALID_OVERRIDER_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))
&& ! (newdecl_is_friend || DECL_FRIEND_P (olddecl)))
{
warning (OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", newdecl);
warning (OPT_Wredundant_decls, "previous declaration of %q+D", 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 old_result;
tree new_result;
old_result = DECL_TEMPLATE_RESULT (olddecl);
new_result = DECL_TEMPLATE_RESULT (newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (old_result);
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
{
DECL_INLINE (old_result)
|= DECL_INLINE (new_result);
DECL_DECLARED_INLINE_P (old_result)
|= DECL_DECLARED_INLINE_P (new_result);
check_redeclaration_exception_specification (newdecl, olddecl);
}
\
\
if (DECL_INITIAL (old_result) == NULL_TREE
&& DECL_INITIAL (new_result) != NULL_TREE)
{
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (old_result)
= DECL_SOURCE_LOCATION (newdecl);
\
DECL_INITIAL (old_result) = DECL_INITIAL (new_result);
\
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
DECL_ARGUMENTS (old_result)
= DECL_ARGUMENTS (new_result);
}
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_NONTRIVIALLY_INITIALIZED_P (newdecl)
|= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
if (DECL_LANG_SPECIFIC (olddecl)
&& CP_DECL_THREADPRIVATE_P (olddecl))
{
if (!DECL_LANG_SPECIFIC (newdecl))
retrofit_lang_decl (newdecl);
DECL_TLS_MODEL (newdecl) = DECL_TLS_MODEL (olddecl);
CP_DECL_THREADPRIVATE_P (newdecl) = 1;
}
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
check_redeclaration_exception_specification (newdecl, olddecl);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
if (TREE_CODE (newdecl) == FUNCTION_DECL)
check_default_args (newdecl);
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;
new_template = NULL_TREE;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
if (!DECL_USE_TEMPLATE (newdecl))
DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
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);
if (DECL_TEMPLATE_INFO (newdecl))
new_template = DECL_TI_TEMPLATE (newdecl);
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);
hidden_friend = (DECL_ANTICIPATED (olddecl)
&& DECL_HIDDEN_FRIEND_P (olddecl)
&& newdecl_is_friend);
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);
DECL_VISIBILITY_SPECIFIED (olddecl) = 0;
}
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 (OPT_Wattributes, "%q+D: visibility attribute ignored "
"because it", newdecl);
warning (OPT_Wattributes, "%Jconflicts with previous "
"declaration here", olddecl);
}
if (DECL_VISIBILITY_SPECIFIED (olddecl))
{
DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
}
if (TREE_CODE (newdecl) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (newdecl))
{
SET_DECL_INIT_PRIORITY (olddecl, DECL_INIT_PRIORITY (newdecl));
DECL_HAS_INIT_PRIORITY_P (olddecl) = 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_common);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
function_size - sizeof (struct tree_common));
memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
(char *) newdecl + sizeof (struct tree_decl_common),
sizeof (struct tree_function_decl) - sizeof (struct tree_decl_common));
if (new_template)
reregister_specialization (newdecl,
new_template,
olddecl);
}
else
{
size_t size = tree_code_size (TREE_CODE (olddecl));
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl_common) - sizeof (struct tree_common));
switch (TREE_CODE (olddecl))
{
case LABEL_DECL:
case VAR_DECL:
case RESULT_DECL:
case PARM_DECL:
case FIELD_DECL:
case TYPE_DECL:
case CONST_DECL:
{
memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
(char *) newdecl + sizeof (struct tree_decl_common),
size - sizeof (struct tree_decl_common)
+ TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
}
break;
default:
memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
(char *) newdecl + sizeof (struct tree_decl_common),
sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common)
+ TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
break;
}
}
DECL_UID (olddecl) = olddecl_uid;
if (olddecl_friend)
DECL_FRIEND_P (olddecl) = 1;
if (hidden_friend)
{
DECL_ANTICIPATED (olddecl) = 1;
DECL_HIDDEN_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 NULL;
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 NULL;
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 NULL;
}
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 (TREE_CODE (newdecl) == VAR_DECL
&& DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)
&& (! DECL_LANG_SPECIFIC (olddecl)
|| ! CP_DECL_THREADPRIVATE_P (olddecl)
|| DECL_THREAD_LOCAL_P (newdecl)))
{
if (DECL_THREAD_LOCAL_P (newdecl))
return "thread-local declaration of %q#D follows "
"non-thread-local declaration";
else
return "non-thread-local declaration of %q#D follows "
"thread-local declaration";
}
else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
{
if (DECL_ANON_UNION_VAR_P (newdecl)
|| DECL_ANON_UNION_VAR_P (olddecl))
return "redeclaration of %q#D";
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return NULL;
return "redefinition of %q#D";
}
else
{
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
return "redeclaration of %q#D";
return NULL;
}
}
static hashval_t
named_label_entry_hash (const void *data)
{
const struct named_label_entry *ent = (const struct named_label_entry *) data;
return DECL_UID (ent->label_decl);
}
static int
named_label_entry_eq (const void *a, const void *b)
{
const struct named_label_entry *ent_a = (const struct named_label_entry *) a;
const struct named_label_entry *ent_b = (const struct named_label_entry *) b;
return ent_a->label_decl == ent_b->label_decl;
}
static tree
make_label_decl (tree id, int local_p)
{
struct named_label_entry *ent;
void **slot;
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);
if (!named_labels)
named_labels = htab_create_ggc (13, named_label_entry_hash,
named_label_entry_eq, NULL);
ent = GGC_CNEW (struct named_label_entry);
ent->label_decl = decl;
slot = htab_find_slot (named_labels, ent, INSERT);
gcc_assert (*slot == NULL);
*slot = ent;
return decl;
}
tree
lookup_label (tree id)
{
tree decl;
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);
decl = make_label_decl (id, 0);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
tree
declare_local_label (tree id)
{
tree decl, shadow;
shadow = tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
current_binding_level->shadowed_labels);
current_binding_level->shadowed_labels = shadow;
decl = make_label_decl (id, 1);
TREE_VALUE (shadow) = decl;
return decl;
}
static int
decl_jump_unsafe (tree decl)
{
if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl)
|| TREE_TYPE (decl) == error_mark_node)
return 0;
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| DECL_NONTRIVIALLY_INITIALIZED_P (decl))
return 2;
if (pod_type_p (TREE_TYPE (decl)))
return 0;
return 1;
}
static void
identify_goto (tree decl, const location_t *locus)
{
if (decl)
pedwarn ("jump to label %qD", decl);
else
pedwarn ("jump to case label");
if (locus)
pedwarn ("%H from here", locus);
}
static bool
check_previous_goto_1 (tree decl, struct cp_binding_level* level, tree names,
bool exited_omp, const location_t *locus)
{
struct cp_binding_level *b;
bool identified = false, saw_eh = false, saw_omp = false;
bool errored_out = false;
if (exited_omp)
{
identify_goto (decl, locus);
error (" exits OpenMP structured block");
identified = saw_omp = true;
errored_out = true;
}
for (b = current_binding_level; b ; b = b->level_chain)
{
tree new_decls, old_decls = (b == level ? names : NULL_TREE);
for (new_decls = b->names; new_decls != old_decls;
new_decls = TREE_CHAIN (new_decls))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
continue;
if (!identified)
{
identify_goto (decl, locus);
identified = true;
}
if (problem > 1)
pedwarn (" crosses initialization of %q+#D", new_decls);
else
pedwarn (" 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)
{
identify_goto (decl, locus);
identified = true;
}
if (b->kind == sk_try)
error (" enters try block");
else
error (" enters catch block");
errored_out = true;
saw_eh = true;
}
if (b->kind == sk_omp && !saw_omp)
{
if (!identified)
{
identify_goto (decl, locus);
identified = true;
}
error (" enters OpenMP structured block");
errored_out = true;
saw_omp = true;
}
}
return !errored_out;
}
static void
check_previous_goto (tree decl, struct named_label_use_entry *use)
{
check_previous_goto_1 (decl, use->binding_level,
use->names_in_scope, use->in_omp_scope,
&use->o_goto_locus);
}
static bool
check_switch_goto (struct cp_binding_level* level)
{
return check_previous_goto_1 (NULL_TREE, level, level->names, false, NULL);
}
void
check_goto (tree decl)
{
struct named_label_entry *ent, dummy;
bool saw_catch = false, identified = false;
tree bad;
if (TREE_CODE (decl) != LABEL_DECL)
return;
if (decl == cdtor_label)
return;
dummy.label_decl = decl;
ent = (struct named_label_entry *) htab_find (named_labels, &dummy);
gcc_assert (ent != NULL);
if (! DECL_INITIAL (decl))
{
struct named_label_use_entry *new_use;
if (ent->uses
&& ent->uses->names_in_scope == current_binding_level->names)
return;
new_use = GGC_NEW (struct named_label_use_entry);
new_use->binding_level = current_binding_level;
new_use->names_in_scope = current_binding_level->names;
new_use->o_goto_locus = input_location;
new_use->in_omp_scope = false;
new_use->next = ent->uses;
ent->uses = new_use;
return;
}
if (ent->in_try_scope || ent->in_catch_scope
|| ent->in_omp_scope || ent->bad_decls)
{
pedwarn ("jump to label %q+D", decl);
pedwarn (" from here");
identified = true;
}
for (bad = ent->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);
saw_catch = true;
}
else if (u > 1)
error (" skips initialization of %q+#D", b);
else
pedwarn (" enters scope of non-POD %q+#D", b);
}
if (ent->in_try_scope)
error (" enters try block");
else if (ent->in_catch_scope && !saw_catch)
error (" enters catch block");
if (ent->in_omp_scope)
error (" enters OpenMP structured block");
else if (flag_openmp)
{
struct cp_binding_level *b;
for (b = current_binding_level; b ; b = b->level_chain)
{
if (b == ent->binding_level)
break;
if (b->kind == sk_omp)
{
if (!identified)
{
pedwarn ("jump to label %q+D", decl);
pedwarn (" from here");
identified = true;
}
error (" exits OpenMP structured block");
break;
}
}
}
}
bool
check_omp_return (void)
{
struct cp_binding_level *b;
for (b = current_binding_level; b ; b = b->level_chain)
if (b->kind == sk_omp)
{
error ("invalid exit from OpenMP structured block");
return false;
}
return true;
}
tree
define_label (location_t location, tree name)
{
struct named_label_entry *ent, dummy;
struct cp_binding_level *p;
tree decl;
timevar_push (TV_NAME_LOOKUP);
decl = lookup_label (name);
dummy.label_decl = decl;
ent = (struct named_label_entry *) htab_find (named_labels, &dummy);
gcc_assert (ent != NULL);
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);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
{
struct named_label_use_entry *use;
DECL_INITIAL (decl) = error_mark_node;
DECL_SOURCE_LOCATION (decl) = location;
ent->binding_level = current_binding_level;
ent->names_in_scope = current_binding_level->names;
for (use = ent->uses; use ; use = use->next)
check_previous_goto (decl, use);
ent->uses = NULL;
}
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 = XNEW (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;
location_t switch_location;
if (EXPR_HAS_LOCATION (cs->switch_stmt))
switch_location = EXPR_LOCATION (cs->switch_stmt);
else
switch_location = input_location;
if (!processing_template_decl)
c_do_switch_warnings (cs->cases, switch_location,
SWITCH_STMT_TYPE (cs->switch_stmt),
SWITCH_STMT_COND (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);
if (!check_switch_goto (switch_stack->level))
return error_mark_node;
r = c_add_case_label (switch_stack->cases, cond, TREE_TYPE (cond),
low_value, high_value);
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;
tree t;
bool want_template;
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);
else if (TREE_CODE (name) == OVERLOAD)
{
error ("%qD is not a type", name);
return error_mark_node;
}
}
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))
return build_typename_type (context, name, fullname, tag_type);
if (!IS_AGGR_TYPE (context))
{
if (complain & tf_error)
error ("%q#T is not a class", context);
return error_mark_node;
}
want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
t = lookup_field (context, name, 0, true);
if (!t)
{
if (complain & tf_error)
error (want_template ? "no class template named %q#T in %q#T"
: "no type named %q#T in %q#T", name, context);
return error_mark_node;
}
if (want_template && !DECL_CLASS_TEMPLATE_P (t))
{
if (complain & tf_error)
error ("%<typename %T::%D%> names %q#T, which is not a class template",
context, name, t);
return error_mark_node;
}
if (!want_template && TREE_CODE (t) != TYPE_DECL)
{
if (complain & tf_error)
error ("%<typename %T::%D%> names %q#T, which is not a type",
context, name, t);
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), t, t);
if (want_template)
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
NULL_TREE, context,
0,
tf_warning_or_error | tf_user);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
return t;
}
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");
error ("%q+D declared here", tmpl);
}
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), tmpl, 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;
}
if (TARGET_KEXTABI == 1)
{
delta2_identifier = get_identifier ("__delta2");
index_identifier = get_identifier ("__index");
pfn_or_delta2_identifier = get_identifier ("__pfn_or_delta2");
}
}
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);
TREE_PUBLIC (global_namespace) = 1;
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 (flag_visibility_ms_compat)
default_visibility = VISIBILITY_HIDDEN;
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;
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
if (TARGET_KEXTABI == 1)
delta_type_node = short_integer_type_node;
else
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;
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, false);
cp_finish_decl (decl, init, false, 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] != '_')
#ifdef TARGET_POWERPC
&& !(class == BUILT_IN_MD
&& code >= ALTIVEC_PIM__FIRST
&& code <= ALTIVEC_PIM__LAST)
#endif
)
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] != '_' && strcmp (name, "alloca"))
{
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;
SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
SET_DECL_LANGUAGE (fn, lang_c);
DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
DECL_VISIBILITY_SPECIFIED (fn) = 1;
record_func_cl_pf_opts_mapping (fn);
return fn;
}
tree
build_library_fn (tree name, tree type)
{
tree fn = build_library_fn_1 (name, ERROR_MARK, type);
TREE_NOTHROW (fn) = 1;
return fn;
}
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))
error ("member %q+#D with constructor not allowed "
"in anonymous aggregate", field);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
error ("member %q+#D with destructor not allowed "
"in anonymous aggregate", field);
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
error ("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)
{
warning (0, "attribute ignored in declaration of %q+#T", t);
warning (0, "attribute for %q+#T must follow the %qs keyword",
t, class_key_or_enum_as_string (t));
}
if (maybe_process_partial_specialization (t) == error_mark_node)
return NULL_TREE;
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;
tree a;
bool was_public;
*pushed_scope_p = NULL_TREE;
#ifdef A_LESS_INEFFICENT_WAY
if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
else if (lookup_attribute ("unavailable", attributes))
deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
#else
for (a = attributes; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);
if (TREE_CODE (name) == IDENTIFIER_NODE)
if (is_attribute_p ("deprecated", name))
{
deprecated_state = DEPRECATED_SUPPRESS;
break;
}
if (is_attribute_p ("unavailable", name))
{
deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
break;
}
}
#endif
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
|| decl == error_mark_node)
return error_mark_node;
type = TREE_TYPE (decl);
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);
return error_mark_node;
case FUNCTION_DECL:
error ("function %q#D is initialized like a variable", decl);
return error_mark_node;
default:
break;
}
if (initialized)
{
if (! toplevel_bindings_p ()
&& DECL_EXTERNAL (decl))
warning (0, "declaration of %q#D has %<extern%> and is initialized",
decl);
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
}
cplus_decl_attributes (&decl, attributes, 0);
if (c_dialect_objc ())
objc_checkon_weak_attribute (decl);
if (initialized && DECL_DLLIMPORT_P (decl))
{
error ("definition of %q#D is marked %<dllimport%>", decl);
DECL_DLLIMPORT_P (decl) = 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 (0, "inline function %q+D given attribute noinline", 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 (initialized && DECL_INITIALIZED_IN_CLASS_P (field))
error ("duplicate initialization of %qD", decl);
if (duplicate_decls (decl, field, false))
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,
false))
decl = field;
}
DECL_IN_AGGR_P (decl) = 0;
if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
{
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
if (!initialized && 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);
}
was_public = TREE_PUBLIC (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 (flag_conserve_space
&& TREE_CODE (tem) == VAR_DECL
&& TREE_PUBLIC (tem)
&& !DECL_THREAD_LOCAL_P (tem)
&& !have_global_bss_p ())
DECL_COMMON (tem) = 1;
if (TREE_CODE (tem) == VAR_DECL
&& DECL_NAMESPACE_SCOPE_P (tem) && !TREE_PUBLIC (tem) && !was_public
&& !DECL_THIS_STATIC (tem) && !DECL_ARTIFICIAL (tem))
{
gcc_assert (cp_type_readonly (TREE_TYPE (tem)));
DECL_THIS_STATIC (tem) = 1;
}
if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
start_decl_1 (tem, initialized);
return tem;
}
void
start_decl_1 (tree decl, bool initialized)
{
tree type;
gcc_assert (!processing_template_decl);
if (error_operand_p (decl))
return;
gcc_assert (TREE_CODE (decl) == VAR_DECL);
type = TREE_TYPE (decl);
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;
}
}
else if (IS_AGGR_TYPE (type)
&& ! DECL_EXTERNAL (decl))
{
if (!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);
}
}
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 bool
check_array_designated_initializer (const constructor_elt *ce)
{
if (ce->index)
{
gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
error ("name %qD used in a GNU-style designated "
"initializer for an array", ce->index);
return false;
}
return true;
}
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 = 0;
if (initializer && TREE_CODE (initializer) == CONSTRUCTOR)
{
VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initializer);
constructor_elt *ce;
HOST_WIDE_INT i;
for (i = 0;
VEC_iterate (constructor_elt, v, i, ce);
++i)
if (!check_array_designated_initializer (ce))
failure = 1;
}
if (!failure)
{
failure = cp_complete_array_type (&TREE_TYPE (decl), initializer,
do_default);
if (failure == 1)
{
error ("initializer fails to determine size of %qD", decl);
TREE_TYPE (decl) = error_mark_node;
}
else if (failure == 2)
{
if (do_default)
{
error ("array size missing in %qD", decl);
TREE_TYPE (decl) = error_mark_node;
}
else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
DECL_EXTERNAL (decl) = 1;
}
else if (failure == 3)
{
error ("zero-size array %qD", decl);
TREE_TYPE (decl) = error_mark_node;
}
}
cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
layout_decl (decl, 0);
}
}
static void
layout_var_decl (tree decl)
{
tree type;
type = TREE_TYPE (decl);
if (type == error_mark_node)
return;
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);
}
}
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;
warning (0, "sorry: semantics of inline function static "
"data %q+#D are wrong (you'll wind up "
"with multiple copies)", decl);
warning (0, "%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);
}
typedef struct reshape_iterator_t
{
constructor_elt *cur;
constructor_elt *end;
} reshape_iter;
static tree reshape_init_r (tree, reshape_iter *, bool);
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 tree
reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d)
{
tree new_init;
bool sized_array_p = (max_index != NULL_TREE);
unsigned HOST_WIDE_INT max_index_cst = 0;
unsigned HOST_WIDE_INT index;
new_init = build_constructor (NULL_TREE, NULL);
if (sized_array_p)
{
if (integer_all_onesp (max_index))
return new_init;
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;
d->cur != d->end && (!sized_array_p || index <= max_index_cst);
++index)
{
tree elt_init;
check_array_designated_initializer (d->cur);
elt_init = reshape_init_r (elt_type, d, false);
if (elt_init == error_mark_node)
return error_mark_node;
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), NULL_TREE, elt_init);
}
return new_init;
}
static tree
reshape_init_array (tree type, reshape_iter *d)
{
tree max_index = NULL_TREE;
gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
if (TYPE_DOMAIN (type))
max_index = array_type_nelts (type);
return reshape_init_array_1 (TREE_TYPE (type), max_index, d);
}
static tree
reshape_init_vector (tree type, reshape_iter *d)
{
tree max_index = NULL_TREE;
tree rtype;
gcc_assert (TREE_CODE (type) == VECTOR_TYPE);
if (COMPOUND_LITERAL_P (d->cur->value))
{
tree value = d->cur->value;
if (!same_type_p (TREE_TYPE (value), type))
{
error ("invalid type %qT as initializer for a vector of type %qT",
TREE_TYPE (d->cur->value), type);
value = error_mark_node;
}
++d->cur;
return value;
}
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)));
return reshape_init_array_1 (TREE_TYPE (type), max_index, d);
}
static tree
reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p)
{
tree field;
tree new_init;
gcc_assert (CLASS_TYPE_P (type));
new_init = build_constructor (NULL_TREE, NULL);
field = next_initializable_field (TYPE_FIELDS (type));
if (!field)
{
if (!first_initializer_p)
{
error ("initializer for %qT must be brace-enclosed", type);
return error_mark_node;
}
return new_init;
}
while (d->cur != d->end)
{
tree field_init;
if (d->cur->index)
{
field = lookup_field_1 (type, d->cur->index, false);
if (!field || TREE_CODE (field) != FIELD_DECL)
{
error ("%qT has no non-static data member named %qD", type,
d->cur->index);
return error_mark_node;
}
}
if (!field)
break;
field_init = reshape_init_r (TREE_TYPE (field), d,
false);
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), field, field_init);
if (TREE_CODE (type) == UNION_TYPE)
break;
field = next_initializable_field (TREE_CHAIN (field));
}
return new_init;
}
static tree
reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p)
{
tree init = d->cur->value;
if (!CP_AGGREGATE_TYPE_P (type))
{
if (TREE_CODE (init) == CONSTRUCTOR
&& BRACE_ENCLOSED_INITIALIZER_P (init))
{
error ("braces around scalar initializer for type %qT", type);
init = error_mark_node;
}
d->cur++;
return init;
}
if (TREE_CODE (init) != CONSTRUCTOR
&& can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL))
{
d->cur++;
return init;
}
if (TREE_CODE (type) == ARRAY_TYPE
&& char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
{
tree str_init = init;
if (!first_initializer_p
&& TREE_CODE (str_init) == CONSTRUCTOR
&& VEC_length (constructor_elt, CONSTRUCTOR_ELTS (str_init)) == 1)
{
str_init = VEC_index (constructor_elt,
CONSTRUCTOR_ELTS (str_init), 0)->value;
}
if (TREE_CODE (str_init) == STRING_CST)
{
d->cur++;
return str_init;
}
}
if (!first_initializer_p)
{
if (TREE_CODE (init) == CONSTRUCTOR)
{
if (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))
;
else if (COMPOUND_LITERAL_P (init))
gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
else
{
++d->cur;
gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
return reshape_init (type, init);
}
}
warning (OPT_Wmissing_braces, "missing braces around initializer for %qT",
type);
}
if (CLASS_TYPE_P (type))
return reshape_init_class (type, d, first_initializer_p);
else if (TREE_CODE (type) == ARRAY_TYPE)
return reshape_init_array (type, d);
else if (TREE_CODE (type) == VECTOR_TYPE)
return reshape_init_vector (type, d);
else
gcc_unreachable();
}
tree
reshape_init (tree type, tree init)
{
VEC(constructor_elt, gc) *v;
reshape_iter d;
tree new_init;
gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
v = CONSTRUCTOR_ELTS (init);
if (VEC_empty (constructor_elt, v))
return init;
d.cur = VEC_index (constructor_elt, v, 0);
d.end = d.cur + VEC_length (constructor_elt, v);
new_init = reshape_init_r (type, &d, true);
if (new_init == error_mark_node)
return error_mark_node;
if (d.cur != d.end)
error ("too many initializers for %qT", type);
return new_init;
}
static tree
check_initializer (tree decl, tree init, int flags, tree *cleanup)
{
tree type = TREE_TYPE (decl);
tree init_code = NULL;
TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
if (type == error_mark_node)
return NULL_TREE;
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree element_type = TREE_TYPE (type);
if (!COMPLETE_TYPE_P (complete_type (element_type)))
{
error ("elements of array %q#D have incomplete type", decl);
return NULL_TREE;
}
if (init
&& ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
|| !TREE_CONSTANT (TYPE_SIZE (element_type))))
{
error ("variable-sized object %qD may not be initialized", decl);
return NULL_TREE;
}
}
else if (!COMPLETE_TYPE_P (type))
{
error ("%qD has incomplete type", decl);
TREE_TYPE (decl) = error_mark_node;
return NULL_TREE;
}
else
gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
if (!CP_AGGREGATE_TYPE_P (type)
&& init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) != 1)
{
error ("scalar object %qD requires one element in initializer", decl);
TREE_TYPE (decl) = error_mark_node;
return NULL_TREE;
}
if (TREE_CODE (decl) == CONST_DECL)
{
gcc_assert (TREE_CODE (type) != 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
&& !COMPOUND_LITERAL_P (init)
&& !TREE_TYPE (init))
{
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 == error_mark_node)
return NULL_TREE;
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
goto initialize_aggr;
else if (TREE_CODE (init) == CONSTRUCTOR)
{
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 (0, "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;
const char *filename;
if (asmspec)
{
if (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
{
set_user_assembler_name (decl, 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);
filename = input_filename;
if (!DECL_VIRTUAL_P (decl)
&& TREE_READONLY (decl)
&& DECL_INITIAL (decl) != NULL_TREE
&& DECL_INITIAL (decl) != error_mark_node
&& filename != NULL
&& ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))
&& toplev
&& !TREE_PUBLIC (decl))
{
struct c_fileinfo *finfo = get_fileinfo (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 && init != NULL_TREE && TREE_READONLY (decl) && toplev)
{
TREE_READONLY (decl) = 0;
rest_of_decl_compilation (decl, toplev, at_eof);
TREE_READONLY (decl) = 1;
}
else
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)
{
gcc_assert (DECL_ARTIFICIAL (decl));
if (TREE_CODE (init) == TREE_LIST)
init = build_constructor_from_list (NULL_TREE, init);
gcc_assert (TREE_CODE (init) == CONSTRUCTOR);
DECL_INITIAL (decl) = 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);
}
static bool
value_dependent_init_p (tree init)
{
if (TREE_CODE (init) == TREE_LIST)
return any_value_dependent_elements_p (init);
else if (TREE_CODE (init) == CONSTRUCTOR)
{
VEC(constructor_elt, gc) *elts;
size_t nelts;
size_t i;
elts = CONSTRUCTOR_ELTS (init);
nelts = VEC_length (constructor_elt, elts);
for (i = 0; i < nelts; ++i)
if (value_dependent_init_p (VEC_index (constructor_elt,
elts, i)->value))
return true;
}
else
return value_dependent_expression_p (init);
return false;
}
void
cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
tree asmspec_tree, int flags)
{
tree type;
tree cleanup;
const char *asmspec = NULL;
int was_readonly = 0;
bool var_definition_p = false;
int saved_processing_template_decl;
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);
gcc_assert (TREE_CODE (decl) != PARM_DECL);
type = TREE_TYPE (decl);
if (type == error_mark_node)
return;
cleanup = NULL_TREE;
saved_processing_template_decl = processing_template_decl;
if (global_scope_p (current_binding_level))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree && asmspec_tree != error_mark_node)
asmspec = TREE_STRING_POINTER (asmspec_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;
if (processing_template_decl)
{
bool type_dependent_p;
if (at_function_scope_p ())
add_decl_expr (decl);
type_dependent_p = dependent_type_p (type);
if (init && init_const_expr_p)
{
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
TREE_CONSTANT (decl) = 1;
}
if (!(init
&& DECL_CLASS_SCOPE_P (decl)
&& DECL_INTEGRAL_CONSTANT_VAR_P (decl)
&& !type_dependent_p
&& !value_dependent_init_p (init)))
{
if (init)
DECL_INITIAL (decl) = init;
if (TREE_CODE (decl) == VAR_DECL
&& !DECL_PRETTY_FUNCTION_P (decl)
&& !type_dependent_p)
maybe_deduce_size_from_array_init (decl, init);
goto finish_end;
}
init = fold_non_dependent_expr (init);
processing_template_decl = 0;
}
if (TREE_CODE (decl) == TYPE_DECL)
{
if (type != error_mark_node
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
warning (0, "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 (! 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_P (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 (!processing_template_decl
&& DECL_FUNCTION_SCOPE_P (decl)
&& TREE_STATIC (decl)
&& !DECL_ARTIFICIAL (decl))
push_local_name (decl);
if (!DECL_INITIALIZED_P (decl)
&& (!DECL_EXTERNAL (decl) || init))
{
if (init)
{
DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
if (init_const_expr_p)
{
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
TREE_CONSTANT (decl) = 1;
}
}
init = check_initializer (decl, init, flags, &cleanup);
if (DECL_THREAD_LOCAL_P (decl) && init)
{
error ("%qD is thread-local and so cannot be dynamically "
"initialized", decl);
init = NULL_TREE;
}
if (DECL_EXTERNAL (decl) && init)
{
error ("%qD cannot be initialized by a non-constant expression"
" when being declared", decl);
DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
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;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
layout_type (type);
}
if (at_function_scope_p ())
add_decl_expr (decl);
if (!saved_processing_template_decl
&& (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL))
{
if (TREE_CODE (decl) == VAR_DECL)
{
layout_var_decl (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);
determine_visibility (decl);
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)
DECL_INITIAL (decl) = init;
else if (!TREE_STATIC (decl))
initialize_local_var (decl, init);
}
if (var_definition_p && TREE_STATIC (decl))
{
if (init)
{
if (TREE_READONLY (decl))
TREE_READONLY (decl) = 0;
was_readonly = 0;
}
expand_static_init (decl, init);
}
}
}
if (cleanup)
push_cleanup (decl, cleanup, false);
finish_end:
processing_template_decl = saved_processing_template_decl;
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, false, asmspec_tree, 0);
}
static 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);
finish_decl (decl, NULL_TREE, NULL_TREE);
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;
bool use_aeabi_atexit;
if (atexit_node)
return atexit_node;
if (flag_use_cxa_atexit)
{
use_aeabi_atexit = targetm.cxx.use_aeabi_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);
if (use_aeabi_atexit)
{
arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
}
else
{
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);
if (use_aeabi_atexit)
name = "__aeabi_atexit";
else
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);
if (targetm.cxx.use_aeabi_atexit ())
{
args = tree_cons (NULL_TREE, cleanup, args);
args = tree_cons (NULL_TREE, null_pointer_node, args);
}
else
{
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 (c_dialect_objc () && flag_objc_gc && init && TREE_CODE (init) == INIT_EXPR)
{
tree result = objc_generate_write_barrier (TREE_OPERAND (init, 0),
INIT_EXPR, TREE_OPERAND (init, 1));
if (result)
init = result;
}
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)
= build3 (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, build2 (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
&& !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (initial_value)))
{
VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
tree value = VEC_index (constructor_elt, v, 0)->value;
if (TREE_CODE (value) == STRING_CST
&& VEC_length (constructor_elt, v) == 1)
initial_value = 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)
error ("%q+D 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)))))
error ("%q+D declared with an exception specification", object);
}
static void
check_class_member_definition_namespace (tree decl)
{
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL);
if (processing_specialization)
return;
if (processing_explicit_instantiation)
return;
if (!is_ancestor (current_namespace, DECL_CONTEXT (decl)))
pedwarn ("definition of %qD is not in namespace enclosing %qT",
decl, DECL_CONTEXT (decl));
}
tree
build_this_parm (tree type, cp_cv_quals quals)
{
tree this_type;
tree qual_type;
tree parm;
cp_cv_quals this_quals;
this_type = TREE_VALUE (TYPE_ARG_TYPES (type));
this_quals = (quals & TYPE_QUAL_RESTRICT) | TYPE_QUAL_CONST;
qual_type = cp_build_qualified_type (this_type, this_quals);
parm = build_artificial_parm (this_identifier, qual_type);
cp_apply_type_quals_to_decl (this_quals, parm);
return parm;
}
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,
bool funcdef_flag,
int template_count,
tree in_namespace,
tree* attrlist)
{
tree decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
tree t;
if (raises)
type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
if (TREE_CODE (type) == METHOD_TYPE)
{
tree parm;
parm = build_this_parm (type, quals);
TREE_CHAIN (parm) = parms;
parms = parm;
}
DECL_ARGUMENTS (decl) = parms;
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
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);
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t)
&& TREE_CODE (TREE_PURPOSE (t)) == 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 (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 (funcdef_flag)
check_class_member_definition_namespace (decl);
}
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");
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)))
pedwarn ("%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, true))
return NULL_TREE;
if (ctype && decl_function_context (decl))
DECL_NO_STATIC_CHAIN (decl) = 1;
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);
}
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * funcdef_flag +
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 && DECL_MAIN_P (decl)
&& !same_type_p (TREE_TYPE (TREE_TYPE (decl)),
integer_type_node))
{
tree oldtypeargs = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree newtype;
error ("%<::main%> must return %<int%>");
newtype = build_function_type (integer_type_node, oldtypeargs);
TREE_TYPE (decl) = newtype;
}
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 ok;
tree pushed_scope;
if (TREE_CODE (old_decl) == TEMPLATE_DECL)
old_decl = DECL_TEMPLATE_RESULT (old_decl);
if (DECL_STATIC_FUNCTION_P (old_decl)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
revert_static_member_fn (decl);
if (DECL_ARTIFICIAL (old_decl))
error ("definition of implicitly-declared %qD", old_decl);
if (TREE_CODE (decl) == TEMPLATE_DECL)
decl = DECL_TEMPLATE_RESULT (decl);
pushed_scope = push_scope (ctype);
ok = duplicate_decls (decl, old_decl, friendp);
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) = FROB_CONTEXT (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;
check_class_member_definition_namespace (decl);
}
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_TLS_MODEL (decl) = decl_default_tls_model (decl);
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 (0, "non-local variable %q#D uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
warning (0, "%q+#D does not refer to the unqualified "
"type, so it is not used for linkage",
TYPE_NAME (t));
}
}
else
warning (0, "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));
if (TARGET_KEXTABI == 1)
{
tree u = make_aggr_type (UNION_TYPE);
SET_IS_AGGR_TYPE (u, 0);
xref_basetypes (u, NULL_TREE);
fields = build_decl (FIELD_DECL, delta2_identifier, delta_type_node);
TREE_CHAIN (fields)
= build_decl (FIELD_DECL, pfn_identifier, type);
finish_builtin_struct (u, "__ptrmemfunc_type", fields, ptr_type_node);
TYPE_NAME (u) = NULL_TREE;
t = make_aggr_type (RECORD_TYPE);
xref_basetypes (t, NULL_TREE);
TYPE_PTRMEMFUNC_FLAG (t) = 1;
SET_IS_AGGR_TYPE (t, 0);
fields = build_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
TREE_CHAIN (fields) =
build_decl (FIELD_DECL, index_identifier, delta_type_node);
TREE_CHAIN (TREE_CHAIN (fields)) =
build_decl (FIELD_DECL, delta_identifier, delta_type_node);
finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
}
else
{
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 itype;
if (error_operand_p (size))
return error_mark_node;
type = TREE_TYPE (size);
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");
size = integer_one_node;
}
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_CODE (itype) == INTEGER_CST
&& 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 = error_mark_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 virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
tree dependent_name = NULL_TREE;
tree typedef_decl = NULL_TREE;
const char *name = NULL;
tree typedef_type = NULL_TREE;
bool funcdef_flag = false;
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 memfn_quals = TYPE_UNQUALIFIED;
int type_quals;
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_storage_class storage_class;
bool unsigned_p, signed_p, short_p, long_p, thread_p;
bool iasm_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];
longlong = declspecs->specs[(int)ds_long] >= 2;
thread_p = declspecs->specs[(int)ds_thread];
iasm_p = declspecs->specs[(int)ds_iasm_asm];
if (decl_context == FUNCDEF)
funcdef_flag = true, decl_context = NORMAL;
else if (decl_context == MEMFUNCDEF)
funcdef_flag = true, 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 (at_function_scope_p ())
{
if (qualifying_scope == global_namespace)
error ("invalid use of qualified-name %<::%D%>",
decl);
else if (TYPE_P (qualifying_scope))
error ("invalid use of qualified-name %<%T::%D%>",
qualifying_scope, decl);
else
error ("invalid use of qualified-name %<%D::%D%>",
qualifying_scope, decl);
return error_mark_node;
}
else 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;
}
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));
dname = decl;
}
break;
case TEMPLATE_ID_EXPR:
{
tree fns = TREE_OPERAND (decl, 0);
dname = fns;
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;
default:
gcc_unreachable ();
}
break;
case cdk_array:
case cdk_pointer:
case cdk_reference:
case cdk_ptrmem:
break;
case cdk_error:
return error_mark_node;
default:
gcc_unreachable ();
}
}
if (id_declarator->kind == cdk_id)
break;
}
if (funcdef_flag && innermost_code != cdk_function)
{
error ("function definition does not declare parameters");
return error_mark_node;
}
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);
return error_mark_node;
}
type = declspecs->type;
if (type == error_mark_node)
{
type = NULL_TREE;
type_was_error_mark_node = true;
}
if (type && TREE_DEPRECATED (type) && TREE_UNAVAILABLE (type))
{
if (deprecated_state != DEPRECATED_UNAVAILABLE_SUPPRESS)
warn_deprecated_use (type);
}
else
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;
#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 (0, "ISO C++ forbids declaration of %qs with no type", name);
type = integer_type_node;
}
ctype = NULL_TREE;
if (long_p && !longlong && 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 ((signed_p || unsigned_p) && TREE_CODE (type) != INTEGER_TYPE)
error ("%<signed%> or %<unsigned%> invalid for %qs", name);
else if (signed_p && unsigned_p)
error ("%<signed%> and %<unsigned%> specified together for %qs", name);
else if (longlong && TREE_CODE (type) != INTEGER_TYPE)
error ("%<long long%> invalid for %qs", name);
else if (long_p && TREE_CODE (type) == REAL_TYPE)
error ("%<long%> invalid for %qs", name);
else if (short_p && TREE_CODE (type) == REAL_TYPE)
error ("%<short%> invalid for %qs", name);
else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
error ("%<long%> or %<short%> invalid 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)
error ("%<long%> and %<short%> specified 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
&& !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_warning_or_error));
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);
storage_class = sc_none;
staticp = 0;
}
friendp = !! declspecs->specs[(int)ds_friend];
if (dependent_name && !friendp)
{
error ("%<%T::%D%> is not a valid declarator", ctype, dependent_name);
return error_mark_node;
}
if (decl_context == PARM)
{
if (declspecs->specs[(int)ds_typedef])
{
error ("typedef declaration invalid in parameter declaration");
return error_mark_node;
}
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 (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;
}
if (declspecs->conflicting_specifiers_p)
{
error ("conflicting specifiers in declaration of %qs", name);
storage_class = sc_none;
}
else if (decl_context != NORMAL
&& ((storage_class != sc_none
&& storage_class != sc_mutable)
|| thread_p))
{
if ((decl_context == 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)
error ("storage class specified for %qs", 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 (0, "%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;
switch (TREE_CODE (unqualified_id))
{
case BIT_NOT_EXPR:
unqualified_id
= constructor_name (TREE_OPERAND (unqualified_id, 0));
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;
}
memfn_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_constructor
|| sfk == sfk_destructor))
{
if (staticp == 2)
error ((flags == DTOR_FLAG)
? "destructor cannot be static member function"
: "constructor cannot be static member function");
if (memfn_quals)
{
error ((flags == DTOR_FLAG)
? "destructors may not be cv-qualified"
: "constructors may not be cv-qualified");
memfn_quals = TYPE_UNQUALIFIED;
}
if (decl_context == FIELD
&& !member_function_or_else (ctype,
current_class_type,
flags))
return error_mark_node;
if (flags != DTOR_FLAG)
{
if (explicitp == 1)
explicitp = 2;
if (virtualp)
{
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
if (decl_context == FIELD
&& sfk != sfk_constructor)
return error_mark_node;
}
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);
}
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 || memfn_quals))
{
memfn_quals |= cp_type_quals (type);
type = build_memfn_type (type,
declarator->u.pointer.class_type,
memfn_quals);
memfn_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)
{
gcc_assert (TREE_CODE (declarator->u.pointer.class_type)
!= NAMESPACE_DECL);
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_SPECIALIZATION (t)
&& !any_dependent_template_arguments_p (CLASSTYPE_TI_ARGS (t)))
break;
if ((CLASSTYPE_USE_TEMPLATE (t) || CLASSTYPE_IS_TEMPLATE (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 (friendp)
pedwarn ("member functions are implicitly friends of their class");
else
pedwarn ("extra qualification %<%T::%> on member %qs",
ctype, name);
}
else if (
!COMPLETE_TYPE_P (ctype)
&& (
funcdef_flag
|| (!friendp && !CLASS_TYPE_P (ctype))
|| !(dependent_type_p (ctype)
|| currently_open_class (ctype)))
&& !complete_type_or_else (ctype, NULL_TREE))
return error_mark_node;
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
tree sname = declarator->u.id.unqualified_name;
if (current_class_type
&& (!friendp || funcdef_flag))
{
error (funcdef_flag
? "cannot define member function %<%T::%s%> within %<%T%>"
: "cannot declare member function %<%T::%s%> within %<%T%>",
ctype, name, current_class_type);
return error_mark_node;
}
if (TREE_CODE (sname) == IDENTIFIER_NODE
&& NEW_DELETE_OPNAME_P (sname))
;
else
type = build_memfn_type (type, ctype, memfn_quals);
}
else if (declspecs->specs[(int)ds_typedef]
&& current_class_type)
{
error ("cannot declare member %<%T::%s%> within %qT",
ctype, name, current_class_type);
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_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
&& TREE_OVERFLOW (TYPE_SIZE_UNIT (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 (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
type = cp_build_qualified_type (type, memfn_quals);
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 (memfn_quals && !ctype && TREE_CODE (type) == FUNCTION_TYPE)
memfn_quals = TYPE_UNQUALIFIED;
if (signed_p
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
bad_specifiers (decl, "type", virtualp,
memfn_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);
}
memfn_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 (memfn_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)
type = build_memfn_type (type, ctype, memfn_quals);
}
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 (type == error_mark_node)
return error_mark_node;
}
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,
memfn_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 %<::%>");
return error_mark_node;
}
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 error_mark_node;
}
if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
{
error ("function %qD declared virtual inside a union",
unqualified_id);
return error_mark_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_memfn_type (type, ctype, memfn_quals);
}
if (sfk == sfk_destructor)
{
if (!ctype)
{
gcc_assert (friendp);
error ("expected qualified name in friend declaration "
"for destructor %qD",
id_declarator->u.id.unqualified_name);
return error_mark_node;
}
if (!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, memfn_quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
sfk,
funcdef_flag, template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
return error_mark_node;
#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, memfn_quals, raises,
friendp ? -1 : 0, friendp, 1, 0, sfk,
funcdef_flag, template_count, in_namespace,
attrlist);
if (decl == NULL_TREE)
return error_mark_node;
}
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);
return error_mark_node;
}
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)
;
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 + 4);
if (decl == error_mark_node)
return error_mark_node;
}
decl = do_friend (ctype, unqualified_id, decl,
*attrlist, flags,
funcdef_flag);
return decl;
}
else
return error_mark_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 error_mark_node;
}
if (staticp)
{
decl = build_lang_decl (VAR_DECL, unqualified_id, type);
set_linkage_for_static_data_member (decl);
DECL_EXTERNAL (decl) = 1;
if (thread_p)
{
if (targetm.have_tls)
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
else
error ("thread-local storage not supported for this target");
}
}
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,
memfn_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 error_mark_node;
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, memfn_quals, raises,
1, friendp,
publicp, inlinep, sfk, funcdef_flag,
template_count, in_namespace, attrlist);
if (decl == NULL_TREE)
return error_mark_node;
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,
memfn_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 (iasm_p)
{
if (flag_iasm_blocks)
{
DECL_IASM_ASM_FUNCTION (decl) = 1;
DECL_IASM_NORETURN (decl) = 0;
DECL_IASM_FRAME_SIZE (decl) = -2;
}
else
error ("asm functions not enabled, use `-fasm-blocks'");
}
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))
&& complete_type_or_else (TREE_TYPE (parms), parms))
{
relayout_decl (parms);
DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
}
else
TREE_TYPE (parms) = error_mark_node;
}
}
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 (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, LOOKUP_NORMAL))
{
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_SELF_REFERENCE_P (type)
&& !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 = NULL_TREE;
else if (init && !processing_template_decl)
init = check_default_argument (decl, init);
}
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 (TREE_CODE (d) == TEMPLATE_DECL
|| (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 (arg_type == error_mark_node)
return 0;
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)
{
tree class_type;
if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
return;
class_type = DECL_CONTEXT (decl);
if (DECL_CONSTRUCTOR_P (decl))
{
int ctor = copy_fn_p (decl);
TYPE_HAS_CONSTRUCTOR (class_type) = 1;
if (ctor > 0)
{
TYPE_HAS_INIT_REF (class_type) = 1;
if (ctor > 1)
TYPE_HAS_CONST_INIT_REF (class_type) = 1;
}
else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
}
else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
{
int assop = copy_fn_p (decl);
if (assop)
{
TYPE_HAS_ASSIGN_REF (class_type) = 1;
if (assop != 1)
TYPE_HAS_CONST_ASSIGN_REF (class_type) = 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 == UNARY_PLUS_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, 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 ellipsis_p;
tree class_type;
for (argtype = argtypes, arity = 0;
argtype && argtype != void_list_node;
argtype = TREE_CHAIN (argtype))
++arity;
ellipsis_p = !argtype;
class_type = DECL_CONTEXT (decl);
if (class_type && !CLASS_TYPE_P (class_type))
class_type = NULL_TREE;
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 (class_type)
switch (operator_code)
{
case NEW_EXPR:
TYPE_HAS_NEW_OPERATOR (class_type) = 1;
break;
case DELETE_EXPR:
TYPE_GETS_DELETE (class_type) |= 1;
break;
case VEC_NEW_EXPR:
TYPE_HAS_ARRAY_NEW_OPERATOR (class_type) = 1;
break;
case VEC_DELETE_EXPR:
TYPE_GETS_DELETE (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);
return false;
}
else if (!TREE_PUBLIC (decl))
{
error ("%qD may not be declared as static", decl);
return false;
}
}
}
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);
return false;
}
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);
return false;
}
for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
{
tree arg = non_reference (TREE_VALUE (p));
if (arg == error_mark_node)
return false;
if (IS_AGGR_TYPE (arg) || TREE_CODE (arg) == ENUMERAL_TYPE)
break;
}
if (!p || p == void_list_node)
{
if (complain)
error ("%qD must have an argument of class or "
"enumerated type", decl);
return false;
}
}
}
if (operator_code == CALL_EXPR)
return true;
if (IDENTIFIER_TYPENAME_P (name)
&& ! DECL_TEMPLATE_INFO (decl)
&& warn_conversion
&& class_type == current_class_type)
{
tree t = TREE_TYPE (name);
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 (class_type)
{
if (t == class_type)
what = "the same type";
else if (IS_AGGR_TYPE (t)
&& COMPLETE_TYPE_P (t)
&& DERIVED_FROM_P (t, class_type))
what = "a base class";
}
if (what)
warning (OPT_Wconversion, "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 ?:");
return false;
}
else if (ellipsis_p)
{
error ("%qD must not have variable number of arguments", decl);
return false;
}
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 UNARY_PLUS_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);
return false;
}
}
else
{
if (methodp)
error ("%qD must take either zero or one argument", decl);
else
error ("%qD must take either one or two arguments", decl);
return false;
}
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 (OPT_Weffc__, "prefix %qD should return %qT", decl,
build_reference_type (arg));
}
else
{
if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
warning (OPT_Weffc__, "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);
return false;
}
}
else
{
if (arity != 2)
{
if (methodp)
error ("%qD must take exactly one argument", decl);
else
error ("%qD must take exactly two arguments", decl);
return false;
}
if (warn_ecpp
&& (operator_code == TRUTH_ANDIF_EXPR
|| operator_code == TRUTH_ORIF_EXPR
|| operator_code == COMPOUND_EXPR))
warning (OPT_Weffc__, "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 (OPT_Weffc__, "%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 false;
}
}
}
return true;
}
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));
error ("%q+D 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));
error ("%q+T has a previous declaration here", type);
return error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
&& tag_code == enum_type)
{
error ("%qT referred to as enum", type);
error ("%q+T 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_prefer_type (name, 2);
if (!decl)
decl = lookup_type_scope (name, ts_within_enclosing_non_class);
}
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);
}
}
else
{
if (template_header_p && IS_AGGR_TYPE (t))
{
if (!redeclare_class_template (t, current_template_parms))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else if (!processing_template_decl
&& CLASS_TYPE_P (t)
&& CLASSTYPE_IS_TEMPLATE (t))
{
error ("redeclaration of %qT as a non-template", t);
error ("previous declaration %q+D", t);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (scope != ts_within_enclosing_non_class
&& hidden_name_p (TYPE_NAME (t)))
{
DECL_ANTICIPATED (TYPE_NAME (t)) = 0;
DECL_FRIEND_P (TYPE_NAME (t)) = 0;
if (TYPE_TEMPLATE_INFO (t))
{
DECL_ANTICIPATED (TYPE_TI_TEMPLATE (t)) = 0;
DECL_FRIEND_P (TYPE_TI_TEMPLATE (t)) = 0;
}
}
}
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);
}
bool
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 false;
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, gc, max_bases);
CLASSTYPE_NON_AGGREGATE (ref) = 1;
if (TREE_CODE (ref) == UNION_TYPE)
{
error ("derived union %qT invalid", ref);
return false;
}
}
if (max_bases > 1)
{
if (TYPE_FOR_JAVA (ref))
{
error ("Java class %qT cannot have multiple bases", ref);
return false;
}
}
if (max_vbases)
{
CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, gc, max_vbases);
if (TYPE_FOR_JAVA (ref))
{
error ("Java class %qT cannot have virtual bases", ref);
return false;
}
}
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);
return false;
}
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);
return false;
}
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;
}
return true;
}
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, ts_current);
}
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 (value == error_mark_node)
value = integer_zero_node;
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))
{
location_t saved_location;
decl = TREE_VALUE (values);
saved_location = input_location;
input_location = DECL_SOURCE_LOCATION (decl);
value = perform_implicit_conversion (underlying_type,
DECL_INITIAL (decl));
input_location = saved_location;
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);
value = error_mark_node;
}
}
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))
{
tree args = TYPE_ARG_TYPES (fntype);
error ("return type %q#T is incomplete", return_type);
if (TREE_CODE (fntype) == METHOD_TYPE)
fntype = build_method_type_directly (TREE_TYPE (TREE_VALUE (args)),
void_type_node,
TREE_CHAIN (args));
else
fntype = build_function_type (void_type_node, args);
TREE_TYPE (decl)
= build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)));
}
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 (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1)));
bool honor_interface;
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 (0, "inline function %q+D given attribute noinline", 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 (OPT_Weffc__, "%<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);
}
\
\
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
{
copy_func_cl_pf_opts_mapping (decl1, olddecl);
decl1 = olddecl;
}
}
else
{
if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
}
fntype = TREE_TYPE (decl1);
if (!DECL_CONTEXT (decl1))
maybe_apply_pragma_weak (decl1);
}
\
current_function_decl = decl1;
gcc_assert (DECL_INITIAL (decl1));
if (DECL_INITIAL (decl1) != error_mark_node)
return;
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 ();
\
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;
}
}
honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1)
&& !DECL_ARTIFICIAL (decl1));
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 && honor_interface)
{
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_INTERFACE_KNOWN (decl1) = 1;
if (!DECL_EXTERNAL (decl1))
mark_needed (decl1);
}
else if (finfo->interface_unknown && finfo->interface_only
&& honor_interface)
{
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;
}
if (!DECL_CLONED_FUNCTION_P (decl1))
determine_visibility (decl1);
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;
}
if (DECL_IASM_ASM_FUNCTION (current_function_decl))
{
iasm_state = iasm_decls;
iasm_in_decl = 0;
current_function_returns_abnormally = 1;
TREE_NO_WARNING (current_function_decl) = 1;
}
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;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
return 0;
record_func_cl_pf_opts_mapping (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 bool
use_eh_spec_block (tree fn)
{
return (flag_exceptions && flag_enforce_eh_specs
&& !processing_template_decl
&& TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))
&& !DECL_CLONED_FUNCTION_P (fn)
&& !DECL_ARTIFICIAL (fn));
}
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 (use_eh_spec_block (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->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 compound_stmt;
if (COMPLETE_TYPE_P (current_class_type))
{
compound_stmt = begin_compound_stmt (0);
initialize_vtbl_ptrs (current_class_ptr);
finish_compound_stmt (compound_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,
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 (! FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
return NULL_TREE;
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)
{
if (compstmt == NULL_TREE)
return;
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 ();
}
static tree
outer_curly_brace_block (tree fndecl)
{
tree block = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl));
if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl))
block = BLOCK_SUBBLOCKS (block);
return block;
}
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 ());
\
gcc_assert (DECL_INITIAL (fndecl) == error_mark_node);
\
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
#ifdef USE_MAPPED_LOCATION
SET_EXPR_LOCATION (stmt, UNKNOWN_LOCATION);
#else
annotate_with_file_line (stmt, input_filename, 0);
#endif
}
if (use_eh_spec_block (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
&& !DECL_REPLACEABLE_P (fndecl))
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 = outer_curly_brace_block (fndecl))
&& 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 (OPT_Wreturn_type, "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;
f->extern_decl_map = NULL;
c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
}
local_names = 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 error_mark_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;
}
}
finish_decl (fndecl, NULL_TREE, NULL_TREE);
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, gc, 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));
special_function_kind dtor = sfk_complete_destructor;
if (TARGET_KEXTABI == 1
&& has_apple_kext_compatibility_attr_p (type))
{
if (! has_empty_operator_delete_p (type) || pedantic)
{
warning (0, "%qD is an instance of a class which does "
"not allow global or stack-based objects; it "
"does not have an empty %<operator delete%>, and "
"so it will ** NOT ** be destructed.", decl);
return NULL_TREE;
}
dtor = sfk_deleting_destructor;
}
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,
dtor, 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"