blob: 37b1d51f05197f388e50e5943d6cefd8f5e6f728 [file] [log] [blame]
/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Process declarations and symbol lookup for C++ front end.
Also constructs types; the standard scalar types at initialization,
and structure, union, array and enum types when they are declared. */
/* ??? not all decl nodes are given the most useful possible
line numbers. For example, the CONST_DECLs for enum values. */
#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 "lex.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"
static tree grokparms (tree, 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 grokfndecl (tree, tree, tree, tree, tree, int,
enum overload_flags, tree,
tree, int, int, int, int, int, int, tree);
static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree);
static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (const char *, tree, tree, int,
enum built_in_class, const char *,
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 code);
static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
static int walk_globals_r (tree, void*);
static int walk_vtables_r (tree, void*);
static tree make_label_decl (tree, int);
static void use_label (tree);
static void check_previous_goto_1 (tree, struct cp_binding_level *, tree,
const location_t *);
static void check_previous_goto (struct named_label_use_list *);
static void check_switch_goto (struct cp_binding_level *);
static void check_previous_gotos (tree);
static void pop_label (tree, tree);
static void pop_labels (tree);
static void maybe_deduce_size_from_array_init (tree, tree);
static void layout_var_decl (tree);
static void maybe_commonize_var (tree);
static tree check_initializer (tree, tree, int, tree *);
static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
static void save_function_data (tree);
static void check_function_type (tree, tree);
static void begin_constructor_body (void);
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 int cp_missing_noreturn_ok_p (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
static tree reshape_init (tree, tree *);
static tree build_typename_type (tree, tree, tree);
/* Erroneous argument lists can use this *IFF* they do not modify it. */
tree error_mark_list;
/* The following symbols are subsumed in the cp_global_trees array, and
listed here individually for documentation purposes.
C++ extensions
tree wchar_decl_node;
tree vtable_entry_type;
tree delta_type_node;
tree __t_desc_type_node;
tree ti_desc_type_node;
tree bltn_desc_type_node, ptr_desc_type_node;
tree ary_desc_type_node, func_desc_type_node, enum_desc_type_node;
tree class_desc_type_node, si_class_desc_type_node, vmi_class_desc_type_node;
tree ptm_desc_type_node;
tree base_desc_type_node;
tree class_type_node;
tree unknown_type_node;
Array type `vtable_entry_type[]'
tree vtbl_type_node;
tree vtbl_ptr_type_node;
Namespaces,
tree std_node;
tree abi_node;
A FUNCTION_DECL which can call `abort'. Not necessarily the
one that the user will declare, but sufficient to be called
by routines that want to abort the program.
tree abort_fndecl;
The FUNCTION_DECL for the default `::operator delete'.
tree global_delete_fndecl;
Used by RTTI
tree type_info_type_node, tinfo_decl_id, tinfo_decl_type;
tree tinfo_var_id;
*/
tree cp_global_trees[CPTI_MAX];
/* Indicates that there is a type value in some namespace, although
that is not necessarily in scope at the moment. */
tree global_type_node;
/* The node that holds the "name" of the global scope. */
tree global_scope_name;
/* Used only for jumps to as-yet undefined labels, since jumps to
defined labels can have their validity checked immediately. */
struct named_label_use_list GTY(())
{
struct cp_binding_level *binding_level;
tree names_in_scope;
tree label_decl;
location_t o_goto_locus;
struct named_label_use_list *next;
};
#define named_label_uses cp_function_chain->x_named_label_uses
#define local_names cp_function_chain->x_local_names
/* A list of objects which have constructors or destructors
which reside in the global scope. The decl is stored in
the TREE_VALUE slot and the initializer is stored
in the TREE_PURPOSE slot. */
tree static_aggregates;
/* -- end of C++ */
/* A node for the integer constants 2, and 3. */
tree integer_two_node, integer_three_node;
/* A list of all LABEL_DECLs in the function that have names. Here so
we can clear out their names' definitions at the end of the
function, and so we can check the validity of jumps to these labels. */
struct named_label_list GTY(())
{
struct cp_binding_level *binding_level;
tree names_in_scope;
tree old_value;
tree label_decl;
tree bad_decls;
struct named_label_list *next;
unsigned int in_try_scope : 1;
unsigned int in_catch_scope : 1;
};
#define named_labels cp_function_chain->x_named_labels
/* The number of function bodies which we are currently processing.
(Zero if we are at namespace scope, one inside the body of a
function, two inside the body of a function in a local class, etc.) */
int function_depth;
/* States indicating how grokdeclarator() should handle declspecs marked
with __attribute__((deprecated)). An object declared as
__attribute__((deprecated)) suppresses warnings of uses of other
deprecated items. */
enum deprecated_states {
DEPRECATED_NORMAL,
DEPRECATED_SUPPRESS
};
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
/* Set by add_implicitly_declared_members() to keep those members from
being flagged as deprecated or reported as using deprecated
types. */
int adding_implicit_members = 0;
/* True if a declaration with an `extern' linkage specifier is being
processed. */
bool have_extern_spec;
/* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or
UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the
time the VAR_DECL was declared, the type was incomplete. */
static GTY(()) tree incomplete_vars;
/* Returns the kind of template specialization we are currently
processing, given that it's declaration contained N_CLASS_SCOPES
explicit scope qualifications. */
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;
/* Scan through the template parameter scopes. */
for (b = current_binding_level;
b->kind == sk_template_parms;
b = b->level_chain)
{
/* If we see a specialization scope inside a parameter scope,
then something is wrong. That corresponds to a declaration
like:
template <class T> template <> ...
which is always invalid since [temp.expl.spec] forbids the
specialization of a class member template if the enclosing
class templates are not explicitly specialized as well. */
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;
}
/* Handle explicit instantiations. */
if (processing_explicit_instantiation)
{
if (n_template_parm_scopes != 0)
/* We've seen a template parameter list during an explicit
instantiation. For example:
template <class T> template void f(int);
This is erroneous. */
return tsk_invalid_expl_inst;
else
return tsk_expl_inst;
}
if (n_template_parm_scopes < n_class_scopes)
/* We've not seen enough template headers to match all the
specialized classes present. For example:
template <class T> void R<T>::S<T>::f(int);
This is invalid; there needs to be one set of template
parameters for each class. */
return tsk_insufficient_parms;
else if (n_template_parm_scopes == n_class_scopes)
/* We're processing a non-template declaration (even though it may
be a member of a template class.) For example:
template <class T> void S<T>::f(int);
The `class T' maches the `S<T>', leaving no template headers
corresponding to the `f'. */
return tsk_none;
else if (n_template_parm_scopes > n_class_scopes + 1)
/* We've got too many template headers. For example:
template <> template <class T> void f (T);
There need to be more enclosing classes. */
return tsk_excessive_parms;
else
/* This must be a template. It's of the form:
template <class T> template <class U> void S<T>::f(U);
This is a specialization if the innermost level was a
specialization; otherwise it's just a definition of the
template. */
return innermost_specialization_p ? tsk_expl_spec : tsk_template;
}
/* Exit the current scope. */
void
finish_scope (void)
{
poplevel (0, 0, 0);
}
/* When a label goes out of scope, check to see if that label was used
in a valid manner, and issue any appropriate warnings or errors. */
static void
pop_label (tree label, tree old_value)
{
if (!processing_template_decl)
{
if (DECL_INITIAL (label) == NULL_TREE)
{
location_t location;
cp_error_at ("label `%D' used but not defined", label);
location.file = input_filename;
location.line = 0;
/* Avoid crashing later. */
define_label (location, DECL_NAME (label));
}
else if (warn_unused_label && !TREE_USED (label))
cp_warning_at ("label `%D' defined but not used", label);
}
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
}
/* At the end of a function, all labels declared within the function
go out of scope. BLOCK is the top-level block for the
function. */
static void
pop_labels (tree block)
{
struct named_label_list *link;
/* Clear out the definitions of all label names, since their scopes
end here. */
for (link = named_labels; link; link = link->next)
{
pop_label (link->label_decl, link->old_value);
/* Put the labels into the "variables" of the top-level block,
so debugger can see them. */
TREE_CHAIN (link->label_decl) = BLOCK_VARS (block);
BLOCK_VARS (block) = link->label_decl;
}
named_labels = NULL;
}
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
If KEEP == 1, this level had explicit declarations, so
and create a "block" (a BLOCK node) for the level
to record its declarations and subblocks for symbol table output.
If FUNCTIONBODY is nonzero, this level is the body of a function,
so create a block as if KEEP were set and also clear out all
label names.
If REVERSE is nonzero, reverse the order of decls before putting
them into the BLOCK. */
tree
poplevel (int keep, int reverse, int functionbody)
{
tree link;
/* The chain of decls was accumulated in reverse order.
Put it into forward order, just for cleanliness. */
tree decls;
int tmp = functionbody;
int real_functionbody;
tree subblocks;
tree block = NULL_TREE;
tree decl;
int leaving_for_scope;
scope_kind kind;
timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (current_binding_level->kind != sk_class, 19990916);
real_functionbody = (current_binding_level->kind == sk_cleanup
? ((functionbody = 0), tmp) : functionbody);
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
my_friendly_assert (!current_binding_level->class_shadowed,
19990414);
/* We used to use KEEP == 2 to indicate that the new block should go
at the beginning of the list of blocks at this binding level,
rather than the end. This hack is no longer used. */
my_friendly_assert (keep == 0 || keep == 1, 0);
if (current_binding_level->keep)
keep = 1;
/* Any uses of undefined labels, and any defined labels, now operate
under constraints of next binding contour. */
if (cfun && !functionbody)
{
struct cp_binding_level *level_chain;
level_chain = current_binding_level->level_chain;
if (level_chain)
{
struct named_label_use_list *uses;
struct named_label_list *labels;
for (labels = named_labels; labels; labels = labels->next)
if (labels->binding_level == current_binding_level)
{
tree decl;
if (current_binding_level->kind == sk_try)
labels->in_try_scope = 1;
if (current_binding_level->kind == sk_catch)
labels->in_catch_scope = 1;
for (decl = labels->names_in_scope; decl;
decl = TREE_CHAIN (decl))
if (decl_jump_unsafe (decl))
labels->bad_decls = tree_cons (NULL_TREE, decl,
labels->bad_decls);
labels->binding_level = level_chain;
labels->names_in_scope = level_chain->names;
}
for (uses = named_label_uses; uses; uses = uses->next)
if (uses->binding_level == current_binding_level)
{
uses->binding_level = level_chain;
uses->names_in_scope = level_chain->names;
}
}
}
/* Get the decls in the order they were written.
Usually current_binding_level->names is in reverse order.
But parameter decls were previously put in forward order. */
if (reverse)
current_binding_level->names
= decls = nreverse (current_binding_level->names);
else
decls = current_binding_level->names;
/* Output any nested inline functions within this block
if they weren't already output. */
for (decl = decls; decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == FUNCTION_DECL
&& ! TREE_ASM_WRITTEN (decl)
&& DECL_INITIAL (decl) != NULL_TREE
&& TREE_ADDRESSABLE (decl)
&& decl_function_context (decl) == current_function_decl)
{
/* If this decl was copied from a file-scope decl
on account of a block-scope extern decl,
propagate TREE_ADDRESSABLE to the file-scope decl. */
if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
else
{
push_function_context ();
output_inline_function (decl);
pop_function_context ();
}
}
/* When not in function-at-a-time mode, expand_end_bindings will
warn about unused variables. But, in function-at-a-time mode
expand_end_bindings is not passed the list of variables in the
current scope, and therefore no warning is emitted. So, we
explicitly warn here. */
if (!processing_template_decl)
warn_about_unused_variables (getdecls ());
/* If there were any declarations or structure tags in that level,
or if this level is a function body,
create a BLOCK to record them for the life of this function. */
block = NULL_TREE;
if (keep == 1 || functionbody)
block = make_node (BLOCK);
if (block != NULL_TREE)
{
BLOCK_VARS (block) = decls;
BLOCK_SUBBLOCKS (block) = subblocks;
}
/* In each subblock, record that this is its superior. */
if (keep >= 0)
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
/* We still support the old for-scope rules, whereby the variables
in a for-init statement were in scope after the for-statement
ended. We only use the new rules if flag_new_for_scope is
nonzero. */
leaving_for_scope
= current_binding_level->kind == sk_for && flag_new_for_scope == 1;
/* Remove declarations for all the DECLs in this level. */
for (link = decls; link; link = TREE_CHAIN (link))
{
if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
&& DECL_NAME (link))
{
cxx_binding *outer_binding
= IDENTIFIER_BINDING (DECL_NAME (link))->previous;
tree ns_binding;
if (!outer_binding)
ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));
else
ns_binding = NULL_TREE;
if (outer_binding
&& outer_binding->scope == current_binding_level->level_chain)
/* We have something like:
int i;
for (int i; ;);
and we are leaving the `for' scope. There's no reason to
keep the binding of the inner `i' in this case. */
pop_binding (DECL_NAME (link), link);
else if ((outer_binding
&& (TREE_CODE (outer_binding->value) == TYPE_DECL))
|| (ns_binding && TREE_CODE (ns_binding) == TYPE_DECL))
/* Here, we have something like:
typedef int I;
void f () {
for (int I; ;);
}
We must pop the for-scope binding so we know what's a
type and what isn't. */
pop_binding (DECL_NAME (link), link);
else
{
/* Mark this VAR_DECL as dead so that we can tell we left it
there only for backward compatibility. */
DECL_DEAD_FOR_LOCAL (link) = 1;
/* Keep track of what should have happened when we
popped the binding. */
if (outer_binding && outer_binding->value)
DECL_SHADOWED_FOR_VAR (link) = outer_binding->value;
/* Add it to the list of dead variables in the next
outermost binding to that we can remove these when we
leave that binding. */
current_binding_level->level_chain->dead_vars_from_for
= tree_cons (NULL_TREE, link,
current_binding_level->level_chain->
dead_vars_from_for);
/* Although we don't pop the cxx_binding, we do clear
its SCOPE since the scope is going away now. */
IDENTIFIER_BINDING (DECL_NAME (link))->scope = NULL;
}
}
else
{
/* Remove the binding. */
decl = link;
if (TREE_CODE (decl) == TREE_LIST)
decl = TREE_VALUE (decl);
if (DECL_P (decl))
pop_binding (DECL_NAME (decl), decl);
else if (TREE_CODE (decl) == OVERLOAD)
pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
else
abort ();
}
}
/* Remove declarations for any `for' variables from inner scopes
that we kept around. */
for (link = current_binding_level->dead_vars_from_for;
link; link = TREE_CHAIN (link))
pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
/* Restore the IDENTIFIER_TYPE_VALUEs. */
for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
/* Restore the IDENTIFIER_LABEL_VALUEs for local labels. */
for (link = current_binding_level->shadowed_labels;
link;
link = TREE_CHAIN (link))
pop_label (TREE_VALUE (link), TREE_PURPOSE (link));
/* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
list if a `using' declaration put them there. The debugging
back-ends won't understand OVERLOAD, so we remove them here.
Because the BLOCK_VARS are (temporarily) shared with
CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have
popped all the bindings. */
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 the level being exited is the top level of a function,
check over all the labels. */
if (functionbody)
{
/* Since this is the top level block of a function, the vars are
the function's parameters. Don't leave them in the BLOCK
because they are found in the FUNCTION_DECL instead. */
BLOCK_VARS (block) = 0;
pop_labels (block);
}
kind = current_binding_level->kind;
leave_scope ();
if (functionbody)
DECL_INITIAL (current_function_decl) = block;
else if (block)
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
/* If we did not make a block for the level just exited,
any blocks made for inner levels
(since they cannot be recorded as subblocks in that level)
must be carried forward so they will later become subblocks
of something else. */
else if (subblocks)
current_binding_level->blocks
= chainon (current_binding_level->blocks, subblocks);
/* Each and every BLOCK node created here in `poplevel' is important
(e.g. for proper debugging information) so if we created one
earlier, mark it as "used". */
if (block)
TREE_USED (block) = 1;
/* Take care of compiler's internal binding structures. */
if (kind == sk_cleanup)
{
tree scope_stmts;
scope_stmts
= add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1);
if (block)
{
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
}
block = poplevel (keep, reverse, functionbody);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
/* Delete the node BLOCK from the current binding level.
This is used for the block inside a stmt expr ({...})
so that the block can be reinserted where appropriate. */
void
delete_block (tree block)
{
tree t;
if (current_binding_level->blocks == block)
current_binding_level->blocks = TREE_CHAIN (block);
for (t = current_binding_level->blocks; t;)
{
if (TREE_CHAIN (t) == block)
TREE_CHAIN (t) = TREE_CHAIN (block);
else
t = TREE_CHAIN (t);
}
TREE_CHAIN (block) = NULL_TREE;
/* Clear TREE_USED which is always set by poplevel.
The flag is set again if insert_block is called. */
TREE_USED (block) = 0;
}
/* Insert BLOCK at the end of the list of subblocks of the
current binding level. This is used when a BIND_EXPR is expanded,
to handle the BLOCK node inside the BIND_EXPR. */
void
insert_block (tree block)
{
TREE_USED (block) = 1;
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
}
/* Set the BLOCK node for the innermost scope
(the one we are currently in). */
void
set_block (tree block ATTRIBUTE_UNUSED )
{
/* The RTL expansion machinery requires us to provide this callback,
but it is not applicable in function-at-a-time mode. */
}
/* Returns nonzero if T is a virtual function table. */
int
vtable_decl_p (tree t, void* data ATTRIBUTE_UNUSED )
{
return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
}
/* Returns nonzero if T is a TYPE_DECL for a type with virtual
functions. */
int
vtype_decl_p (tree t, void *data ATTRIBUTE_UNUSED )
{
return (TREE_CODE (t) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
&& TYPE_POLYMORPHIC_P (TREE_TYPE (t)));
}
struct walk_globals_data {
walk_globals_pred p;
walk_globals_fn f;
void *data;
};
/* Walk the vtable declarations in NAMESPACE. Whenever one is found
for which P returns nonzero, call F with its address. If any call
to F returns a nonzero value, return a nonzero value. */
static int
walk_vtables_r (tree namespace, void* data)
{
struct walk_globals_data* wgd = (struct walk_globals_data *) data;
walk_globals_fn f = wgd->f;
void *d = wgd->data;
tree decl = NAMESPACE_LEVEL (namespace)->vtables;
int result = 0;
for (; decl ; decl = TREE_CHAIN (decl))
result |= (*f) (&decl, d);
return result;
}
/* Walk the vtable declarations. Whenever one is found for which P
returns nonzero, call F with its address. If any call to F
returns a nonzero value, return a nonzero value. */
bool
walk_vtables (walk_globals_pred p, walk_globals_fn f, void *data)
{
struct walk_globals_data wgd;
wgd.p = p;
wgd.f = f;
wgd.data = data;
return walk_namespaces (walk_vtables_r, &wgd);
}
/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
itself, calling F for each. The DATA is passed to F as well. */
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;
}
/* Walk all the namespaces, calling F for each. The DATA is passed to
F as well. */
int
walk_namespaces (walk_namespaces_fn f, void* data)
{
return walk_namespaces_r (global_namespace, f, data);
}
/* Walk the global declarations in NAMESPACE. Whenever one is found
for which P returns nonzero, call F with its address. If any call
to F returns a nonzero value, return a nonzero value. */
static int
walk_globals_r (tree namespace, void* data)
{
struct walk_globals_data* wgd = (struct walk_globals_data *) data;
walk_globals_pred p = wgd->p;
walk_globals_fn f = wgd->f;
void *d = wgd->data;
tree *t;
int result = 0;
t = &NAMESPACE_LEVEL (namespace)->names;
while (*t)
{
tree glbl = *t;
if ((*p) (glbl, d))
result |= (*f) (t, d);
/* If F changed *T, then *T still points at the next item to
examine. */
if (*t == glbl)
t = &TREE_CHAIN (*t);
}
return result;
}
/* Walk the global declarations. Whenever one is found for which P
returns true, call F with its address. If any call to F
returns true, return true. */
bool
walk_globals (walk_globals_pred p, walk_globals_fn f, void *data)
{
struct walk_globals_data wgd;
wgd.p = p;
wgd.f = f;
wgd.data = data;
return walk_namespaces (walk_globals_r, &wgd);
}
/* Call wrapup_globals_declarations for the globals in NAMESPACE. If
DATA is non-NULL, this is the last time we will call
wrapup_global_declarations for this NAMESPACE. */
int
wrapup_globals_for_namespace (tree namespace, void* data)
{
struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
varray_type statics = level->static_decls;
tree *vec = &VARRAY_TREE (statics, 0);
int len = VARRAY_ACTIVE_SIZE (statics);
int last_time = (data != 0);
if (last_time)
{
check_global_declarations (vec, len);
return 0;
}
/* Write out any globals that need to be output. */
return wrapup_global_declarations (vec, len);
}
/* In C++, you don't have to write `struct S' to refer to `S'; you
can just use `S'. We accomplish this by creating a TYPE_DECL as
if the user had written `typedef struct S S'. Create and return
the TYPE_DECL for TYPE. */
tree
create_implicit_typedef (tree name, tree type)
{
tree decl;
decl = build_decl (TYPE_DECL, name, type);
DECL_ARTIFICIAL (decl) = 1;
/* There are other implicit type declarations, like the one *within*
a class that allows you to write `S::S'. We must distinguish
amongst these. */
SET_DECL_IMPLICIT_TYPEDEF_P (decl);
TYPE_NAME (type) = decl;
return decl;
}
/* Remember a local name for name-mangling purposes. */
static void
push_local_name (tree decl)
{
size_t i, nelts;
tree t, name;
timevar_push (TV_NAME_LOOKUP);
if (!local_names)
VARRAY_TREE_INIT (local_names, 8, "local_names");
name = DECL_NAME (decl);
nelts = VARRAY_ACTIVE_SIZE (local_names);
for (i = 0; i < nelts; i++)
{
t = VARRAY_TREE (local_names, i);
if (DECL_NAME (t) == name)
{
if (!DECL_LANG_SPECIFIC (decl))
retrofit_lang_decl (decl);
DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1;
if (DECL_LANG_SPECIFIC (t))
DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
else
DECL_DISCRIMINATOR (decl) = 1;
VARRAY_TREE (local_names, i) = decl;
timevar_pop (TV_NAME_LOOKUP);
return;
}
}
VARRAY_PUSH_TREE (local_names, decl);
timevar_pop (TV_NAME_LOOKUP);
}
/* Subroutine of duplicate_decls: return truthvalue of whether
or not types of these decls match.
For C++, we must compare the parameter list so that `int' can match
`int&' in a parameter position, but `int&' is not confused with
`const int&'. */
int
decls_match (tree newdecl, tree olddecl)
{
int types_match;
if (newdecl == olddecl)
return 1;
if (TREE_CODE (newdecl) != TREE_CODE (olddecl))
/* If the two DECLs are not even the same kind of thing, we're not
interested in their types. */
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_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;
}
/* If NEWDECL is `static' and an `extern' was seen previously,
warn about it. OLDDECL is the previous declaration.
Note that this does not apply to the C++ case of declaring
a variable `extern const' and then later `const'.
Don't complain about built-in functions, since they are beyond
the user's control. */
void
warn_extern_redeclared_static (tree newdecl, tree olddecl)
{
static const char *const explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
static const char *const implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
tree name;
if (TREE_CODE (newdecl) == TYPE_DECL
|| TREE_CODE (newdecl) == TEMPLATE_DECL
|| TREE_CODE (newdecl) == CONST_DECL
|| TREE_CODE (newdecl) == NAMESPACE_DECL)
return;
/* Don't get confused by static member functions; that's a different
use of `static'. */
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_STATIC_FUNCTION_P (newdecl))
return;
/* If the old declaration was `static', or the new one isn't, then
then everything is OK. */
if (DECL_THIS_STATIC (olddecl) || !DECL_THIS_STATIC (newdecl))
return;
/* It's OK to declare a builtin function as `static'. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
return;
name = DECL_ASSEMBLER_NAME (newdecl);
pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
? implicit_extern_static_warning
: explicit_extern_static_warning, newdecl);
cp_pedwarn_at ("previous declaration of `%D'", olddecl);
}
/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
If the redeclaration is invalid, a diagnostic is issued, and the
error_mark_node is returned. Otherwise, OLDDECL is returned.
If NEWDECL is not a redeclaration of OLDDECL, NULL_TREE is
returned. */
tree
duplicate_decls (tree newdecl, tree olddecl)
{
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0;
int new_defines_function = 0;
if (newdecl == olddecl)
return olddecl;
types_match = decls_match (newdecl, olddecl);
/* If either the type of the new decl or the type of the old decl is an
error_mark_node, then that implies that we have already issued an
error (earlier) for some bogus type specification, and in that case,
it is rather pointless to harass the user with yet more error message
about the same declaration, so just pretend the types match here. */
if (TREE_TYPE (newdecl) == error_mark_node
|| TREE_TYPE (olddecl) == error_mark_node)
types_match = 1;
if (DECL_P (olddecl)
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
{
if (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
/* Already warned elsewhere. */;
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
/* Already warned. */;
else if (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
warning ("%Jfunction '%D' redeclared as inline", newdecl, newdecl);
warning ("%Jprevious declaration of '%D' with attribute noinline",
olddecl, olddecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
warning ("%Jfunction '%D' redeclared with attribute noinline",
newdecl, newdecl);
warning ("%Jprevious declaration of '%D' was inline",
olddecl, olddecl);
}
}
/* Check for redeclaration and other discrepancies. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
/* Avoid warnings redeclaring anticipated built-ins. */
if (DECL_ANTICIPATED (olddecl))
return NULL_TREE;
/* If you declare a built-in or predefined function name as static,
the old definition is overridden, but optionally warn this was a
bad choice of name. */
if (! TREE_PUBLIC (newdecl))
{
if (warn_shadow)
warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
/* Discard the old built-in function. */
return NULL_TREE;
}
/* If the built-in is not ansi, then programs can override
it even globally without an error. */
else if (! DECL_BUILT_IN (olddecl))
warning ("library function `%#D' redeclared as non-function `%#D'",
olddecl, newdecl);
else
{
error ("declaration of `%#D'", newdecl);
error ("conflicts with built-in declaration `%#D'",
olddecl);
}
return NULL_TREE;
}
else if (!types_match)
{
/* Avoid warnings redeclaring anticipated built-ins. */
if (DECL_ANTICIPATED (olddecl))
; /* Do nothing yet. */
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))))
{
/* A near match; override the builtin. */
if (TREE_PUBLIC (newdecl))
{
warning ("new declaration `%#D'", newdecl);
warning ("ambiguates built-in declaration `%#D'",
olddecl);
}
else if (warn_shadow)
warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
}
else
/* Discard the old built-in function. */
return NULL_TREE;
/* Replace the old RTL to avoid problems with inlining. */
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
/* Even if the types match, prefer the new declarations type
for anticipated built-ins, for exception lists, etc... */
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;
}
/* Whether or not the builtin can throw exceptions has no
bearing on this declarator. */
TREE_NOTHROW (olddecl) = 0;
if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
{
/* If a builtin function is redeclared as `static', merge
the declarations, but make the original one static. */
DECL_THIS_STATIC (olddecl) = 1;
TREE_PUBLIC (olddecl) = 0;
/* Make the old declaration consistent with the new one so
that all remnants of the builtin-ness of this function
will be banished. */
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
&& TREE_CODE (newdecl) != TYPE_DECL
&& ! (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
|| (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
&& TREE_CODE (olddecl) != TYPE_DECL
&& ! (TREE_CODE (olddecl) == TEMPLATE_DECL
&& (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
== TYPE_DECL))))
{
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the TYPE_DECL
get shadowed, and know that if we need to find a TYPE_DECL
for a given name, we can look in the IDENTIFIER_TYPE_VALUE
slot of the identifier. */
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 ("`%#D' redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
cp_error_at ("previous declaration of `%#D'", olddecl);
/* New decl is completely inconsistent with the old one =>
tell caller to replace the old one. */
return NULL_TREE;
}
else if (!types_match)
{
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
/* These are certainly not duplicate declarations; they're
from different scopes. */
return NULL_TREE;
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
/* The name of a class template may not be declared to refer to
any other template, class, function, object, namespace, value,
or type in the same scope. */
if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
|| TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
{
error ("declaration of template `%#D'", newdecl);
cp_error_at ("conflicts with previous declaration `%#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))
/* Template functions can be disambiguated by
return type. */
&& same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
TREE_TYPE (TREE_TYPE (olddecl))))
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#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 `%#D' conflicts with",
newdecl);
cp_error_at ("previous declaration `%#D' here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
else
return NULL_TREE;
}
/* Already complained about this, so don't do so again. */
else if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
{
error ("conflicting declaration '%#D'", newdecl);
cp_error_at ("'%D' has a previous declaration as `%#D'",
olddecl, olddecl);
return NULL_TREE;
}
}
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))))))
/* It's OK to have a template specialization and a non-template
with the same type, or to have specializations of two
different templates with the same type. Note that if one is a
specialization, and the other is an instantiation of the same
template, that we do not exit at this point. That situation
can occur if we instantiate a template class, and then
specialize one of its methods. This situation is valid, but
the declarations must be merged in the usual way. */
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))))
/* One of the declarations is a template instantiation, and the
other is not a template at all. That's OK. */
return NULL_TREE;
else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
{
/* In [namespace.alias] we have:
In a declarative region, a namespace-alias-definition can be
used to redefine a namespace-alias declared in that declarative
region to refer only to the namespace to which it already
refers.
Therefore, if we encounter a second alias directive for the same
alias, we can just ignore the second directive. */
if (DECL_NAMESPACE_ALIAS (newdecl)
&& (DECL_NAMESPACE_ALIAS (newdecl)
== DECL_NAMESPACE_ALIAS (olddecl)))
return olddecl;
/* [namespace.alias]
A namespace-name or namespace-alias shall not be declared as
the name of any other entity in the same declarative region.
A namespace-name defined at global scope shall not be
declared as the name of any other entity in any glogal scope
of the program. */
error ("declaration of `namespace %D' conflicts with", newdecl);
cp_error_at ("previous declaration of `namespace %D' here", olddecl);
return error_mark_node;
}
else
{
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
error (errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
&& namespace_bindings_p ())
? "`%#D' previously defined here"
: "`%#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)
{
/* Prototype decl follows defn w/o prototype. */
cp_warning_at ("prototype for `%#D'", newdecl);
warning ("%Jfollows non-prototype definition here", olddecl);
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
{
/* extern "C" int foo ();
int foo () { bar (); }
is OK. */
if (current_lang_depth () == 0)
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
else
{
cp_error_at ("previous declaration of `%#D' with %L linkage",
olddecl, DECL_LANGUAGE (olddecl));
error ("conflicts with new declaration with %L 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 `%#D'",
i, newdecl);
cp_pedwarn_at ("after previous specification in `%#D'",
olddecl);
}
else
{
error ("default argument given for parameter %d of `%#D'",
i, newdecl);
cp_error_at ("after previous specification in `%#D'",
olddecl);
}
}
if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& TREE_ADDRESSABLE (olddecl) && warn_inline)
{
warning ("`%#D' was used before it was declared inline", newdecl);
warning ("%Jprevious non-inline declaration here", olddecl);
}
}
}
/* Do not merge an implicit typedef with an explicit one. In:
class A;
...
typedef class A A __attribute__ ((foo));
the attribute should apply only to the typedef. */
if (TREE_CODE (olddecl) == TYPE_DECL
&& (DECL_IMPLICIT_TYPEDEF_P (olddecl)
|| DECL_IMPLICIT_TYPEDEF_P (newdecl)))
return NULL_TREE;
/* If new decl is `static' and an `extern' was seen previously,
warn about it. */
warn_extern_redeclared_static (newdecl, olddecl);
/* We have committed to returning 1 at this point. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
/* Now that functions must hold information normally held
by field decls, there is extra work to do so that
declaration information does not get destroyed during
definition. */
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_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_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;
/* Optionally warn about more than one declaration for the same
name, but don't warn about a function declaration followed by a
definition. */
if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
/* Don't warn about extern decl followed by definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
/* Don't warn about friends, let add_friend take care of it. */
&& ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
{
warning ("redundant redeclaration of `%D' in same scope", newdecl);
cp_warning_at ("previous declaration of `%D'", olddecl);
}
}
/* Deal with C++: must preserve virtual function table size. */
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);
}
/* Copy all the DECL_... slots specified in the new decl
except for any that we copy here from the old type. */
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
/* If the new declaration is a definition, update the file and
line information on the declaration. */
if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
{
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
= DECL_SOURCE_LOCATION (newdecl);
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (olddecl))
= DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (newdecl));
}
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
{
DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl))
|= DECL_INLINE (DECL_TEMPLATE_RESULT (newdecl));
DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (olddecl))
|= DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (newdecl));
}
return olddecl;
}
if (types_match)
{
/* Automatically handles default parameters. */
tree oldtype = TREE_TYPE (olddecl);
tree newtype;
/* Merge the data types specified in the two decls. */
newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
/* If merge_types produces a non-typedef type, just use the old type. */
if (TREE_CODE (newdecl) == TYPE_DECL
&& newtype == DECL_ORIGINAL_TYPE (newdecl))
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
{
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
}
/* Do this after calling `merge_types' so that default
parameters don't confuse us. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
!= TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
{
TREE_TYPE (newdecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
TREE_TYPE (olddecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (oldtype));
if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
&& DECL_SOURCE_LINE (olddecl) != 0
&& flag_exceptions
&& !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
{
error ("declaration of `%F' throws different exceptions",
newdecl);
cp_error_at ("than previous declaration `%F'", olddecl);
}
}
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
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);
/* Merge the type qualifiers. */
if (TREE_READONLY (newdecl))
TREE_READONLY (olddecl) = 1;
if (TREE_THIS_VOLATILE (newdecl))
TREE_THIS_VOLATILE (olddecl) = 1;
/* Merge the initialization information. */
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_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
}
}
/* Merge the section attribute.
We want to issue an error if the sections conflict but that must be
done later in decl_attributes since we are called before attributes
are assigned. */
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);
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
}
else if (TREE_CODE (newdecl) == VAR_DECL
&& (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
{
/* Keep the old RTL. We cannot keep the old RTL if the old
declaration was for an incomplete object and the new
declaration is not since many attributes of the RTL will
change. */
COPY_DECL_RTL (olddecl, newdecl);
}
}
/* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */
else
{
/* Clean out any memory we had of the old declaration. */
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 the storage class information. */
merge_weak (newdecl, olddecl);
DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl);
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0;
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
|= DECL_INITIALIZED_IN_CLASS_P (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
/* Only functions have DECL_BEFRIENDING_CLASSES. */
if (TREE_CODE (newdecl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (newdecl))
{
DECL_BEFRIENDING_CLASSES (newdecl)
= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
DECL_BEFRIENDING_CLASSES (olddecl));
/* DECL_THUNKS is only valid for virtual functions,
otherwise it is a DECL_FRIEND_CONTEXT. */
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))
{
/* If newdecl is not a specialization, then it is not a
template-related function at all. And that means that we
should have exited above, returning 0. */
my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
0);
if (TREE_USED (olddecl))
/* From [temp.expl.spec]:
If a template, a member template or the member of a class
template is explicitly specialized then that
specialization shall be declared before the first use of
that specialization that would cause an implicit
instantiation to take place, in every translation unit in
which such a use occurs. */
error ("explicit specialization of %D after first use",
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
/* [temp.expl.spec/14] We don't inline explicit specialization
just because the primary template says so. */
}
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 either decl says `inline', this fn is inline, unless
its definition was passed already. */
if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
DECL_INLINE (olddecl) = 1;
DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
}
/* Preserve abstractness on cloned [cd]tors. */
DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
if (! types_match)
{
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl);
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
if (! types_match || new_defines_function)
{
/* These need to be copied so that the names are available.
Note that if the types do match, we'll preserve inline
info and other bits, but if not, we won't. */
DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
}
if (new_defines_function)
/* If defining a function declared with other language
linkage, use the previously declared language linkage. */
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
else if (types_match)
{
/* If redeclaring a builtin function, and not a definition,
it stays built in. */
if (DECL_BUILT_IN (olddecl))
{
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
/* If we're keeping the built-in definition, keep the rtl,
regardless of declaration matches. */
SET_DECL_RTL (newdecl, DECL_RTL (olddecl));
}
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
/* Don't clear out the arguments if we're redefining a function. */
if (DECL_ARGUMENTS (olddecl))
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
}
}
else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl);
/* Now preserve various other info from the definition. */
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 either declaration has a nondefault visibility, use it. */
if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
{
if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
warning ("%J'%D': visibility attribute ignored because it",
newdecl, newdecl);
warning ("%Jconflicts with previous declaration here", olddecl);
}
DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
function_size = sizeof (struct tree_decl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
function_size - sizeof (struct tree_common));
if (DECL_TEMPLATE_INSTANTIATION (newdecl))
/* If newdecl is a template instantiation, it is possible that
the following sequence of events has occurred:
o A friend function was declared in a class template. The
class template was instantiated.
o The instantiation of the friend declaration was
recorded on the instantiation list, and is newdecl.
o Later, however, instantiate_class_template called pushdecl
on the newdecl to perform name injection. But, pushdecl in
turn called duplicate_decls when it discovered that another
declaration of a global function with the same name already
existed.
o Here, in duplicate_decls, we decided to clobber newdecl.
If we're going to do that, we'd better make sure that
olddecl, and not newdecl, is on the list of
instantiations so that if we try to do the instantiation
again we won't get the clobbered declaration. */
reregister_specialization (newdecl,
DECL_TI_TEMPLATE (newdecl),
olddecl);
}
else
{
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common)
+ TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
}
DECL_UID (olddecl) = olddecl_uid;
if (olddecl_friend)
DECL_FRIEND_P (olddecl) = 1;
/* NEWDECL contains the merged attribute lists.
Update OLDDECL to be the same. */
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
/* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
so that encode_section_info has a chance to look at the new decl
flags and attributes. */
if (DECL_RTL_SET_P (olddecl)
&& (TREE_CODE (olddecl) == FUNCTION_DECL
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl, NULL);
return olddecl;
}
/* Generate an implicit declaration for identifier FUNCTIONID
as a function of type int (). Print a warning if appropriate. */
tree
implicitly_declare (tree functionid)
{
tree decl;
/* We used to reuse an old implicit decl here,
but this loses with inline functions because it can clobber
the saved decl chains. */
decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
/* ISO standard says implicit declarations are in the innermost block.
So we record the decl in the standard fashion. */
pushdecl (decl);
rest_of_decl_compilation (decl, NULL, 0, 0);
if (warn_implicit
/* Only one warning per identifier. */
&& IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE)
{
pedwarn ("implicit declaration of function `%#D'", decl);
}
SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
return decl;
}
/* Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
Otherwise return an error message format string with a %s
where the identifier should go. */
static const char *
redeclaration_error_message (tree newdecl, tree olddecl)
{
if (TREE_CODE (newdecl) == TYPE_DECL)
{
/* Because C++ can put things into name space for free,
constructs like "typedef struct foo { ... } foo"
would look like an erroneous redeclaration. */
if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
return 0;
else
return "redefinition of `%#D'";
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
/* If this is a pure function, its olddecl will actually be
the original initialization to `0' (which we force to call
abort()). Don't complain about redefinition in this case. */
if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl))
return 0;
/* If both functions come from different namespaces, this is not
a redeclaration - this is a conflict with a used function. */
if (DECL_NAMESPACE_SCOPE_P (olddecl)
&& DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl))
return "`%D' conflicts with used function";
/* We'll complain about linkage mismatches in
warn_extern_redeclared_static. */
/* Defining the same name twice is no good. */
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
if (DECL_NAME (olddecl) == NULL_TREE)
return "`%#D' not declared in class";
else
return "redefinition of `%#D'";
}
return 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
tree nt, ot;
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
{
if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
&& COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
return "redefinition of `%#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 `%#D'";
return NULL;
}
else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
{
/* Objects declared at top level: */
/* If at least one is a reference, it's ok. */
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
/* Reject two definitions. */
return "redefinition of `%#D'";
}
else
{
/* Objects declared with block scope: */
/* Reject two definitions, and reject a definition
together with an external reference. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
return "redeclaration of `%#D'";
return 0;
}
}
/* Create a new label, named ID. */
static tree
make_label_decl (tree id, int local_p)
{
tree decl;
decl = build_decl (LABEL_DECL, id, void_type_node);
DECL_CONTEXT (decl) = current_function_decl;
DECL_MODE (decl) = VOIDmode;
C_DECLARED_LABEL_FLAG (decl) = local_p;
/* Say where one reference is to the label, for the sake of the
error if it is not defined. */
DECL_SOURCE_LOCATION (decl) = input_location;
/* Record the fact that this identifier is bound to this label. */
SET_IDENTIFIER_LABEL_VALUE (id, decl);
return decl;
}
/* Record this label on the list of used labels so that we can check
at the end of the function to see whether or not the label was
actually defined, and so we can check when the label is defined whether
this use is valid. */
static void
use_label (tree decl)
{
if (named_label_uses == NULL
|| named_label_uses->names_in_scope != current_binding_level->names
|| named_label_uses->label_decl != decl)
{
struct named_label_use_list *new_ent;
new_ent = ggc_alloc (sizeof (struct named_label_use_list));
new_ent->label_decl = decl;
new_ent->names_in_scope = current_binding_level->names;
new_ent->binding_level = current_binding_level;
new_ent->o_goto_locus = input_location;
new_ent->next = named_label_uses;
named_label_uses = new_ent;
}
}
/* Look for a label named ID in the current function. If one cannot
be found, create one. (We keep track of used, but undefined,
labels, and complain about them at the end of a function.) */
tree
lookup_label (tree id)
{
tree decl;
struct named_label_list *ent;
timevar_push (TV_NAME_LOOKUP);
/* You can't use labels at global scope. */
if (current_function_decl == NULL_TREE)
{
error ("label `%s' referenced outside of any function",
IDENTIFIER_POINTER (id));
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* See if we've already got this label. */
decl = IDENTIFIER_LABEL_VALUE (id);
if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
IDENTIFIER_LABEL_VALUE before the new label is declared. */
ent = ggc_alloc_cleared (sizeof (struct named_label_list));
ent->old_value = IDENTIFIER_LABEL_VALUE (id);
ent->next = named_labels;
named_labels = ent;
/* We need a new label. */
decl = make_label_decl (id, /*local_p=*/0);
/* Now fill in the information we didn't have before. */
ent->label_decl = decl;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Declare a local label named ID. */
tree
declare_local_label (tree id)
{
tree decl;
/* Add a new entry to the SHADOWED_LABELS list so that when we leave
this scope we can restore the old value of
IDENTIFIER_TYPE_VALUE. */
current_binding_level->shadowed_labels
= tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
current_binding_level->shadowed_labels);
/* Look for the label. */
decl = make_label_decl (id, /*local_p=*/1);
/* Now fill in the information we didn't have before. */
TREE_VALUE (current_binding_level->shadowed_labels) = decl;
return decl;
}
/* Returns nonzero if it is ill-formed to jump past the declaration of
DECL. Returns 2 if it's also a real problem. */
static int
decl_jump_unsafe (tree decl)
{
if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
return 0;
if (DECL_INITIAL (decl) == NULL_TREE
&& pod_type_p (TREE_TYPE (decl)))
return 0;
/* This is really only important if we're crossing an initialization.
The POD stuff is just pedantry; why should it matter if the class
contains a field of pointer to member type? */
if (DECL_INITIAL (decl)
|| (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
return 2;
return 1;
}
/* Check that a single previously seen jump to a newly defined label
is OK. DECL is the LABEL_DECL or 0; LEVEL is the binding_level for
the jump context; NAMES are the names in scope in LEVEL at the jump
context; FILE and LINE are the source position of the jump or 0. */
static void
check_previous_goto_1 (tree decl,
struct cp_binding_level* level,
tree names, const location_t *locus)
{
int identified = 0;
int saw_eh = 0;
struct cp_binding_level *b = current_binding_level;
for (; b; b = b->level_chain)
{
tree new_decls = b->names;
tree old_decls = (b == level ? names : NULL_TREE);
for (; new_decls != old_decls;
new_decls = TREE_CHAIN (new_decls))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
continue;
if (! identified)
{
if (decl)
pedwarn ("jump to label `%D'", decl);
else
pedwarn ("jump to case label");
if (locus)
pedwarn ("%H from here", locus);
identified = 1;
}
if (problem > 1)
cp_error_at (" crosses initialization of `%#D'",
new_decls);
else
cp_pedwarn_at (" enters scope of non-POD `%#D'",
new_decls);
}
if (b == level)
break;
if ((b->kind == sk_try || b->kind == sk_catch) && ! saw_eh)
{
if (! identified)
{
if (decl)
pedwarn ("jump to label `%D'", decl);
else
pedwarn ("jump to case label");
if (locus)
pedwarn ("%H from here", locus);
identified = 1;
}
if (b->kind == sk_try)
error (" enters try block");
else
error (" enters catch block");
saw_eh = 1;
}
}
}
static void
check_previous_goto (struct named_label_use_list* use)
{
check_previous_goto_1 (use->label_decl, use->binding_level,
use->names_in_scope, &use->o_goto_locus);
}
static void
check_switch_goto (struct cp_binding_level* level)
{
check_previous_goto_1 (NULL_TREE, level, level->names, NULL);
}
/* Check that any previously seen jumps to a newly defined label DECL
are OK. Called by define_label. */
static void
check_previous_gotos (tree decl)
{
struct named_label_use_list **usep;
if (! TREE_USED (decl))
return;
for (usep = &named_label_uses; *usep; )
{
struct named_label_use_list *use = *usep;
if (use->label_decl == decl)
{
check_previous_goto (use);
*usep = use->next;
}
else
usep = &(use->next);
}
}
/* Check that a new jump to a label DECL is OK. Called by
finish_goto_stmt. */
void
check_goto (tree decl)
{
int identified = 0;
tree bad;
struct named_label_list *lab;
/* We can't know where a computed goto is jumping. So we assume
that it's OK. */
if (! DECL_P (decl))
return;
/* If the label hasn't been defined yet, defer checking. */
if (! DECL_INITIAL (decl))
{
use_label (decl);
return;
}
for (lab = named_labels; lab; lab = lab->next)
if (decl == lab->label_decl)
break;
/* If the label is not on named_labels it's a gcc local label, so
it must be in an outer scope, so jumping to it is always OK. */
if (lab == 0)
return;
if ((lab->in_try_scope || lab->in_catch_scope || lab->bad_decls)
&& !identified)
{
cp_pedwarn_at ("jump to label `%D'", decl);
pedwarn (" from here");
identified = 1;
}
for (bad = lab->bad_decls; bad; bad = TREE_CHAIN (bad))
{
tree b = TREE_VALUE (bad);
int u = decl_jump_unsafe (b);
if (u > 1 && DECL_ARTIFICIAL (b))
/* Can't skip init of __exception_info. */
error ("%J enters catch block", b);
else if (u > 1)
cp_error_at (" skips initialization of `%#D'", b);
else
cp_pedwarn_at (" enters scope of non-POD `%#D'", b);
}
if (lab->in_try_scope)
error (" enters try block");
else if (lab->in_catch_scope)
error (" enters catch block");
}
/* Define a label, specifying the location in the source file.
Return the LABEL_DECL node for the label. */
tree
define_label (location_t location, tree name)
{
tree decl = lookup_label (name);
struct named_label_list *ent;
struct cp_binding_level *p;
timevar_push (TV_NAME_LOOKUP);
for (ent = named_labels; ent; ent = ent->next)
if (ent->label_decl == decl)
break;
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
for (p = current_binding_level;
p->kind != sk_function_parms;
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 `%D'", decl);
else
{
/* Mark label as having been defined. */
DECL_INITIAL (decl) = error_mark_node;
/* Say where in the source. */
DECL_SOURCE_LOCATION (decl) = location;
if (ent)
{
ent->names_in_scope = current_binding_level->names;
ent->binding_level = current_binding_level;
}
check_previous_gotos (decl);
}
timevar_pop (TV_NAME_LOOKUP);
return decl;
}
struct cp_switch
{
struct cp_binding_level *level;
struct cp_switch *next;
/* The SWITCH_STMT being built. */
tree switch_stmt;
/* A splay-tree mapping the low element of a case range to the high
element, or NULL_TREE if there is no high element. Used to
determine whether or not a new case label duplicates an old case
label. We need a tree, rather than simply a hash table, because
of the GNU case range extension. */
splay_tree cases;
};
/* A stack of the currently active switch statements. The innermost
switch statement is on the top of the stack. There is no need to
mark the stack for garbage collection because it is only active
during the processing of the body of a function, and we never
collect at that point. */
static struct cp_switch *switch_stack;
/* Called right after a switch-statement condition is parsed.
SWITCH_STMT is the switch statement being parsed. */
void
push_switch (tree switch_stmt)
{
struct cp_switch *p = xmalloc (sizeof (struct cp_switch));
p->level = current_binding_level;
p->next = switch_stack;
p->switch_stmt = switch_stmt;
p->cases = splay_tree_new (case_compare, NULL, NULL);
switch_stack = p;
}
void
pop_switch (void)
{
struct cp_switch *cs;
cs = switch_stack;
splay_tree_delete (cs->cases);
switch_stack = switch_stack->next;
free (cs);
}
/* Note that we've seen a definition of a case label, and complain if this
is a bad place for one. */
tree
finish_case_label (tree low_value, tree high_value)
{
tree cond, r;
struct cp_binding_level *p;
if (processing_template_decl)
{
tree label;
/* For templates, just add the case label; we'll do semantic
analysis at instantiation-time. */
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
return add_stmt (build_case_label (low_value, high_value, label));
}
/* Find the condition on which this switch statement depends. */
cond = SWITCH_COND (switch_stack->switch_stmt);
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
check_switch_goto (switch_stack->level);
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
for (p = current_binding_level;
p->kind != sk_function_parms;
p = p->level_chain)
p->more_cleanups_ok = 0;
return r;
}
/* Hash a TYPENAME_TYPE. K is really of type `tree'. */
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;
}
/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
static int
typename_compare (const void * k1, const void * k2)
{
tree t1;
tree t2;
tree d1;
tree d2;
t1 = (tree) k1;
t2 = (tree) k2;
d1 = TYPE_NAME (t1);
d2 = TYPE_NAME (t2);
return (DECL_NAME (d1) == DECL_NAME (d2)
&& TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2)
&& ((TREE_TYPE (t1) != NULL_TREE)
== (TREE_TYPE (t2) != NULL_TREE))
&& same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
&& TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
}
/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is
the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE
is non-NULL, this type is being created by the implicit typename
extension, and BASE_TYPE is a type named `t' in some base class of
`T' which depends on template parameters.
Returns the new TYPENAME_TYPE. */
static GTY ((param_is (union tree_node))) htab_t typename_htab;
static tree
build_typename_type (tree context, tree name, tree fullname)
{
tree t;
tree d;
void **e;
if (typename_htab == NULL)
{
typename_htab = htab_create_ggc (61, &typename_hash,
&typename_compare, NULL);
}
/* Build the TYPENAME_TYPE. */
t = make_aggr_type (TYPENAME_TYPE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
TYPENAME_TYPE_FULLNAME (t) = fullname;
/* Build the corresponding TYPE_DECL. */
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;
/* See if we already have this type. */
e = htab_find_slot (typename_htab, t, INSERT);
if (*e)
t = (tree) *e;
else
*e = t;
return t;
}
/* Resolve `typename CONTEXT::NAME'. Returns an appropriate type,
unless an error occurs, in which case error_mark_node is returned.
If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
set, we return that, rather than the _TYPE it corresponds to, in
other cases we look through the type decl. If TF_ERROR is set,
complain about errors, otherwise be quiet. */
tree
make_typename_type (tree context, tree name, tsubst_flags_t complain)
{
tree fullname;
if (name == error_mark_node
|| context == NULL_TREE
|| context == error_mark_node)
return error_mark_node;
if (TYPE_P (name))
{
if (!(TYPE_LANG_SPECIFIC (name)
&& (CLASSTYPE_IS_TEMPLATE (name)
|| CLASSTYPE_USE_TEMPLATE (name))))
name = TYPE_IDENTIFIER (name);
else
/* Create a TEMPLATE_ID_EXPR for the type. */
name = build_nt (TEMPLATE_ID_EXPR,
CLASSTYPE_TI_TEMPLATE (name),
CLASSTYPE_TI_ARGS (name));
}
else if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
fullname = name;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
name = TREE_OPERAND (name, 0);
if (TREE_CODE (name) == TEMPLATE_DECL)
name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);
}
if (TREE_CODE (name) == TEMPLATE_DECL)
{
error ("`%D' used without template parameters", name);
return error_mark_node;
}
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030802);
if (TREE_CODE (context) == NAMESPACE_DECL)
{
/* We can get here from typename_sub0 in the explicit_template_type
expansion. Just fail. */
if (complain & tf_error)
error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
if (!dependent_type_p (context)
|| currently_open_class (context))
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
{
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
NULL_TREE, context,
/*entering_scope=*/0,
tf_error | tf_warning | tf_user);
}
else
{
tree t;
if (!IS_AGGR_TYPE (context))
{
if (complain & tf_error)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
t = lookup_field (context, name, 0, true);
if (t)
{
if (TREE_CODE (t) != TYPE_DECL)
{
if (complain & tf_error)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), t);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
return t;
}
}
}
/* If the CONTEXT is not a template type, then either the field is
there now or its never going to be. */
if (!dependent_type_p (context))
{
if (complain & tf_error)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
return build_typename_type (context, name, fullname);
}
/* Resolve `CONTEXT::template NAME'. Returns an appropriate type,
unless an error occurs, in which case error_mark_node is returned.
If we locate a TYPE_DECL, we return that, rather than the _TYPE it
corresponds to. If COMPLAIN zero, don't complain about any errors
that occur. */
tree
make_unbound_class_template (tree context, tree name, 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);
if (TREE_CODE (name) != IDENTIFIER_NODE)
abort ();
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 `%#T' in `%#T'", name, context);
return error_mark_node;
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
return tmpl;
}
/* Build the UNBOUND_CLASS_TEMPLATE. */
t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
TREE_TYPE (t) = NULL_TREE;
/* Build the corresponding TEMPLATE_DECL. */
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;
return t;
}
/* A chain of TYPE_DECLs for the builtin types. */
static GTY(()) tree builtin_type_decls;
/* Return a chain of TYPE_DECLs for the builtin types. */
tree
cxx_builtin_type_decls (void)
{
return builtin_type_decls;
}
/* Push the declarations of builtin types into the namespace.
RID_INDEX is the index of the builtin type in the array
RID_POINTERS. NAME is the name used when looking up the builtin
type. TYPE is the _TYPE node for the builtin type. */
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);
/* The calls to SET_IDENTIFIER_GLOBAL_VALUE below should be
eliminated. Built-in types should not be looked up name; their
names are keywords that the parser can recognize. However, there
is code in c-common.c that uses identifier_global_value to look
up built-in types by 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)
{
TREE_CHAIN (tdecl) = builtin_type_decls;
builtin_type_decls = tdecl;
}
}
/* Record one of the standard Java types.
* Declare it as having the given NAME.
* If SIZE > 0, it is the size of one of the integral types;
* otherwise it is the negative of the size of one of the other types. */
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)
{ /* "__java_char" or ""__java_boolean". */
type = make_unsigned_type (-size);
/*if (size == -1) TREE_SET_CODE (type, BOOLEAN_TYPE);*/
}
else
{ /* "__java_float" or ""__java_double". */
type = make_node (REAL_TYPE);
TYPE_PRECISION (type) = - size;
layout_type (type);
}
record_builtin_type (RID_MAX, name, type);
decl = TYPE_NAME (type);
/* Suppress generate debug symbol entries for these types,
since for normal C++ they are just clutter.
However, push_lang_context undoes this if extern "Java" is seen. */
DECL_IGNORED_P (decl) = 1;
TYPE_FOR_JAVA (type) = 1;
return type;
}
/* Push a type into the namespace so that the back-ends ignore it. */
static void
record_unknown_type (tree type, const char* name)
{
tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
/* Make sure the "unknown type" typedecl gets ignored for debug info. */
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);
}
/* An string for which we should create an IDENTIFIER_NODE at
startup. */
typedef struct predefined_identifier
{
/* The name of the identifier. */
const char *const name;
/* The place where the IDENTIFIER_NODE should be stored. */
tree *const node;
/* Nonzero if this is the name of a constructor or destructor. */
const int ctor_or_dtor_p;
} predefined_identifier;
/* Create all the predefined identifiers. */
static void
initialize_predefined_identifiers (void)
{
const predefined_identifier *pid;
/* A table of identifiers to create at startup. */
static const predefined_identifier predefined_identifiers[] = {
{ "C++", &lang_name_cplusplus, 0 },
{ "C", &lang_name_c, 0 },
{ "Java", &lang_name_java, 0 },
{ CTOR_NAME, &ctor_identifier, 1 },
{ "__base_ctor", &base_ctor_identifier, 1 },
{ "__comp_ctor", &complete_ctor_identifier, 1 },
{ DTOR_NAME, &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;
}
}
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *)0).
Initialize the global binding level.
Make definitions for built-in primitive functions. */
void
cxx_init_decl_processing (void)
{
tree void_ftype;
tree void_ftype_ptr;
/* Create all the identifiers we need. */
initialize_predefined_identifiers ();
/* Fill in back-end hooks. */
lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
/* Create the global variables. */
push_to_top_level ();
current_function_decl = NULL_TREE;
current_binding_level = NULL;
/* Enter the global namespace. */
my_friendly_assert (global_namespace == NULL_TREE, 375);
global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
void_type_node);
begin_scope (sk_namespace, global_namespace);
current_lang_name = NULL_TREE;
/* Adjust various flags based on command-line settings. */
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;
flag_inline_functions = 0;
}
/* Force minimum function alignment if using the least significant
bit of function pointers to store the virtual bit. */
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
&& force_align_functions_log < 1)
force_align_functions_log = 1;
/* Initially, C. */
current_lang_name = lang_name_c;
build_common_tree_nodes (flag_signed_char);
error_mark_list = build_tree_list (error_mark_node, error_mark_node);
TREE_TYPE (error_mark_list) = error_mark_node;
/* Create the `std' namespace. */
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_2 (2, 0);
TREE_TYPE (integer_two_node) = integer_type_node;
integer_three_node = build_int_2 (3, 0);
TREE_TYPE (integer_three_node) = integer_type_node;
record_builtin_type (RID_BOOL, "bool", boolean_type_node);
truthvalue_type_node = boolean_type_node;
truthvalue_false_node = boolean_false_node;
truthvalue_true_node = boolean_true_node;
empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
#if 0
record_builtin_type (RID_MAX, NULL, string_type_node);
#endif
delta_type_node = ptrdiff_type_node;
vtable_index_type = ptrdiff_type_node;
vtt_parm_type = build_pointer_type (const_ptr_type_node);
void_ftype = build_function_type (void_type_node, void_list_node);
void_ftype_ptr = build_function_type (void_type_node,
tree_cons (NULL_TREE,
ptr_type_node,
void_list_node));
void_ftype_ptr
= build_exception_variant (void_ftype_ptr, empty_except_spec);
/* C++ extensions */
unknown_type_node = make_node (UNKNOWN_TYPE);
record_unknown_type (unknown_type_node, "unknown type");
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TREE_TYPE (unknown_type_node) = unknown_type_node;
/* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same
result. */
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
{
/* Make sure we get a unique function type, so we can give
its pointer type a name. (This wins for gdb.) */
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");
/* Now, C++. */
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);
/* Perform other language dependent initializations. */
init_class_processing ();
init_search_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 ();
/* Show we use EH for cleanups. */
using_eh_for_cleanups ();
/* Maintain consistency. Perhaps we should just complain if they
say -fwritable-strings? */
if (flag_writable_strings)
flag_const_strings = 0;
}
/* Generate an initializer for a function naming variable from
NAME. NAME may be NULL, to indicate a dependent name. TYPE_P is
filled in with the type of the init. */
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;
}
/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
decl, NAME is the initialization string and TYPE_DEP indicates whether
NAME depended on the type of the function. We make use of that to detect
__PRETTY_FUNCTION__ inside a template fn. This is being done
lazily at the point of first use, so we musn't push the decl now. */
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);
/* As we're using pushdecl_with_scope, we must set the context. */
DECL_CONTEXT (decl) = current_function_decl;
DECL_PRETTY_FUNCTION_P (decl) = type_dep;
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = init;
TREE_USED (decl) = 1;
if (current_function_decl)
{<