#include "c-pragma.h"
#include "diagnostic.h"
#include "debug.h"
+#include "timevar.h"
static tree grokparms (tree);
static const char *redeclaration_error_message (tree, tree);
static void require_complete_types_for_parms (tree);
static int ambi_op_p (enum tree_code);
static int unary_op_p (enum tree_code);
-static tree store_bindings (tree, tree);
+static cxx_saved_binding *store_bindings (tree, cxx_saved_binding *);
static tree lookup_tag_reverse (tree, tree);
static void push_local_name (tree);
static void warn_extern_redeclared_static (tree, tree);
static int add_binding (tree, tree);
static void pop_binding (tree, tree);
static tree local_variable_p_walkfn (tree *, int *, void *);
-static tree find_binding (tree, tree);
-static tree select_decl (tree, int);
+static tree select_decl (cxx_binding *, int);
static int lookup_flags (int, int);
static tree qualify_lookup (tree, int);
static tree record_builtin_java_type (const char *, int);
static tree make_label_decl (tree, int);
static void use_label (tree);
static void check_previous_goto_1 (tree, struct cp_binding_level *, tree,
- const char *, int);
+ const location_t *);
static void check_previous_goto (struct named_label_use_list *);
static void check_switch_goto (struct cp_binding_level *);
static void check_previous_gotos (tree);
static tree reshape_init (tree, tree *);
static tree build_typename_type (tree, tree, tree);
-#if defined (DEBUG_BINDING_LEVELS)
-static void indent (void);
-#endif
-
/* Erroneous argument lists can use this *IFF* they do not modify it. */
tree error_mark_list;
struct cp_binding_level *binding_level;
tree names_in_scope;
tree label_decl;
- const char *filename_o_goto;
- int lineno_o_goto;
+ location_t o_goto_locus;
struct named_label_use_list *next;
};
/* A chain of NAMESPACE_DECL nodes. */
tree namespaces;
+ /* An array of static functions and variables (for namespaces only) */
+ varray_type static_decls;
+
/* A chain of VTABLE_DECL nodes. */
tree vtables;
- /* A list of structure, union and enum definitions, for looking up
- tag names.
- It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
- or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
- or ENUMERAL_TYPE node.
-
- C++: the TREE_VALUE nodes can be simple types for
- component_bindings. */
- tree tags;
+ /* A dictionary for looking up user-defined-types. */
+ binding_table type_decls;
/* A list of USING_DECL nodes. */
tree usings;
/* The binding level currently in effect. */
#define current_binding_level \
- (cfun && cp_function_chain->bindings \
- ? cp_function_chain->bindings \
- : scope_chain->bindings)
+ (*(cfun && cp_function_chain->bindings \
+ ? &cp_function_chain->bindings \
+ : &scope_chain->bindings))
/* The binding level of the current class, if any. */
static GTY((deletable (""))) struct cp_binding_level *free_binding_level;
-/* The outermost binding level, for names of file scope.
- This is created when the compiler is started and exists
- through the entire run. */
-
-static GTY(()) struct cp_binding_level *global_binding_level;
-
/* Nonzero means unconditionally make a BLOCK for the next level pushed. */
static int keep_next_level_flag;
static GTY(()) tree incomplete_vars;
-#if defined(DEBUG_BINDING_LEVELS)
+#ifndef ENABLE_SCOPE_CHECKING
+# define ENABLE_SCOPE_CHECKING 0
+#else
+# define ENABLE_SCOPE_CHECKING 1
+#endif
+
static int binding_depth = 0;
static int is_class_level = 0;
static void
-indent (void)
+indent (int depth)
{
- register unsigned i;
+ int i;
- for (i = 0; i < binding_depth*2; i++)
+ for (i = 0; i < depth * 2; i++)
putc (' ', stderr);
}
-#endif /* defined(DEBUG_BINDING_LEVELS) */
static tree pushdecl_with_scope (tree, struct cp_binding_level *);
newlevel->more_cleanups_ok = 1;
newlevel->keep = keep;
-#if defined(DEBUG_BINDING_LEVELS)
- newlevel->binding_depth = binding_depth;
- indent ();
- fprintf (stderr, "push %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block", newlevel, lineno);
- is_class_level = 0;
- binding_depth++;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ {
+ newlevel->binding_depth = binding_depth;
+ indent (binding_depth);
+ verbatim ("push %s level %p line %d\n",
+ (is_class_level) ? "class" : "block",
+ (void *) newlevel, input_line);
+ is_class_level = 0;
+ binding_depth++;
+ }
}
/* Find the innermost enclosing class scope, and reset
static void
pop_binding_level (void)
{
- if (global_binding_level)
+ if (NAMESPACE_LEVEL (global_namespace))
+ /* Cannot pop a level, if there are none left to pop. */
+ my_friendly_assert (!global_scope_p (current_binding_level), 20030527);
+ /* Pop the current level, and free the structure for reuse. */
+ if (ENABLE_SCOPE_CHECKING)
{
- /* Cannot pop a level, if there are none left to pop. */
- if (current_binding_level == global_binding_level)
- abort ();
+ indent (--binding_depth);
+ verbatim ("pop %s level %p line %d\n",
+ (is_class_level) ? "class" : "block",
+ (void*) current_binding_level, input_line);
+ if (is_class_level != (current_binding_level == class_binding_level))
+ {
+ indent (binding_depth);
+ verbatim ("XXX is_class_level != (current_binding_level "
+ "== class_binding_level)\n");
+ }
+ is_class_level = 0;
}
- /* Pop the current level, and free the structure for reuse. */
-#if defined(DEBUG_BINDING_LEVELS)
- binding_depth--;
- indent ();
- fprintf (stderr, "pop %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block",
- current_binding_level, lineno);
- if (is_class_level != (current_binding_level == class_binding_level))
- {
- indent ();
- fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
- }
- is_class_level = 0;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
{
register struct cp_binding_level *level = current_binding_level;
current_binding_level = current_binding_level->level_chain;
level->level_chain = free_binding_level;
-#if 0 /* defined(DEBUG_BINDING_LEVELS) */
- if (level->binding_depth != binding_depth)
- abort ();
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+ if (level->parm_flag == 2)
+ level->type_decls = NULL;
+ else
+ binding_table_free (level->type_decls);
+ my_friendly_assert (!ENABLE_SCOPE_CHECKING
+ || level->binding_depth == binding_depth,
+ 20030529);
free_binding_level = level;
find_class_binding_level ();
}
if (class_binding_level)
current_binding_level = class_binding_level;
- if (global_binding_level)
+ if (NAMESPACE_LEVEL (global_namespace))
+ /* Cannot suspend a level, if there are none left to suspend. */
+ my_friendly_assert (!global_scope_p (current_binding_level), 20030527);
+ /* Suspend the current level. */
+ if (ENABLE_SCOPE_CHECKING)
{
- /* Cannot suspend a level, if there are none left to suspend. */
- if (current_binding_level == global_binding_level)
- abort ();
+ indent (--binding_depth);
+ verbatim ("suspend %s level %p line %d\n",
+ (is_class_level) ? "class" : "block",
+ (void *) current_binding_level, input_line);
+ if (is_class_level != (current_binding_level == class_binding_level))
+ {
+ indent (binding_depth);
+ verbatim ("XXX is_class_level != (current_binding_level "
+ "== class_binding_level)\n");
+ }
+ is_class_level = 0;
}
- /* Suspend the current level. */
-#if defined(DEBUG_BINDING_LEVELS)
- binding_depth--;
- indent ();
- fprintf (stderr, "suspend %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block",
- current_binding_level, lineno);
- if (is_class_level != (current_binding_level == class_binding_level))
- {
- indent ();
- fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
- }
- is_class_level = 0;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
current_binding_level = current_binding_level->level_chain;
find_class_binding_level ();
}
/* 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_BINDING_LEVELS)
- b->binding_depth = binding_depth;
- indent ();
- fprintf (stderr, "resume %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block", b, lineno);
- is_class_level = 0;
- binding_depth++;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ {
+ b->binding_depth = binding_depth;
+ indent (binding_depth);
+ verbatim ("resume %s level %p line %d\n",
+ (is_class_level) ? "class" : "block", b, input_line);
+ is_class_level = 0;
+ binding_depth++;
+ }
}
\f
/* Create a new `struct cp_binding_level'. */
int
global_bindings_p (void)
{
- return current_binding_level == global_binding_level;
+ return global_scope_p (current_binding_level);
}
/* Return the innermost binding level that is not for a class scope. */
return (current_binding_level->blocks != NULL_TREE
|| current_binding_level->keep
|| current_binding_level->names != NULL_TREE
- || (current_binding_level->tags != NULL_TREE
+ || (current_binding_level->type_decls != NULL
&& !current_binding_level->tag_transparent));
}
return;
/* Reuse or create a struct for this binding level. */
-#if defined(DEBUG_BINDING_LEVELS)
- if (0)
-#else /* !defined(DEBUG_BINDING_LEVELS) */
- if (free_binding_level)
-#endif /* !defined(DEBUG_BINDING_LEVELS) */
+ if (!ENABLE_SCOPE_CHECKING && free_binding_level)
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
poplevel (0, 0, 0);
}
-/* For a binding between a name and an entity at a block scope,
- this is the `struct cp_binding_level' for the block. */
-#define BINDING_LEVEL(NODE) \
- (((struct tree_binding*)(NODE))->scope.level)
-
-/* A free list of CPLUS_BINDING nodes, connected by their
- TREE_CHAINs. */
-
-static GTY((deletable (""))) tree free_bindings;
-
/* Make DECL the innermost binding for ID. The LEVEL is the binding
level at which this declaration is being bound. */
static void
-push_binding (tree id,
- tree decl,
- struct cp_binding_level* level)
+push_binding (tree id, tree decl, cxx_scope* level)
{
- tree binding;
-
- if (free_bindings)
- {
- binding = free_bindings;
- free_bindings = TREE_CHAIN (binding);
- }
- else
- binding = make_node (CPLUS_BINDING);
+ cxx_binding *binding = cxx_binding_make (decl, NULL);
/* Now, fill in the binding information. */
- BINDING_VALUE (binding) = decl;
- BINDING_TYPE (binding) = NULL_TREE;
- BINDING_LEVEL (binding) = level;
+ binding->previous = IDENTIFIER_BINDING (id);
+ BINDING_SCOPE (binding) = level;
INHERITED_VALUE_BINDING_P (binding) = 0;
LOCAL_BINDING_P (binding) = (level != class_binding_level);
- BINDING_HAS_LEVEL_P (binding) = 1;
/* And put it on the front of the list of bindings for ID. */
- TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
IDENTIFIER_BINDING (id) = binding;
}
static int
add_binding (tree id, tree decl)
{
- tree binding = IDENTIFIER_BINDING (id);
+ cxx_binding *binding = IDENTIFIER_BINDING (id);
int ok = 1;
+ timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
/* The new name is the type name. */
BINDING_TYPE (binding) = decl;
ok = 0;
}
- return ok;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
}
/* Add DECL to the list of things declared in B. */
TREE_CHAIN (decl) = b->names;
b->names = decl;
b->names_size++;
+
+ /* If appropriate, add decl to separate list of statics */
+ if (b->namespace_p)
+ if ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl))))
+ VARRAY_PUSH_TREE (b->static_decls, decl);
}
}
push_class_binding (tree id, tree decl)
{
int result = 1;
- tree binding = IDENTIFIER_BINDING (id);
+ cxx_binding *binding = IDENTIFIER_BINDING (id);
tree context;
+ timevar_push (TV_NAME_LOOKUP);
/* Note that we declared this value so that we can issue an error if
this is an invalid redeclaration of a name already used for some
other purpose. */
note_name_declared_in_class (id, decl);
- if (binding && BINDING_LEVEL (binding) == class_binding_level)
+ if (binding && BINDING_SCOPE (binding) == class_binding_level)
/* Supplement the existing binding. */
result = add_binding (id, decl);
else
in this class. */
INHERITED_VALUE_BINDING_P (binding) = 1;
- return result;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result);
}
/* Remove the binding for DECL which should be the innermost binding
static void
pop_binding (tree id, tree decl)
{
- tree binding;
+ cxx_binding *binding;
if (id == NULL_TREE)
/* It's easiest to write the loops that call this function without
binding = IDENTIFIER_BINDING (id);
/* The name should be bound. */
- my_friendly_assert (binding != NULL_TREE, 0);
+ my_friendly_assert (binding != NULL, 0);
/* The DECL will be either the ordinary binding or the type
binding for this identifier. Remove that binding. */
{
/* We're completely done with the innermost binding for this
identifier. Unhook it from the list of bindings. */
- IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+ IDENTIFIER_BINDING (id) = binding->previous;
/* Add it to the free list. */
- TREE_CHAIN (binding) = free_bindings;
- free_bindings = binding;
+ cxx_binding_free (binding);
- /* Clear the BINDING_LEVEL so the garbage collector doesn't walk
+ /* Clear the BINDING_SCOPE so the garbage collector doesn't walk
it. */
- BINDING_LEVEL (binding) = NULL;
+ BINDING_SCOPE (binding) = NULL;
}
}
tree decls;
int tmp = functionbody;
int real_functionbody;
- tree tags;
tree subblocks;
tree block = NULL_TREE;
tree decl;
int leaving_for_scope;
+ timevar_push (TV_NAME_LOOKUP);
if (cfun && !doing_semantic_analysis_p ())
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
my_friendly_assert (current_binding_level->parm_flag != 2,
19990916);
real_functionbody = (current_binding_level->keep == 2
? ((functionbody = 0), tmp) : functionbody);
- tags = functionbody >= 0 ? current_binding_level->tags : 0;
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
my_friendly_assert (!current_binding_level->class_shadowed,
if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
&& DECL_NAME (link))
{
- tree outer_binding
- = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+ cxx_binding *outer_binding
+ = IDENTIFIER_BINDING (DECL_NAME (link))->previous;
tree ns_binding;
if (!outer_binding)
ns_binding = NULL_TREE;
if (outer_binding
- && (BINDING_LEVEL (outer_binding)
+ && (BINDING_SCOPE (outer_binding)
== current_binding_level->level_chain))
/* We have something like:
there only for backward compatibility. */
DECL_DEAD_FOR_LOCAL (link) = 1;
- /* Keep track of what should of have happenned when we
+ /* Keep track of what should have happened when we
popped the binding. */
if (outer_binding && BINDING_VALUE (outer_binding))
DECL_SHADOWED_FOR_VAR (link)
current_binding_level->level_chain->
dead_vars_from_for);
- /* Although we don't pop the CPLUS_BINDING, we do clear
- its BINDING_LEVEL since the level is going away now. */
- BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
- = 0;
+ /* Although we don't pop the cxx_binding, we do clear
+ its BINDING_SCOPE since the level is going away now. */
+ BINDING_SCOPE (IDENTIFIER_BINDING (DECL_NAME (link))) = 0;
}
}
else
block = poplevel (keep, reverse, functionbody);
}
- return block;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
/* Delete the node BLOCK from the current binding level.
register struct cp_binding_level *newlevel;
/* Reuse or create a struct for this binding level. */
-#if defined(DEBUG_BINDING_LEVELS)
- if (0)
-#else /* !defined(DEBUG_BINDING_LEVELS) */
- if (free_binding_level)
-#endif /* !defined(DEBUG_BINDING_LEVELS) */
+ if (!ENABLE_SCOPE_CHECKING && free_binding_level)
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
else
newlevel = make_binding_level ();
-#if defined(DEBUG_BINDING_LEVELS)
- is_class_level = 1;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ is_class_level = 1;
push_binding_level (newlevel, 0, 0);
register struct cp_binding_level *level = class_binding_level;
tree shadowed;
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (level != 0, 354);
/* If we're leaving a toplevel class, don't bother to do the setting
shadowed;
shadowed = TREE_CHAIN (shadowed))
{
- tree t;
-
- t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
- while (t && BINDING_LEVEL (t) != b)
- t = TREE_CHAIN (t);
+ cxx_binding *binding;
+
+ binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
+ while (binding && BINDING_SCOPE (binding) != b)
+ binding = binding->previous;
- if (t)
+ if (binding)
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
- = BINDING_VALUE (t);
+ = BINDING_VALUE (binding);
}
}
else
/* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
-#if defined(DEBUG_BINDING_LEVELS)
- is_class_level = 1;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ is_class_level = 1;
pop_binding_level ();
+ timevar_pop (TV_NAME_LOOKUP);
}
/* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE
int
wrapup_globals_for_namespace (tree namespace, void* data)
{
- tree globals = cp_namespace_decls (namespace);
- int len = NAMESPACE_LEVEL (namespace)->names_size;
- tree *vec = (tree *) alloca (sizeof (tree) * len);
- int i;
- int result;
- tree decl;
+ struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
+ varray_type statics = level->static_decls;
+ tree *vec = &VARRAY_TREE (statics, 0);
+ int len = VARRAY_ACTIVE_SIZE (statics);
int last_time = (data != 0);
- if (last_time && namespace == global_namespace)
- /* Let compile_file handle the global namespace. */
- return 0;
-
- /* Process the decls in reverse order--earliest first.
- Put them into VEC from back to front, then take out from front. */
- for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
- vec[len - i - 1] = decl;
-
if (last_time)
{
check_global_declarations (vec, len);
}
/* Write out any globals that need to be output. */
- result = wrapup_global_declarations (vec, len);
-
- return result;
+ return wrapup_global_declarations (vec, len);
}
\f
static int no_print_functions = 0;
static int no_print_builtins = 0;
+/* Called from print_binding_level through binding_table_foreach to
+ print the content of binding ENTRY. DATA is a pointer to line offset
+ marker. */
+static void
+bt_print_entry (binding_entry entry, void *data)
+{
+ int *p = (int *) data;
+ int len;
+
+ if (entry->name == NULL)
+ len = 3;
+ else if (entry->name == TYPE_IDENTIFIER (entry->type))
+ len = 2;
+ else
+ len = 4;
+ len = 4;
+
+ *p += len;
+
+ if (*p > 5)
+ {
+ fprintf (stderr, "\n\t");
+ *p = len;
+ }
+ if (entry->name == NULL)
+ {
+ print_node_brief (stderr, "<unnamed-typedef", entry->type, 0);
+ fprintf (stderr, ">");
+ }
+ else if (entry->name == TYPE_IDENTIFIER (entry->type))
+ print_node_brief (stderr, "", entry->type, 0);
+ else
+ {
+ print_node_brief (stderr, "<typedef", entry->name, 0);
+ print_node_brief (stderr, "", entry->type, 0);
+ fprintf (stderr, ">");
+ }
+}
+
void
print_binding_level (struct cp_binding_level* lvl)
{
tree t;
int i = 0, len;
fprintf (stderr, " blocks=");
- fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
+ fprintf (stderr, HOST_PTR_PRINTF, (void *) lvl->blocks);
if (lvl->tag_transparent)
fprintf (stderr, " tag-transparent");
if (lvl->more_cleanups_ok)
if (i)
fprintf (stderr, "\n");
}
- if (lvl->tags)
+ if (lvl->type_decls)
{
fprintf (stderr, " tags:\t");
i = 0;
- for (t = lvl->tags; t; t = TREE_CHAIN (t))
- {
- if (TREE_PURPOSE (t) == NULL_TREE)
- len = 3;
- else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
- len = 2;
- else
- len = 4;
- i += len;
- if (i > 5)
- {
- fprintf (stderr, "\n\t");
- i = len;
- }
- if (TREE_PURPOSE (t) == NULL_TREE)
- {
- print_node_brief (stderr, "<unnamed-typedef", TREE_VALUE (t), 0);
- fprintf (stderr, ">");
- }
- else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
- print_node_brief (stderr, "", TREE_VALUE (t), 0);
- else
- {
- print_node_brief (stderr, "<typedef", TREE_PURPOSE (t), 0);
- print_node_brief (stderr, "", TREE_VALUE (t), 0);
- fprintf (stderr, ">");
- }
- }
+ binding_table_foreach (lvl->type_decls, bt_print_entry, &i);
if (i)
fprintf (stderr, "\n");
}
print_other_binding_stack (struct cp_binding_level *stack)
{
struct cp_binding_level *level;
- for (level = stack; level != global_binding_level; level = level->level_chain)
+ for (level = stack; !global_scope_p (level); level = level->level_chain)
{
fprintf (stderr, "binding level ");
- fprintf (stderr, HOST_PTR_PRINTF, level);
+ fprintf (stderr, HOST_PTR_PRINTF, (void *) level);
fprintf (stderr, "\n");
print_binding_level (level);
}
{
struct cp_binding_level *b;
fprintf (stderr, "current_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, current_binding_level);
+ fprintf (stderr, HOST_PTR_PRINTF, (void *) current_binding_level);
fprintf (stderr, "\nclass_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, class_binding_level);
- fprintf (stderr, "\nglobal_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, global_binding_level);
+ fprintf (stderr, HOST_PTR_PRINTF, (void *) class_binding_level);
+ fprintf (stderr, "\nNAMESPACE_LEVEL (global_namespace)=");
+ fprintf (stderr, HOST_PTR_PRINTF,
+ (void *) NAMESPACE_LEVEL (global_namespace));
fprintf (stderr, "\n");
if (class_binding_level)
{
b = current_binding_level;
print_other_binding_stack (b);
fprintf (stderr, "global:\n");
- print_binding_level (global_binding_level);
+ print_binding_level (NAMESPACE_LEVEL (global_namespace));
}
/* 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. */
-
-/* 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 (tree name, tree scope)
-{
- 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)
- {
- /* Move binding found to the front 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;
- }
- return NULL_TREE;
-}
-
-/* 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. */
-
-tree
-binding_for_name (tree name, tree scope)
-{
- tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- tree result;
-
- 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 one. */
- 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;
- return result;
-}
-
-/* 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 (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);
-}
-
-/* Set the binding value for name in scope. If modifying the binding
- of global_namespace is attempted, try to optimize it. */
-
-void
-set_namespace_binding (tree name, tree scope, tree val)
-{
- tree b;
-
- if (scope == NULL_TREE)
- scope = global_namespace;
-
- if (scope == global_namespace)
- {
- b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING)
- {
- IDENTIFIER_NAMESPACE_BINDINGS (name) = val;
- return;
- }
- }
- b = binding_for_name (name, scope);
- BINDING_VALUE (b) = val;
-}
+ NULL_TREE, a list of "cxx_binding"s. */
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
select a name that is unique to this compilation unit. */
int need_new = 1;
int implicit_use = 0;
int global = 0;
+
+ timevar_push (TV_NAME_LOOKUP);
+
if (!global_namespace)
{
/* This must be ::. */
pushlevel (0);
declare_namespace_level ();
NAMESPACE_LEVEL (d) = current_binding_level;
+ current_binding_level->type_decls =
+ binding_table_new (name == std_identifier
+ ? NAMESPACE_STD_HT_SIZE
+ : NAMESPACE_ORDINARY_HT_SIZE);
+ VARRAY_TREE_INIT (current_binding_level->static_decls,
+ name != std_identifier ? 10 : 200,
+ "Static declarations");
}
}
else
do_using_directive (d);
/* Enter the name space. */
current_namespace = d;
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Pop from the scope of the current namespace. */
void
pop_nested_namespace (tree ns)
{
+ timevar_push (TV_NAME_LOOKUP);
while (ns != global_namespace)
{
pop_namespace ();
}
pop_from_top_level ();
+ timevar_pop (TV_NAME_LOOKUP);
}
\f
+/* Allocate storage for saving a C++ binding. */
+#define cxx_saved_binding_make() \
+ (ggc_alloc (sizeof (cxx_saved_binding)))
+
+struct cxx_saved_binding GTY(())
+{
+ /* Link that chains saved C++ bindings for a given name into a stack. */
+ cxx_saved_binding *previous;
+ /* The name of the current binding. */
+ tree identifier;
+ /* The binding we're saving. */
+ cxx_binding *binding;
+ tree class_value;
+ tree real_type_value;
+};
+
/* Subroutines for reverting temporarily to top-level for instantiation
of templates and such. We actually need to clear out the class- and
local-value slots of all identifiers, so that only the global values
scope isn't enough, because more binding levels may be pushed. */
struct saved_scope *scope_chain;
-static tree
-store_bindings (tree names, tree old_bindings)
+static cxx_saved_binding *
+store_bindings (tree names, cxx_saved_binding *old_bindings)
{
tree t;
- tree search_bindings = old_bindings;
+ cxx_saved_binding *search_bindings = old_bindings;
+ timevar_push (TV_NAME_LOOKUP);
for (t = names; t; t = TREE_CHAIN (t))
{
- tree binding, t1, id;
+ tree id;
+ cxx_saved_binding *saved;
+ cxx_saved_binding *t1;
if (TREE_CODE (t) == TREE_LIST)
id = TREE_PURPOSE (t);
|| !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
continue;
- for (t1 = search_bindings; t1; t1 = TREE_CHAIN (t1))
- if (TREE_VEC_ELT (t1, 0) == id)
+ for (t1 = search_bindings; t1; t1 = t1->previous)
+ if (t1->identifier == id)
goto skip_it;
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
- binding = make_tree_vec (4);
- TREE_VEC_ELT (binding, 0) = id;
- TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
- TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
- TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_BINDING (id) = NULL_TREE;
+ saved = cxx_saved_binding_make ();
+ saved->previous = old_bindings;
+ saved->identifier = id;
+ saved->binding = IDENTIFIER_BINDING (id);
+ saved->class_value = IDENTIFIER_CLASS_VALUE (id);;
+ saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
+ IDENTIFIER_BINDING (id) = NULL;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
- TREE_CHAIN (binding) = old_bindings;
- old_bindings = binding;
+ old_bindings = saved;
skip_it:
;
}
- return old_bindings;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings);
}
void
{
struct saved_scope *s;
struct cp_binding_level *b;
- tree old_bindings;
+ cxx_saved_binding *old_bindings;
int need_pop;
+ timevar_push (TV_NAME_LOOKUP);
s = (struct saved_scope *) ggc_alloc_cleared (sizeof (struct saved_scope));
b = scope_chain ? current_binding_level : 0;
else
need_pop = 0;
- old_bindings = NULL_TREE;
+ old_bindings = NULL;
if (scope_chain && previous_class_type)
old_bindings = store_bindings (previous_class_values, old_bindings);
- /* Have to include global_binding_level, because class-level decls
+ /* Have to include the global scope, because class-scope decls
aren't listed anywhere useful. */
for (; b; b = b->level_chain)
{
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->template_parms_p))
+ if (global_scope_p (b) || (pseudo && b->template_parms_p))
break;
old_bindings = store_bindings (b->names, old_bindings);
s->need_pop_function_context = need_pop;
s->function_decl = current_function_decl;
s->last_parms = last_function_parms;
- s->check_access = flag_access_control;
scope_chain = s;
current_function_decl = NULL_TREE;
VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
current_lang_name = lang_name_cplusplus;
current_namespace = global_namespace;
+ timevar_pop (TV_NAME_LOOKUP);
}
void
pop_from_top_level (void)
{
struct saved_scope *s = scope_chain;
- tree t;
+ cxx_saved_binding *saved;
+ timevar_push (TV_NAME_LOOKUP);
/* Clear out class-level bindings cache. */
if (previous_class_type)
invalidate_class_lookup_cache ();
current_lang_base = 0;
scope_chain = s->prev;
- for (t = s->old_bindings; t; t = TREE_CHAIN (t))
+ for (saved = s->old_bindings; saved; saved = saved->previous)
{
- tree id = TREE_VEC_ELT (t, 0);
+ tree id = saved->identifier;
- SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
- IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
- IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
+ IDENTIFIER_BINDING (id) = saved->binding;
+ IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
+ SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value);
}
/* If we were in the middle of compiling a function, restore our
pop_function_context_from (NULL_TREE);
current_function_decl = s->function_decl;
last_function_parms = s->last_parms;
+ timevar_pop (TV_NAME_LOOKUP);
}
\f
/* Push a definition of struct, union or enum tag "name".
}
else
{
- tree binding = binding_for_name (id, current_namespace);
+ cxx_binding *binding =
+ binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
BINDING_TYPE (binding) = type;
/* Store marker instead of real type. */
type = global_type_node;
tree
identifier_type_value (tree id)
{
+ timevar_push (TV_NAME_LOOKUP);
/* There is no type with that name, anywhere. */
if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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, LOOKUP_COMPLAIN);
if (id)
- return TREE_TYPE (id);
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* Pop off extraneous binding levels left over due to syntax errors.
void
pop_everything (void)
{
-#ifdef DEBUG_BINDING_LEVELS
- fprintf (stderr, "XXX entering pop_everything ()\n");
-#endif
+ if (ENABLE_SCOPE_CHECKING)
+ verbatim ("XXX entering pop_everything ()\n");
while (!toplevel_bindings_p ())
{
if (current_binding_level->parm_flag == 2)
else
poplevel (0, 0, 0);
}
-#ifdef DEBUG_BINDING_LEVELS
- fprintf (stderr, "XXX leaving pop_everything ()\n");
-#endif
+ if (ENABLE_SCOPE_CHECKING)
+ verbatim ("XXX leaving pop_everything ()\n");
}
/* The type TYPE is being declared. If it is a class template, or a
&& b->level_chain->parm_flag == 2)
{
finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
- /* Put this tag on the list of tags for the class, since
+ /* Put this UDT in the table of UDTs 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 =
- tree_cons (name, type, b->level_chain->tags);
+ if (b->level_chain->type_decls == NULL)
+ b->level_chain->type_decls =
+ binding_table_new (SCOPE_DEFAULT_HT_SIZE);
+ binding_table_insert (b->level_chain->type_decls, name, type);
if (!COMPLETE_TYPE_P (current_class_type))
{
maybe_add_class_template_decl_list (current_class_type,
type, /*friend_p=*/0);
- CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+ CLASSTYPE_NESTED_UTDS (current_class_type) =
+ b->level_chain->type_decls;
}
}
}
size_t i, nelts;
tree t, name;
+ timevar_push (TV_NAME_LOOKUP);
if (!local_names)
VARRAY_TREE_INIT (local_names, 8, "local_names");
DECL_DISCRIMINATOR (decl) = 1;
VARRAY_TREE (local_names, i) = decl;
+ timevar_pop (TV_NAME_LOOKUP);
return;
}
}
VARRAY_PUSH_TREE (local_names, decl);
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Push a tag name NAME for struct/class/union/enum type TYPE.
{
register struct cp_binding_level *b;
+ timevar_push (TV_NAME_LOOKUP);
b = current_binding_level;
while (b->tag_transparent
|| (b->parm_flag == 2
|| COMPLETE_TYPE_P (b->this_class))))
b = b->level_chain;
- b->tags = tree_cons (name, type, b->tags);
+ if (b->type_decls == NULL)
+ b->type_decls = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
+ binding_table_insert (b->type_decls, name, type);
if (name)
{
{
maybe_add_class_template_decl_list (current_class_type,
type, /*friend_p=*/0);
- CLASSTYPE_TAGS (current_class_type) = b->tags;
+ CLASSTYPE_NESTED_UTDS (current_class_type) = b->type_decls;
}
}
}
tree d = build_decl (TYPE_DECL, NULL_TREE, type);
TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Counter used to create anonymous type names. */
return get_identifier (buf);
}
-/* Clear the TREE_PURPOSE slot of tags which have anonymous typenames.
+/* Clear the TREE_PURPOSE slot of UTDs which have anonymous typenames.
This keeps dbxout from getting confused. */
void
clear_anon_tags (void)
{
register struct cp_binding_level *b;
- register tree tags;
static int last_cnt = 0;
/* Fast out if no new anon names were declared. */
b = current_binding_level;
while (b->tag_transparent)
b = b->level_chain;
- tags = b->tags;
- while (tags)
- {
- /* A NULL purpose means we have already processed all tags
- from here to the end of the list. */
- if (TREE_PURPOSE (tags) == NULL_TREE)
- break;
- if (ANON_AGGRNAME_P (TREE_PURPOSE (tags)))
- TREE_PURPOSE (tags) = NULL_TREE;
- tags = TREE_CHAIN (tags);
- }
+ if (b->type_decls != NULL)
+ binding_table_remove_anonymous_types (b->type_decls);
last_cnt = anon_cnt;
}
\f
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warning_with_decl (newdecl,
- "function `%s' redeclared as inline");
- warning_with_decl (olddecl,
- "previous declaration of function `%s' with attribute noinline");
+ warning ("%Hfunction '%D' redeclared as inline",
+ &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ warning ("%Hprevious declaration of '%D' with attribute noinline",
+ &DECL_SOURCE_LOCATION (olddecl), olddecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
- warning_with_decl (newdecl,
- "function `%s' redeclared with attribute noinline");
- warning_with_decl (olddecl,
- "previous declaration of function `%s' was inline");
+ warning ("%Hfunction '%D' redeclared with attribute noinline",
+ &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ warning ("%Hprevious declaration of '%D' was inline",
+ &DECL_SOURCE_LOCATION (olddecl), olddecl);
}
}
/* Replace the old RTL to avoid problems with inlining. */
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
+ /* Even if the types match, prefer the new declarations type
+ for anticipated built-ins, for exception lists, etc... */
+ else if (DECL_ANTICIPATED (olddecl))
+ TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
{
&& TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
CLASSTYPE_FRIEND_CLASSES (newtype)
= CLASSTYPE_FRIEND_CLASSES (oldtype);
-\
+
DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl);
}
{
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
- DECL_NO_LIMIT_STACK (newdecl)
- |= DECL_NO_LIMIT_STACK (olddecl);
+ DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
+ TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+ TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+ TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl);
+ DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+ DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
}
DECL_BEFRIENDING_CLASSES (newdecl)
= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
DECL_BEFRIENDING_CLASSES (olddecl));
- DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
+ /* DECL_THUNKS is only valid for virtual functions,
+ otherwise it is a DECL_FRIEND_CONTEXT. */
+ if (DECL_VIRTUAL_P (newdecl))
+ DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
}
}
{
/* If newdecl is not a specialization, then it is not a
template-related function at all. And that means that we
- shoud have exited above, returning 0. */
+ should have exited above, returning 0. */
my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
0);
Update OLDDECL to be the same. */
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
+ /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
+ so that encode_section_info has a chance to look at the new decl
+ flags and attributes. */
+ if (DECL_RTL_SET_P (olddecl)
+ && (TREE_CODE (olddecl) == FUNCTION_DECL
+ || (TREE_CODE (olddecl) == VAR_DECL
+ && TREE_STATIC (olddecl))))
+ make_decl_rtl (olddecl, NULL);
+
return 1;
}
register tree name;
int need_new_binding;
+ timevar_push (TV_NAME_LOOKUP);
/* We shouldn't be calling pushdecl when we're generating RTL for a
function that we already did semantic analysis on previously. */
my_friendly_assert (!cfun || doing_semantic_analysis_p (),
/* Check for duplicate params. */
if (duplicate_decls (x, t))
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if ((DECL_EXTERN_C_FUNCTION_P (x)
|| DECL_FUNCTION_TEMPLATE_P (x))
TREE_TYPE (x));
/* Throw away the redeclaration. */
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
if (duplicate_decls (x, t))
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (duplicate_decls (x, t))
{
else if (TREE_CODE (t) == FUNCTION_DECL)
check_default_args (t);
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (DECL_MAIN_P (x))
{
error ("as `%D'", x);
/* We don't try to push this declaration since that
causes a crash. */
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
}
{
t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x)
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
if (!namespace_bindings_p ())
/* We do not need to create a binding for this name;
push_overloaded_decl will have already done so if
t = push_overloaded_decl (x, PUSH_GLOBAL);
if (t == x)
add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)));
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* If declaring a type as a typedef, copy the type (unless we're
if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
/* Inline decls shadow nothing. */
&& !DECL_FROM_INLINE (x)
- && TREE_CODE (oldlocal) == PARM_DECL)
+ && TREE_CODE (oldlocal) == PARM_DECL
+ /* Don't check the `this' parameter. */
+ && !DECL_ARTIFICIAL (oldlocal))
{
bool err = false;
}
if (warn_shadow && !err)
- shadow_warning ("a parameter", name, oldlocal);
+ shadow_warning (SW_PARAM,
+ IDENTIFIER_POINTER (name), oldlocal);
}
/* Maybe warn if shadowing something else. */
IDENTIFIER_POINTER (name));
else if (oldlocal != NULL_TREE
&& TREE_CODE (oldlocal) == VAR_DECL)
- shadow_warning ("a previous local", name, oldlocal);
+ shadow_warning (SW_LOCAL,
+ IDENTIFIER_POINTER (name), oldlocal);
else if (oldglobal != NULL_TREE
&& TREE_CODE (oldglobal) == VAR_DECL)
/* XXX shadow warnings in outer-more namespaces */
- shadow_warning ("a global declaration", name, oldglobal);
+ shadow_warning (SW_GLOBAL,
+ IDENTIFIER_POINTER (name), oldglobal);
}
}
? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
: current_binding_level);
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Same as pushdecl, but define X in binding-level LEVEL. We rely on the
register struct cp_binding_level *b;
tree function_decl = current_function_decl;
+ timevar_push (TV_NAME_LOOKUP);
current_function_decl = NULL_TREE;
if (level->parm_flag == 2)
{
current_binding_level = b;
}
current_function_decl = function_decl;
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Like pushdecl, only it places X in the current namespace,
register struct cp_binding_level *b = current_binding_level;
register tree t;
+ timevar_push (TV_NAME_LOOKUP);
t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
/* Now, the type_shadowed stack may screw us. Munge it so it does
tree name = DECL_NAME (x);
tree newval;
tree *ptr = (tree *)0;
- for (; b != global_binding_level; b = b->level_chain)
+ for (; !global_scope_p (b); b = b->level_chain)
{
tree shadowed = b->type_shadowed;
for (; shadowed; shadowed = TREE_CHAIN (shadowed))
*ptr = newval;
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
-/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
- if appropriate. */
+/* Like pushdecl, only it places X in the global scope if appropriate. */
tree
pushdecl_top_level (tree x)
{
+ timevar_push (TV_NAME_LOOKUP);
push_to_top_level ();
x = pushdecl_namespace_level (x);
pop_from_top_level ();
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Make the declaration of X appear in CLASS scope. */
{
tree name;
+ timevar_push (TV_NAME_LOOKUP);
/* Get the name of X. */
if (TREE_CODE (x) == OVERLOAD)
name = DECL_NAME (get_first_fn (x));
for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
pushdecl_class_level (f);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Enter DECL into the symbol table, if that's appropriate. Returns
void
push_class_level_binding (tree name, tree x)
{
- tree binding;
+ cxx_binding *binding;
+ timevar_push (TV_NAME_LOOKUP);
/* The class_binding_level will be NULL if x is a template
parameter name in a member template. */
if (!class_binding_level)
- return;
+ {
+ timevar_pop (TV_NAME_LOOKUP);
+ return;
+ }
/* Make sure that this new member does not have the same name
as a template parameter. */
INHERITED_VALUE_BINDING_P (binding) = 0;
TREE_TYPE (shadow) = x;
IDENTIFIER_CLASS_VALUE (name) = x;
+ timevar_pop (TV_NAME_LOOKUP);
return;
}
}
what to pop later. */
TREE_TYPE (class_binding_level->class_shadowed) = x;
}
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Insert another USING_DECL into the current binding level, returning
{
tree decl;
+ timevar_push (TV_NAME_LOOKUP);
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 namespace_bindings_p () ? decl : NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ namespace_bindings_p () ? decl : 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;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Add namespace to using_directives. Return NULL_TREE if nothing was
tree ud = current_binding_level->using_directives;
tree iter, ancestor;
+ timevar_push (TV_NAME_LOOKUP);
/* Check if we already have this. */
if (purpose_member (used, ud) != NULL_TREE)
- return NULL_TREE;
-
- /* Recursively add all namespaces used. */
- for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
- push_using_directive (TREE_PURPOSE (iter));
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
ancestor = namespace_ancestor (current_decl_namespace (), used);
ud = current_binding_level->using_directives;
ud = tree_cons (used, ancestor, ud);
current_binding_level->using_directives = ud;
- return ud;
+
+ /* Recursively add all namespaces used. */
+ for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
+ push_using_directive (TREE_PURPOSE (iter));
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ud);
}
/* DECL is a FUNCTION_DECL for a non-member function, which may have
tree new_binding;
int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
+ timevar_push (TV_NAME_LOOKUP);
if (doing_global)
old = namespace_binding (name, DECL_CONTEXT (decl));
else
decl, fn);
if (duplicate_decls (decl, fn))
- return fn;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
}
}
else if (old == error_mark_node)
{
cp_error_at ("previous non-function declaration `%#D'", old);
error ("conflicts with function declaration `%#D'", decl);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
}
{
tree *d;
- for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names;
+ for (d = &BINDING_SCOPE (IDENTIFIER_BINDING (name))->names;
*d;
d = &TREE_CHAIN (*d))
if (*d == old
*d = tree_cons (NULL_TREE, new_binding,
TREE_CHAIN (*d));
- /* And update the CPLUS_BINDING node. */
+ /* And update the cxx_binding node. */
BINDING_VALUE (IDENTIFIER_BINDING (name))
= new_binding;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* We should always find a previous binding in this case. */
push_local_binding (name, new_binding, flags);
}
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
\f
/* Generate an implicit declaration for identifier FUNCTIONID
/* Say where one reference is to the label, for the sake of the
error if it is not defined. */
- DECL_SOURCE_LINE (decl) = lineno;
- DECL_SOURCE_FILE (decl) = input_filename;
+ DECL_SOURCE_LOCATION (decl) = input_location;
/* Record the fact that this identifier is bound to this label. */
SET_IDENTIFIER_LABEL_VALUE (id, decl);
new_ent->label_decl = decl;
new_ent->names_in_scope = current_binding_level->names;
new_ent->binding_level = current_binding_level;
- new_ent->lineno_o_goto = lineno;
- new_ent->filename_o_goto = input_filename;
+ new_ent->o_goto_locus = input_location;
new_ent->next = named_label_uses;
named_label_uses = new_ent;
}
tree decl;
struct named_label_list *ent;
+ timevar_push (TV_NAME_LOOKUP);
/* You can't use labels at global scope. */
if (current_function_decl == NULL_TREE)
{
error ("label `%s' referenced outside of any function",
IDENTIFIER_POINTER (id));
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* See if we've already got this label. */
decl = IDENTIFIER_LABEL_VALUE (id);
if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
/* Now fill in the information we didn't have before. */
ent->label_decl = decl;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Declare a local label named ID. */
static void
check_previous_goto_1 (tree decl,
struct cp_binding_level* level,
- tree names,
- const char* file,
- int line)
+ tree names, const location_t *locus)
{
int identified = 0;
int saw_eh = 0;
else
pedwarn ("jump to case label");
- if (file)
- pedwarn_with_file_and_line (file, line, " from here");
+ if (locus)
+ pedwarn ("%H from here", locus);
identified = 1;
}
else
pedwarn ("jump to case label");
- if (file)
- pedwarn_with_file_and_line (file, line, " from here");
+ if (locus)
+ pedwarn ("%H from here", locus);
identified = 1;
}
if (b->is_try_scope)
check_previous_goto (struct named_label_use_list* use)
{
check_previous_goto_1 (use->label_decl, use->binding_level,
- use->names_in_scope, use->filename_o_goto,
- use->lineno_o_goto);
+ use->names_in_scope, &use->o_goto_locus);
}
static void
check_switch_goto (struct cp_binding_level* level)
{
- check_previous_goto_1 (NULL_TREE, level, level->names, NULL, 0);
+ check_previous_goto_1 (NULL_TREE, level, level->names, NULL);
}
/* Check that any previously seen jumps to a newly defined label DECL
struct named_label_list *ent;
register struct cp_binding_level *p;
+ timevar_push (TV_NAME_LOOKUP);
for (ent = named_labels; ent; ent = ent->next)
if (ent->label_decl == decl)
break;
if (DECL_INITIAL (decl) != NULL_TREE)
{
error ("duplicate label `%D'", decl);
- return 0;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
else
{
ent->binding_level = current_binding_level;
}
check_previous_gotos (decl);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
struct cp_switch
return current_binding_level->names;
}
-/* Return the list of type-tags (for structs, etc) of the current level. */
-
-tree
-gettags (void)
-{
- return current_binding_level->tags;
-}
-
/* Store the list of declarations of the current level.
This is done for the parameter declarations of a function being defined,
after they are modified in the light of any missing parameters. */
current_binding_level->names = decls;
}
-/* Similarly, store the list of tags of the current level. */
-
+/* Set the current binding TABLE for type declarations.. This is a
+ temporary workaround of the fact that the data structure classtypes
+ does not currently carry its allocated cxx_scope structure. */
void
-storetags (tree tags)
+cxx_remember_type_decls (binding_table table)
{
- current_binding_level->tags = tags;
+ current_binding_level->type_decls = table;
}
\f
/* Return the type that should be used when TYPE's name is preceded
/* Given NAME, an IDENTIFIER_NODE,
return the structure (or union or enum) definition for that name.
- Searches binding levels from BINDING_LEVEL up to the global level.
+ Searches binding levels from BINDING_SCOPE up to the global level.
If THISLEVEL_ONLY is nonzero, searches only the specified context
(but skips any tag-transparent contexts to find one that is
meaningful for tags).
reported. */
static tree
-lookup_tag (enum tree_code form,
- tree name,
- struct cp_binding_level* binding_level,
- int thislevel_only)
+lookup_tag (enum tree_code form, tree name,
+ struct cp_binding_level* binding_level, int thislevel_only)
{
register struct cp_binding_level *level;
/* Nonzero if, we should look past a template parameter level, even
if THISLEVEL_ONLY. */
int allow_template_parms_p = 1;
+ bool type_is_anonymous = ANON_AGGRNAME_P (name);
+ timevar_push (TV_NAME_LOOKUP);
for (level = binding_level; level; level = level->level_chain)
{
register tree tail;
- if (ANON_AGGRNAME_P (name))
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- /* There's no need for error checking here, because
- anon names are unique throughout the compilation. */
- if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
- return TREE_VALUE (tail);
- }
+ if (type_is_anonymous && level->type_decls != NULL)
+ {
+ tree type = binding_table_find_anon_type (level->type_decls, name);
+ /* There is no need for error checking here, because
+ anon names are unique throughout the compilation. */
+ if (type != NULL)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
+ }
else if (level->namespace_p)
/* Do namespace lookup. */
for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
{
- tree old = binding_for_name (name, tail);
+ cxx_binding *binding =
+ cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (tail), name);
+ tree old;
/* If we just skipped past a template parameter level,
even though THISLEVEL_ONLY, and we find a template
class declaration, then we use the _TYPE node for the
template. See the example below. */
if (thislevel_only && !allow_template_parms_p
- && old && BINDING_VALUE (old)
- && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
- old = TREE_TYPE (BINDING_VALUE (old));
- else
- old = BINDING_TYPE (old);
+ && binding && BINDING_VALUE (binding)
+ && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
+ old = TREE_TYPE (BINDING_VALUE (binding));
+ else if (binding)
+ old = BINDING_TYPE (binding);
+ else
+ old = NULL_TREE;
if (old)
{
if the typedef doesn't refer to a taggable type. */
old = follow_tag_typedef (old);
if (!old)
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
if (TREE_CODE (old) != form
&& (form == ENUMERAL_TYPE
|| TREE_CODE (old) == ENUMERAL_TYPE))
{
error ("`%#D' redeclared as %C", old, form);
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
- return old;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old);
}
if (thislevel_only || tail == global_namespace)
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
- else
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- if (TREE_PURPOSE (tail) == name)
- {
- enum tree_code code = TREE_CODE (TREE_VALUE (tail));
+ else if (level->type_decls != NULL)
+ {
+ binding_entry entry = binding_table_find (level->type_decls, name);
+ if (entry != NULL)
+ {
+ enum tree_code code = TREE_CODE (entry->type);
- if (code != form
- && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
- {
- /* Definition isn't the kind we were looking for. */
- error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
- return NULL_TREE;
- }
- return TREE_VALUE (tail);
- }
+ if (code != form
+ && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
+ {
+ /* Definition isn't the kind we were looking for. */
+ error ("`%#D' redeclared as %C", entry->type, form);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ }
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->type);
+ }
}
if (thislevel_only && ! level->tag_transparent)
{
continue;
}
else
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* Given a type, find the tag that was defined for it and return the tag name.
{
register struct cp_binding_level *level;
+ timevar_push (TV_NAME_LOOKUP);
for (level = current_binding_level; level; level = level->level_chain)
{
- register tree tail;
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- if (TREE_VALUE (tail) == type)
- {
- if (name)
- TREE_PURPOSE (tail) = name;
- return TREE_PURPOSE (tail);
- }
- }
+ binding_entry entry = level->type_decls == NULL
+ ? NULL
+ : binding_table_reverse_maybe_remap (level->type_decls, type, name);
+ if (entry)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->name);
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
\f
/* Look up NAME in the NAMESPACE. */
{
tree val;
tree template_id = NULL_TREE;
+ cxx_binding binding;
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
if (TREE_CODE (name) == NAMESPACE_DECL)
/* This happens for A::B<int> when B is a namespace. */
- return name;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, name);
else if (TREE_CODE (name) == TEMPLATE_DECL)
{
/* This happens for A::B where B is a template, and there are no
template arguments. */
error ("invalid use of `%D'", name);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
namespace = ORIGINAL_NAMESPACE (namespace);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
- val = make_node (CPLUS_BINDING);
- if (!qualified_lookup_using_namespace (name, namespace, val, 0))
- return error_mark_node;
+ cxx_binding_clear (&binding);
+ if (!qualified_lookup_using_namespace (name, namespace, &binding, 0))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- if (BINDING_VALUE (val))
+ if (binding.value)
{
- val = BINDING_VALUE (val);
+ val = binding.value;
if (template_id)
{
{
error ("`%D::%D' is not a template",
namespace, name);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
}
if (!val || !DECL_P(val)
|| !DECL_LANG_SPECIFIC(val)
|| !DECL_ANTICIPATED (val))
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
error ("`%D' undeclared in namespace `%D'", name, namespace);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
/* Hash a TYPENAME_TYPE. K is really of type `tree'. */
{
tree fullname;
+ if (name == error_mark_node
+ || context == NULL_TREE
+ || context == error_mark_node)
+ return error_mark_node;
+
if (TYPE_P (name))
{
if (!(TYPE_LANG_SPECIFIC (name)
{
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
- tmpl = lookup_field (context, name, 0, 0);
+ tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
}
if (complain & tf_error)
- {
- if (complain & tf_parsing)
- perform_or_defer_access_check (context, tmpl);
- else
- enforce_access (context, tmpl);
- }
+ perform_or_defer_access_check (context, tmpl);
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
return error_mark_node;
}
- t = lookup_field (context, name, 0, 1);
+ t = lookup_field (context, name, 0, true);
if (t)
{
if (TREE_CODE (t) != TYPE_DECL)
}
if (complain & tf_error)
- {
- if (complain & tf_parsing)
- perform_or_defer_access_check (context, t);
- else
- enforce_access (context, t);
- }
+ perform_or_defer_access_check (context, t);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
- tmpl = lookup_field (context, name, 0, 0);
+ tmpl = lookup_field (context, name, 0, false);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
}
if (complain & tf_error)
- {
- if (complain & tf_parsing)
- perform_or_defer_access_check (context, tmpl);
- else
- enforce_access (context, tmpl);
- }
+ perform_or_defer_access_check (context, tmpl);
return tmpl;
}
/* Select the right _DECL from multiple choices. */
static tree
-select_decl (tree binding, int flags)
+select_decl (cxx_binding *binding, int flags)
{
tree val;
val = BINDING_VALUE (binding);
+ timevar_push (TV_NAME_LOOKUP);
if (LOOKUP_NAMESPACES_ONLY (flags))
{
/* We are not interested in types. */
if (val && TREE_CODE (val) == NAMESPACE_DECL)
- return val;
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* If we could have a type and
|| !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
/* Unscoped lookup of a global: iterate over current namespaces,
tree
unqualified_namespace_lookup (tree name, int flags, tree* spacesp)
{
- tree b = make_node (CPLUS_BINDING);
tree initial = current_decl_namespace ();
tree scope = initial;
tree siter;
struct cp_binding_level *level;
tree val = NULL_TREE;
+ cxx_binding binding;
+ timevar_push (TV_NAME_LOOKUP);
+ cxx_binding_clear (&binding);
if (spacesp)
*spacesp = NULL_TREE;
for (; !val; scope = CP_DECL_CONTEXT (scope))
{
+ cxx_binding *b =
+ cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
if (spacesp)
*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
- val = binding_for_name (name, scope);
/* Ignore anticipated built-in functions. */
- if (val && BINDING_VALUE (val)
- && DECL_P (BINDING_VALUE (val))
- && DECL_LANG_SPECIFIC (BINDING_VALUE (val))
- && DECL_ANTICIPATED (BINDING_VALUE (val)))
- {
- BINDING_VALUE (b) = NULL_TREE;
- BINDING_TYPE (b) = NULL_TREE;
- }
- else
+ if (b && BINDING_VALUE (b)
+ && DECL_P (BINDING_VALUE (b))
+ && DECL_LANG_SPECIFIC (BINDING_VALUE (b))
+ && DECL_ANTICIPATED (BINDING_VALUE (b)))
+ /* Keep binding cleared. */;
+ else if (b)
{
/* Initialize binding for this context. */
- BINDING_VALUE (b) = BINDING_VALUE (val);
- BINDING_TYPE (b) = BINDING_TYPE (val);
+ binding.value = BINDING_VALUE (b);
+ binding.type = BINDING_TYPE (b);
}
/* 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,
+ if (!lookup_using_namespace (name, &binding, level->using_directives,
scope, flags, spacesp))
/* Give up because of error. */
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
/* 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),
+ if (!lookup_using_namespace (name, &binding,
+ DECL_NAMESPACE_USING (siter),
scope, flags, spacesp))
/* Give up because of error. */
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
- val = select_decl (b, flags);
+ val = select_decl (&binding, flags);
if (scope == global_namespace)
break;
}
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
/* Combine prefer_type and namespaces_only into flags. */
{
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
- tree val;
+ cxx_binding binding;
- val = make_node (CPLUS_BINDING);
+ cxx_binding_clear (&binding);
flags |= LOOKUP_COMPLAIN;
if (is_type_p)
flags |= LOOKUP_PREFER_TYPES;
- if (!qualified_lookup_using_namespace (name, scope, val, flags))
+ if (!qualified_lookup_using_namespace (name, scope, &binding, flags))
return NULL_TREE;
- return select_decl (val, flags);
+ return select_decl (&binding, flags);
}
else
return lookup_member (scope, name, 0, is_type_p);
using IDENTIFIER_CLASS_VALUE. */
tree
-lookup_name_real (tree name,
- int prefer_type,
- int nonclass,
- int namespaces_only,
- int flags)
+lookup_name_real (tree name, int prefer_type, int nonclass,
+ int namespaces_only, int flags)
{
- tree t;
+ cxx_binding *iter;
tree val = NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
/* Conversion operators are handled specially because ordinary
unqualified name lookup will not find template conversion
operators. */
class_type = level->this_class;
operators = lookup_fnfields (class_type, name, /*protect=*/0);
if (operators)
- return operators;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, operators);
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
flags |= lookup_flags (prefer_type, namespaces_only);
if (current_class_type == NULL_TREE)
nonclass = 1;
- for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
+ for (iter = IDENTIFIER_BINDING (name); iter; iter = iter->previous)
{
tree binding;
- if (!LOCAL_BINDING_P (t) && nonclass)
+ if (!LOCAL_BINDING_P (iter) && nonclass)
/* We're not looking for class-scoped bindings, so keep going. */
continue;
/* If this is the kind of thing we're looking for, we're done. */
- if (qualify_lookup (BINDING_VALUE (t), flags))
- binding = BINDING_VALUE (t);
+ if (qualify_lookup (BINDING_VALUE (iter), flags))
+ binding = BINDING_VALUE (iter);
else if ((flags & LOOKUP_PREFER_TYPES)
- && qualify_lookup (BINDING_TYPE (t), flags))
- binding = BINDING_TYPE (t);
+ && qualify_lookup (BINDING_TYPE (iter), flags))
+ binding = BINDING_TYPE (iter);
else
binding = NULL_TREE;
/* Now lookup in namespace scopes. */
if (!val)
{
- t = unqualified_namespace_lookup (name, flags, 0);
+ tree t = unqualified_namespace_lookup (name, flags, 0);
if (t)
val = t;
}
val = OVL_FUNCTION (val);
}
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
tree
struct cp_binding_level *b;
tree t = NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
b = current_binding_level;
while (b->parm_flag == 2)
b = b->level_chain;
{
while (1)
{
- if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
- return IDENTIFIER_VALUE (name);
+ if (BINDING_SCOPE (IDENTIFIER_BINDING (name)) == b)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* Like lookup_name_current_level, but for types. */
{
register tree t = NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (! current_binding_level->namespace_p, 980716);
if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
while (1)
{
if (purpose_member (name, b->type_shadowed))
- return REAL_IDENTIFIER_TYPE_VALUE (name);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ REAL_IDENTIFIER_TYPE_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
else
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
\f
if (name)
tname = get_identifier (name);
- TYPE_BUILT_IN (type) = 1;
-
if (tname)
{
tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
/* Make the binding_level structure for global names. */
pushlevel (0);
- global_binding_level = current_binding_level;
+ current_binding_level->type_decls = binding_table_new (GLOBAL_SCOPE_HT_SIZE);
/* The global level is the namespace level of ::. */
- NAMESPACE_LEVEL (global_namespace) = global_binding_level;
+ NAMESPACE_LEVEL (global_namespace) = current_binding_level;
declare_namespace_level ();
+ VARRAY_TREE_INIT (current_binding_level->static_decls,
+ 200,
+ "Static declarations");
+
/* Create the `std' namespace. */
push_namespace (std_identifier);
std_node = current_namespace;
cplus_decl_attributes (&decl, attributes, 0);
/* If #pragma weak was used, mark the decl weak now. */
- if (current_binding_level == global_binding_level)
+ if (global_scope_p (current_binding_level))
maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
- warning_with_decl (decl,
- "inline function `%s' given attribute noinline");
+ warning ("%Hinline function '%D' given attribute noinline",
+ &DECL_SOURCE_LOCATION (decl), decl);
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
if (TREE_CODE (decl) == VAR_DECL)
{
- tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
+ tree field = lookup_field (context, DECL_NAME (decl), 0, false);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
error ("`%#D' is not a static member of `%#T'", decl, context);
else
DECL_INITIAL for local references (instead assigning to them
explicitly); we need to allow the temporary to be initialized
first. */
- tmp = convert_to_reference
- (type, init, CONV_IMPLICIT,
- LOOKUP_ONLYCONVERTING|LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND,
- decl);
+ tmp = initialize_reference (type, init, decl);
if (tmp == error_mark_node)
return NULL_TREE;
if (TREE_STATIC (decl)
/* Don't mess with __FUNCTION__. */
&& ! DECL_ARTIFICIAL (decl)
- && current_function_decl
- && DECL_CONTEXT (decl) == current_function_decl
- && (DECL_DECLARED_INLINE_P (current_function_decl)
- || DECL_TEMPLATE_INSTANTIATION (current_function_decl))
- && TREE_PUBLIC (current_function_decl))
- {
- /* If flag_weak, we don't need to mess with this, as we can just
- make the function weak, and let it refer to its unique local
- copy. This works because we don't allow the function to be
- inlined. */
- if (! flag_weak)
- {
- if (DECL_INTERFACE_KNOWN (current_function_decl))
- {
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
- }
- else if (DECL_INITIAL (decl) == NULL_TREE
- || DECL_INITIAL (decl) == error_mark_node)
+ && DECL_FUNCTION_SCOPE_P (decl)
+ /* Unfortunately, import_export_decl has not always been called
+ before the function is processed, so we cannot simply check
+ DECL_COMDAT. */
+ && (DECL_COMDAT (DECL_CONTEXT (decl))
+ || ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
+ || DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
+ && TREE_PUBLIC (DECL_CONTEXT (decl)))))
+ {
+ if (flag_weak)
+ {
+ /* With weak symbols, we simply make the variable COMDAT;
+ that will cause copies in multiple translations units to
+ be merged. */
+ comdat_linkage (decl);
+ }
+ else
+ {
+ if (DECL_INITIAL (decl) == NULL_TREE
+ || DECL_INITIAL (decl) == error_mark_node)
{
+ /* Without weak symbols, we can use COMMON to merge
+ uninitialized variables. */
TREE_PUBLIC (decl) = 1;
DECL_COMMON (decl) = 1;
}
- /* else we lose. We can only do this if we can use common,
- which we can't if it has been initialized. */
-
- if (!TREE_PUBLIC (decl))
+ else
{
+ /* While for initialized variables, we must use internal
+ linkage -- which means that multiple copies will not
+ be merged. */
+ TREE_PUBLIC (decl) = 0;
+ DECL_COMMON (decl) = 0;
cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
cp_warning_at (" you can work around this by removing the initializer", decl);
}
}
- else
- comdat_linkage (decl);
}
else if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
/* Set it up again; we might have set DECL_INITIAL since the last
else
{
/* Build a CONSTRUCTOR to hold the contents of the aggregate. */
- new_init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ new_init = build_constructor (type, NULL_TREE);
TREE_HAS_CONSTRUCTOR (new_init) = 1;
if (CLASS_TYPE_P (type))
{
/* Loop through the initializable fields, gathering
initializers. */
- while (*initp && field)
+ while (*initp)
{
tree field_init;
+ /* Handle designated initializers, as an extension. */
+ if (TREE_PURPOSE (*initp))
+ {
+ if (pedantic)
+ pedwarn ("ISO C++ does not allow designated initializers");
+ field = lookup_field_1 (type, TREE_PURPOSE (*initp),
+ /*want_type=*/false);
+ if (!field || TREE_CODE (field) != FIELD_DECL)
+ error ("`%T' has no non-static data member named `%D'",
+ type, TREE_PURPOSE (*initp));
+ }
+ if (!field)
+ break;
+
field_init = reshape_init (TREE_TYPE (field), initp);
TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
CONSTRUCTOR_ELTS (new_init) = field_init;
initializer for the first member of the union. */
if (TREE_CODE (type) == UNION_TYPE)
break;
- if (TREE_PURPOSE (field_init))
- field = TREE_PURPOSE (field_init);
field = next_initializable_field (TREE_CHAIN (field));
}
}
scalar, so just don't call it. */
if (CP_AGGREGATE_TYPE_P (type))
init = reshape_init (type, &init);
+
+ if ((*targetm.vector_opaque_p) (type))
+ {
+ error ("opaque vector types cannot be initialized");
+ init = error_mark_node;
+ }
}
/* If DECL has an array type without a specific bound, deduce the
void
maybe_inject_for_scope_var (tree decl)
{
+ timevar_push (TV_NAME_LOOKUP);
if (!DECL_NAME (decl))
- return;
+ {
+ timevar_pop (TV_NAME_LOOKUP);
+ return;
+ }
/* Declarations of __FUNCTION__ and its ilk appear magically when
the variable is first used. If that happens to be inside a
for-loop, we don't want to do anything special. */
if (DECL_PRETTY_FUNCTION_P (decl))
- return;
+ {
+ timevar_pop (TV_NAME_LOOKUP);
+ return;
+ }
if (current_binding_level->is_for_scope)
{
Otherwise, we need to preserve the temp slot for decl to last
into the outer binding level. */
- tree outer_binding
- = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+ cxx_binding *outer_binding
+ = IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
- if (outer_binding && BINDING_LEVEL (outer_binding) == outer
- && (TREE_CODE (BINDING_VALUE (outer_binding))
- == VAR_DECL)
+ if (outer_binding && BINDING_SCOPE (outer_binding) == outer
+ && (TREE_CODE (BINDING_VALUE (outer_binding)) == VAR_DECL)
&& DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
{
BINDING_VALUE (outer_binding)
current_binding_level->is_for_scope = 0;
}
}
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Generate code to initialize DECL (a local variable). */
}
/* If a name was specified, get the string. */
- if (current_binding_level == global_binding_level)
+ if (global_scope_p (current_binding_level))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
necessary zero-initialization has already been performed. */
if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
+ /*nelts=*/NULL_TREE,
/*static_storage_p=*/true);
/* Remember that the initialization for this variable has
taken place. */
tree compound_stmt;
tree args;
tree fcall;
- int saved_flag_access_control;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
to the original function, rather than the anonymous one. That
will make the back-end think that nested functions are in use,
which causes confusion. */
- saved_flag_access_control = flag_access_control;
- scope_chain->check_access = flag_access_control = 0;
+
+ push_deferring_access_checks (dk_no_check);
fcall = build_cleanup (decl);
- scope_chain->check_access = flag_access_control = saved_flag_access_control;
+ pop_deferring_access_checks ();
/* Create the body of the anonymous function. */
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
or enumeration declared in a local scope) shall not be used to
declare an entity with linkage.
- Only check this for public decls for now. */
+ Only check this for public decls for now. See core 319, 389. */
t = no_linkage_check (TREE_TYPE (decl));
if (t)
{
DECL_NOT_REALLY_EXTERN (decl) = 1;
}
+ DID_INLINE_FUNC (decl) = 0;
/* If the declaration was declared inline, mark it as such. */
if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1;
/* We inline functions that are explicitly declared inline, or, when
the user explicitly asks us to, all functions. */
- if (DECL_DECLARED_INLINE_P (decl) || flag_inline_trees == 2)
+ if (DECL_DECLARED_INLINE_P (decl))
DECL_INLINE (decl) = 1;
+ if (flag_inline_trees == 2 && !DECL_INLINE (decl))
+ {
+ DID_INLINE_FUNC (decl) = 1;
+ DECL_INLINE (decl) = 1;
+ }
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
if (old_decl)
{
+ bool ok;
+
/* Since we've smashed OLD_DECL to its
DECL_TEMPLATE_RESULT, we must do the same to DECL. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
/* Attempt to merge the declarations. This can fail, in
the case of some invalid specialization declarations. */
push_scope (ctype);
- if (!duplicate_decls (decl, old_decl))
- error ("no `%#D' member function declared in class `%T'",
- decl, ctype);
+ ok = duplicate_decls (decl, old_decl);
pop_scope (ctype);
+ if (!ok)
+ {
+ error ("no `%#D' member function declared in class `%T'",
+ decl, ctype);
+ return NULL_TREE;
+ }
return old_decl;
}
}
&& TREE_OPERAND (size, 0) == current_class_type)
{
tree t = lookup_field (current_class_type,
- TREE_OPERAND (size, 1), 0, 0);
+ TREE_OPERAND (size, 1), 0, false);
if (t)
size = t;
}
type = error_mark_node;
}
- if (decl_context == FIELD
+ if ((decl_context == FIELD || decl_context == PARM)
&& !processing_template_decl
&& variably_modified_type_p (type))
{
- error ("data member may not have variably modified type `%T'", type);
+ if (decl_context == FIELD)
+ error ("data member may not have variably modified type `%T'", type);
+ else
+ error ("parameter may not have variably modified type `%T'", type);
type = error_mark_node;
}
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
- if (current_class_name == NULL_TREE || decl_context == PARM || friendp)
+ if (decl_context != FIELD || friendp)
{
error ("non-member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
return void_type_node;
}
- /* 9.2p13 [class.mem] */
- if (constructor_name_p (declarator, current_class_type)
- /* The standard does not allow non-static data members
- here either, but we agreed at the 10/99 meeting
- to change that in TC 1 so that they are allowed in
- classes with no user-defined constructors. */
- && staticp)
- pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
- declarator);
-
if (staticp)
{
+ /* [class.mem] forbids static data members with the
+ same name as the enclosing class. Non-static data
+ members are checked in check_field_decls. */
+ if (constructor_name_p (declarator, current_class_type))
+ pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
+ declarator);
+
/* C++ allows static class members. All other work
for this is done by grokfield. */
decl = build_lang_decl (VAR_DECL, declarator, type);
}
}
+/* Name lookup in an elaborated-type-specifier (after the keyword
+ indicated by TAG_CODE) has found TYPE. If the
+ elaborated-type-specifier is invalid, issue a diagnostic and return
+ error_mark_node; otherwise, return TYPE itself. */
+
+static tree
+check_elaborated_type_specifier (enum tag_types tag_code,
+ tree type)
+{
+ tree t;
+
+ t = follow_tag_typedef (type);
+
+ /* [dcl.type.elab] If the identifier resolves to a typedef-name or a
+ template type-parameter, the elaborated-type-specifier is
+ ill-formed. */
+ if (!t)
+ {
+ error ("using typedef-name `%D' after `%s'",
+ TYPE_NAME (type), tag_name (tag_code));
+ t = error_mark_node;
+ }
+ else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ {
+ error ("using template type parameter `%T' after `%s'",
+ type, tag_name (tag_code));
+ t = error_mark_node;
+ }
+
+ return t;
+}
+
/* Get the struct, enum or union (CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
struct cp_binding_level *b = current_binding_level;
tree context = NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
switch (tag_code)
{
case record_type:
{
if (t)
{
- ref = follow_tag_typedef (t);
-
- /* [dcl.type.elab] If the identifier resolves to a
- typedef-name or a template type-parameter, the
- elaborated-type-specifier is ill-formed. */
- if (!ref)
- {
- pedwarn ("using typedef-name `%D' after `%s'",
- TYPE_NAME (t), tag_name (tag_code));
- ref = t;
- }
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- error ("using template type parameter `%T' after `%s'",
- t, tag_name (tag_code));
+ ref = check_elaborated_type_specifier (tag_code, t);
+ if (ref == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
ref = lookup_tag (code, name, b, 0);
template, so we want this type. */
ref = DECL_TEMPLATE_RESULT (ref);
- if (ref && TREE_CODE (ref) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (ref)) == code)
- ref = TREE_TYPE (ref);
+ if (ref && TREE_CODE (ref) == TYPE_DECL)
+ {
+ ref = check_elaborated_type_specifier (tag_code,
+ TREE_TYPE (ref));
+ if (ref == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ if (ref && TREE_CODE (ref) != code)
+ ref = NULL_TREE;
+ }
else
ref = NULL_TREE;
}
TYPE_ATTRIBUTES (ref) = attributes;
- return ref;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ref);
}
tree
}
/* REF is a type (named NAME), for which we have just seen some
- baseclasses. BINFO is a list of those baseclasses; the
+ baseclasses. BASE_LIST is a list of those baseclasses; the
TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
- the base-class. CODE_TYPE_NODE indicates whether REF is a class,
+ the base-class. TREE_VIA_VIRTUAL indicates virtual
+ inheritance. CODE_TYPE_NODE indicates whether REF is a class,
struct, or union. */
void
-xref_basetypes (tree ref, tree binfo)
+xref_basetypes (tree ref, tree base_list)
{
/* In the declaration `A : X, Y, ... Z' we mark all the types
(A, X, Y, ..., Z) so we can check for duplicates. */
- tree binfos;
tree *basep;
int i;
instantiated. This ensures that if we call ourselves recursively
we do not get confused about which classes are marked and which
are not. */
- basep = &binfo;
+ basep = &base_list;
while (*basep)
{
tree basetype = TREE_VALUE (*basep);
if (!(processing_template_decl && uses_template_parms (basetype))
&& !complete_type_or_else (basetype, NULL))
- /* An incomplete type. Remove it form the list. */
+ /* An incomplete type. Remove it from the list. */
*basep = TREE_CHAIN (*basep);
else
basep = &TREE_CHAIN (*basep);
}
SET_CLASSTYPE_MARKED (ref);
- BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos
- = make_tree_vec (list_length (binfo));
-
- for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
- {
- /* The base of a derived struct is public by default. */
- int via_public
- = (TREE_PURPOSE (binfo) == access_public_node
- || TREE_PURPOSE (binfo) == access_public_virtual_node
- || (tag_code != class_type
- && (TREE_PURPOSE (binfo) == access_default_node
- || TREE_PURPOSE (binfo) == access_default_virtual_node)));
- int via_protected
- = (TREE_PURPOSE (binfo) == access_protected_node
- || TREE_PURPOSE (binfo) == access_protected_virtual_node);
- int via_virtual
- = (TREE_PURPOSE (binfo) == access_private_virtual_node
- || TREE_PURPOSE (binfo) == access_protected_virtual_node
- || TREE_PURPOSE (binfo) == access_public_virtual_node
- || TREE_PURPOSE (binfo) == access_default_virtual_node);
- tree basetype = TREE_VALUE (binfo);
- tree base_binfo;
-
- if (basetype && TREE_CODE (basetype) == TYPE_DECL)
- basetype = TREE_TYPE (basetype);
- if (!basetype
- || (TREE_CODE (basetype) != RECORD_TYPE
- && TREE_CODE (basetype) != TYPENAME_TYPE
- && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
- && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
- {
- error ("base type `%T' fails to be a struct or class type",
- TREE_VALUE (binfo));
- continue;
- }
-
- if (CLASSTYPE_MARKED (basetype))
+ i = list_length (base_list);
+ if (i)
+ {
+ tree binfo = TYPE_BINFO (ref);
+ tree binfos = make_tree_vec (i);
+ tree accesses = make_tree_vec (i);
+
+ BINFO_BASETYPES (binfo) = binfos;
+ BINFO_BASEACCESSES (binfo) = accesses;
+
+ for (i = 0; base_list; base_list = TREE_CHAIN (base_list))
{
- if (basetype == ref)
- error ("recursive type `%T' undefined", basetype);
+ tree access = TREE_PURPOSE (base_list);
+ int via_virtual = TREE_VIA_VIRTUAL (base_list);
+ tree basetype = TREE_VALUE (base_list);
+ tree base_binfo;
+
+ if (access == access_default_node)
+ /* The base of a derived struct is public by default. */
+ access = (tag_code == class_type
+ ? access_private_node : access_public_node);
+
+ if (basetype && TREE_CODE (basetype) == TYPE_DECL)
+ basetype = TREE_TYPE (basetype);
+ if (!basetype
+ || (TREE_CODE (basetype) != RECORD_TYPE
+ && TREE_CODE (basetype) != TYPENAME_TYPE
+ && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
+ {
+ error ("base type `%T' fails to be a struct or class type",
+ basetype);
+ continue;
+ }
+
+ if (CLASSTYPE_MARKED (basetype))
+ {
+ if (basetype == ref)
+ error ("recursive type `%T' undefined", basetype);
+ else
+ error ("duplicate base type `%T' invalid", basetype);
+ continue;
+ }
+
+ if (TYPE_FOR_JAVA (basetype)
+ && (current_lang_depth () == 0))
+ TYPE_FOR_JAVA (ref) = 1;
+
+ if (CLASS_TYPE_P (basetype))
+ {
+ base_binfo = TYPE_BINFO (basetype);
+ /* This flag will be in the binfo of the base type, we must
+ clear it after copying the base binfos. */
+ BINFO_DEPENDENT_BASE_P (base_binfo)
+ = dependent_type_p (basetype);
+ }
else
- error ("duplicate base type `%T' invalid", basetype);
- continue;
+ base_binfo = make_binfo (size_zero_node, basetype,
+ NULL_TREE, NULL_TREE);
+
+ TREE_VEC_ELT (binfos, i) = base_binfo;
+ TREE_VEC_ELT (accesses, i) = access;
+ /* This flag will be in the binfo of the base type, we must
+ clear it after copying the base binfos. */
+ TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
+
+ SET_CLASSTYPE_MARKED (basetype);
+
+ /* We are free to modify these bits because they are meaningless
+ at top level, and BASETYPE is a top-level type. */
+ if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+ {
+ TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
+ /* Converting to a virtual base class requires looking
+ up the offset of the virtual base. */
+ TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
+ }
+
+ if (CLASS_TYPE_P (basetype))
+ {
+ TYPE_HAS_NEW_OPERATOR (ref)
+ |= TYPE_HAS_NEW_OPERATOR (basetype);
+ TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
+ |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
+ TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+ /* If the base-class uses multiple inheritance, so do we. */
+ TYPE_USES_MULTIPLE_INHERITANCE (ref)
+ |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
+ /* Likewise, if converting to a base of the base may require
+ code, then we may need to generate code to convert to a
+ base as well. */
+ TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
+ |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
+ }
+ i++;
}
-
- if (TYPE_FOR_JAVA (basetype)
- && (current_lang_depth () == 0))
- 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
- inherited with different `accessibility' by different
- derived classes. (Each BINFO record describing an
- individual inheritance contains flags which say what
- the `accessibility' of that particular inheritance is.) */
-
- base_binfo
- = make_binfo (size_zero_node, basetype,
- CLASS_TYPE_P (basetype)
- ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
- CLASS_TYPE_P (basetype)
- ? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE);
-
- TREE_VEC_ELT (binfos, i) = base_binfo;
- TREE_VIA_PUBLIC (base_binfo) = via_public;
- TREE_VIA_PROTECTED (base_binfo) = via_protected;
- TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
- BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
-
- /* We need to unshare the binfos now so that lookups during class
- definition work. */
- unshare_base_binfos (base_binfo);
-
- SET_CLASSTYPE_MARKED (basetype);
-
- /* We are free to modify these bits because they are meaningless
- at top level, and BASETYPE is a top-level type. */
- if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
- /* Converting to a virtual base class requires looking
- up the offset of the virtual base. */
+ if (i)
+ TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;
+ else
+ BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE;
+
+ if (i > 1)
+ {
+ TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
+ /* If there is more than one non-empty they cannot be at the same
+ address. */
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
}
-
+ }
+
+ /* Copy the base binfos, collect the virtual bases and set the
+ inheritance order chain. */
+ copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
+ CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));
+
+ /* Unmark all the types. */
+ while (i--)
+ {
+ tree basetype = BINFO_TYPE (BINFO_BASETYPE (TYPE_BINFO (ref), i));
+
+ CLEAR_CLASSTYPE_MARKED (basetype);
if (CLASS_TYPE_P (basetype))
{
- TYPE_HAS_NEW_OPERATOR (ref)
- |= TYPE_HAS_NEW_OPERATOR (basetype);
- TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
- |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
- TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
- /* If the base-class uses multiple inheritance, so do we. */
- TYPE_USES_MULTIPLE_INHERITANCE (ref)
- |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
- /* Likewise, if converting to a base of the base may require
- code, then we may need to generate code to convert to a
- base as well. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
- |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
+ TREE_VIA_VIRTUAL (TYPE_BINFO (basetype)) = 0;
+ BINFO_DEPENDENT_BASE_P (TYPE_BINFO (basetype)) = 0;
}
-
- i += 1;
}
- if (i)
- TREE_VEC_LENGTH (binfos) = i;
- else
- BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
-
- if (i > 1)
- {
- TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
- /* If there is more than one non-empty they cannot be at the same
- address. */
- TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
- }
-
- /* Unmark all the types. */
- while (--i >= 0)
- CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
CLEAR_CLASSTYPE_MARKED (ref);
-
- /* Now that we know all the base-classes, set up the list of virtual
- bases. */
- get_vbase_types (ref);
}
\f
/* We built up the VALUES in reverse order. */
TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
- /* [dcl.enum]
-
- Following the closing brace of an enum-specifier, each
- enumerator has the type of its enumeration. Prior to the
- closing brace, the type of each enumerator is the type of
- its initializing value. */
- for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
- TREE_TYPE (TREE_VALUE (pair)) = enumtype;
-
- /* For an enum defined in a template, all further processing is
- postponed until the template is instantiated. */
+ /* For an enum defined in a template, just set the type of the values;
+ all further processing is postponed until the template is
+ instantiated. We need to set the type so that tsubst of a CONST_DECL
+ works. */
if (processing_template_decl)
{
+ for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
+ TREE_TYPE (TREE_VALUE (pair)) = enumtype;
if (at_function_scope_p ())
add_stmt (build_min (TAG_DEFN, enumtype));
return;
}
- /* Figure out what the minimum and maximum values of the enumerators
- are. */
if (TYPE_VALUES (enumtype))
{
minnode = maxnode = NULL_TREE;
- for (pair = TYPE_VALUES (enumtype);
- pair;
- pair = TREE_CHAIN (pair))
+ for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
{
- tree value;
+ tree decl = TREE_VALUE (pair);
+ tree value = DECL_INITIAL (decl);
- value = DECL_INITIAL (TREE_VALUE (pair));
+ /* [dcl.enum]: Following the closing brace of an enum-specifier,
+ each enumerator has the type of its enumeration. Prior to the
+ closing brace, the type of each enumerator is the type of its
+ initializing value. */
+ TREE_TYPE (decl) = enumtype;
+ /* Figure out what the minimum and maximum values of the
+ enumerators are. */
if (!minnode)
minnode = maxnode = value;
else if (tree_int_cst_lt (maxnode, value))
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
+
+ /* Set the TREE_TYPE for the values as well. That's so that when
+ we call decl_constant_value we get an entity of the right type
+ (but with the constant value). But first make a copy so we
+ don't clobber shared INTEGER_CSTs. */
+ if (TREE_TYPE (value) != enumtype)
+ {
+ value = DECL_INITIAL (decl) = copy_node (value);
+ TREE_TYPE (value) = enumtype;
+ }
+
+ /* In addition, transform the TYPE_VALUES list to contain the
+ values, rather than the CONST_DECLs for them. */
+ TREE_VALUE (pair) = value;
}
}
else
highprec = min_precision (maxnode, unsignedp);
precision = MAX (lowprec, highprec);
- /* Set the TREE_TYPE for the values as well. That's so that when we
- call decl_constant_value we get an entity of the right type (but
- with the constant value). In addition, transform the TYPE_VALUES
- list to contain the values, rather than the CONST_DECLs for them. */
- for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
- {
- tree value = DECL_INITIAL (TREE_VALUE (pair));
-
- TREE_TYPE (value) = enumtype;
- TREE_VALUE (pair) = value;
- }
-
/* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
TYPE_SIZE (enumtype) = NULL_TREE;
TYPE_PRECISION (enumtype) = precision;
tree decl;
tree context;
tree type;
- tree values;
/* Remove no-op casts from the value. */
if (value)
}
/* Default based on previous value. */
- if (value == NULL_TREE && ! processing_template_decl)
+ if (value == NULL_TREE)
{
tree prev_value;
}
/* Remove no-op casts from the value. */
- if (value)
- STRIP_TYPE_NOPS (value);
-#if 0
- /* To fix MAX_VAL enum consts. (bkoz) */
- TREE_TYPE (value) = integer_type_node;
-#endif
+ STRIP_TYPE_NOPS (value);
}
- /* We always have to copy here; not all INTEGER_CSTs are unshared.
- Even in other cases, we will later (in finish_enum) be setting
- the type of VALUE. But, we don't need to make a copy if this
- VALUE is one of the enumeration constants for this same
- enumeration type. */
- for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
- if (TREE_VALUE (values) == value)
- break;
- /* If we didn't break out of the loop, then we do need a copy. */
- if (!values && value)
- value = copy_node (value);
-
/* C++ associates enums with global, function, or class declarations. */
context = current_scope ();
decl = build_decl (CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
+ TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;
- TREE_READONLY (decl) = 1;
if (context && context == current_class_type)
/* In something like `struct S { enum E { i = 7 }; };' we put `i'
cplus_decl_attributes (&decl1, attrs, 0);
/* If #pragma weak was used, mark the decl weak now. */
- if (current_binding_level == global_binding_level)
+ if (global_scope_p (current_binding_level))
maybe_apply_pragma_weak (decl1);
fntype = TREE_TYPE (decl1);
ctype = TYPE_METHOD_BASETYPE (fntype);
else if (DECL_MAIN_P (decl1))
{
- /* If this doesn't return integer_type, complain. */
- if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
+ /* If this doesn't return integer_type, or a typedef to
+ integer_type, complain. */
+ if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
{
if (pedantic || warn_return_type)
pedwarn ("return type for `main' changed to `int'");
if (DECL_DECLARED_INLINE_P (decl1)
&& lookup_attribute ("noinline", attrs))
- warning_with_decl (decl1,
- "inline function `%s' given attribute noinline");
+ warning ("%Hinline function '%D' given attribute noinline",
+ &DECL_SOURCE_LOCATION (decl1), decl1);
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
/* This is a constructor, we must ensure that any default args
CFUN set up, and our per-function variables initialized.
FIXME factor out the non-RTL stuff. */
bl = current_binding_level;
- init_function_start (decl1, input_filename, lineno);
+ init_function_start (decl1, input_filename, input_line);
current_binding_level = bl;
/* Even though we're inside a function body, we still don't want to
/* Start the statement-tree, start the tree now. */
begin_stmt_tree (&DECL_SAVED_TREE (decl1));
+ /* Don't double-count statements in templates. */
+ DECL_NUM_STMTS (decl1) = 0;
+
/* Let the user know we're compiling this function. */
announce_function (decl1);
function. This is all and only the PARM_DECLs that were
pushed into scope by the loop above. */
DECL_ARGUMENTS (fndecl) = getdecls ();
- storetags (gettags ());
}
else
DECL_ARGUMENTS (fndecl) = NULL_TREE;
/* If we're saving up tree structure, tie off the function now. */
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ /* If this function can't throw any exceptions, remember that. */
+ if (!processing_template_decl
+ && !cp_function_chain->can_throw
+ && !flag_non_call_exceptions)
+ TREE_NOTHROW (fndecl) = 1;
+
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
this function's blocks. */
if (current_function_return_value)
{
tree r = current_function_return_value;
- /* This is only worth doing for fns that return in memory--and
- simpler, since we don't have to worry about promoted modes. */
+ tree outer;
+
if (r != error_mark_node
- && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
+ /* This is only worth doing for fns that return in memory--and
+ simpler, since we don't have to worry about promoted modes. */
+ && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)))
+ /* Only allow this for variables declared in the outer scope of
+ the function so we know that their lifetime always ends with a
+ return; see g++.dg/opt/nrv6.C. We could be more flexible if
+ we were to do this optimization in tree-ssa. */
+ /* Skip the artificial function body block. */
+ && (outer = BLOCK_SUBBLOCKS (BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))),
+ chain_member (r, BLOCK_VARS (outer))))
{
+
DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
nullify_returns_r, r);
DECL_DECLARED_INLINE_P (fndecl) = 1;
+ DID_INLINE_FUNC (fndecl) = 0;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
{
case DEFAULT_ARG: return TS_CP_DEFAULT_ARG;
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
- case CPLUS_BINDING: return TS_CP_BINDING;
case OVERLOAD: return TS_CP_OVERLOAD;
case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
case PTRMEM_CST: return TS_CP_PTRMEM;
case BASELINK: return TS_CP_BASELINK;
case WRAPPER: return TS_CP_WRAPPER;
- case SRCLOC: return TS_CP_SRCLOC;
default: return TS_CP_GENERIC;
}
}