-/* Process declarations and variables for C++ compiler.
- Copyright (C) 1988, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
- Hacked by Michael Tiemann (tiemann@cygnus.com)
+/* Process declarations and variables for C compiler.
+ Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
#include "config.h"
#include "system.h"
-#include <stdio.h>
#include "tree.h"
#include "rtl.h"
#include "flags.h"
#include "defaults.h"
#include "output.h"
#include "except.h"
+#include "toplev.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
extern tree builtin_return_address_fndecl;
extern struct obstack permanent_obstack;
+extern struct obstack* saveable_obstack;
extern int current_class_depth;
extern tree current_namespace;
extern tree global_namespace;
+extern void (*print_error_function) PROTO((char *));
+
/* Stack of places to restore the search obstack back to. */
/* Obstack used for remembering local class declarations (like
static tree lookup_nested_type PROTO((tree, tree));
static char *redeclaration_error_message PROTO((tree, tree));
static tree push_overloaded_decl PROTO((tree, int));
-static void push_overloaded_decl_top_level PROTO((tree, int));
static struct stack_level *push_decl_level PROTO((struct stack_level *,
struct obstack *));
static struct binding_level *make_binding_level PROTO((void));
static int namespace_bindings_p PROTO((void));
static void declare_namespace_level PROTO((void));
-static tree get_unique_name PROTO((void));
static void signal_catch PROTO((int));
static void storedecls PROTO((tree));
static void storetags PROTO((tree));
static tree lookup_tag_reverse PROTO((tree, tree));
static tree obscure_complex_init PROTO((tree, tree));
static tree maybe_build_cleanup_1 PROTO((tree, tree));
-static tree lookup_name_real PROTO((tree, int, int));
+static tree lookup_name_real PROTO((tree, int, int, int));
static void warn_extern_redeclared_static PROTO((tree, tree));
static void grok_reference_init PROTO((tree, tree, tree));
static tree grokfndecl PROTO((tree, tree, tree, tree, int,
- enum overload_flags,
- tree, tree, tree, int, int, int, int, int, int));
-static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int));
+ enum overload_flags, tree,
+ tree, tree, int, int, int, int, int, int, tree));
+static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int, tree));
static tree lookup_tag PROTO((enum tree_code, tree,
struct binding_level *, int));
static void set_identifier_type_value_with_scope
PROTO((tree, tree, struct binding_level *));
static void record_builtin_type PROTO((enum rid, char *, tree));
+static void record_unknown_type PROTO((tree, char *));
static int member_function_or_else PROTO((tree, tree, char *));
static void bad_specifiers PROTO((tree, char *, int, int, int, int,
int));
-static tree make_implicit_typename PROTO((tree, tree));
+static void lang_print_error_function PROTO((char *));
+
+#if defined (DEBUG_CP_BINDING_LEVELS)
+static void indent PROTO((void));
+#endif
-/* a node which has tree code ERROR_MARK, and whose type is itself.
+/* A node which has tree code ERROR_MARK, and whose type is itself.
All erroneous expressions are replaced with this node. All functions
that accept nodes as arguments should avoid generating error messages
if this node is one of the arguments, since it is undesirable to get
tree intHI_type_node;
tree intSI_type_node;
tree intDI_type_node;
+tree intTI_type_node;
tree unsigned_intQI_type_node;
tree unsigned_intHI_type_node;
tree unsigned_intSI_type_node;
tree unsigned_intDI_type_node;
+tree unsigned_intTI_type_node;
+
+tree java_byte_type_node;
+tree java_short_type_node;
+tree java_int_type_node;
+tree java_long_type_node;
+tree java_float_type_node;
+tree java_double_type_node;
+tree java_char_type_node;
+tree java_boolean_type_node;
-/* a VOID_TYPE node, and the same, packaged in a TREE_LIST. */
+/* A VOID_TYPE node, and the same, packaged in a TREE_LIST. */
tree void_type_node, void_list_node;
tree void_zero_node;
/* The bool data type, and constants */
tree boolean_type_node, boolean_true_node, boolean_false_node;
-/* type `int ()' -- used for implicit declaration of functions. */
+/* Type `int ()' -- used for implicit declaration of functions. */
tree default_function_type;
-/* function types `double (double)' and `double (double, double)', etc. */
+/* Function types `double (double)' and `double (double, double)', etc. */
static tree double_ftype_double, double_ftype_double_double;
static tree int_ftype_int, long_ftype_long;
tree __ptmf_desc_array_type, __ptmd_desc_array_type;
#endif
+/* Indicates that there is a type value in some namespace, although
+ that is not necessarily in scope at the moment. */
+
+static tree global_type_node;
+
tree class_star_type_node;
tree class_type_node, record_type_node, union_type_node, enum_type_node;
tree unknown_type_node;
/* namespace std */
tree std_node;
+int in_std = 0;
+
+/* Expect only namespace names now. */
+static int only_namespace_names;
/* In a destructor, the point at which all derived class destroying
has been done, just before any base class destroying will be done. */
/* A list (chain of TREE_LIST nodes) of named label uses.
The TREE_PURPOSE field is the list of variables defined
- the the label's scope defined at the point of use.
+ in the label's scope defined at the point of use.
The TREE_VALUE field is the LABEL_DECL used.
The TREE_TYPE field holds `current_binding_level' at the
point of the label's use.
component_bindings. */
tree tags;
+ /* A list of USING_DECL nodes. */
+ tree usings;
+
+ /* A list of used namespaces. PURPOSE is the namespace,
+ VALUE the common ancestor with this binding_level's namespace. */
+ tree using_directives;
+
/* For each level, a list of shadowed outer-level local definitions
to be restored when this level is popped.
Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
if (global_binding_level)
{
- /* cannot pop a level, if there are none left to pop. */
+ /* Cannot pop a level, if there are none left to pop. */
if (current_binding_level == global_binding_level)
my_friendly_abort (123);
}
if (global_binding_level)
{
- /* cannot suspend a level, if there are none left to suspend. */
+ /* Cannot suspend a level, if there are none left to suspend. */
if (current_binding_level == global_binding_level)
my_friendly_abort (123);
}
resume_binding_level (b)
struct binding_level *b;
{
- if (class_binding_level)
- {
-#if 1
- /* These are here because we cannot deal with shadows yet. */
- sorry ("cannot resume a namespace inside class");
- return;
-#else
- b->level_chain = class_binding_level;
- class_binding_level = (struct binding_level *)0;
-#endif
- }
- else
- {
-#if 1
- /* These are here because we cannot deal with shadows yet. */
- if (b->level_chain != current_binding_level)
- {
- sorry ("cannot resume a namespace inside a different namespace");
- return;
- }
-#endif
- b->level_chain = current_binding_level;
- }
+ /* Resuming binding levels is meant only for namespaces,
+ and those cannot nest into classes. */
+ my_friendly_assert(!class_binding_level, 386);
+ /* Also, resuming a non-directly nested namespace is a no-no. */
+ my_friendly_assert(b->level_chain == current_binding_level, 386);
current_binding_level = b;
#if defined(DEBUG_CP_BINDING_LEVELS)
b->binding_depth = binding_depth;
/* Nonzero if we are currently in a toplevel binding level. This
means either the global binding level or a namespace in a toplevel
- binding level. */
+ binding level.
+ Since there are no non-toplevel namespace levels, this really
+ means any namespace or pseudo-global level. */
int
toplevel_bindings_p ()
{
- struct binding_level *b = current_binding_level;
-
- while (1)
- {
- if (b == global_binding_level)
- return 1;
- if (b->pseudo_global)
- return 1;
- if (! b->namespace_p)
- return 0;
- b=b->level_chain;
- }
+ return current_binding_level->namespace_p
+ || current_binding_level->pseudo_global;
}
/* Nonzero if this is a namespace scope. */
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
}
/* If the level being exited is the top level of a function,
return block;
}
-/* Resume a binding level for a namespace. */
-
-void
-resume_level (b)
- struct binding_level *b;
-{
- tree decls, link;
-
- resume_binding_level (b);
-
- /* Resume the variable caches. */
- decls = current_binding_level->names;
-
- /* Restore the meanings of the local variables of this level. */
-
- for (link = decls; link; link = TREE_CHAIN (link))
- {
- /* If it doesn't have a name, there is nothing left to do with it. */
- if (DECL_NAME (link) == NULL_TREE)
- continue;
-
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = link;
-
- /* If this is a TYPE_DECL, push it into the type value slot. */
- if (TREE_CODE (link) == TYPE_DECL)
- SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (link), TREE_TYPE (link));
- }
-}
-
/* 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. */
for (shadowed = level->type_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
(HOST_WIDE_INT) class_binding_level->level_chain,
if (class_binding_level->parm_flag != 2)
class_binding_level = (struct binding_level *)0;
- /* Now, pop out of the the binding level which we created up in the
+ /* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
#if defined(DEBUG_CP_BINDING_LEVELS)
is_class_level = 1;
print_binding_level (global_binding_level);
}
-/* Return the tree_binding for the name in the given scope
- If there are no bindings for the name in the scope, make a new
- bindings node. This bindings list of this node will be empty, though. */
+/* Namespace binding access routines: The namespace_bindings field of
+ the identifier is polymorphic, with three possible values:
+ NULL_TREE, a list of CPLUS_BINDINGS, or any other tree_node
+ indicating the BINDING_VALUE of global_namespace. */
-tree
-binding_for_name (name, scope)
+/* Check whether the a binding for the name to scope is known.
+ Assumes that the bindings of the name are already a list
+ of bindings. Returns the binding found, or NULL_TREE. */
+
+static tree
+find_binding (name, scope)
tree name;
tree scope;
{
- tree iter;
+ tree iter, prev = NULL_TREE;
+
+ scope = ORIGINAL_NAMESPACE (scope);
+
for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
iter = TREE_CHAIN (iter))
{
my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374);
if (BINDING_SCOPE (iter) == scope)
- return iter;
+ {
+ /* Move binding found to the fron of the list, so
+ subsequent lookups will find it faster. */
+ if (prev)
+ {
+ TREE_CHAIN (prev) = TREE_CHAIN (iter);
+ TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
+ }
+ return iter;
+ }
+ prev = iter;
}
- /* not found, make a new permanent one */
- push_obstacks (&permanent_obstack, &permanent_obstack);
- iter = make_node (CPLUS_BINDING);
- TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
- IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
- BINDING_SCOPE (iter) = scope;
- BINDING_VALUE (iter) = NULL_TREE;
- pop_obstacks ();
- return iter;
+ return NULL_TREE;
}
-extern char * first_global_object_name;
+/* Always returns a binding for name in scope. If the
+ namespace_bindings is not a list, convert it to one first.
+ If no binding is found, make a new one. */
-/* Get a unique name for each call to this routine for unnamed namespaces.
- Mostly copied from get_file_function_name. */
-
-static tree
-get_unique_name ()
+tree
+binding_for_name (name, scope)
+ tree name;
+ tree scope;
{
- static int temp_name_counter = 0;
- char *buf;
- register char *p;
+ tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ tree result;
- if (first_global_object_name)
- p = first_global_object_name;
- else if (main_input_filename)
- p = main_input_filename;
- else
- p = input_filename;
+ scope = ORIGINAL_NAMESPACE (scope);
+
+ if (b && TREE_CODE (b) != CPLUS_BINDING)
+ {
+ /* Get rid of optimization for global scope. */
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE;
+ BINDING_VALUE (binding_for_name (name, global_namespace)) = b;
+ b = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ }
+ if (b && (result = find_binding (name, scope)))
+ return result;
+ /* Not found, make a new permanent one. */
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ result = make_node (CPLUS_BINDING);
+ TREE_CHAIN (result) = b;
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
+ BINDING_SCOPE (result) = scope;
+ BINDING_TYPE (result) = NULL_TREE;
+ BINDING_VALUE (result) = NULL_TREE;
+ pop_obstacks ();
+ return result;
+}
-#define UNNAMED_NAMESPACE_FORMAT "__%s_%d"
+/* Return the binding value for name in scope, considering that
+ namespace_binding may or may not be a list of CPLUS_BINDINGS. */
+
+tree
+namespace_binding (name, scope)
+ tree name;
+ tree scope;
+{
+ tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ if (b == NULL_TREE)
+ return NULL_TREE;
+ if (scope == NULL_TREE)
+ scope = global_namespace;
+ if (TREE_CODE (b) != CPLUS_BINDING)
+ return (scope == global_namespace) ? b : NULL_TREE;
+ name = find_binding (name,scope);
+ if (name == NULL_TREE)
+ return name;
+ return BINDING_VALUE (name);
+}
- buf = (char *) alloca (sizeof (UNNAMED_NAMESPACE_FORMAT) + strlen (p));
+/* Set the binding value for name in scope. If modifying the binding
+ of global_namespace is attempted, try to optimize it. */
- sprintf (buf, UNNAMED_NAMESPACE_FORMAT, p, temp_name_counter++);
+void
+set_namespace_binding (name, scope, val)
+ tree name;
+ tree scope;
+ tree val;
+{
+ tree b;
- /* Don't need to pull weird characters out of global names. */
- if (p != first_global_object_name)
+ if (scope == NULL_TREE)
+ scope = global_namespace;
+
+ if (scope == global_namespace)
{
- for (p = buf+2; *p; p++)
- if (! ((*p >= '0' && *p <= '9')
-#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */
- || *p == '$'
-#endif
-#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */
- || *p == '.'
-#endif
- || (*p >= 'A' && *p <= 'Z')
- || (*p >= 'a' && *p <= 'z')))
- *p = '_';
+ b = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING)
+ {
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = val;
+ return;
+ }
}
-
- return get_identifier (buf);
+ b = binding_for_name (name, scope);
+ BINDING_VALUE (b) = val;
}
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
push_namespace (name)
tree name;
{
-#if 1
tree d;
int need_new = 1;
int implicit_use = 0;
- int nodecl = 0;
+ int global = 0;
if (!global_namespace)
{
- /* this must be :: */
+ /* This must be ::. */
my_friendly_assert (name == get_identifier ("::"), 377);
- nodecl = 1;
+ global = 1;
}
else if (!name)
{
- name = get_unique_name ();
+ /* The name of anonymous namespace is unique for the translation
+ unit. */
+ static tree anon_name = NULL_TREE;
+ if (!anon_name)
+ anon_name = get_file_function_name ('N');
+ name = anon_name;
+ d = IDENTIFIER_NAMESPACE_VALUE (name);
+ if (d)
+ /* Reopening anonymous namespace. */
+ need_new = 0;
implicit_use = 1;
- }
+ }
+ else if (current_namespace == global_namespace
+ && name == DECL_NAME (std_node))
+ {
+ in_std++;
+ return;
+ }
else
{
- /* check whether this is an extended namespace definition */
+ /* Check whether this is an extended namespace definition. */
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
- need_new = 0;
+ {
+ need_new = 0;
+ if (DECL_NAMESPACE_ALIAS (d))
+ {
+ cp_error ("namespace alias `%D' not allowed here, assuming `%D'",
+ d, DECL_NAMESPACE_ALIAS (d));
+ d = DECL_NAMESPACE_ALIAS (d);
+ }
+ }
}
if (need_new)
{
- /* make a new namespace, binding the name to it */
+ /* Make a new namespace, binding the name to it. */
d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
- if (!nodecl)
- d = pushdecl (d);
+ /* The global namespace is not pushed, and the global binding
+ level is set elsewhere. */
+ if (!global)
+ {
+ d = pushdecl (d);
+ pushlevel (0);
+ declare_namespace_level ();
+ NAMESPACE_LEVEL (d) = current_binding_level;
+ }
}
+ else
+ resume_binding_level (NAMESPACE_LEVEL (d));
+
if (implicit_use)
do_using_directive (d);
- /* enter the name space */
+ /* Enter the name space. */
current_namespace = d;
-
-#else
- tree old_id = get_namespace_id ();
- char *buf;
- tree d;
-
- if (! name)
- {
- /* Create a truly ugly name! */
- name = get_unique_name ();
- }
-
- d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
-
- /* Mark them as external, so redeclaration_error_message doesn't think
- they are duplicates. */
-
- DECL_EXTERNAL (d) = 1;
- d = pushdecl (d);
-
- if (NAMESPACE_LEVEL (d) == 0)
- {
- /* This is new for this compilation unit. */
- pushlevel (0);
- declare_namespace_level ();
- NAMESPACE_LEVEL (d) = current_binding_level;
- }
- else
- resume_level (NAMESPACE_LEVEL (d));
-
- /* This code is just is bit old now... */
- current_namespace = tree_cons (NULL_TREE, name, current_namespace);
- buf = (char *) alloca (4 + (old_id ? IDENTIFIER_LENGTH (old_id) : 0)
- + IDENTIFIER_LENGTH (name));
- sprintf (buf, "%s%s", old_id ? IDENTIFIER_POINTER (old_id) : "",
- IDENTIFIER_POINTER (name));
- TREE_PURPOSE (current_namespace) = get_identifier (buf);
-#endif
}
/* Pop from the scope of the current namespace. */
void
pop_namespace ()
{
-#if 1
- current_namespace = DECL_NAMESPACE (current_namespace);
-#else
- tree decls, link;
- current_namespace = TREE_CHAIN (current_namespace);
-
- /* Just in case we get out of sync. */
- if (! namespace_bindings_p ())
- poplevel (0, 0, 0);
+ if (current_namespace == global_namespace)
+ {
+ my_friendly_assert (in_std>0, 980421);
+ in_std--;
+ return;
+ }
+ current_namespace = CP_DECL_CONTEXT (current_namespace);
+ /* The binding level is not popped, as it might be re-opened later. */
+ suspend_binding_level ();
+}
- decls = current_binding_level->names;
+/* Concatenate the binding levels of all namespaces. */
- /* Clear out the meanings of the local variables of this level. */
+void
+cat_namespace_levels()
+{
+ tree current;
+ tree last;
+ struct binding_level *b;
- for (link = decls; link; link = TREE_CHAIN (link))
+ last = NAMESPACE_LEVEL (global_namespace) -> names;
+ /* The nested namespaces appear in the names list of their ancestors. */
+ for (current = last; current; current = TREE_CHAIN (current))
{
- if (DECL_NAME (link) != NULL_TREE)
+ if (TREE_CODE (current) != NAMESPACE_DECL)
+ continue;
+ if (!DECL_LANG_SPECIFIC (current))
{
- /* If the ident. was used or addressed via a local extern decl,
- don't forget that fact. */
- if (DECL_EXTERNAL (link))
- {
- if (TREE_USED (link))
- TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1;
- if (TREE_ADDRESSABLE (link))
- TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
- }
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
+ /* Hmm. std. */
+ my_friendly_assert (current == std_node, 393);
+ continue;
}
+ b = NAMESPACE_LEVEL (current);
+ while (TREE_CHAIN (last))
+ last = TREE_CHAIN (last);
+ TREE_CHAIN (last) = NAMESPACE_LEVEL (current) -> names;
}
-
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-
- /* suspend a level. */
- suspend_binding_level ();
-#endif
}
\f
/* Subroutines for reverting temporarily to top-level for instantiation
struct saved_scope {
struct binding_level *old_binding_level;
tree old_bindings;
+ tree old_namespace;
struct saved_scope *prev;
tree class_name, class_type, function_decl;
struct binding_level *class_bindings;
{
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
TREE_VEC_ELT (binding, 0) = id;
- TREE_VEC_ELT (binding, 1) = IDENTIFIER_TYPE_VALUE (id);
+ TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
{
tree t;
+ /* Template IDs are inserted into the global level. If they were
+ inserted into namespace level, finish_file wouldn't find them
+ when doing pending instantiations. Therefore, don't stop at
+ namespace level, but continue until :: . */
if (b == global_binding_level || (pseudo && b->pseudo_global))
break;
s->old_binding_level = current_binding_level;
current_binding_level = b;
+ s->old_namespace = current_namespace;
s->class_name = current_class_name;
s->class_type = current_class_type;
s->function_decl = current_function_decl;
current_lang_name = lang_name_cplusplus;
strict_prototype = strict_prototypes_lang_cplusplus;
named_labels = NULL_TREE;
+ shadowed_labels = NULL_TREE;
minimal_parse_mode = 0;
previous_class_type = previous_class_values = NULL_TREE;
processing_specialization = 0;
processing_explicit_instantiation = 0;
- if (!pseudo)
- {
- current_template_parms = NULL_TREE;
- processing_template_decl = 0;
- }
+ current_template_parms = NULL_TREE;
+ processing_template_decl = 0;
+ current_namespace = global_namespace;
s->prev = current_saved_scope;
s->old_bindings = old_bindings;
tree id = TREE_VEC_ELT (t, 0);
if (id)
{
- IDENTIFIER_TYPE_VALUE (id) = TREE_VEC_ELT (t, 1);
+ SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2);
IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
}
TREE_CHAIN (save) = free_binding_vecs;
free_binding_vecs = save;
}
+ current_namespace = s->old_namespace;
current_class_name = s->class_name;
current_class_type = s->class_type;
current_function_decl = s->function_decl;
tree type;
struct binding_level *b;
{
- if (b != global_binding_level)
+ if (!b->namespace_p)
{
- tree old_type_value = IDENTIFIER_TYPE_VALUE (id);
+ /* Shadow the marker, not the real thing, so that the marker
+ gets restored later. */
+ tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
b->type_shadowed
= tree_cons (id, old_type_value, b->type_shadowed);
}
+ else
+ {
+ tree binding = binding_for_name (id, current_namespace);
+ BINDING_TYPE (binding) = type;
+ /* Store marker instead of real type. */
+ type = global_type_node;
+ }
SET_IDENTIFIER_TYPE_VALUE (id, type);
}
set_identifier_type_value_with_scope (id, type, inner_binding_level);
}
+/* Return the type associated with id. */
+
+tree
+identifier_type_value (id)
+ tree id;
+{
+ /* There is no type with that name, anywhere. */
+ if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
+ return NULL_TREE;
+ /* This is not the type marker, but the real thing. */
+ if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)
+ return REAL_IDENTIFIER_TYPE_VALUE (id);
+ /* Have to search for it. It must be on the global level, now.
+ Ask lookup_name not to return non-types. */
+ id = lookup_name_real (id, 2, 1, 0);
+ if (id)
+ return TREE_TYPE (id);
+ return NULL_TREE;
+}
+
/* Pop off extraneous binding levels left over due to syntax errors.
We don't pop past namespaces, as they might be valid. */
}
/* Push a tag name NAME for struct/class/union/enum type TYPE.
- Normally put into into the inner-most non-tag-transparent scope,
+ Normally put it into the inner-most non-tag-transparent scope,
but if GLOBALIZE is true, put it in the inner-most non-class scope.
The latter is needed for implicit declarations. */
c_decl = TREE_CODE (context) == FUNCTION_DECL
? context : TYPE_MAIN_DECL (context);
+ if (!context)
+ context = current_namespace;
+
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
{
newdecl = 1;
d = build_decl (TYPE_DECL, name, type);
+ if (current_lang_name == lang_name_java)
+ TYPE_FOR_JAVA (type) = 1;
SET_DECL_ARTIFICIAL (d);
if (! in_class)
set_identifier_type_value_with_scope (name, type, b);
d = TYPE_MAIN_DECL (d);
TYPE_NAME (type) = d;
- DECL_CONTEXT (d) = context;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
- if (! globalize && processing_template_decl
- && IS_AGGR_TYPE (type))
- {
- d = push_template_decl (d);
- if (b->pseudo_global && b->level_chain->parm_flag == 2)
- pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
- b->level_chain);
+ if (processing_template_parmlist)
+ /* You can't declare a new template type in a template
+ parameter list. But, you can declare a non-template
+ type:
+
+ template <class A*> struct S;
+
+ is a forward-declaration of `A'. */
+ ;
+ else if (IS_AGGR_TYPE (type)
+ && (/* If !GLOBALIZE then we are looking at a
+ definition. It may not be a primary template.
+ (For example, in:
+
+ template <class T>
+ struct S1 { class S2 {}; }
+
+ we have to push_template_decl for S2.) */
+ (processing_template_decl && !globalize)
+ /* If we are declaring a friend template class, we
+ will have GLOBALIZE set, since something like:
+
+ template <class T>
+ struct S1 {
+ template <class U>
+ friend class S2;
+ };
+
+ declares S2 to be at global scope. */
+ || (processing_template_decl >
+ template_class_depth (current_class_type))))
+ {
+ d = push_template_decl_real (d, globalize);
+ /* If the current binding level is the binding level for
+ the template parameters (see the comment in
+ begin_template_parm_list) and the enclosing level is
+ a class scope, and we're not looking at a friend,
+ push the declaration of the member class into the
+ class scope. In the friend case, push_template_decl
+ will already have put the friend into global scope,
+ if appropriate. */
+ if (!globalize && b->pseudo_global &&
+ b->level_chain->parm_flag == 2)
+ {
+ pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
+ b->level_chain);
+ /* Put this tag on the list of tags for the class,
+ since that won't happen below because B is not
+ the class binding level, but is instead the
+ pseudo-global level. */
+ b->level_chain->tags =
+ saveable_tree_cons (name, type, b->level_chain->tags);
+ TREE_NONLOCAL_FLAG (type) = 1;
+ if (TYPE_SIZE (current_class_type) == NULL_TREE)
+ CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+ }
}
if (b->parm_flag == 2)
extern struct obstack permanent_obstack;
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0;
- int new_defines_function;
+ int new_defines_function = 0;
if (newdecl == olddecl)
return 1;
- if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
- DECL_MACHINE_ATTRIBUTES (newdecl)
- = merge_machine_decl_attributes (olddecl, newdecl);
-
types_match = decls_match (newdecl, olddecl);
- if (TREE_CODE (olddecl) != TREE_LIST)
- olddecl_friend = DECL_LANG_SPECIFIC (olddecl) && DECL_FRIEND_P (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 well just pretent the types match here. */
+ 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;
-
+
+ /* Check for redeclaration and other discrepancies. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl)
&& (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl)))
cp_error (errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
- && current_binding_level == global_binding_level)
+ && namespace_bindings_p ())
? "`%#D' previously defined here"
: "`%#D' previously declared here", olddecl);
}
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
if (DECL_CLASS_CONTEXT (olddecl))
DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl);
- if (DECL_CHAIN (newdecl) == NULL_TREE)
- DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
DECL_ABSTRACT_VIRTUAL_P (newdecl) |= DECL_ABSTRACT_VIRTUAL_P (olddecl);
DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_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))
+ {
+ cp_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. */
}
}
- /* Special handling ensues if new decl is a function definition. */
- new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL
- && 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 (tentative) definition. */
- && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl)))
- {
- cp_warning ("redundant redeclaration of `%D' in same scope", newdecl);
- cp_warning_at ("previous declaration of `%D'", olddecl);
- }
-
/* Copy all the DECL_... slots specified in the new decl
except for any that we copy here from the old type. */
+ DECL_MACHINE_ATTRIBUTES (newdecl)
+ = merge_machine_decl_attributes (olddecl, newdecl);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
}
+ DECL_TEMPLATE_SPECIALIZATIONS (newdecl)
+ = DECL_TEMPLATE_SPECIALIZATIONS (olddecl);
+
return 1;
}
-
+
if (types_match)
{
/* Automatically handles default parameters. */
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
- if (oldtype != TREE_TYPE (newdecl)
+ if (newtype != CANONICAL_TYPE_VARIANT (oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0;
-
- if (DECL_LANG_SPECIFIC (newdecl))
+
+ 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);
+ /* 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_ACCESS (newdecl) = DECL_ACCESS (olddecl);
+ DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
+ if (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
+ {
+ DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+ DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
+ }
+ olddecl_friend = DECL_FRIEND_P (olddecl);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl);
}
- if (TREE_CODE (newdecl) == TEMPLATE_DECL)
- {
- DECL_TEMPLATE_SPECIALIZATIONS (newdecl)
- = DECL_TEMPLATE_SPECIALIZATIONS (olddecl);
- if (DECL_CHAIN (newdecl) == NULL_TREE)
- DECL_CHAIN (newdecl) = DECL_CHAIN (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);
DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl);
- /* Don't really know how much of the language-specific
- values we should copy from old to new. */
- if (DECL_LANG_SPECIFIC (olddecl))
- {
- DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
- DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
- DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
- if (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
- {
- DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
- DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
- }
- }
-
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
TREE_VALUE (decls) = olddecl;
}
- if ((char *)newdecl + ROUND (function_size)
- + ROUND (sizeof (struct lang_decl))
- == obstack_next_free (&permanent_obstack))
+ if (((char *)newdecl + ROUND (function_size) == (char *)nl
+ && ((char *)newdecl + ROUND (function_size)
+ + ROUND (sizeof (struct lang_decl))
+ == obstack_next_free (&permanent_obstack)))
+ || ((char *)newdecl + ROUND (function_size)
+ == obstack_next_free (&permanent_obstack)))
{
DECL_MAIN_VARIANT (newdecl) = olddecl;
DECL_LANG_SPECIFIC (olddecl) = ol;
register tree name = DECL_ASSEMBLER_NAME (x);
register struct binding_level *b = current_binding_level;
- if (x != current_function_decl
+ if (current_function_decl && x != current_function_decl
+ /* A local declaration for a function doesn't constitute nesting. */
+ && (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
/* Don't change DECL_CONTEXT of virtual methods. */
&& (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
&& ! DECL_CONTEXT (x))
DECL_CONTEXT (x) = current_function_decl;
- /* A local declaration for a function doesn't constitute nesting. */
- if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0)
- DECL_CONTEXT (x) = 0;
+ if (!DECL_CONTEXT (x))
+ DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
/* Type are looked up using the DECL_NAME, as that is what the rest of the
compiler wants to use. */
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = TREE_OPERAND (name, 0);
- t = lookup_name_current_level (name);
+ /* Namespace-scoped variables are not found in the current level. */
+ if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x))
+ t = namespace_binding (name, DECL_CONTEXT (x));
+ else
+ t = lookup_name_current_level (name);
if (t == error_mark_node)
{
/* error_mark_node is 0 for a while during initialization! */
else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c)
|| DECL_FUNCTION_TEMPLATE_P (x))
&& is_overloaded_fn (t))
- /* don't do anything just yet */;
+ /* Don't do anything just yet. */;
else if (t == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
return t;
}
+ else if (DECL_MAIN_P (x))
+ {
+ /* A redeclaration of main, but not a duplicate of the
+ previous one.
+
+ [basic.start.main]
+
+ This function shall not be overloaded. */
+ cp_error_at ("invalid redeclaration of `%D'", t);
+ cp_error ("as `%D'", x);
+ /* We don't try to push this declaration since that
+ causes a crash. */
+ return x;
+ }
}
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
}
- else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_CONTEXT (x) == NULL_TREE)
+ else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
return push_overloaded_decl (x, 0);
- /* If declaring a type as a typedef, and the type has no known
- typedef name, install this TYPE_DECL as its typedef name. */
+ /* If declaring a type as a typedef, copy the type (unless we're
+ at line 0), and install this TYPE_DECL as the new type's typedef
+ name. See the extensive comment in ../c-decl.c (pushdecl). */
if (TREE_CODE (x) == TYPE_DECL)
{
tree type = TREE_TYPE (x);
- tree name = (type != error_mark_node) ? TYPE_NAME (type) : x;
+ if (DECL_SOURCE_LINE (x) == 0)
+ {
+ if (TYPE_NAME (type) == 0)
+ TYPE_NAME (type) = x;
+ }
+ else if (type != error_mark_node && TYPE_NAME (type) != x)
+ {
+ push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
+
+ DECL_ORIGINAL_TYPE (x) = type;
+ type = build_type_copy (type);
+ TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
+ TYPE_NAME (type) = x;
+ TREE_TYPE (x) = type;
- if (name == NULL_TREE || TREE_CODE (name) != TYPE_DECL)
- {
- /* If these are different names, and we're at the global
- binding level, make two equivalent definitions. */
- name = x;
- if (global_bindings_p ())
- TYPE_NAME (type) = x;
- }
- my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140);
+ pop_obstacks ();
+ }
if (type != error_mark_node
&& TYPE_NAME (type)
/* This name is new in its binding level.
Install the new declaration and return it. */
- if (b == global_binding_level)
+ if (namespace_bindings_p ())
{
/* Install a global value. */
tree bindings = binding_for_name (name, current_namespace);
return x;
}
-/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
+/* Like pushdecl, only it places X in the current namespace,
if appropriate. */
tree
-pushdecl_top_level (x)
+pushdecl_namespace_level (x)
tree x;
{
register struct binding_level *b = inner_binding_level;
- register tree t = pushdecl_with_scope (x, global_binding_level);
+ register tree t;
+
+ t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
/* Now, the type_shadowed stack may screw us. Munge it so it does
what we want. */
return t;
}
-/* Like push_overloaded_decl, only it places X in GLOBAL_BINDING_LEVEL,
+/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
if appropriate. */
-static void
-push_overloaded_decl_top_level (x, forget)
+tree
+pushdecl_top_level (x)
tree x;
- int forget;
{
- struct binding_level *b = current_binding_level;
-
- current_binding_level = global_binding_level;
- push_overloaded_decl (x, forget);
- current_binding_level = b;
+ tree cur_namespace = current_namespace;
+ current_namespace = global_namespace;
+ x = pushdecl_namespace_level (x);
+ current_namespace = cur_namespace;
+ return x;
}
/* Make the declaration of X appear in CLASS scope. */
{
if (TYPE_BEING_DEFINED (current_class_type))
{
- /* Check for inconsistent use of this name in the class body.
+ /* A name N used in a class S shall refer to the same declaration
+ in its context and when re-evaluated in the completed scope of S.
+
Types, enums, and static vars are checked here; other
members are checked in finish_struct. */
tree icv = IDENTIFIER_CLASS_VALUE (name);
if (icv && icv != x
+ && flag_optional_diags
/* Don't complain about inherited names. */
&& id_in_current_class (name)
/* Or shadowed tags. */
- && !(TREE_CODE (icv) == TYPE_DECL
+ && !(DECL_DECLARES_TYPE_P (icv)
&& DECL_CONTEXT (icv) == current_class_type))
{
- cp_error ("declaration of identifier `%D' as `%#D'", name, x);
- cp_error_at ("conflicts with previous use in class as `%#D'",
- icv);
+ cp_pedwarn ("declaration of identifier `%D' as `%#D'", name, x);
+ cp_pedwarn_at ("conflicts with previous use in class as `%#D'",
+ icv);
}
}
obstack_ptr_grow (&decl_obstack, x);
}
-/* Tell caller how to interpret a TREE_LIST which contains
- chains of FUNCTION_DECLS. */
+/* Insert another USING_DECL into the current binding level,
+ returning this declaration. If this is a redeclaration,
+ do nothing and return NULL_TREE. */
-int
-overloaded_globals_p (list)
- tree list;
+tree
+push_using_decl (scope, name)
+ tree scope;
+ tree name;
{
- my_friendly_assert (TREE_CODE (list) == TREE_LIST, 142);
+ tree decl;
+
+ my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
+ for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
+ if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
+ break;
+ if (decl)
+ return NULL_TREE;
+ decl = build_lang_decl (USING_DECL, name, void_type_node);
+ DECL_INITIAL (decl) = scope;
+ TREE_CHAIN (decl) = current_binding_level->usings;
+ current_binding_level->usings = decl;
+ return decl;
+}
- /* Don't commit caller to seeing them as globals. */
- if (TREE_NONLOCAL_FLAG (list))
- return -1;
- /* Do commit caller to not seeing them as globals. */
- if (TREE_CODE (TREE_VALUE (list)) == TREE_LIST)
- return 0;
- /* Do commit caller to seeing them as globals. */
- return 1;
+/* Add namespace to using_directives. Return NULL_TREE if nothing was
+ changed (i.e. there was already a directive), or the fresh
+ TREE_LIST otherwise. */
+
+tree
+push_using_directive (used, ancestor)
+ tree used;
+ tree ancestor;
+{
+ tree ud = current_binding_level->using_directives;
+
+ /* Check if we already have this. */
+ if (purpose_member (used, ud) != NULL_TREE)
+ return NULL_TREE;
+
+ ud = perm_tree_cons (used, ancestor, ud);
+ current_binding_level->using_directives = ud;
+ return ud;
}
/* DECL is a FUNCTION_DECL which may have other definitions already in
{
tree orig_name = DECL_NAME (decl);
tree old;
- int doing_global = (global_bindings_p () || ! forgettable);
+ int doing_global = (namespace_bindings_p () || ! forgettable);
if (doing_global)
{
- old = IDENTIFIER_NAMESPACE_VALUE (orig_name);
+ old = namespace_binding (orig_name, DECL_CONTEXT (decl));
if (old && TREE_CODE (old) == FUNCTION_DECL
&& DECL_ARTIFICIAL (old)
&& (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
{
tree tmp;
- for (tmp = get_first_fn (old); tmp; tmp = DECL_CHAIN (tmp))
- if (decl == tmp || duplicate_decls (decl, tmp))
- return tmp;
+ for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
+ if (decl == OVL_CURRENT (tmp)
+ || duplicate_decls (decl, OVL_CURRENT (tmp)))
+ return OVL_CURRENT (tmp);
}
else
{
if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{
- if (old && is_overloaded_fn (old))
- DECL_CHAIN (decl) = get_first_fn (old);
- else
- DECL_CHAIN (decl) = NULL_TREE;
- old = tree_cons (orig_name, decl, NULL_TREE);
- TREE_TYPE (old) = unknown_type_node;
+ if (old && TREE_CODE (old) != OVERLOAD)
+ old = ovl_cons (old, NULL_TREE);
+ old = ovl_cons (decl, old);
}
else
/* orig_name is not ambiguous. */
old = decl;
if (doing_global)
- IDENTIFIER_NAMESPACE_VALUE (orig_name) = old;
+ set_namespace_binding (orig_name, DECL_CONTEXT (decl), old);
else
IDENTIFIER_LOCAL_VALUE (orig_name) = old;
if (DECL_LANG_SPECIFIC (olddecl) && DECL_ABSTRACT_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. */
+ /* Defining the same name twice is no good. */
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
{
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE);
- SET_IDENTIFIER_LABEL_VALUE (decl, NULL_TREE);
}
return lookup_label (name);
if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
return TREE_VALUE (tail);
}
+ else if (level->namespace_p)
+ /* Do namespace lookup. */
+ /* XXX: is this a real lookup, considering using-directives etc. ??? */
+ for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
+ {
+ tree old = BINDING_TYPE (binding_for_name (name, tail));
+ /* If it has an original type, it is a typedef, and we
+ should not return it. */
+ if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
+ old = NULL_TREE;
+ if (old && TREE_CODE (old) != form
+ && !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL))
+ {
+ cp_error ("`%#D' redeclared as %C", old, form);
+ return NULL_TREE;
+ }
+ if (old)
+ return old;
+ if (thislevel_only || tail == global_namespace)
+ return NULL_TREE;
+ }
else
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
{
if (level->pseudo_global)
{
- /* XXX MvL */
- tree t = IDENTIFIER_NAMESPACE_VALUE (name);
- if (t && TREE_CODE (t) == TEMPLATE_DECL
- && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
+ tree t = IDENTIFIER_CLASS_VALUE (name);
+ if (t && DECL_CLASS_TEMPLATE_P (t))
+ return TREE_TYPE (t);
+ t = IDENTIFIER_NAMESPACE_VALUE (name);
+ if (t && DECL_CLASS_TEMPLATE_P (t))
return TREE_TYPE (t);
}
return NULL_TREE;
}
- if (current_class_type && level->level_chain == global_binding_level)
+ if (current_class_type && level->level_chain->namespace_p)
{
/* Try looking in this class's tags before heading into
global binding level. */
lookup_namespace_name (namespace, name)
tree namespace, name;
{
-#if 1
+ struct tree_binding _b;
tree val;
+
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
- val = qualified_lookup_using_namespace (name, namespace);
- if (val)
- return val;
+ val = binding_init (&_b);
+ if (!qualified_lookup_using_namespace (name, namespace, val))
+ return error_mark_node;
+
+ if (BINDING_VALUE (val))
+ return BINDING_VALUE (val);
cp_error ("`%D' undeclared in namespace `%D'", name, namespace);
return error_mark_node;
-#else
- struct binding_level *b = (struct binding_level *)NAMESPACE_LEVEL (namespace);
- tree x = NULL_TREE;
-#if 1
- /* This searches just one level. */
- if (b)
- {
- for (x = b->names; x; x = TREE_CHAIN (x))
- if (DECL_NAME (x) == name || DECL_ASSEMBLER_NAME (x) == name)
- break;
- }
-#else
- /* This searches all levels. */
- for (; b && !x; b = b->level_chain)
- {
- for (x = b->names; x; x = TREE_CHAIN (x))
- if (DECL_NAME (x) == name || DECL_ASSEMBLER_NAME (x) == name)
- break;
- }
-#endif
- return x;
-#endif
}
tree
my_friendly_abort (2000);
if (! uses_template_parms (context)
- || context == current_class_type)
+ || currently_open_class (context))
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
{
if (processing_template_decl)
pop_obstacks ();
- TYPE_CONTEXT (t) = context;
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
TYPE_NAME (TREE_TYPE (d)) = d;
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
- DECL_CONTEXT (d) = context;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
CLASSTYPE_GOT_SEMICOLON (t) = 1;
return t;
}
+/* Select the right _DECL from multiple choices. */
+
+static tree
+select_decl (binding, prefer_type, namespaces_only)
+ tree binding;
+ int prefer_type, namespaces_only;
+{
+ tree val;
+ val = BINDING_VALUE (binding);
+ if (namespaces_only)
+ {
+ /* We are not interested in types. */
+ if (val && TREE_CODE (val) == NAMESPACE_DECL)
+ return val;
+ return NULL_TREE;
+ }
+
+ /* If we could have a type and
+ we have nothing or we need a type and have none. */
+ if (BINDING_TYPE (binding)
+ && (!val || (prefer_type && TREE_CODE (val) != TYPE_DECL)))
+ val = TYPE_STUB_DECL (BINDING_TYPE (binding));
+ /* Don't return non-types if we really prefer types. */
+ else if (val && prefer_type > 1 && TREE_CODE (val) != TYPE_DECL
+ && (!looking_for_template || TREE_CODE (val) != TEMPLATE_DECL))
+ val = NULL_TREE;
+ return val;
+}
+
+/* Unscoped lookup of a global, iterate over namespaces, considering
+ using namespace statements. */
+
+static tree
+unqualified_namespace_lookup (name, prefer_type, namespaces_only)
+ tree name;
+ int prefer_type;
+ int namespaces_only;
+{
+ struct tree_binding _binding;
+ tree b = binding_init (&_binding);
+ tree initial = current_decl_namespace();
+ tree scope = initial;
+ tree siter;
+ struct binding_level *level;
+ tree val = NULL_TREE;
+
+ while (!val)
+ {
+ val = binding_for_name (name, scope);
+
+ /* Initialize binding for this context. */
+ BINDING_VALUE (b) = BINDING_VALUE (val);
+ BINDING_TYPE (b) = BINDING_TYPE (val);
+
+ /* Add all _DECLs seen through local using-directives. */
+ for (level = current_binding_level;
+ !level->namespace_p;
+ level = level->level_chain)
+ if (!lookup_using_namespace (name, b, level->using_directives, scope))
+ /* Give up because of error. */
+ return NULL_TREE;
+
+ /* Add all _DECLs seen through global using-directives. */
+ /* XXX local and global using lists should work equally. */
+ siter = initial;
+ while (1)
+ {
+ if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
+ scope))
+ /* Give up because of error. */
+ return NULL_TREE;
+ if (siter == scope) break;
+ siter = CP_DECL_CONTEXT (siter);
+ }
+
+ val = select_decl (b, prefer_type, namespaces_only);
+ if (scope == global_namespace)
+ break;
+ scope = DECL_CONTEXT (scope);
+ if (scope == NULL_TREE)
+ scope = global_namespace;
+ }
+ return val;
+}
+
/* Look up NAME in the current binding level and its superiors in the
namespace of variables, functions and typedefs. Return a ..._DECL
node of some kind representing its definition if there is only one
such declaration, or return a TREE_LIST with all the overloaded
definitions if there are many, or return 0 if it is undefined.
- If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
+ If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
+ If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
Otherwise we prefer non-TYPE_DECLs.
using IDENTIFIER_CLASS_VALUE. */
static tree
-lookup_name_real (name, prefer_type, nonclass)
+lookup_name_real (name, prefer_type, nonclass, namespaces_only)
tree name;
- int prefer_type, nonclass;
+ int prefer_type, nonclass, namespaces_only;
{
register tree val;
int yylex = 0;
tree from_obj = NULL_TREE;
tree locval, classval;
+ /* Hack: copy flag set by parser, if set. */
+ if (only_namespace_names)
+ namespaces_only = 1;
+
if (prefer_type == -2)
{
extern int looking_for_typename;
if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
type = TREE_TYPE (type);
- type = complete_type (type);
+ if (TYPE_P (type))
+ type = complete_type (type);
- if (type == void_type_node)
- val = IDENTIFIER_GLOBAL_VALUE (name);
- else if (TREE_CODE (type) == NAMESPACE_DECL)
+ if (TREE_CODE (type) == VOID_TYPE)
+ type = global_namespace;
+ if (TREE_CODE (type) == NAMESPACE_DECL)
{
- val = NAMESPACE_BINDING (name, type);
+ struct tree_binding b;
+ val = binding_init (&b);
+ if (!qualified_lookup_using_namespace (name, type, val))
+ return NULL_TREE;
+ val = select_decl (val, prefer_type, namespaces_only);
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
- val = lookup_field (type, name, 0, prefer_type);
+ val = lookup_member (type, name, 0, prefer_type);
}
else
val = NULL_TREE;
locval = classval = NULL_TREE;
- if (current_binding_level != global_binding_level
- && IDENTIFIER_LOCAL_VALUE (name))
+ if (!namespaces_only && !current_binding_level->namespace_p
+ && IDENTIFIER_LOCAL_VALUE (name)
+ /* Kludge to avoid infinite recursion with identifier_type_value. */
+ && (prefer_type <= 0
+ || TREE_CODE (IDENTIFIER_LOCAL_VALUE (name)) == TYPE_DECL))
locval = IDENTIFIER_LOCAL_VALUE (name);
/* In C++ class fields are between local and global scope,
TYPE_DECLs. */
classval = lookup_field (current_class_type, name, 0, 1);
- /* yylex() calls this with -2, since we should never start digging for
- the nested name at the point where we haven't even, for example,
- created the COMPONENT_REF or anything like that. */
- if (classval == NULL_TREE)
- classval = lookup_nested_field (name, ! yylex);
-
/* Add implicit 'typename' to types from template bases. lookup_field
- will do this for us. */
+ will do this for us. If classval is actually from an enclosing
+ scope, lookup_nested_field will get it for us. */
if (processing_template_decl
&& classval && TREE_CODE (classval) == TYPE_DECL
- && DECL_CONTEXT (classval) != current_class_type
+ && ! currently_open_class (DECL_CONTEXT (classval))
&& uses_template_parms (current_class_type)
&& ! DECL_ARTIFICIAL (classval))
classval = lookup_field (current_class_type, name, 0, 1);
+
+ /* yylex() calls this with -2, since we should never start digging for
+ the nested name at the point where we haven't even, for example,
+ created the COMPONENT_REF or anything like that. */
+ if (classval == NULL_TREE)
+ classval = lookup_nested_field (name, ! yylex);
}
if (locval && classval)
else if (classval)
val = classval;
else
- {
- /* unscoped lookup of a global, iterate over namespaces,
- considering using namespace statements */
- tree binding;
- tree scope = current_namespace;
- do
- {
- binding = binding_for_name (name, scope);
- val = BINDING_VALUE (binding);
- val = lookup_using_namespace (name, val, current_namespace, scope);
- if (scope == global_namespace)
- break;
- scope = DECL_NAMESPACE (scope);
- }
- while (!val);
- }
+ val = unqualified_namespace_lookup (name, prefer_type, namespaces_only);
done:
if (val)
if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
|| TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
;
+ /* Caller wants a class-or-namespace-name. */
+ else if (prefer_type == 1 && TREE_CODE (val) == NAMESPACE_DECL)
+ ;
else if (IDENTIFIER_HAS_TYPE_VALUE (name))
val = TYPE_MAIN_DECL (IDENTIFIER_TYPE_VALUE (name));
else if (TREE_TYPE (val) == error_mark_node)
lookup_name_nonclass (name)
tree name;
{
- return lookup_name_real (name, 0, 1);
+ return lookup_name_real (name, 0, 1, 0);
+}
+
+tree
+lookup_function_nonclass (name, args)
+ tree name;
+ tree args;
+{
+ return lookup_arg_dependent (name, lookup_name_nonclass (name), args);
+}
+
+tree
+lookup_name_namespace_only (name)
+ tree name;
+{
+ /* type-or-namespace, nonclass, namespace_only */
+ return lookup_name_real (name, 1, 1, 1);
}
tree
tree name;
int prefer_type;
{
- return lookup_name_real (name, prefer_type, 0);
+ return lookup_name_real (name, prefer_type, 0, 0);
}
/* Similar to `lookup_name' but look only at current binding level. */
{
register tree t = NULL_TREE;
- if (current_binding_level == global_binding_level)
+ if (current_binding_level->namespace_p)
{
t = IDENTIFIER_NAMESPACE_VALUE (name);
return t;
}
+
+void
+begin_only_namespace_names ()
+{
+ only_namespace_names = 1;
+}
+
+void
+end_only_namespace_names ()
+{
+ only_namespace_names = 0;
+}
\f
/* Arrange for the user to get a source line number, even when the
compiler is going down in flames, so that she at least has a
static void
signal_catch (sig)
- int sig;
+ int sig ATTRIBUTE_UNUSED;
{
signal (SIGSEGV, SIG_DFL);
#ifdef SIGIOT
tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
set_identifier_type_value (tname, NULL_TREE);
if ((int) rid_index < (int) RID_MAX)
- /* builtin types live in the global namespace */
- IDENTIFIER_GLOBAL_VALUE (tname) = tdecl;
+ /* Built-in types live in the global namespace. */
+ SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
}
if (rname != NULL_TREE)
{
if (tname != NULL_TREE)
{
set_identifier_type_value (rname, NULL_TREE);
- IDENTIFIER_GLOBAL_VALUE (rname) = tdecl;
+ SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl);
}
else
{
}
}
+/* 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 (name, size)
+ 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);
+ 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 (type, name)
+ tree type;
+ 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_MODE (type) = TYPE_MODE (void_type_node);
+}
+
/* Push overloaded decl, in global scope, with one argument so it
can be used as a callback from define_function. */
void
init_decl_processing ()
{
- tree decl;
register tree endlink, int_endlink, double_endlink, unsigned_endlink;
tree fields[20];
/* Data type of memcpy. */
/* Have to make these distinct before we try using them. */
lang_name_cplusplus = get_identifier ("C++");
lang_name_c = get_identifier ("C");
+ lang_name_java = get_identifier ("Java");
- /* enter the global namespace */
+ /* Enter the global namespace. */
my_friendly_assert (global_namespace == NULL_TREE, 375);
my_friendly_assert (current_lang_name == NULL_TREE, 375);
current_lang_name = lang_name_cplusplus;
/* Make the binding_level structure for global names. */
pushlevel (0);
global_binding_level = current_binding_level;
+ /* The global level is the namespace level of ::. */
+ NAMESPACE_LEVEL (global_namespace) = global_binding_level;
+ declare_namespace_level ();
this_identifier = get_identifier (THIS_NAME);
in_charge_identifier = get_identifier (IN_CHARGE_NAME);
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
+ intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
+ unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
float_type_node = make_node (REAL_TYPE);
TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
TREE_TYPE (complex_long_double_type_node) = long_double_type_node;
layout_type (complex_long_double_type_node);
+ 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_zero_node = build_int_2 (0, 0);
TREE_TYPE (integer_zero_node) = integer_type_node;
integer_one_node = build_int_2 (1, 0);
initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */
array_domain_type = build_index_type (build_int_2 (200, 0));
- /* make a type for arrays of characters.
+ /* Make a type for arrays of characters.
With luck nothing will ever really depend on the length of this
array type. */
char_array_type_node
temp = tree_cons (NULL_TREE,
build_pointer_type (build_function_type (void_type_node,
NULL_TREE)),
- ptr_ftype_sizetype);
+ tree_cons (NULL_TREE, ptr_ftype_sizetype, NULL_TREE));
builtin_function ("__builtin_apply",
build_function_type (ptr_type_node, temp),
BUILT_IN_APPLY, NULL_PTR);
/* C++ extensions */
unknown_type_node = make_node (UNKNOWN_TYPE);
- decl = pushdecl (build_decl (TYPE_DECL, get_identifier ("unknown type"),
- unknown_type_node));
- /* Make sure the "unknown type" typedecl gets ignored for debug info. */
- DECL_IGNORED_P (decl) = 1;
- TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
- TYPE_SIZE (unknown_type_node) = TYPE_SIZE (void_type_node);
- TYPE_ALIGN (unknown_type_node) = 1;
- TYPE_MODE (unknown_type_node) = TYPE_MODE (void_type_node);
+ 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;
record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type);
}
- std_node = build_decl (NAMESPACE_DECL, get_identifier ("std"),
+ std_node = build_decl (NAMESPACE_DECL,
+ get_identifier (flag_honor_std ? "fake std":"std"),
void_type_node);
pushdecl (std_node);
+ 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_type_node = xref_tag
+ tree bad_alloc_type_node, newtype, deltype;
+ if (flag_honor_std)
+ push_namespace (get_identifier ("std"));
+ bad_alloc_type_node = xref_tag
(class_type_node, get_identifier ("bad_alloc"), NULL_TREE, 1);
- tree newtype = build_exception_variant
+ if (flag_honor_std)
+ pop_namespace ();
+ newtype = build_exception_variant
(ptr_ftype_sizetype, build_tree_list (NULL_TREE, bad_alloc_type_node));
- tree deltype = build_exception_variant
+ deltype = build_exception_variant
(void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE));
auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
/* Show we use EH for cleanups. */
using_eh_for_cleanups ();
+
+ print_error_function = lang_print_error_function;
+ lang_get_alias_set = &c_get_alias_set;
+}
+
+/* Function to print any language-specific context for an error message. */
+
+static void
+lang_print_error_function (file)
+ char *file;
+{
+ default_print_error_function (file);
+ maybe_print_template_context ();
}
/* Make a definition for a builtin function named NAME and whose data type
TREE_PUBLIC (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
+ my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+
/* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
we cannot change DECL_ASSEMBLER_NAME until we have installed this
function in the namespace. */
int debug_temp_inits = 1;
tree
-start_decl (declarator, declspecs, initialized)
+start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree declarator, declspecs;
int initialized;
+ tree attributes, prefix_attributes;
{
register tree decl;
register tree type, tem;
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
NULL_TREE);
- if (decl == NULL_TREE || decl == void_type_node)
+ if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
type = TREE_TYPE (decl);
? DECL_CLASS_CONTEXT (decl)
: DECL_CONTEXT (decl);
+ if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
+ && context != current_namespace && TREE_CODE (decl) == VAR_DECL)
+ {
+ /* When parsing the initializer, lookup should use the object's
+ namespace. */
+ push_decl_namespace (context);
+ }
+
+ /* We are only interested in class contexts, later. */
+ if (context && TREE_CODE (context) == NAMESPACE_DECL)
+ context = NULL_TREE;
+
if (initialized)
/* Is it valid for this decl to have an initializer at all?
If not, set INITIALIZED to zero, which will indirectly
}
/* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set. */
- if (DECL_LANG_SPECIFIC (decl))
- DECL_IN_AGGR_P (decl) = 0;
- if (DECL_USE_TEMPLATE (decl) || CLASSTYPE_USE_TEMPLATE (context))
+ DECL_IN_AGGR_P (decl) = 0;
+ if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
+ || CLASSTYPE_USE_TEMPLATE (context))
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
- /* Stupid stupid stupid stupid (jason 7/21/95) */
- if (pedantic && DECL_EXTERNAL (decl)
- && ! DECL_TEMPLATE_SPECIALIZATION (decl))
+ if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
cp_pedwarn ("declaration of `%#D' outside of class is not definition",
decl);
pushclass (context, 2);
}
+ /* Set attributes here so if duplicate decl, will have proper attributes. */
+ cplus_decl_attributes (decl, attributes, prefix_attributes);
+
/* Add this decl to the current binding level, but not if it
comes from another scope, e.g. a static member variable.
TEM may equal DECL or it may be a previous decl of the same name. */
- if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE)
- || (TREE_CODE (decl) == TEMPLATE_DECL && !global_bindings_p ())
+ if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE
+ /* Definitions of namespace members outside their namespace are
+ possible. */
+ && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
+ || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
|| TREE_CODE (type) == LANG_TYPE
/* The declaration of template specializations does not affect
the functions available for overload resolution, so we do not
if (! current_function_decl)
tem = push_template_decl (tem);
else if (minimal_parse_mode)
- DECL_VINDEX (decl)
+ DECL_VINDEX (tem)
= build_min_nt (DECL_STMT, copy_to_permanent (declarator),
copy_to_permanent (declspecs),
NULL_TREE);
}
/* Handle initialization of references.
- These three arguments from from `cp_finish_decl', and have the
+ These three arguments are from `cp_finish_decl', and have the
same meaning here that they do there.
Quotes on semantics can be found in ARM 8.4.3. */
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
+ if (init && TREE_CODE (init) == NAMESPACE_DECL)
+ {
+ cp_error ("Cannot initialize `%D' to namespace `%D'",
+ decl, init);
+ init = NULL_TREE;
+ }
+
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_CONTEXT (decl)
+ && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
+ && DECL_CONTEXT (decl) != current_namespace
+ && init)
+ {
+ /* Leave the namespace of the object. */
+ pop_decl_namespace ();
+ }
+
/* If the type of the thing we are declaring either has
a constructor, or has a virtual function table pointer,
AND its initialization was accepted by `start_decl',
/* Let debugger know it should output info for this type. */
note_debug_info_needed (ttype);
- if (TREE_STATIC (decl) && DECL_CONTEXT (decl)
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
+ if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl))
note_debug_info_needed (DECL_CONTEXT (decl));
if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
if (was_temp)
end_temporary_allocation ();
- /* Extern inline function static data has external linkage. */
+ /* Extern inline function static data has external linkage.
+ Instead of trying to deal with that, we disable inlining of
+ such functions. The ASM_WRITTEN check is to avoid hitting this
+ for __FUNCTION__. */
if (TREE_CODE (decl) == VAR_DECL
&& TREE_STATIC (decl)
+ && ! TREE_ASM_WRITTEN (decl)
&& current_function_decl
&& DECL_CONTEXT (decl) == current_function_decl
&& DECL_THIS_INLINE (current_function_decl)
&& TREE_PUBLIC (current_function_decl))
{
- if (DECL_INTERFACE_KNOWN (current_function_decl))
- {
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
- }
- /* We can only do this if we can use common or weak, and we
- can't if it has been initialized and we don't support weak. */
- else if (DECL_INITIAL (decl) == NULL_TREE
- || DECL_INITIAL (decl) == error_mark_node)
- {
- TREE_PUBLIC (decl) = 1;
- DECL_COMMON (decl) = 1;
- }
- else if (flag_weak)
- make_decl_one_only (decl);
-
- if (TREE_PUBLIC (decl))
- DECL_ASSEMBLER_NAME (decl)
- = build_static_name (current_function_decl, DECL_NAME (decl));
- else if (! DECL_ARTIFICIAL (decl))
- cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
+ current_function_cannot_inline
+ = "function with static variable cannot be inline";
}
else if (TREE_CODE (decl) == VAR_DECL
make_decl_one_only (decl);
else
{
- /* we can't do anything useful; leave vars for explicit
+ /* We can't do anything useful; leave vars for explicit
instantiation. */
DECL_EXTERNAL (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 0;
destructor, so we don't complain about the 'resource
allocation is initialization' idiom. */
/* Now set attribute((unused)) on types so decls of
- of that type will be marked used. (see TREE_USED, above.)
+ that type will be marked used. (see TREE_USED, above.)
This avoids the warning problems this particular code
tried to work around. */
static tree
grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
raises, attrlist, check, friendp, publicp, inlinep, funcdef_flag,
- template_count)
+ template_count, in_namespace)
tree ctype, type;
tree declarator;
tree orig_declarator;
enum overload_flags flags;
tree quals, raises, attrlist;
int check, friendp, publicp, inlinep, funcdef_flag, template_count;
+ tree in_namespace;
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
}
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
- /* propagate volatile out from type to decl */
+ /* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
+ /* This decl is not from the current namespace. */
+ if (in_namespace)
+ set_decl_namespace (decl, in_namespace);
+
/* Should probably propagate const out from type to decl I bet (mrs). */
if (staticp)
{
if (ctype)
DECL_CLASS_CONTEXT (decl) = ctype;
- if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
+ if (ctype == NULL_TREE && MAIN_NAME_P (declarator))
{
if (inlinep)
error ("cannot declare `main' to be inline");
break;
}
- if (friendp &&
- TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
+ if (friendp
+ && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
{
- /* A friend declaration of the form friend void f<>(). Record
- the information in the TEMPLATE_ID_EXPR. */
- SET_DECL_IMPLICIT_INSTANTIATION (decl);
- DECL_TEMPLATE_INFO (decl)
- = perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
- TREE_OPERAND (orig_declarator, 1),
- NULL_TREE);
+ if (funcdef_flag)
+ cp_error
+ ("defining explicit specialization `%D' in friend declaration",
+ orig_declarator);
+ else
+ {
+ /* A friend declaration of the form friend void f<>(). Record
+ the information in the TEMPLATE_ID_EXPR. */
+ SET_DECL_IMPLICIT_INSTANTIATION (decl);
+ DECL_TEMPLATE_INFO (decl)
+ = perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
+ TREE_OPERAND (orig_declarator, 1),
+ NULL_TREE);
+ }
}
/* Caller will do the rest of this. */
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
- if (check)
+ if ((! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+ && check)
{
tmp = check_classfn (ctype, decl);
if (check == 0 && ! current_function_decl)
{
- /* assembler names live in the global namespace */
+ /* Assembler names live in the global namespace. */
tmp = IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl));
if (tmp == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
+ SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
else if (TREE_CODE (tmp) != TREE_CODE (decl))
cp_error ("inconsistent declarations for `%D'", decl);
else
{
duplicate_decls (decl, tmp);
decl = tmp;
- /* avoid creating circularities. */
- DECL_CHAIN (decl) = NULL_TREE;
}
make_decl_rtl (decl, NULL_PTR, 1);
}
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
-
- if (ctype != NULL_TREE && check)
+ if (ctype != NULL_TREE
+ && (! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+ && check)
{
tmp = check_classfn (ctype, decl);
IDENTIFIER_GLOBAL_VALUE. */
tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
if (tmp == NULL_TREE)
- IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
+ SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
else if (TREE_CODE (tmp) != TREE_CODE (decl))
cp_error ("inconsistent declarations for `%D'", decl);
else
{
duplicate_decls (decl, tmp);
decl = tmp;
- /* avoid creating circularities. */
- DECL_CHAIN (decl) = NULL_TREE;
}
}
}
static tree
-grokvardecl (type, declarator, specbits_in, initialized, constp)
+grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
tree type;
tree declarator;
RID_BIT_TYPE *specbits_in;
int initialized;
int constp;
+ tree in_namespace;
{
tree decl;
RID_BIT_TYPE specbits;
}
else
{
+ tree context = in_namespace ? in_namespace : current_namespace;
decl = build_decl (VAR_DECL, declarator, complete_type (type));
- if (current_namespace != global_namespace)
- DECL_ASSEMBLER_NAME (decl) = build_static_name (current_namespace,
+ if (context != global_namespace && namespace_bindings_p ())
+ DECL_ASSEMBLER_NAME (decl) = build_static_name (context,
declarator);
}
+ if (in_namespace)
+ set_decl_namespace (decl, in_namespace);
+
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
DECL_THIS_EXTERN (decl) = 1;
/* In class context, static means one per class,
public access, and static storage. */
- if (DECL_FIELD_CONTEXT (decl) != NULL_TREE
- && IS_AGGR_TYPE (DECL_FIELD_CONTEXT (decl)))
+ if (DECL_CLASS_SCOPE_P (decl))
{
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
t = make_lang_type (RECORD_TYPE);
- /* Let the front-end know this is a pointer to member function. */
+ /* Let the front-end know this is a pointer to member function... */
TYPE_PTRMEMFUNC_FLAG (t) = 1;
- /* and not really an aggregate. */
+ /* ... and not really an aggregate. */
IS_AGGR_TYPE (t) = 0;
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
tree quals = NULL_TREE;
tree raises = NULL_TREE;
int template_count = 0;
+ tree in_namespace = NULL_TREE;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
next = &TREE_OPERAND (decl, 0);
break;
- case BIT_NOT_EXPR: /* for C++ destructors! */
+ case BIT_NOT_EXPR: /* For C++ destructors! */
{
tree name = TREE_OPERAND (decl, 0);
tree rename = NULL_TREE;
break;
case ADDR_EXPR: /* C++ reference declaration */
- /* fall through */
+ /* Fall through. */
case ARRAY_REF:
case INDIRECT_REF:
ctype = NULL_TREE;
*next = TREE_OPERAND (decl, 0);
init = TREE_OPERAND (decl, 1);
- decl = start_decl (declarator, declspecs, 1);
+ decl = start_decl (declarator, declspecs, 1, NULL_TREE, NULL_TREE);
/* Look for __unused__ attribute */
if (TREE_USED (TREE_TYPE (decl)))
TREE_USED (decl) = 1;
else
my_friendly_abort (0);
}
- /* fall through */
+ /* Fall through. */
case IDENTIFIER_NODE:
if (TREE_CODE (decl) == IDENTIFIER_NODE)
tree cname = TREE_OPERAND (decl, 0);
if (cname == NULL_TREE)
ctype = NULL_TREE;
+ else if (TREE_CODE (cname) == NAMESPACE_DECL)
+ {
+ ctype = NULL_TREE;
+ in_namespace = TREE_OPERAND (decl, 0);
+ TREE_OPERAND (decl, 0) = NULL_TREE;
+ }
else if (! is_aggr_type (cname, 1))
TREE_OPERAND (decl, 0) = NULL_TREE;
/* Must test TREE_OPERAND (decl, 1), in case user gives
{
if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
{
- if (pedantic && ! in_system_header)
+ if (pedantic && ! in_system_header && warn_long_long)
pedwarn ("ANSI C++ does not support `long long'");
if (longlong)
error ("`long long long' is too long for GCC");
constp = !! RIDBIT_SETP (RID_CONST, specbits) + TYPE_READONLY (type);
volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type);
- type = TYPE_MAIN_VARIANT (type);
+ type = build_type_variant (type, 0, 0);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
/* Static anonymous unions are dealt with here. */
if (staticp && decl_context == TYPENAME
&& TREE_CODE (declspecs) == TREE_LIST
- && TREE_CODE (TREE_VALUE (declspecs)) == UNION_TYPE
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_VALUE (declspecs))))
+ && ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
decl_context = FIELD;
/* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual'
/* Check for some types that there cannot be arrays of. */
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
+ if (TREE_CODE (type) == VOID_TYPE)
{
cp_error ("declaration of `%D' as array of voids", dname);
type = error_mark_node;
the function; then build_vec_delete will need this
value. */
int yes = suspend_momentary ();
- /* might be a cast */
+ /* Might be a cast. */
if (TREE_CODE (size) == NOP_EXPR
&& TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
size = TREE_OPERAND (size, 0);
return void_type_node;
}
}
- else /* it's a constructor. */
+ else /* It's a constructor. */
{
if (explicitp == 1)
explicitp = 2;
}
else
{
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
+ if (TREE_CODE (type) == VOID_TYPE)
error ("invalid type: `void &'");
else
type = build_reference_type (type);
if (TREE_COMPLEXITY (declarator) == 0)
/* This needs to be here, in case we are called
multiple times. */ ;
+ else if (TREE_COMPLEXITY (declarator) == -1)
+ /* Namespace member. */
+ pop_decl_namespace ();
else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
- /* don't fall out into global scope. Hides real bug? --eichin */ ;
+ /* Don't fall out into global scope. Hides real bug? --eichin */ ;
else if (! IS_AGGR_TYPE_CODE
(TREE_CODE (TREE_OPERAND (declarator, 0))))
;
else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
|| TYPE_SIZE (complete_type (ctype)) != NULL_TREE)
{
- /* have to move this code elsewhere in this function.
+ /* Have to move this code elsewhere in this function.
this code is used for i.e., typedef int A::M; M *pm;
It is? How? jason 10/2/94 */
in typenames, fields or parameters. */
if (constp || volatilep)
type = cp_build_type_variant (type, constp, volatilep);
+ if (current_lang_name == lang_name_java)
+ TYPE_FOR_JAVA (type) = 1;
if (decl_context == FIELD)
{
SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1;
}
else
- decl = build_decl (TYPE_DECL, declarator, type);
+ {
+ /* Make sure this typedef lives as long as its type,
+ since it might be used as a template parameter. */
+ if (type != error_mark_node)
+ push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
+ decl = build_decl (TYPE_DECL, declarator, type);
+ if (type != error_mark_node)
+ pop_obstacks ();
+ }
/* If the user declares "struct {...} foo" then `foo' will have
an anonymous name. Fill that name in now. Nothing can
refer to it, so nothing needs know about the name change.
The TYPE_NAME field was filled in by build_struct_xref. */
if (type != error_mark_node
+ && !TYPE_READONLY (type) && !TYPE_VOLATILE (type)
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
{
- /* replace the anonymous name with the real name everywhere. */
+ /* Replace the anonymous name with the real name everywhere. */
lookup_tag_reverse (type, declarator);
TYPE_NAME (type) = decl;
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_ANONYMOUS (type) = 1;
+ /* XXX Temporarily set the scope.
+ When returning, start_decl expects it as NULL_TREE,
+ and will then then set it using pushdecl. */
+ my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 980404);
+ if (current_class_type)
+ DECL_CONTEXT (decl) = current_class_type;
+ else
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+
DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
DECL_ASSEMBLER_NAME (decl)
= get_identifier (build_overload_name (type, 1, 1));
+ DECL_CONTEXT (decl) = NULL_TREE;
}
if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE)
We don't complain about parms either, but that is because
a better error message can be made later. */
- if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM)
+ if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM)
{
if (! declarator)
error ("unnamed variable or field declared void");
type = build_pointer_type (type);
else if (TREE_CODE (type) == OFFSET_TYPE)
type = build_pointer_type (type);
- else if (type == void_type_node && declarator)
+ else if (TREE_CODE (type) == VOID_TYPE && declarator)
{
error ("declaration of `%s' as void", name);
return NULL_TREE;
declarator,
virtualp, flags, quals, raises, attrlist,
friendp ? -1 : 0, friendp, publicp, inlinep,
- funcdef_flag, template_count);
+ funcdef_flag, template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
#if 0
decl = grokfndecl (ctype, type, declarator, declarator,
virtualp, flags, quals, raises, attrlist,
friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
- template_count);
+ template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
}
cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
declarator);
- if (pedantic && ! INTEGRAL_TYPE_P (type))
+ if (pedantic && ! INTEGRAL_TYPE_P (type)
+ && !uses_template_parms (type))
cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", declarator, type);
}
if (current_lang_name == lang_name_cplusplus
&& ! processing_template_decl
- && ! (IDENTIFIER_LENGTH (original_name) == 4
- && IDENTIFIER_POINTER (original_name)[0] == 'm'
- && strcmp (IDENTIFIER_POINTER (original_name), "main") == 0)
+ && ! MAIN_NAME_P (original_name)
&& ! (IDENTIFIER_LENGTH (original_name) > 10
&& IDENTIFIER_POINTER (original_name)[0] == '_'
&& IDENTIFIER_POINTER (original_name)[1] == '_'
virtualp, flags, quals, raises, attrlist,
1, friendp,
publicp, inlinep, funcdef_flag,
- template_count);
+ template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
+ /* Among other times, could occur from check_explicit_specialization
+ returning an error_mark_node. */
+ if (decl == error_mark_node)
+ return error_mark_node;
+
if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c
&& (! DECL_USE_TEMPLATE (decl) ||
name_mangling_version < 1))
-#if 0
- /* XXX is support for the old __ns_ mangling really needed? MvL */
- DECL_ASSEMBLER_NAME (decl) = current_namespace_id (declarator);
-#else
DECL_ASSEMBLER_NAME (decl) = declarator;
-#endif
if (staticp == 1)
{
}
/* An uninitialized decl with `extern' is a reference. */
- decl = grokvardecl (type, declarator, &specbits, initialized, constp);
+ decl = grokvardecl (type, declarator, &specbits,
+ initialized, constp, in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
}
else if (first_parm != NULL_TREE
&& TREE_CODE (TREE_VALUE (first_parm)) != TREE_LIST
- && TREE_VALUE (first_parm) != void_type_node)
+ && TREE_CODE (TREE_VALUE (first_parm)) != VOID_TYPE)
my_friendly_abort (145);
else
{
chain = TREE_CHAIN (parm);
/* @@ weak defense against parse errors. */
- if (decl != void_type_node && TREE_CODE (decl) != TREE_LIST)
+ if (TREE_CODE (decl) != VOID_TYPE
+ && TREE_CODE (decl) != TREE_LIST)
{
/* Give various messages as the need arises. */
if (TREE_CODE (decl) == STRING_CST)
continue;
}
- if (decl != void_type_node)
+ if (TREE_CODE (decl) != VOID_TYPE)
{
decl = grokdeclarator (TREE_VALUE (decl),
TREE_PURPOSE (decl),
if (! decl)
continue;
type = TREE_TYPE (decl);
- if (TYPE_MAIN_VARIANT (type) == void_type_node)
+ if (TREE_CODE (type) == VOID_TYPE)
decl = void_type_node;
else if (TREE_CODE (type) == METHOD_TYPE)
{
&& CLASSTYPE_ABSTRACT_VIRTUALS (type))
{
abstract_virtuals_error (decl, type);
- any_error = 1; /* seems like a good idea */
+ any_error = 1; /* Seems like a good idea. */
}
else if (TREE_CODE (type) == RECORD_TYPE
&& TYPE_LANG_SPECIFIC (type)
&& IS_SIGNATURE (type))
{
signature_error (decl, type);
- any_error = 1; /* seems like a good idea */
+ any_error = 1; /* Seems like a good idea. */
}
}
- if (decl == void_type_node)
+ if (TREE_CODE (decl) == VOID_TYPE)
{
if (result == NULL_TREE)
{
else
init = require_instantiated_type (type, init, integer_zero_node);
if (! processing_template_decl
+ && init != error_mark_node
&& TREE_CODE (init) != DEFAULT_ARG
&& ! can_convert_arg (type, TREE_TYPE (init), init))
cp_pedwarn ("invalid type `%T' for default argument to `%#D'",
added to any ctor so we can tell if the class has been initialized
yet. This could screw things up in this function, so we deliberately
ignore the leading int if we're in that situation. */
- if (parmtypes
- && TREE_VALUE (parmtypes) == integer_type_node
- && TYPE_USES_VIRTUAL_BASECLASSES (ctype))
+ if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))
{
+ my_friendly_assert (parmtypes
+ && TREE_VALUE (parmtypes) == integer_type_node,
+ 980529);
parmtypes = TREE_CHAIN (parmtypes);
parmtype = TREE_VALUE (parmtypes);
}
if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype)
- {
- if (TREE_CHAIN (parmtypes) == NULL_TREE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
+ && (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
- {
- TYPE_HAS_INIT_REF (ctype) = 1;
- if (TYPE_READONLY (TREE_TYPE (parmtype)))
- TYPE_HAS_CONST_INIT_REF (ctype) = 1;
- }
- else
- TYPE_GETS_INIT_AGGR (ctype) = 1;
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes))))
+ {
+ TYPE_HAS_INIT_REF (ctype) = 1;
+ if (TYPE_READONLY (TREE_TYPE (parmtype)))
+ TYPE_HAS_CONST_INIT_REF (ctype) = 1;
}
- else if (TYPE_MAIN_VARIANT (parmtype) == ctype)
+ else if (TYPE_MAIN_VARIANT (parmtype) == ctype
+ && TREE_CHAIN (parmtypes) != NULL_TREE
+ && TREE_CHAIN (parmtypes) == void_list_node)
{
- if (TREE_CHAIN (parmtypes) != NULL_TREE
- && TREE_CHAIN (parmtypes) == void_list_node)
- {
- cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
- ctype, ctype);
- SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
-
- return 0;
- }
- else
- TYPE_GETS_INIT_AGGR (ctype) = 1;
+ cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
+ ctype, ctype);
+ SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
+ return 0;
}
else if (TREE_CODE (parmtype) == VOID_TYPE
|| TREE_PURPOSE (parmtypes) != NULL_TREE)
cp_error ("`%D' must be either a non-static member function or a non-member function", decl);
if (p)
- for (; TREE_VALUE (p) != void_type_node ; p = TREE_CHAIN (p))
+ for (; TREE_CODE (TREE_VALUE (p)) != VOID_TYPE ; p = TREE_CHAIN (p))
{
tree arg = TREE_VALUE (p);
if (TREE_CODE (arg) == REFERENCE_TYPE)
}
if (name == ansi_opname[(int) CALL_EXPR])
- return; /* no restrictions on args */
+ return; /* No restrictions on args. */
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
register tree ref, t;
struct binding_level *b = inner_binding_level;
int got_type = 0;
+ tree attributes = NULL_TREE;
+
+ /* If we are called from the parser, code_type_node will sometimes be a
+ TREE_LIST. This indicates that the user wrote
+ "class __attribute__ ((foo)) bar". Extract the attributes so we can
+ use them later. */
+ if (TREE_CODE (code_type_node) == TREE_LIST)
+ {
+ attributes = TREE_PURPOSE (code_type_node);
+ code_type_node = TREE_VALUE (code_type_node);
+ }
tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
switch (tag_code)
{
/* Try finding it as a type declaration. If that wins, use it. */
ref = lookup_name (name, 1);
+
+ if (ref != NULL_TREE
+ && processing_template_decl
+ && DECL_CLASS_TEMPLATE_P (ref)
+ && template_class_depth (current_class_type) == 0)
+ /* Since GLOBALIZE is true, we're declaring a global
+ template, so we want this type. */
+ ref = DECL_RESULT (ref);
+
if (ref && TREE_CODE (ref) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (ref)) == code)
ref = TREE_TYPE (ref);
/* If it no longer looks like a nested type, make sure it's
in global scope.
If it is not an IDENTIFIER, this is not a declaration */
- if (b == global_binding_level && !class_binding_level
+ if (b->namespace_p && !class_binding_level
&& TREE_CODE (name) == IDENTIFIER_NODE)
{
- tree binding;
- binding = binding_for_name (name, current_namespace);
- if (BINDING_VALUE (binding) == NULL_TREE)
- BINDING_VALUE (binding) = TYPE_NAME (ref);
+ if (IDENTIFIER_NAMESPACE_VALUE (name) == NULL_TREE)
+ SET_IDENTIFIER_NAMESPACE_VALUE (name, TYPE_NAME (ref));
}
if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref))
- redeclare_class_template (ref);
+ redeclare_class_template (ref, current_template_parms);
}
if (binfo)
pop_obstacks ();
+ TREE_TYPE (ref) = attributes;
+
return ref;
}
tree basetype = TREE_VALUE (binfo);
tree base_binfo;
- GNU_xref_hier (IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TREE_VALUE (binfo)),
- via_public, via_virtual, 0);
-
if (basetype && TREE_CODE (basetype) == TYPE_DECL)
basetype = TREE_TYPE (basetype);
if (!basetype
TREE_VALUE (binfo));
continue;
}
+
+ GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
+
#if 1
/* This code replaces similar code in layout_basetypes.
We put the complete_type first for implicit `typename'. */
- else if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
- && ! (current_template_parms && uses_template_parms (basetype)))
+ if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
+ && ! (current_template_parms && uses_template_parms (basetype)))
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
continue;
}
+ if (TYPE_FOR_JAVA (basetype)
+ && current_lang_stack == current_lang_base)
+ TYPE_FOR_JAVA (ref) = 1;
+
/* Note that the BINFO records which describe individual
inheritances are *not* shared in the lattice! They
cannot be shared because a given baseclass may be
register tree enumtype = NULL_TREE;
struct binding_level *b = inner_binding_level;
+ /* We are wasting space here and putting these on the permanent_obstack so
+ that typeid(local enum) will work correctly. */
+#if 0
if (processing_template_decl && current_function_decl)
- end_temporary_allocation ();
+#endif
+
+ end_temporary_allocation ();
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
}
/* Finish debugging output for this type. */
- rest_of_type_compilation (enumtype, global_bindings_p ());
+ rest_of_type_compilation (enumtype, namespace_bindings_p ());
return enumtype;
}
int doing_friend = 0;
/* Sanity check. */
- my_friendly_assert (TREE_VALUE (void_list_node) == void_type_node, 160);
+ my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
/* Assume, until we see it does. */
if (! DECL_ARGUMENTS (decl1)
&& !DECL_STATIC_FUNCTION_P (decl1)
- && DECL_CONTEXT (decl1)
+ && DECL_CLASS_SCOPE_P (decl1)
&& TYPE_IDENTIFIER (DECL_CONTEXT (decl1))
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (DECL_CONTEXT (decl1))))
{
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
- else if (IDENTIFIER_LENGTH (DECL_NAME (decl1)) == 4
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (decl1)), "main")
- && DECL_CONTEXT (decl1) == NULL_TREE)
+ else if (DECL_MAIN_P (decl1))
{
/* If this doesn't return integer_type, complain. */
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
/* Effective C++ rule 15. See also c_expand_return. */
if (warn_ecpp
&& DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
- && TREE_TYPE (fntype) == void_type_node)
+ && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
cp_warning ("`operator=' should return a reference to `*this'");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
else if (pre_parsed_p == 0)
{
/* A specialization is not used to guide overload resolution. */
- if (flag_guiding_decls
- || !DECL_TEMPLATE_SPECIALIZATION (decl1))
+ if ((flag_guiding_decls
+ || !DECL_TEMPLATE_SPECIALIZATION (decl1))
+ && ! DECL_FUNCTION_MEMBER_P (decl1))
decl1 = pushdecl (decl1);
+ else
+ {
+ /* We need to set the DECL_CONTEXT. */
+ if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
+ DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
+ /* And make sure we have enough default args. */
+ check_default_args (decl1);
+ }
DECL_MAIN_VARIANT (decl1) = decl1;
fntype = TREE_TYPE (decl1);
}
{
pushdecl (parm);
}
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
+ else if (TREE_CODE (TREE_TYPE (parm)) == VOID_TYPE)
cp_error ("parameter `%D' declared void", parm);
else
{
/* If this function is `main', emit a call to `__main'
to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
- && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- {
- expand_main_function ();
- }
+ if (DECL_MAIN_P (fndecl))
+ expand_main_function ();
/* Now that we have initialized the parms, we can start their
cleanups. We cannot do this before, since expand_decl_cleanup
virtual_size = c_sizeof (current_class_type);
/* At the end, call delete if that's what's requested. */
- if (TYPE_GETS_REG_DELETE (current_class_type))
- /* This NOP_EXPR means we are in a static call context. */
- exprstmt
- = build_method_call (build_indirect_ref (build1 (NOP_EXPR,
- build_pointer_type (current_class_type),
- error_mark_node),
- NULL_PTR),
- ansi_opname[(int) DELETE_EXPR],
- expr_tree_cons (NULL_TREE, current_class_ptr,
- build_expr_list (NULL_TREE, virtual_size)),
- NULL_TREE, LOOKUP_NORMAL);
- else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- exprstmt = build_x_delete (ptr_type_node, current_class_ptr, 0,
- virtual_size);
+
+ /* FDIS sez: At the point of definition of a virtual destructor
+ (including an implicit definition), non-placement operator
+ delete shall be looked up in the scope of the destructor's
+ class and if found shall be accessible and unambiguous.
+
+ This is somewhat unclear, but I take it to mean that if the
+ class only defines placement deletes we don't do anything here.
+ So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain
+ for us if they ever try to delete one of these. */
+
+ if (TYPE_GETS_REG_DELETE (current_class_type)
+ || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ exprstmt = build_op_delete_call
+ (DELETE_EXPR, current_class_ptr, virtual_size,
+ LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
else
exprstmt = NULL_TREE;
expand_end_bindings (decls, decls != NULL_TREE, 0);
poplevel (decls != NULL_TREE, 0, 0);
}
- c_expand_return (current_class_ptr);
+ /* c_expand_return knows to return 'this' from a constructor. */
+ c_expand_return (NULL_TREE);
}
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (
- DECL_RESULT (current_function_decl))) != void_type_node
+ else if (TREE_CODE (TREE_TYPE (DECL_RESULT (current_function_decl))) != VOID_TYPE
&& return_label != NULL_RTX)
no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
poplevel (decls != NULL_TREE, 1, 0);
}
- c_expand_return (current_class_ptr);
+ /* c_expand_return knows to return 'this' from a constructor. */
+ c_expand_return (NULL_TREE);
current_function_assigns_this = 0;
current_function_just_assigned_this = 0;
}
- else if (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
- && DECL_CONTEXT (fndecl) == NULL_TREE)
+ else if (DECL_MAIN_P (fndecl))
{
/* Make it so that `main' always returns 0 by default. */
#ifdef VMS
if (cleanup_label)
{
- /* remove the binding contour which is used
+ /* Remove the binding contour which is used
to catch cleanup-generated temporaries. */
expand_end_bindings (0, 0, 0);
poplevel (0, 0, 0);
my_friendly_abort (122);
poplevel (1, 0, 1);
- /* reset scope for C++: if we were in the scope of a class,
+ /* Reset scope for C++: if we were in the scope of a class,
then when we finish this function, we are not longer so.
This cannot be done until we know for sure that no more
class members will ever be referenced in this function
cp_warning ("`noreturn' function `%D' does return", fndecl);
else if ((warn_return_type || pedantic)
&& current_function_returns_null
- && TYPE_MAIN_VARIANT (TREE_TYPE (fntype)) != void_type_node)
+ && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE)
{
/* If this function returns non-void and control can drop through,
complain. */
return NULL_TREE;
/* Pass friends other than inline friend functions back. */
- if (TYPE_MAIN_VARIANT (fndecl) == void_type_node)
+ if (fndecl == void_type_node)
return fndecl;
if (TREE_CODE (fndecl) != FUNCTION_DECL)
{
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type)
{
- if (DECL_CONTEXT (fndecl))
+ if (DECL_CONTEXT (fndecl)
+ && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
cp_error ("`%D' is already defined in class %s", fndecl,
TYPE_NAME_STRING (DECL_CONTEXT (fndecl)));
}
if (! DECL_FRIEND_P (fndecl))
{
- if (DECL_CHAIN (fndecl) != NULL_TREE)
- {
- /* Need a fresh node here so that we don't get circularity
- when we link these together. If FNDECL was a friend, then
- `pushdecl' does the right thing, which is nothing wrt its
- current value of DECL_CHAIN. */
- fndecl = copy_node (fndecl);
- }
if (TREE_CHAIN (fndecl))
{
fndecl = copy_node (fndecl);
register tree link;
- if (TYPE_MAIN_VARIANT (decl) == void_type_node)
+ if (decl == void_type_node)
return decl;
old_initial = DECL_INITIAL (fndecl);
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link))
- IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
libg++ to miscompile, and tString to core dump. */
exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
#endif
+
+ /* Strip unused implicit INDIRECT_REFs of references. */
+ if (TREE_CODE (exp) == INDIRECT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
+ exp = TREE_OPERAND (exp, 0);
+
/* If we don't do this, we end up down inside expand_expr
trying to do TYPE_MODE on the ERROR_MARK, and really
go outside the bounds of the type. */