static int add_binding (tree, tree);
static void pop_binding (tree, tree);
static tree local_variable_p_walkfn (tree *, int *, void *);
-static cxx_binding *find_binding (tree, tree, cxx_binding *);
static tree select_decl (cxx_binding *, int);
static int lookup_flags (int, int);
static tree qualify_lookup (tree, 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 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) ((NODE)->scope.level)
-
-/* A free list of cxx_binding nodes, connected by their
- TREE_CHAINs. */
-
-static GTY((deletable (""))) cxx_binding *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)
{
- cxx_binding *binding;
-
- if (free_bindings)
- {
- binding = free_bindings;
- free_bindings = binding->previous;
- }
- else
- binding = cxx_binding_make ();
+ cxx_binding *binding = cxx_binding_make (decl, NULL);
/* Now, fill in the binding information. */
binding->previous = IDENTIFIER_BINDING (id);
- BINDING_VALUE (binding) = decl;
- BINDING_TYPE (binding) = NULL_TREE;
- BINDING_LEVEL (binding) = level;
+ 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. */
IDENTIFIER_BINDING (id) = binding;
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
IDENTIFIER_BINDING (id) = binding->previous;
/* Add it to the free list. */
- binding->previous = 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;
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,
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)
dead_vars_from_for);
/* Although we don't pop the cxx_binding, we do clear
- its BINDING_LEVEL since the level is going away now. */
- BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
- = 0;
+ its BINDING_SCOPE since the level is going away now. */
+ BINDING_SCOPE (IDENTIFIER_BINDING (DECL_NAME (link))) = 0;
}
}
else
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);
cxx_binding *binding;
binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
- while (binding && BINDING_LEVEL (binding) != b)
+ while (binding && BINDING_SCOPE (binding) != b)
binding = binding->previous;
if (binding)
/* 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);
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 "cxx_binding"s. */
-/* 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 inline cxx_binding *
-find_binding (tree name, tree scope, cxx_binding *front)
-{
- cxx_binding *iter;
- cxx_binding *prev = NULL;
-
- timevar_push (TV_NAME_LOOKUP);
- scope = ORIGINAL_NAMESPACE (scope);
-
- for (iter = front; iter != NULL; iter = iter->previous)
- {
- if (BINDING_SCOPE (iter) == scope)
- {
- /* Move binding found to the front of the list, so
- subsequent lookups will find it faster. */
- if (prev)
- {
- prev->previous = iter->previous;
- iter->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
- IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
- }
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, iter);
- }
- prev = iter;
- }
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL);
-}
-
-/* Return the binding for NAME in SCOPE, if any. Otherwise, return NULL. */
-cxx_binding *
-cxx_scope_find_binding_for_name (tree scope, tree name)
-{
- cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- if (b)
- {
- scope = ORIGINAL_NAMESPACE (scope);
- /* Fold-in case where NAME is used only once. */
- if (scope == BINDING_SCOPE (b) && b->previous == NULL)
- return b;
- return find_binding (name, scope, b);
- }
- return b;
-}
-
-/* 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. */
-
-cxx_binding *
-binding_for_name (tree name, tree scope)
-{
- cxx_binding *result;
-
- scope = ORIGINAL_NAMESPACE (scope);
- result = cxx_scope_find_binding_for_name (scope, name);
- if (result)
- return result;
- /* Not found, make a new one. */
- result = cxx_binding_make ();
- result->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
- BINDING_TYPE (result) = NULL_TREE;
- BINDING_VALUE (result) = NULL_TREE;
- BINDING_SCOPE (result) = scope;
- result->is_local = false;
- result->value_is_inherited = false;
- result->has_level = false;
- IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
- return result;
-}
-
-/* Return the binding value for name in scope. */
-
-tree
-namespace_binding (tree name, tree scope)
-{
- cxx_binding *b =
- cxx_scope_find_binding_for_name (scope ? scope : global_namespace, name);
-
- return b ? b->value : NULL_TREE;
-}
-
-/* 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)
-{
- cxx_binding *b;
-
- timevar_push (TV_NAME_LOOKUP);
- if (scope == NULL_TREE)
- scope = global_namespace;
- b = binding_for_name (name, scope);
- BINDING_VALUE (b) = val;
- timevar_pop (TV_NAME_LOOKUP);
-}
-
/* 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. */
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");
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;
}
else
{
- cxx_binding *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;
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;
}
}
}
DECL_DISCRIMINATOR (decl) = 1;
VARRAY_TREE (local_names, i) = decl;
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+ timevar_pop (TV_NAME_LOOKUP);
+ return;
}
}
|| 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;
}
}
}
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
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
/* Even if the types match, prefer the new declarations type
- for anitipated built-ins, for exception lists, etc... */
+ for anticipated built-ins, for exception lists, etc... */
else if (DECL_ANTICIPATED (olddecl))
TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
&& 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);
}
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;
}
}
if (warn_shadow && !err)
- shadow_warning (SW_PARAM, false,
+ shadow_warning (SW_PARAM,
IDENTIFIER_POINTER (name), oldlocal);
}
IDENTIFIER_POINTER (name));
else if (oldlocal != NULL_TREE
&& TREE_CODE (oldlocal) == VAR_DECL)
- shadow_warning (SW_LOCAL, false,
+ 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 (SW_GLOBAL, false,
+ shadow_warning (SW_GLOBAL,
IDENTIFIER_POINTER (name), oldglobal);
}
}
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))
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)
/* The class_binding_level will be NULL if x is a template
parameter name in a member template. */
if (!class_binding_level)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+ {
+ 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;
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+ timevar_pop (TV_NAME_LOOKUP);
+ return;
}
}
{
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
/* 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;
}
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
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).
/* 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)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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))
{
cxx_binding *binding =
- cxx_scope_find_binding_for_name (tail, name);
+ cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (tail), name);
tree old;
/* If we just skipped past a template parameter level,
if (thislevel_only || tail == global_namespace)
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);
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
- }
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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)
{
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;
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_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)
}
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),
}
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);
}
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;
}
for (; !val; scope = CP_DECL_CONTEXT (scope))
{
- cxx_binding *b = cxx_scope_find_binding_for_name (scope, name);
+ cxx_binding *b =
+ cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
if (spacesp)
*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
{
while (1)
{
- if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
+ if (BINDING_SCOPE (IDENTIFIER_BINDING (name)) == b)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
if (b->keep == 2)
/* 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 (global_binding_level->static_decls,
+ VARRAY_TREE_INIT (current_binding_level->static_decls,
200,
"Static declarations");
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
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. */
- /* FIXME support non-trivial labeled 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;
{
timevar_push (TV_NAME_LOOKUP);
if (!DECL_NAME (decl))
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+ {
+ 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))
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+ {
+ timevar_pop (TV_NAME_LOOKUP);
+ return;
+ }
if (current_binding_level->is_for_scope)
{
cxx_binding *outer_binding
= IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
- if (outer_binding && BINDING_LEVEL (outer_binding) == outer
+ if (outer_binding && BINDING_SCOPE (outer_binding) == outer
&& (TREE_CODE (BINDING_VALUE (outer_binding)) == VAR_DECL)
&& DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
{
}
/* 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);
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)
{
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;
}
}
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.
{
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;
}
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'");
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
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. */
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;
}
}