extern tree global_namespace;
extern void (*print_error_function) PROTO((char *));
+extern int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree));
-/* Stack of places to restore the search obstack back to. */
-
/* Obstack used for remembering local class declarations (like
enums and static (const) members. */
#include "stack.h"
static tree grokparms PROTO((tree, int));
static tree lookup_nested_type PROTO((tree, tree));
-static char *redeclaration_error_message PROTO((tree, tree));
+static const char *redeclaration_error_message PROTO((tree, tree));
static struct stack_level *push_decl_level PROTO((struct stack_level *,
struct obstack *));
static void declare_namespace_level PROTO((void));
static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
static void storedecls PROTO((tree));
-static void storetags PROTO((tree));
static void require_complete_types_for_parms PROTO((tree));
static void push_overloaded_decl_1 PROTO((tree));
static int ambi_op_p PROTO((tree));
static void grok_reference_init PROTO((tree, tree, tree));
static tree grokfndecl PROTO((tree, tree, tree, tree, int,
enum overload_flags, tree,
- tree, tree, int, int, int, int, int, int, tree));
+ tree, int, int, int, int, int, int, tree));
static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int, tree));
static tree lookup_tag PROTO((enum tree_code, tree,
struct binding_level *, int));
static void set_identifier_type_value_with_scope
PROTO((tree, tree, struct binding_level *));
-static void record_builtin_type PROTO((enum rid, char *, tree));
-static void record_unknown_type PROTO((tree, char *));
-static int member_function_or_else PROTO((tree, tree, char *));
-static void bad_specifiers PROTO((tree, char *, int, int, int, int,
+static void record_builtin_type PROTO((enum rid, const char *, tree));
+static void record_unknown_type PROTO((tree, const char *));
+static int member_function_or_else PROTO((tree, tree, const char *));
+static void bad_specifiers PROTO((tree, const char *, int, int, int, int,
int));
static void lang_print_error_function PROTO((char *));
static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*));
static unsigned long typename_hash PROTO((hash_table_key));
static boolean typename_compare PROTO((hash_table_key, hash_table_key));
static void push_binding PROTO((tree, tree, struct binding_level*));
-static void add_binding PROTO((tree, tree));
+static int add_binding PROTO((tree, tree));
static void pop_binding PROTO((tree, tree));
static tree local_variable_p PROTO((tree));
+static tree find_binding PROTO((tree, tree));
+static tree select_decl PROTO((tree, int));
+static tree unqualified_namespace_lookup PROTO((tree, int));
+static int lookup_flags PROTO((int, int));
+static tree qualify_lookup PROTO((tree, int));
+static tree record_builtin_java_type PROTO((const char *, int));
+static const char *tag_name PROTO((enum tag_types code));
+static void find_class_binding_level PROTO((void));
+static struct binding_level *innermost_nonclass_level PROTO((void));
+static tree poplevel_class PROTO((void));
+static void warn_about_implicit_typename_lookup PROTO((tree, tree));
+static int walk_namespaces_r PROTO((tree, walk_namespaces_fn, void *));
+static int walk_globals_r PROTO((tree, void *));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
tree long_unsigned_type_node;
tree long_long_unsigned_type_node;
+/* These are used for integer literals that are larger than
+ a long long. The largest integer literals we can handle
+ are the width of two HOST_WIDE_INTs. If two HOST_WIDE_INTs
+ are not larger than the target's long long, then these
+ will never be used. */
+tree widest_integer_literal_type_node;
+tree widest_unsigned_literal_type_node;
+
tree ptrdiff_type_node;
tree unsigned_char_type_node;
#define NULL_BINDING_LEVEL ((struct binding_level *) NULL)
-/* The (non-class) binding level currently in effect. */
+/* The binding level currently in effect. */
static struct binding_level *current_binding_level;
static struct binding_level *class_binding_level;
-/* The current (class or non-class) binding level currently in effect. */
-
-#define inner_binding_level \
- (class_binding_level ? class_binding_level : current_binding_level)
-
/* A chain of binding_level structures awaiting reuse. */
static struct binding_level *free_binding_level;
/* Add this level to the front of the chain (stack) of levels that
are active. */
*newlevel = clear_binding_level;
- if (class_binding_level)
- {
- newlevel->level_chain = class_binding_level;
- class_binding_level = (struct binding_level *)0;
- }
- else
- {
- newlevel->level_chain = current_binding_level;
- }
+ newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
newlevel->tag_transparent = tag_transparent;
newlevel->more_cleanups_ok = 1;
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
}
+/* Find the innermost enclosing class scope, and reset
+ CLASS_BINDING_LEVEL appropriately. */
+
static void
-pop_binding_level ()
+find_class_binding_level ()
{
- if (class_binding_level)
- current_binding_level = class_binding_level;
+ struct binding_level *level = current_binding_level;
+
+ while (level && level->parm_flag != 2)
+ level = level->level_chain;
+ if (level && level->parm_flag == 2)
+ class_binding_level = level;
+ else
+ class_binding_level = 0;
+}
+static void
+pop_binding_level ()
+{
if (global_binding_level)
{
/* Cannot pop a level, if there are none left to pop. */
if (level->binding_depth != binding_depth)
abort ();
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
- free_binding_level = level;
-
- class_binding_level = current_binding_level;
- if (class_binding_level->parm_flag != 2)
- class_binding_level = 0;
- while (current_binding_level->parm_flag == 2)
- current_binding_level = current_binding_level->level_chain;
+ free_binding_level = level;
+ find_class_binding_level ();
}
}
}
is_class_level = 0;
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
- {
- current_binding_level = current_binding_level->level_chain;
- class_binding_level = current_binding_level;
- if (class_binding_level->parm_flag != 2)
- class_binding_level = 0;
- while (current_binding_level->parm_flag == 2)
- current_binding_level = current_binding_level->level_chain;
- }
+ current_binding_level = current_binding_level->level_chain;
+ find_class_binding_level ();
}
static void
return current_binding_level == global_binding_level;
}
+/* Return the innermost binding level that is not for a class scope. */
+
+static struct binding_level *
+innermost_nonclass_level ()
+{
+ struct binding_level *b;
+
+ b = current_binding_level;
+ while (b->parm_flag == 2)
+ b = b->level_chain;
+
+ return b;
+}
+
/* Nonzero if we are currently in a toplevel binding level. This
means either the global binding level or a namespace in a toplevel
- binding level.
- Since there are no non-toplevel namespace levels, this really
- means any namespace or pseudo-global level. */
+ binding level. Since there are no non-toplevel namespace levels,
+ this really means any namespace or pseudo-global level. We also
+ include a class whose context is toplevel. */
int
toplevel_bindings_p ()
{
- return current_binding_level->namespace_p
- || current_binding_level->pseudo_global;
+ struct binding_level *b = innermost_nonclass_level ();
+
+ return b->namespace_p || b->pseudo_global;
}
-/* Nonzero if this is a namespace scope. */
+/* Nonzero if this is a namespace scope, or if we are defining a class
+ which is itself at namespace scope, or whose enclosing class is
+ such a class, etc. */
int
namespace_bindings_p ()
{
- return current_binding_level->namespace_p;
+ struct binding_level *b = innermost_nonclass_level ();
+
+ return b->namespace_p;
}
void
int
pseudo_global_level_p ()
{
- return current_binding_level->pseudo_global;
+ struct binding_level *b = innermost_nonclass_level ();
+
+ return b->pseudo_global;
}
void
BINDING_VALUE (binding) = decl;
BINDING_TYPE (binding) = NULL_TREE;
BINDING_LEVEL (binding) = level;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
LOCAL_BINDING_P (binding) = (level != class_binding_level);
- /* And put it on the front of the ilst of bindings for ID. */
+ /* And put it on the front of the list of bindings for ID. */
TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
IDENTIFIER_BINDING (id) = binding;
}
stat' hack whereby a non-typedef class-name or enum-name can be
bound at the same level as some other kind of entity. It's the
responsibility of the caller to check that inserting this name is
- legal here. */
-static void
+ legal here. Returns nonzero if the new binding was successful. */
+static int
add_binding (id, decl)
tree id;
tree decl;
{
tree binding = IDENTIFIER_BINDING (id);
+ int ok = 1;
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
/* The new name is the type name. */
BINDING_TYPE (binding) = decl;
- else
- {
- /* The old name must be the type name. It was placed in
- IDENTIFIER_VALUE because it was thought, at the point it
- was declared, to be the only entity with such a name. */
- my_friendly_assert (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
- && DECL_ARTIFICIAL (BINDING_VALUE (binding)),
- 0);
-
- /* Move the type name into the type slot; it is now hidden by
- the new binding. */
+ else if (!BINDING_VALUE (binding))
+ /* This situation arises when push_class_level_binding moves an
+ inherited type-binding out of the way to make room for a new
+ value binding. */
+ BINDING_VALUE (binding) = decl;
+ else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+ && DECL_ARTIFICIAL (BINDING_VALUE (binding)))
+ {
+ /* The old binding was a type name. It was placed in
+ BINDING_VALUE because it was thought, at the point it was
+ declared, to be the only entity with such a name. Move the
+ type name into the type slot; it is now hidden by the new
+ binding. */
BINDING_TYPE (binding) = BINDING_VALUE (binding);
BINDING_VALUE (binding) = decl;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ }
+ else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+ && TREE_CODE (decl) == TYPE_DECL
+ && DECL_NAME (decl) == DECL_NAME (BINDING_VALUE (binding))
+ && same_type_p (TREE_TYPE (decl),
+ TREE_TYPE (BINDING_VALUE (binding))))
+ /* We have two typedef-names, both naming the same type to have
+ the same name. This is OK because of:
+
+ [dcl.typedef]
+
+ In a given scope, a typedef specifier can be used to redefine
+ the name of any type declared in that scope to refer to the
+ type to which it already refers. */
+ ok = 0;
+ else
+ {
+ cp_error ("declaration of `%#D'", decl);
+ cp_error_at ("conflicts with previous declaration `%#D'",
+ BINDING_VALUE (binding));
+ ok = 0;
}
+
+ return ok;
}
/* Bind DECL to ID in the current_binding_level.
tree decl;
int flags;
{
- tree d = decl;
+ struct binding_level *b;
+
+ /* Skip over any local classes. This makes sense if we call
+ push_local_binding with a friend decl of a local class. */
+ b = current_binding_level;
+ while (b->parm_flag == 2)
+ b = b->level_chain;
if (lookup_name_current_level (id))
- /* Supplement the existing binding. */
- add_binding (id, d);
+ {
+ /* Supplement the existing binding. */
+ if (!add_binding (id, decl))
+ /* It didn't work. Something else must be bound at this
+ level. Do not add DECL to the list of things to pop
+ later. */
+ return;
+ }
else
/* Create a new binding. */
- push_binding (id, d, current_binding_level);
+ push_binding (id, decl, b);
if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING))
/* We must put the OVERLOAD into a TREE_LIST since the
/* And put DECL on the list of things declared by the current
binding level. */
- TREE_CHAIN (decl) = current_binding_level->names;
- current_binding_level->names = decl;
+ TREE_CHAIN (decl) = b->names;
+ b->names = decl;
}
-/* Bind DECL to ID in the class_binding_level. */
+/* Bind DECL to ID in the class_binding_level. Returns nonzero if the
+ binding was successful. */
-void
+int
push_class_binding (id, decl)
tree id;
tree decl;
{
- if (IDENTIFIER_BINDING (id)
- && BINDING_LEVEL (IDENTIFIER_BINDING (id)) == class_binding_level)
+ int result = 1;
+ tree binding = IDENTIFIER_BINDING (id);
+ tree context;
+
+ /* Note that we declared this value so that we can issue an error if
+ this an illegal 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)
/* Supplement the existing binding. */
- add_binding (id, decl);
+ result = add_binding (id, decl);
else
/* Create a new binding. */
push_binding (id, decl, class_binding_level);
a class-name or enum-name we might prefer a field-name, or some
such. */
IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id));
+
+ /* If this is a binding from a base class, mark it as such. */
+ binding = IDENTIFIER_BINDING (id);
+ if (BINDING_VALUE (binding) == decl && TREE_CODE (decl) != TREE_LIST)
+ {
+ /* Any implicit typename must be from a base-class. The
+ context for an implicit typename declaration is always
+ the derived class in which the lookup was done, so the checks
+ based on the context of DECL below will not trigger. */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (decl)))
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+ else
+ {
+ if (TREE_CODE (decl) == OVERLOAD)
+ context = DECL_REAL_CONTEXT (OVL_CURRENT (decl));
+ else
+ {
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd',
+ 0);
+ context = DECL_REAL_CONTEXT (decl);
+ }
+
+ if (is_properly_derived_from (current_class_type, context))
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+ else
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ }
+ }
+ else if (BINDING_VALUE (binding) == decl)
+ /* We only encounter a TREE_LIST when push_class_decls detects an
+ ambiguity. Such an ambiguity can be overridden by a definition
+ in this class. */
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+
+ return result;
}
/* Remove the binding for DECL which should be the innermost binding
int block_previously_created;
int leaving_for_scope;
- if (current_binding_level->parm_flag == 2
- || current_binding_level->class_shadowed)
- /* We should not be using poplevel to pop a class binding level.
- Use poplevel_class instead. */
- my_friendly_abort (0);
+ if (current_binding_level->parm_flag == 2)
+ return poplevel_class ();
+
+ my_friendly_assert (!current_binding_level->class_shadowed,
+ 19990414);
/* We used to use KEEP == 2 to indicate that the new block should go
at the beginning of the list of blocks at this binding level,
decl_stack = push_decl_level (decl_stack, &decl_obstack);
class_binding_level = current_binding_level;
class_binding_level->parm_flag = 2;
- /* We have just pushed into a new binding level. Now, fake out the rest
- of the compiler. Set the `current_binding_level' back to point to
- the most closely containing non-class binding level. */
- do
- {
- current_binding_level = current_binding_level->level_chain;
- }
- while (current_binding_level->parm_flag == 2);
}
-/* ...and a poplevel for class declarations. FORCE is used to force
- clearing out of CLASS_VALUEs after a class definition. */
+/* ...and a poplevel for class declarations. */
-tree
-poplevel_class (force)
- int force;
+static tree
+poplevel_class ()
{
register struct binding_level *level = class_binding_level;
- tree block = NULL_TREE;
tree shadowed;
my_friendly_assert (level != 0, 354);
shouldn't even be used when current_class_type isn't set, and second,
if we don't touch it here, we're able to use the cache effect if the
next time we're entering a class scope, it is the same class. */
- if (current_class_depth != 1 || force)
- for (shadowed = level->class_shadowed;
- shadowed;
- shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
+ if (current_class_depth != 1)
+ {
+ struct binding_level* b;
+
+ /* Clear out our IDENTIFIER_CLASS_VALUEs. */
+ for (shadowed = level->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE;
+
+ /* Find the next enclosing class, and recreate
+ IDENTIFIER_CLASS_VALUEs appropriate for that class. */
+ b = level->level_chain;
+ while (b && b->parm_flag != 2)
+ b = b->level_chain;
+
+ if (b)
+ for (shadowed = b->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ {
+ tree t;
+
+ t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
+ while (t && BINDING_LEVEL (t) != b)
+ t = TREE_CHAIN (t);
+
+ if (t)
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
+ = BINDING_VALUE (t);
+ }
+ }
else
/* Remember to save what IDENTIFIER's were bound in this scope so we
can recover from cache misses. */
class_binding_level->parm_flag,
class_binding_level->keep);
- if (class_binding_level->parm_flag != 2)
- class_binding_level = (struct binding_level *)0;
-
/* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
#if defined(DEBUG_CP_BINDING_LEVELS)
pop_binding_level ();
- return block;
+ return NULL_TREE;
+}
+
+/* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE
+ for any names in enclosing classes. */
+
+void
+clear_identifier_class_values ()
+{
+ tree t;
+
+ if (!class_binding_level)
+ return;
+
+ for (t = class_binding_level->class_shadowed;
+ t;
+ t = TREE_CHAIN (t))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
+}
+
+/* Returns non-zero if T is a virtual function table. */
+
+int
+vtable_decl_p (t, data)
+ tree t;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
+}
+
+/* Returns non-zero if T is a TYPE_DECL for a type with virtual
+ functions. */
+
+int
+vtype_decl_p (t, data)
+ tree t;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (TREE_CODE (t) == TYPE_DECL
+ && TREE_TYPE (t) != error_mark_node
+ && TYPE_LANG_SPECIFIC (TREE_TYPE (t))
+ && CLASSTYPE_VSIZE (TREE_TYPE (t)));
+}
+
+/* Returns non-zero if T is a signature table. */
+
+int
+sigtable_decl_p (t, data)
+ tree t;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (TREE_CODE (t) == VAR_DECL
+ && TREE_TYPE (t) != error_mark_node
+ && IS_SIGNATURE (TREE_TYPE (t)));
+}
+
+/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
+ itself, calling F for each. The DATA is passed to F as well. */
+
+static int
+walk_namespaces_r (namespace, f, data)
+ tree namespace;
+ walk_namespaces_fn f;
+ void *data;
+{
+ tree current;
+ int result = 0;
+
+ result |= (*f) (namespace, data);
+
+ for (current = NAMESPACE_LEVEL (namespace)->names;
+ current;
+ current = TREE_CHAIN (current))
+ {
+ if (TREE_CODE (current) != NAMESPACE_DECL
+ || DECL_NAMESPACE_ALIAS (current))
+ continue;
+ if (!DECL_LANG_SPECIFIC (current))
+ {
+ /* Hmm. std. */
+ my_friendly_assert (current == std_node, 393);
+ continue;
+ }
+
+ /* We found a namespace. */
+ result |= walk_namespaces_r (current, f, data);
+ }
+
+ return result;
+}
+
+/* Walk all the namespaces, calling F for each. The DATA is passed to
+ F as well. */
+
+int
+walk_namespaces (f, data)
+ walk_namespaces_fn f;
+ void *data;
+{
+ return walk_namespaces_r (global_namespace, f, data);
+}
+
+struct walk_globals_data {
+ walk_globals_pred p;
+ walk_globals_fn f;
+ void *data;
+};
+
+/* Walk the global declarations in NAMESPACE. Whenever one is found
+ for which P returns non-zero, call F with its address. If any call
+ to F returns a non-zero value, return a non-zero value. */
+
+static int
+walk_globals_r (namespace, data)
+ tree namespace;
+ void *data;
+{
+ struct walk_globals_data* wgd = (struct walk_globals_data *) data;
+ walk_globals_pred p = wgd->p;
+ walk_globals_fn f = wgd->f;
+ void *d = wgd->data;
+ tree *t;
+ int result = 0;
+
+ t = &NAMESPACE_LEVEL (namespace)->names;
+
+ while (*t)
+ {
+ tree glbl = *t;
+
+ if ((*p) (glbl, d))
+ result |= (*f) (t, d);
+
+ /* If F changed *T, then *T still points at the next item to
+ examine. */
+ if (*t == glbl)
+ t = &TREE_CHAIN (*t);
+ }
+
+ return result;
+}
+
+/* Walk the global declarations. Whenever one is found for which P
+ returns non-zero, call F with its address. If any call to F
+ returns a non-zero value, return a non-zero value. */
+
+int
+walk_globals (p, f, data)
+ walk_globals_pred p;
+ walk_globals_fn f;
+ void *data;
+{
+ struct walk_globals_data wgd;
+ wgd.p = p;
+ wgd.f = f;
+ wgd.data = data;
+
+ return walk_namespaces (walk_globals_r, &wgd);
}
+
+/* Call wrapup_globals_declarations for the globals in NAMESPACE. If
+ DATA is non-NULL, this is the last time we will call
+ wrapup_global_declarations for this NAMESPACE. */
+
+int
+wrapup_globals_for_namespace (namespace, data)
+ tree namespace;
+ void *data;
+{
+ tree globals = NAMESPACE_LEVEL (namespace)->names;
+ int len = list_length (globals);
+ tree *vec = (tree *) alloca (sizeof (tree) * len);
+ int i;
+ int result;
+ tree decl;
+ 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);
+ return 0;
+ }
+
+ /* Temporarily mark vtables as external. That prevents
+ wrapup_global_declarations from writing them out; we must process
+ them ourselves in finish_vtable_vardecl. */
+ for (i = 0; i < len; ++i)
+ if (vtable_decl_p (vec[i], /*data=*/0) && !DECL_EXTERNAL (vec[i]))
+ {
+ DECL_NOT_REALLY_EXTERN (vec[i]) = 1;
+ DECL_EXTERNAL (vec[i]) = 1;
+ }
+
+ /* Write out any globals that need to be output. */
+ result = wrapup_global_declarations (vec, len);
+
+ /* Undo the hack to DECL_EXTERNAL above. */
+ for (i = 0; i < len; ++i)
+ if (vtable_decl_p (vec[i], /*data=*/0)
+ && DECL_NOT_REALLY_EXTERN (vec[i]))
+ {
+ DECL_NOT_REALLY_EXTERN (vec[i]) = 0;
+ DECL_EXTERNAL (vec[i]) = 0;
+ }
+
+ return result;
+}
+
\f
/* For debugging. */
static int no_print_functions = 0;
suspend_binding_level ();
}
-/* Concatenate the binding levels of all namespaces. */
+/* Push into the scope of the namespace NS, even if it is deeply
+ nested within another namespace. */
void
-cat_namespace_levels()
+push_nested_namespace (ns)
+ tree ns;
{
- tree current;
- tree last;
- struct binding_level *b;
-
- last = NAMESPACE_LEVEL (global_namespace) -> names;
- /* The nested namespaces appear in the names list of their ancestors. */
- for (current = last; current; current = TREE_CHAIN (current))
+ if (ns == global_namespace)
+ push_to_top_level ();
+ else
{
- /* Catch simple infinite loops. */
- if (TREE_CHAIN (current) == current)
- my_friendly_abort (990126);
+ push_nested_namespace (CP_DECL_CONTEXT (ns));
+ push_namespace (DECL_NAME (ns));
+ }
+}
- if (TREE_CODE (current) != NAMESPACE_DECL
- || DECL_NAMESPACE_ALIAS (current))
- continue;
- if (!DECL_LANG_SPECIFIC (current))
- {
- /* Hmm. std. */
- my_friendly_assert (current == std_node, 393);
- continue;
- }
- b = NAMESPACE_LEVEL (current);
- while (TREE_CHAIN (last))
- last = TREE_CHAIN (last);
- TREE_CHAIN (last) = NAMESPACE_LEVEL (current) -> names;
+/* Pop back from the scope of the namespace NS, which was previously
+ entered with push_nested_namespace. */
+
+void
+pop_nested_namespace (ns)
+ tree ns;
+{
+ while (ns != global_namespace)
+ {
+ pop_namespace ();
+ ns = CP_DECL_CONTEXT (ns);
}
+
+ pop_from_top_level ();
}
+
\f
/* Subroutines for reverting temporarily to top-level for instantiation
of templates and such. We actually need to clear out the class- and
tree previous_class_type, previous_class_values;
int processing_specialization;
int processing_explicit_instantiation;
+ char *class_cache_firstobj;
};
static struct saved_scope *current_saved_scope;
extern int current_lang_stacksize;
struct saved_scope *s
= (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
- struct binding_level *b = inner_binding_level;
+ struct binding_level *b = current_binding_level;
tree old_bindings = NULL_TREE;
push_cp_function_context (NULL_TREE);
s->processing_template_decl = processing_template_decl;
s->previous_class_type = previous_class_type;
s->previous_class_values = previous_class_values;
+ s->class_cache_firstobj = class_cache_firstobj;
s->processing_specialization = processing_specialization;
s->processing_explicit_instantiation = processing_explicit_instantiation;
shadowed_labels = NULL_TREE;
minimal_parse_mode = 0;
previous_class_type = previous_class_values = NULL_TREE;
+ class_cache_firstobj = 0;
processing_specialization = 0;
processing_explicit_instantiation = 0;
current_template_parms = NULL_TREE;
/* Clear out class-level bindings cache. */
if (previous_class_type)
- {
- popclass (-1);
- previous_class_type = NULL_TREE;
- }
+ invalidate_class_lookup_cache ();
pop_obstacks ();
previous_class_values = s->previous_class_values;
processing_specialization = s->processing_specialization;
processing_explicit_instantiation = s->processing_explicit_instantiation;
+ class_cache_firstobj = s->class_cache_firstobj;
free (s);
SET_IDENTIFIER_TYPE_VALUE (id, type);
}
-/* As set_identifier_type_value_with_scope, but using inner_binding_level. */
+/* As set_identifier_type_value_with_scope, but using current_binding_level. */
void
set_identifier_type_value (id, type)
tree id;
tree type;
{
- set_identifier_type_value_with_scope (id, type, inner_binding_level);
+ set_identifier_type_value_with_scope (id, type, current_binding_level);
}
/* Return the type associated with id. */
#ifdef DEBUG_CP_BINDING_LEVELS
fprintf (stderr, "XXX entering pop_everything ()\n");
#endif
- while (! toplevel_bindings_p () && ! pseudo_global_level_p ())
+ while (!toplevel_bindings_p ())
{
- if (class_binding_level)
- pop_nested_class (1);
+ if (current_binding_level->parm_flag == 2)
+ pop_nested_class ();
else
poplevel (0, 0, 0);
}
|| TREE_CODE (type) == ENUMERAL_TYPE, 0);
- if (/* If !GLOBALIZE then we are looking at a definition.
- It may not be a primary template. (For example, in:
-
- template <class T>
- struct S1 { class S2 {}; }
-
- we have to push_template_decl for S2.) */
- (processing_template_decl && !globalize)
- /* If we are declaring a friend template class, we will
- have GLOBALIZE set, since something like:
-
- template <class T>
- struct S1 {
- template <class U>
- friend class S2;
- };
-
- declares S2 to be at global scope. */
- || PROCESSING_REAL_TEMPLATE_DECL_P ())
+ if (processing_template_decl)
{
/* This may change after the call to
push_template_decl_real, but we want the original value. */
&& !globalize && b->pseudo_global
&& b->level_chain->parm_flag == 2)
{
- pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
- b->level_chain);
finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
/* Put this tag on the list of tags for the class, since
that won't happen below because B is not the class
binding level, but is instead the pseudo-global level. */
b->level_chain->tags =
saveable_tree_cons (name, type, b->level_chain->tags);
- TREE_NONLOCAL_FLAG (type) = 1;
if (TYPE_SIZE (current_class_type) == NULL_TREE)
CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
}
int globalize;
{
register struct binding_level *b;
- tree context = 0;
- tree c_decl = 0;
- b = inner_binding_level;
+ b = current_binding_level;
while (b->tag_transparent
|| (globalize && b->parm_flag == 2))
b = b->level_chain;
if (name)
{
- context = type ? TYPE_CONTEXT (type) : NULL_TREE;
- if (! context)
- {
- tree cs = current_scope ();
-
- if (! globalize)
- context = cs;
- else if (cs != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
- /* When declaring a friend class of a local class, we want
- to inject the newly named class into the scope
- containing the local class, not the namespace scope. */
- context = hack_decl_function_context (get_type_decl (cs));
- }
- if (context)
- c_decl = TREE_CODE (context) == FUNCTION_DECL
- ? context : TYPE_MAIN_DECL (context);
-
- if (!context)
- context = current_namespace;
-
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
register tree d = NULL_TREE;
int newdecl = 0, in_class = 0;
+ tree context;
+ tree c_decl = NULL_TREE;
+
+ context = type ? TYPE_CONTEXT (type) : NULL_TREE;
+ if (! context)
+ {
+ tree cs = current_scope ();
+
+ if (! globalize)
+ context = cs;
+ else if (cs != NULL_TREE
+ && TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
+ /* When declaring a friend class of a local class, we want
+ to inject the newly named class into the scope
+ containing the local class, not the namespace scope. */
+ context = hack_decl_function_context (get_type_decl (cs));
+ }
+ if (context)
+ c_decl = TREE_CODE (context) == FUNCTION_DECL
+ ? context : TYPE_MAIN_DECL (context);
+
+ if (!context)
+ context = current_namespace;
if ((b->pseudo_global && b->level_chain->parm_flag == 2)
|| b->parm_flag == 2)
if (b->parm_flag == 2)
{
- pushdecl_class_level (d);
if (newdecl && !PROCESSING_REAL_TEMPLATE_DECL_P ())
/* Put this TYPE_DECL on the TYPE_FIELDS list for the
class. But if it's a member template class, we
want the TEMPLATE_DECL, not the TYPE_DECL, so this
is done later. */
finish_member_declaration (d);
+ else
+ pushdecl_class_level (d);
}
else
d = pushdecl_with_scope (d, b);
}
if (b->parm_flag == 2)
{
- TREE_NONLOCAL_FLAG (type) = 1;
if (TYPE_SIZE (current_class_type) == NULL_TREE)
CLASSTYPE_TAGS (current_class_type) = b->tags;
}
{
tree name;
- static char *explicit_extern_static_warning
+ static const char *explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
- static char *implicit_extern_static_warning
+ static const char *implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
if (TREE_CODE (newdecl) == TYPE_DECL)
return 1;
else
{
- char *errmsg = redeclaration_error_message (newdecl, olddecl);
+ const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
cp_error (errmsg, newdecl);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
- if (newtype != canonical_type_variant (oldtype)
+ if (! same_type_p (newtype, oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
+
+ /* Only functions have DECL_BEFRIENDING_CLASSES. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (newdecl))
+ DECL_BEFRIENDING_CLASSES (newdecl)
+ = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+ DECL_BEFRIENDING_CLASSES (olddecl));
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
- char *warnstring = NULL;
+ const char *warnstring = NULL;
if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
warnstring = "declaration of `%s' shadows a parameter";
We will reverse them later if necessary. */
TREE_CHAIN (x) = current_binding_level->names;
current_binding_level->names = x;
- if (! (current_binding_level != global_binding_level
- || TREE_PERMANENT (x)))
+ if (current_binding_level == global_binding_level
+ && !TREE_PERMANENT (x))
my_friendly_abort (124);
}
pushdecl_namespace_level (x)
tree x;
{
- register struct binding_level *b = inner_binding_level;
+ register struct binding_level *b = current_binding_level;
register tree t;
t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
{
/* Don't use DECL_ASSEMBLER_NAME here! Everything that looks in class
scope looks for the pre-mangled name. */
- register tree name = DECL_NAME (x);
+ register tree name;
+
+ if (TREE_CODE (x) == OVERLOAD)
+ x = OVL_CURRENT (x);
+ name = DECL_NAME (x);
if (name)
{
- if (TYPE_BEING_DEFINED (current_class_type))
- {
- /* A name N used in a class S shall refer to the same declaration
- in its context and when re-evaluated in the completed scope of S.
- Types, enums, and static vars are checked here; other
- members are checked in finish_struct. */
- tree icv = IDENTIFIER_CLASS_VALUE (name);
-
- /* This should match check_member_decl_is_same_in_complete_scope. */
- if (icv && icv != x
- && flag_optional_diags
- /* Don't complain about inherited names. */
- && id_in_current_class (name)
- /* Or shadowed tags. */
- && !(DECL_DECLARES_TYPE_P (icv)
- && DECL_CONTEXT (icv) == current_class_type))
- {
- cp_pedwarn ("declaration of identifier `%D' as `%#D'", name, x);
- cp_pedwarn_at ("conflicts with previous use in class as `%#D'",
- icv);
- }
-
- check_template_shadow (x);
- }
-
push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
set_identifier_type_value (name, TREE_TYPE (x));
}
+ else if (ANON_AGGR_TYPE_P (TREE_TYPE (x)))
+ {
+ tree f;
+
+ for (f = TYPE_FIELDS (TREE_TYPE (x));
+ f;
+ f = TREE_CHAIN (f))
+ pushdecl_class_level (f);
+ }
}
#if 0
tree name;
tree x;
{
+ tree binding;
/* The class_binding_level will be NULL if x is a template
parameter name in a member template. */
if (!class_binding_level)
return;
+ /* Make sure that this new member does not have the same name
+ as a template parameter. */
+ if (TYPE_BEING_DEFINED (current_class_type))
+ check_template_shadow (x);
+
/* If this declaration shadows a declaration from an enclosing
class, then we will need to restore IDENTIFIER_CLASS_VALUE when
we leave this class. Record the shadowed declaration here. */
- maybe_push_cache_obstack ();
- class_binding_level->class_shadowed
- = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
- class_binding_level->class_shadowed);
- TREE_TYPE (class_binding_level->class_shadowed)
- = x;
- pop_obstacks ();
-
- /* Put the binding on the stack of bindings for the identifier, and
- update IDENTIFIER_CLASS_VALUE. */
- push_class_binding (name, x);
+ binding = IDENTIFIER_BINDING (name);
+ if (binding
+ && ((TREE_CODE (x) == OVERLOAD
+ && BINDING_VALUE (binding)
+ && is_overloaded_fn (BINDING_VALUE (binding)))
+ || INHERITED_VALUE_BINDING_P (binding)))
+ {
+ tree shadow;
+ tree old_decl;
+
+ /* If the old binding was from a base class, and was for a tag
+ name, slide it over to make room for the new binding. The
+ old binding is still visible if explicitly qualified with a
+ class-key. */
+ if (INHERITED_VALUE_BINDING_P (binding)
+ && BINDING_VALUE (binding)
+ && TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+ && DECL_ARTIFICIAL (BINDING_VALUE (binding))
+ && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+ {
+ old_decl = BINDING_TYPE (binding);
+ BINDING_TYPE (binding) = BINDING_VALUE (binding);
+ BINDING_VALUE (binding) = NULL_TREE;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ }
+ else
+ old_decl = BINDING_VALUE (binding);
+
+ /* There was already a binding for X containing fewer
+ functions than are named in X. Find the previous
+ declaration of X on the class-shadowed list, and update it. */
+ for (shadow = class_binding_level->class_shadowed;
+ shadow;
+ shadow = TREE_CHAIN (shadow))
+ if (TREE_PURPOSE (shadow) == name
+ && TREE_TYPE (shadow) == old_decl)
+ {
+ BINDING_VALUE (binding) = x;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ TREE_TYPE (shadow) = x;
+ return;
+ }
+ }
- obstack_ptr_grow (&decl_obstack, x);
+ /* If we didn't replace an existing binding, put the binding on the
+ stack of bindings for the identifier, and update
+ IDENTIFIER_CLASS_VALUE. */
+ if (push_class_binding (name, x))
+ {
+ push_cache_obstack ();
+ class_binding_level->class_shadowed
+ = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
+ class_binding_level->class_shadowed);
+ pop_obstacks ();
+ /* Record the value we are binding NAME to so that we can know
+ what to pop later. */
+ TREE_TYPE (class_binding_level->class_shadowed) = x;
+ }
}
/* Insert another USING_DECL into the current binding level,
Otherwise return an error message format string with a %s
where the identifier should go. */
-static char *
+static const char *
redeclaration_error_message (newdecl, olddecl)
tree newdecl, olddecl;
{
&& !(DECL_INITIAL (new_decls) == NULL_TREE
&& pod_type_p (TREE_TYPE (new_decls))))
{
- if (! identified)
+ /* This is really only important if we're crossing
+ an initialization. The POD stuff is just
+ pedantry; why should it matter if the class
+ contains a field of pointer to member type? */
+ int problem = (DECL_INITIAL (new_decls)
+ || (TYPE_NEEDS_CONSTRUCTING
+ (TREE_TYPE (new_decls))));
+
+ if (! identified)
{
- cp_error ("jump to label `%D'", decl);
- error_with_file_and_line (uses->filename_o_goto,
- uses->lineno_o_goto,
- " from here");
+ if (problem)
+ {
+ cp_error ("jump to label `%D'", decl);
+ error_with_file_and_line
+ (uses->filename_o_goto,
+ uses->lineno_o_goto, " from here");
+ }
+ else
+ {
+ cp_pedwarn ("jump to label `%D'", decl);
+ pedwarn_with_file_and_line
+ (uses->filename_o_goto,
+ uses->lineno_o_goto, " from here");
+ }
identified = 1;
}
- if (DECL_INITIAL (new_decls)
- || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls)))
+
+ if (problem)
cp_error_at (" crosses initialization of `%#D'",
new_decls);
else
- cp_error_at (" enters scope of non-POD `%#D'",
+ cp_pedwarn_at (" enters scope of non-POD `%#D'",
new_decls);
}
new_decls = TREE_CHAIN (new_decls);
/* Similarly, store the list of tags of the current level. */
-static void
+void
storetags (tags)
tree tags;
{
else
return NULL_TREE;
}
- if (current_class_type && level->level_chain->namespace_p)
- {
- /* Try looking in this class's tags before heading into
- global binding level. */
- tree context = current_class_type;
- while (context)
- {
- switch (TREE_CODE_CLASS (TREE_CODE (context)))
- {
- tree these_tags;
- case 't':
- these_tags = CLASSTYPE_TAGS (context);
- if (ANON_AGGRNAME_P (name))
- while (these_tags)
- {
- if (TYPE_IDENTIFIER (TREE_VALUE (these_tags))
- == name)
- return TREE_VALUE (tail);
- these_tags = TREE_CHAIN (these_tags);
- }
- else
- while (these_tags)
- {
- if (TREE_PURPOSE (these_tags) == name)
- {
- if (TREE_CODE (TREE_VALUE (these_tags)) != form)
- {
- cp_error ("`%#D' redeclared as %C in class scope",
- TREE_VALUE (tail), form);
- return NULL_TREE;
- }
- return TREE_VALUE (tail);
- }
- these_tags = TREE_CHAIN (these_tags);
- }
- /* If this type is not yet complete, then don't
- look at its context. */
- if (TYPE_SIZE (context) == NULL_TREE)
- goto no_context;
- /* Go to next enclosing type, if any. */
- context = DECL_CONTEXT (TYPE_MAIN_DECL (context));
- break;
- case 'd':
- context = DECL_CONTEXT (context);
- break;
- default:
- my_friendly_abort (10);
- }
- continue;
- no_context:
- break;
- }
- }
}
return NULL_TREE;
}
{
struct tree_binding _b;
tree val;
+ tree template_id = NULL_TREE;
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
namespace = ORIGINAL_NAMESPACE (namespace);
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ template_id = name;
+ name = TREE_OPERAND (name, 0);
+ if (TREE_CODE (name) == OVERLOAD)
+ name = DECL_NAME (OVL_CURRENT (name));
+ else if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd')
+ name = DECL_NAME (name);
+ }
+
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
val = binding_init (&_b);
{
val = BINDING_VALUE (val);
+ if (template_id)
+ {
+ if (DECL_CLASS_TEMPLATE_P (val))
+ val = lookup_template_class (val,
+ TREE_OPERAND (template_id, 1),
+ /*in_decl=*/NULL_TREE,
+ /*context=*/NULL_TREE,
+ /*entering_scope=*/0);
+ else if (DECL_FUNCTION_TEMPLATE_P (val)
+ || TREE_CODE (val) == OVERLOAD)
+ val = lookup_template_function (val,
+ TREE_OPERAND (template_id, 1));
+ else
+ {
+ cp_error ("`%D::%D' is not a template",
+ namespace, name);
+ return error_mark_node;
+ }
+ }
+
/* If we have a single function from a using decl, pull it out. */
if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
val = OVL_FUNCTION (val);
&typename_compare))
fatal ("virtual memory exhausted");
+ /* The FULLNAME needs to exist for the life of the hash table, i.e.,
+ for the entire compilation. */
+ if (!TREE_PERMANENT (fullname))
+ fullname = copy_to_permanent (fullname);
+
/* Build the TYPENAME_TYPE. */
t = make_lang_type (TYPENAME_TYPE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
make_typename_type (context, name)
tree context, name;
{
- tree t;
tree fullname;
if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
- name = TYPE_IDENTIFIER (name);
+ {
+ if (!(TYPE_LANG_SPECIFIC (name)
+ && (CLASSTYPE_IS_TEMPLATE (name)
+ || CLASSTYPE_USE_TEMPLATE (name))))
+ name = TYPE_IDENTIFIER (name);
+ else
+ /* Create a TEMPLATE_ID_EXPR for the type. */
+ name = build_nt (TEMPLATE_ID_EXPR,
+ CLASSTYPE_TI_TEMPLATE (name),
+ CLASSTYPE_TI_ARGS (name));
+ }
else if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
{
+ tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
- t = lookup_field (context, name, 0, 0);
- else
+ tmpl = lookup_field (context, name, 0, 0);
+ if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
cp_error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
- if (t && DECL_CLASS_TEMPLATE_P (t))
- return lookup_template_class (t, TREE_OPERAND (fullname, 1),
- NULL_TREE, context,
- /*entering_scope=*/0);
+ return lookup_template_class (tmpl,
+ TREE_OPERAND (fullname, 1),
+ NULL_TREE, context,
+ /*entering_scope=*/0);
}
else
{
- if (IS_AGGR_TYPE (context))
- t = lookup_field (context, name, 0, 1);
- else
+ tree t;
+
+ if (!IS_AGGR_TYPE (context))
{
cp_error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
+ t = lookup_field (context, name, 0, 1);
if (t)
return TREE_TYPE (t);
}
}
+
+ /* If the CONTEXT is not a template type, then either the field is
+ there now or its never going to be. */
+ if (!uses_template_parms (context))
+ {
+ cp_error ("no type named `%#T' in `%#T'", name, context);
+ return error_mark_node;
+ }
+
return build_typename_type (context, name, fullname, NULL_TREE);
}
val = TYPE_STUB_DECL (BINDING_TYPE (binding));
/* Don't return non-types if we really prefer types. */
else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
- && (!looking_for_template || TREE_CODE (val) != TEMPLATE_DECL))
+ && (TREE_CODE (val) != TEMPLATE_DECL
+ || !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
return val;
if (!lookup_using_namespace (name, b, level->using_directives,
scope, flags))
/* Give up because of error. */
- return NULL_TREE;
+ return error_mark_node;
/* Add all _DECLs seen through global using-directives. */
/* XXX local and global using lists should work equally. */
if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
scope, flags))
/* Give up because of error. */
- return NULL_TREE;
+ return error_mark_node;
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
return val;
}
+/* Any other BINDING overrides an implicit TYPENAME. Warn about
+ that. */
+
+static void
+warn_about_implicit_typename_lookup (typename, binding)
+ tree typename;
+ tree binding;
+{
+ tree subtype = TREE_TYPE (TREE_TYPE (typename));
+ tree name = DECL_NAME (typename);
+
+ if (! (TREE_CODE (binding) == TEMPLATE_DECL
+ && CLASSTYPE_TEMPLATE_INFO (subtype)
+ && CLASSTYPE_TI_TEMPLATE (subtype) == binding)
+ && ! (TREE_CODE (binding) == TYPE_DECL
+ && same_type_p (TREE_TYPE (binding), subtype)))
+ {
+ cp_warning ("lookup of `%D' finds `%#D'",
+ name, binding);
+ cp_warning (" instead of `%D' from dependent base class",
+ typename);
+ cp_warning (" (use `typename %T::%D' if that's what you meant)",
+ constructor_name (current_class_type), name);
+ }
+}
+
/* Look up NAME in the current binding level and its superiors in the
namespace of variables, functions and typedefs. Return a ..._DECL
node of some kind representing its definition if there is only one
tree name;
int prefer_type, nonclass, namespaces_only;
{
- register tree val;
+ tree t;
+ tree val = NULL_TREE;
int yylex = 0;
tree from_obj = NULL_TREE;
int flags;
+ int val_is_implicit_typename = 0;
/* Hack: copy flag set by parser, if set. */
if (only_namespace_names)
prefer_type = looking_for_typename;
flags = lookup_flags (prefer_type, namespaces_only);
- /* During parsing, we need to complain. */
- flags |= LOOKUP_COMPLAIN;
/* If the next thing is '<', class templates are types. */
if (looking_for_template)
flags |= LOOKUP_TEMPLATES_EXPECTED;
|| TREE_CODE (type) == TYPENAME_TYPE)
/* Someone else will give an error about this if needed. */
val = NULL_TREE;
- else if (TYPE_BEING_DEFINED (type))
- {
- val = IDENTIFIER_CLASS_VALUE (name);
- if (val && DECL_CONTEXT (val) != type)
- {
- struct binding_level *b = class_binding_level;
- for (val = NULL_TREE; b; b = b->level_chain)
- {
- tree t = purpose_member (name, b->class_shadowed);
- if (t && TREE_VALUE (t)
- && DECL_CONTEXT (TREE_VALUE (t)) == type)
- {
- val = TREE_VALUE (t);
- break;
- }
- }
- }
- if (val == NULL_TREE)
- val = lookup_field (type, name, 0, 1);
- }
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
from_obj = val;
}
else
- flags = lookup_flags (prefer_type, namespaces_only);
+ {
+ flags = lookup_flags (prefer_type, namespaces_only);
+ /* If we're not parsing, we need to complain. */
+ flags |= LOOKUP_COMPLAIN;
+ }
/* First, look in non-namespace scopes. */
- for (val = IDENTIFIER_BINDING (name); val; val = TREE_CHAIN (val))
+ for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
{
- if (!LOCAL_BINDING_P (val) && nonclass)
+ tree binding;
+
+ if (!LOCAL_BINDING_P (t) && 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 (val), flags))
- {
- val = BINDING_VALUE (val);
- break;
- }
+
+ /* 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);
else if ((flags & LOOKUP_PREFER_TYPES)
- && qualify_lookup (BINDING_TYPE (val), flags))
- {
- val = BINDING_TYPE (val);
- break;
+ && qualify_lookup (BINDING_TYPE (t), flags))
+ binding = BINDING_TYPE (t);
+ else
+ binding = NULL_TREE;
+
+ if (binding
+ && (!val || !(TREE_CODE (binding) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (binding)))))
+ {
+ if (val_is_implicit_typename && !yylex)
+ warn_about_implicit_typename_lookup (val, binding);
+ val = binding;
+ val_is_implicit_typename
+ = (TREE_CODE (val) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (val)));
+ if (!val_is_implicit_typename)
+ break;
}
}
- /* If VAL is a type from a dependent base, we're not really supposed
- to be able to see it; the fact that we can is the "implicit
- typename" extension. We call lookup_field here to turn VAL into
- a TYPE_DECL for a TYPENAME_TYPE. */
- if (processing_template_decl && val
- && val == IDENTIFIER_CLASS_VALUE (name)
- && TREE_CODE (val) == TYPE_DECL
- && !currently_open_class (DECL_CONTEXT (val))
- && uses_template_parms (current_class_type))
- val = lookup_field (current_class_type, name, 0, 1);
-
- /* We don't put names from baseclasses onto the IDENTIFIER_BINDING
- list when we're defining a type. It would probably be simpler to
- do this, but we don't. So, we must lookup names from base
- classes explicitly. */
- if (!val && !nonclass
- && current_class_type && TYPE_BEING_DEFINED (current_class_type))
+ /* Now lookup in namespace scopes. */
+ if (!val || val_is_implicit_typename)
{
- val = qualify_lookup (lookup_field (current_class_type, name, 0, 0),
- flags);
- if (!val)
- val = qualify_lookup (lookup_nested_field (name, !yylex),
- flags);
- }
-
- /* If we found a type from a dependent base class (using the
- implicit typename extension) make sure that there's not some
- global name which should be chosen instead. */
- if (val && TREE_CODE (val) == TYPE_DECL
- && IMPLICIT_TYPENAME_P (TREE_TYPE (val)))
- {
- tree global_val;
-
- /* Any other name takes precedence over an implicit typename. Warn the
- user about this potentially confusing lookup. */
- global_val = unqualified_namespace_lookup (name, flags);
-
- if (global_val)
- {
- tree subtype;
-
- /* Only warn when not lexing; we don't want to warn if they
- use this name as a declarator. */
- subtype = TREE_TYPE (TREE_TYPE (val));
- if (! yylex
- && ! (TREE_CODE (global_val) == TEMPLATE_DECL
- && CLASSTYPE_TEMPLATE_INFO (subtype)
- && CLASSTYPE_TI_TEMPLATE (subtype) == global_val)
- && ! (TREE_CODE (global_val) == TYPE_DECL
- && same_type_p (TREE_TYPE (global_val), subtype)))
- {
- cp_warning ("lookup of `%D' finds `%#D'", name, global_val);
- cp_warning (" instead of `%D' from dependent base class",
- val);
- cp_warning (" (use `typename %T::%D' if that's what you meant)",
- constructor_name (current_class_type), name);
- }
-
- /* Use the global value instead of the implicit typename. */
- val = global_val;
+ t = unqualified_namespace_lookup (name, flags);
+ if (t)
+ {
+ if (val_is_implicit_typename && !yylex)
+ warn_about_implicit_typename_lookup (val, t);
+ val = t;
}
}
- else if (!val)
- /* No local, or class-scoped binding. Look for a namespace-scope
- declaration. */
- val = unqualified_namespace_lookup (name, flags);
done:
if (val)
return lookup_name_real (name, prefer_type, 0, 0);
}
-/* Similar to `lookup_name' but look only at current binding level. */
+/* Similar to `lookup_name' but look only in the innermost non-class
+ binding level. */
tree
lookup_name_current_level (name)
tree name;
{
- register tree t = NULL_TREE;
+ struct binding_level *b;
+ tree t = NULL_TREE;
- if (current_binding_level->namespace_p)
+ b = current_binding_level;
+ while (b->parm_flag == 2)
+ b = b->level_chain;
+
+ if (b->namespace_p)
{
t = IDENTIFIER_NAMESPACE_VALUE (name);
else if (IDENTIFIER_BINDING (name)
&& LOCAL_BINDING_P (IDENTIFIER_BINDING (name)))
{
- struct binding_level *b = current_binding_level;
-
while (1)
{
if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
static void
record_builtin_type (rid_index, name, type)
enum rid rid_index;
- char *name;
+ const char *name;
tree type;
{
tree rname = NULL_TREE, tname = NULL_TREE;
static tree
record_builtin_java_type (name, size)
- char *name;
+ const char *name;
int size;
{
tree type, decl;
}
record_builtin_type (RID_MAX, name, type);
decl = TYPE_NAME (type);
+
+ /* Suppress generate debug symbol entries for these types,
+ since for normal C++ they are just clutter.
+ However, push_lang_context undoes this if extern "Java" is seen. */
DECL_IGNORED_P (decl) = 1;
+
TYPE_FOR_JAVA (type) = 1;
return type;
}
static void
record_unknown_type (type, name)
tree type;
- char *name;
+ const char *name;
{
tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
/* Make sure the "unknown type" typedecl gets ignored for debug info. */
: make_unsigned_type (CHAR_TYPE_SIZE));
record_builtin_type (RID_CHAR, "char", char_type_node);
+ /* `signed' is the same as `int' */
+ record_builtin_type (RID_SIGNED, NULL_PTR, integer_type_node);
+
long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
record_builtin_type (RID_LONG, "long int", long_integer_type_node);
unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node);
+ /* Create the widest literal types. */
+ widest_integer_literal_type_node = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ widest_integer_literal_type_node));
+
+ widest_unsigned_literal_type_node = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ widest_unsigned_literal_type_node));
+
/* These are types that type_for_size and type_for_mode use. */
intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
print_error_function = lang_print_error_function;
lang_get_alias_set = &c_get_alias_set;
+ valid_lang_attribute = cp_valid_lang_attribute;
/* Maintain consistency. Perhaps we should just complain if they
say -fwritable-strings? */
tree
define_function (name, type, function_code, pfn, library_name)
- char *name;
+ const char *name;
tree type;
enum built_in_function function_code;
void (*pfn) PROTO((tree));
- char *library_name;
+ const char *library_name;
{
tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
union type.) */
void
-fixup_anonymous_union (t)
+fixup_anonymous_aggr (t)
tree t;
{
tree *q;
TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0;
TYPE_HAS_ASSIGN_REF (t) = 0;
- TYPE_HAS_ASSIGNMENT (t) = 0;
TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
/* Splice the implicitly generated functions out of the TYPE_METHODS
Until we have a good way of detecting the latter, don't warn. */
if (t == NULL_TREE && ! current_class_type)
pedwarn ("declaration does not declare anything");
- else if (t && ANON_UNION_TYPE_P (t))
- /* Anonymous unions are objects, so they can have specifiers. */;
+
+ /* Check for an anonymous union. We're careful
+ accessing TYPE_IDENTIFIER because some built-in types, like
+ pointer-to-member types, do not have TYPE_NAME. */
+ else if (t && IS_AGGR_TYPE_CODE (TREE_CODE (t))
+ && TYPE_NAME (t)
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ {
+ /* Anonymous unions are objects, so they can have specifiers. */;
+ SET_ANON_AGGR_TYPE_P (t);
+
+ if (TREE_CODE (t) != UNION_TYPE && pedantic && ! in_system_header)
+ pedwarn ("ISO C++ prohibits anonymous structs");
+ }
+
else if (ob_modifier)
{
if (ob_modifier == ridpointers[(int) RID_INLINE]
union { ... } ;
because there is no declarator after the union, the parser
sends that declaration here. */
- if (t && ANON_UNION_TYPE_P (t))
+ if (t && ANON_AGGR_TYPE_P (t))
{
- fixup_anonymous_union (t);
+ fixup_anonymous_aggr (t);
if (TYPE_FIELDS (t))
{
tree context;
extern int have_extern_spec;
extern int used_extern_spec;
+ tree attrlist;
#if 0
/* See code below that used this. */
used_extern_spec = 1;
}
+ if (attributes || prefix_attributes)
+ attrlist = build_scratch_list (attributes, prefix_attributes);
+ else
+ attrlist = NULL_TREE;
+
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
- NULL_TREE);
+ attrlist);
+
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return NULL_TREE;
+
/* Don't lose if destructors must be executed at file-level. */
if (! processing_template_decl && TREE_STATIC (decl)
&& TYPE_NEEDS_DESTRUCTOR (complete_type (type))
break;
default:
- if (! processing_template_decl)
- {
- if (type != error_mark_node)
- {
- if (TYPE_SIZE (type) != NULL_TREE
- && ! TREE_CONSTANT (TYPE_SIZE (type)))
- {
- cp_error
- ("variable-sized object `%D' may not be initialized",
- decl);
- initialized = 0;
- }
-
- if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
- {
- cp_error
- ("elements of array `%#D' have incomplete type", decl);
- initialized = 0;
- }
- }
- }
+ break;
}
if (initialized)
if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
{
- pushclass (context, 2);
+ push_nested_class (context, 2);
if (TREE_CODE (decl) == VAR_DECL)
{
tree type = TREE_TYPE (decl);
int initialized = (DECL_INITIAL (decl) != NULL_TREE);
+ if (type == error_mark_node)
+ return;
+
/* If this type of object needs a cleanup, and control may
jump past it, make a new binding level so that it is cleaned
up only when it is initialized first. */
{
/* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */
- if (type == error_mark_node)
- ; /* Don't complain again. */
- else if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
+ if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
char *asmspec = NULL;
int was_readonly = 0;
int already_used = 0;
+ tree core_type;
/* If this is 0, then we did not change obstacks. */
if (! decl)
goto finish_end0;
}
+
/* Take care of TYPE_DECLs up front. */
if (TREE_CODE (decl) == TYPE_DECL)
{
DECL_CONTEXT (decl) == NULL_TREE, at_eof);
goto finish_end;
}
+
if (TREE_CODE (decl) != FUNCTION_DECL)
- {
- ttype = target_type (type);
- }
+ ttype = target_type (type);
if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
&& TYPE_NEEDS_CONSTRUCTING (type))
{
-
/* Currently, GNU C++ puts constants in text space, making them
impossible to initialize. In the future, one would hope for
an operating system which understood the difference between
init = NULL_TREE;
}
+ /* Check for certain invalid initializations. */
+ if (init)
+ {
+ if (TYPE_SIZE (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
+ {
+ cp_error ("variable-sized object `%D' may not be initialized", decl);
+ init = NULL_TREE;
+ }
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && !TYPE_SIZE (complete_type (TREE_TYPE (type))))
+ {
+ cp_error ("elements of array `%#D' have incomplete type", decl);
+ init = NULL_TREE;
+ }
+ }
+
GNU_xref_decl (current_function_decl, decl);
+ core_type = type;
+ while (TREE_CODE (core_type) == ARRAY_TYPE)
+ core_type = TREE_TYPE (core_type);
+
if (TREE_CODE (decl) == FIELD_DECL)
;
else if (TREE_CODE (decl) == CONST_DECL)
else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
&& (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
{
- tree ctype = type;
- while (TREE_CODE (ctype) == ARRAY_TYPE)
- ctype = TREE_TYPE (ctype);
- if (! TYPE_NEEDS_CONSTRUCTING (ctype))
+ if (! TYPE_NEEDS_CONSTRUCTING (core_type))
{
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype))
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
cp_error ("structure `%D' with uninitialized const members", decl);
- if (CLASSTYPE_REF_FIELDS_NEED_INIT (ctype))
+ if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
cp_error ("structure `%D' with uninitialized reference members",
decl);
}
else if (! DECL_ARTIFICIAL (decl))
{
cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
- cp_warning_at (" you can work around this by removing the initializer"), decl;
+ cp_warning_at (" you can work around this by removing the initializer", decl);
}
}
}
else if (TREE_CODE (decl) == VAR_DECL
&& DECL_LANG_SPECIFIC (decl)
&& DECL_COMDAT (decl))
- {
- /* Dynamically initialized vars go into common. */
- if (DECL_INITIAL (decl) == NULL_TREE
- || DECL_INITIAL (decl) == error_mark_node)
- DECL_COMMON (decl) = 1;
- else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
- {
- DECL_COMMON (decl) = 1;
- DECL_INITIAL (decl) = error_mark_node;
- }
- else
- {
- /* Statically initialized vars are weak or comdat, if
- supported. */
- if (flag_weak)
- make_decl_one_only (decl);
- else
- {
- /* We can't do anything useful; leave vars for explicit
- instantiation. */
- DECL_EXTERNAL (decl) = 1;
- DECL_NOT_REALLY_EXTERN (decl) = 0;
- }
- }
- }
+ /* Set it up again; we might have set DECL_INITIAL since the
+ last time. */
+ comdat_linkage (decl);
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
make_decl_rtl (decl, NULL_PTR, toplev);
resume_temporary_allocation ();
if (type != error_mark_node
- && TYPE_LANG_SPECIFIC (type)
- && CLASSTYPE_ABSTRACT_VIRTUALS (type))
- abstract_virtuals_error (decl, type);
+ && TYPE_LANG_SPECIFIC (core_type)
+ && CLASSTYPE_ABSTRACT_VIRTUALS (core_type))
+ abstract_virtuals_error (decl, core_type);
else if ((TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type))
&& CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (type)))
abstract_virtuals_error (decl, TREE_TYPE (type));
- if (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE (type))
- signature_error (decl, type);
+ if (TYPE_LANG_SPECIFIC (core_type) && IS_SIGNATURE (core_type))
+ signature_error (decl, core_type);
else if ((TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type))
the binding level.. */
&& TYPE_SIZE (context) != NULL_TREE
&& context == current_class_type)
- popclass (1);
+ pop_nested_class ();
}
}
if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
cp_error ("multiple initializations given for `%D'", decl);
}
- else if (! toplevel_bindings_p () && ! pseudo_global_level_p ())
+ else if (! toplevel_bindings_p ())
{
/* Emit code to perform this initialization but once. */
tree temp;
/* Begin the conditional initialization. */
expand_start_cond (build_binary_op (EQ_EXPR, temp,
- integer_zero_node, 1), 0);
+ integer_zero_node), 0);
expand_start_target_temps ();
/* Do the initialization itself. */
{
tree cleanup, fcall;
static tree Atexit = 0;
+ int saved_flag_access_control;
+
if (Atexit == 0)
{
tree atexit_fndecl, PFV, pfvlist;
pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
push_lang_context (lang_name_c);
+ /* Note that we do not call pushdecl for this function;
+ there's no reason that this declaration should be
+ accessible to anyone. */
atexit_fndecl
- = builtin_function ("atexit",
- build_function_type (void_type_node,
- pfvlist),
- NOT_BUILT_IN, NULL_PTR);
+ = define_function ("atexit",
+ build_function_type (void_type_node,
+ pfvlist),
+ NOT_BUILT_IN,
+ /*pfn=*/0,
+ NULL_PTR);
mark_used (atexit_fndecl);
Atexit = default_conversion (atexit_fndecl);
pop_lang_context ();
so that any access checks will be done relative to the
current scope, rather than the scope of the anonymous
function. */
- fcall = build_cleanup (decl);
+ build_cleanup (decl);
+
+ /* Now start the function. */
cleanup = start_anon_func ();
+
+ /* Now, recompute the cleanup. It may contain SAVE_EXPRs
+ that refer 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;
+ flag_access_control = 0;
+ fcall = build_cleanup (decl);
+ flag_access_control = saved_flag_access_control;
+
+ /* Finish off the function. */
expand_expr_stmt (fcall);
end_anon_func ();
+
+ /* Call atexit with the cleanup function. */
mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
- fcall = build_function_call (Atexit, expr_tree_cons (NULL_TREE, cleanup, NULL_TREE));
+ fcall = build_function_call (Atexit,
+ expr_tree_cons (NULL_TREE,
+ cleanup,
+ NULL_TREE));
expand_expr_stmt (fcall);
}
expand_end_cond ();
- if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
- {
- static_aggregates = perm_tree_cons (temp, decl, static_aggregates);
- TREE_STATIC (static_aggregates) = 1;
- }
-
/* Resume old (possibly temporary) allocation. */
pop_obstacks ();
}
else
{
- /* This code takes into account memory allocation
- policy of `start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING
- does not hold for this object, then we must make permanent
- the storage currently in the temporary obstack. */
- if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ /* This code takes into account memory allocation policy of
+ `start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING does not
+ hold for this object, then we must make permanent the storage
+ currently in the temporary obstack. */
+ if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
preserve_initializer ();
static_aggregates = perm_tree_cons (init, decl, static_aggregates);
}
\f
/* Make TYPE a complete type based on INITIAL_VALUE.
Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
- 2 if there was no information (in which case assume 1 if DO_DEFAULT). */
+ 2 if there was no information (in which case assume 0 if DO_DEFAULT). */
int
complete_array_type (type, initial_value, do_default)
{
register tree maxindex = NULL_TREE;
int value = 0;
-
+
+ /* Allocate on the same obstack as TYPE. */
+ push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
+
if (initial_value)
{
/* Note MAXINDEX is really the maximum index,
/* Make an error message unless that happened already. */
if (initial_value != error_mark_node)
value = 1;
+ else
+ initial_value = NULL_TREE;
/* Prevent further error messages. */
maxindex = build_int_2 (0, 0);
if (maxindex)
{
tree itype;
+ tree domain;
+
+ domain = build_index_type (maxindex);
+ TYPE_DOMAIN (type) = domain;
- TYPE_DOMAIN (type) = build_index_type (maxindex);
if (! TREE_TYPE (maxindex))
- TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+ TREE_TYPE (maxindex) = domain;
if (initial_value)
itype = TREE_TYPE (initial_value);
else
itype = NULL;
if (itype && !TYPE_DOMAIN (itype))
- TYPE_DOMAIN (itype) = TYPE_DOMAIN (type);
+ TYPE_DOMAIN (itype) = domain;
/* The type of the main variant should never be used for arrays
of different sizes. It should only ever be completed with the
size of the array. */
if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)))
- TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = TYPE_DOMAIN (type);
+ TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain;
}
+ pop_obstacks();
+
/* Lay out the type now that we can get the real answer. */
layout_type (type);
static int
member_function_or_else (ctype, cur_type, string)
tree ctype, cur_type;
- char *string;
+ const char *string;
{
if (ctype && ctype != cur_type)
{
static void
bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
tree object;
- char *type;
+ const char *type;
int virtualp, quals, friendp, raises, inlinep;
{
if (virtualp)
static tree
grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
- raises, attrlist, check, friendp, publicp, inlinep, funcdef_flag,
+ raises, check, friendp, publicp, inlinep, funcdef_flag,
template_count, in_namespace)
tree ctype, type;
tree declarator;
tree orig_declarator;
int virtualp;
enum overload_flags flags;
- tree quals, raises, attrlist;
+ tree quals, raises;
int check, friendp, publicp, inlinep, funcdef_flag, template_count;
tree in_namespace;
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
+ int has_default_arg = 0;
tree t;
if (ctype)
if (TREE_PURPOSE (t)
&& TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
{
- add_defarg_fn (decl);
+ has_default_arg = 1;
break;
}
return NULL_TREE;
}
+
/* A friend declaration of the form friend void f<>(). Record
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
= perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
TREE_OPERAND (orig_declarator, 1),
NULL_TREE);
+
+ if (has_default_arg)
+ {
+ cp_error ("default arguments are not allowed in declaration of friend template specialization `%D'",
+ decl);
+ return NULL_TREE;
+ }
+
+ if (inlinep)
+ {
+ cp_error ("`inline' is not allowed in declaration of friend template specialization `%D'",
+ decl);
+ return NULL_TREE;
+ }
}
}
+ if (has_default_arg)
+ add_defarg_fn (decl);
+
/* Plain overloading: will not be grok'd by grokclassfn. */
if (! ctype && ! processing_template_decl
&& DECL_LANGUAGE (decl) != lang_c
if (ctype == NULL_TREE || check)
return decl;
- if (attrlist)
- cplus_decl_attributes (decl, TREE_PURPOSE (attrlist),
- TREE_VALUE (attrlist));
- make_decl_rtl (decl, NULL_PTR, 1);
-
if (virtualp)
{
DECL_VIRTUAL_P (decl) = 1;
return t;
}
+/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
+ Check to see that the definition is valid. Issue appropriate error
+ messages. Return 1 if the definition is particularly bad, or 0
+ otherwise. */
+
+int
+check_static_variable_definition (decl, type)
+ tree decl;
+ tree type;
+{
+ /* Motion 10 at San Diego: If a static const integral data member is
+ initialized with an integral constant expression, the initializer
+ may appear either in the declaration (within the class), or in
+ the definition, but not both. If it appears in the class, the
+ member is a member constant. The file-scope definition is always
+ required. */
+ if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ cp_error ("in-class initialization of static data member of non-integral type `%T'",
+ type);
+ /* If we just return the declaration, crashes will sometimes
+ occur. We therefore return void_type_node, as if this was a
+ friend declaration, to cause callers to completely ignore
+ this declaration. */
+ return 1;
+ }
+ else if (!CP_TYPE_CONST_P (type))
+ cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
+ decl);
+ else if (pedantic && !INTEGRAL_TYPE_P (type))
+ cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+
+ return 0;
+}
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
BITFIELD for a field with specified width.
INITIALIZED is 1 if the decl has an initializer.
+ ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and
+ normal attributes in TREE_PURPOSE, or NULL_TREE.
+
In the TYPENAME case, DECLARATOR is really an absolute declarator.
It may also be so in the PARM case, for a prototype where the
argument type is specified but not the name.
enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
-/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
- Check to see that the definition is valid. Issue appropriate error
- messages. Return 1 if the definition is particularly bad, or 0
- otherwise. */
-
-int
-check_static_variable_definition (decl, type)
- tree decl;
- tree type;
-{
- /* Motion 10 at San Diego: If a static const integral data member is
- initialized with an integral constant expression, the initializer
- may appear either in the declaration (within the class), or in
- the definition, but not both. If it appears in the class, the
- member is a member constant. The file-scope definition is always
- required. */
- if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
- {
- cp_error ("in-class initialization of static data member of non-integral type `%T'",
- type);
- /* If we just return the declaration, crashes will sometimes
- occur. We therefore return void_type_node, as if this was a
- friend declaration, to cause callers to completely ignore
- this declaration. */
- return 1;
- }
- else if (!CP_TYPE_CONST_P (type))
- cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
- decl);
- else if (pedantic && !INTEGRAL_TYPE_P (type))
- cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
-
- return 0;
-}
-
tree
grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree declspecs;
case CALL_EXPR:
if (parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
{
- /* This is actually a variable declaration using constructor
- syntax. We need to call start_decl and cp_finish_decl so we
- can get the variable initialized... */
+ /* This is actually a variable declaration using
+ constructor syntax. We need to call start_decl and
+ cp_finish_decl so we can get the variable
+ initialized... */
+
+ tree attributes, prefix_attributes;
*next = TREE_OPERAND (decl, 0);
init = TREE_OPERAND (decl, 1);
- decl = start_decl (declarator, declspecs, 1, NULL_TREE, NULL_TREE);
+ if (attrlist)
+ {
+ attributes = TREE_PURPOSE (attrlist);
+ prefix_attributes = TREE_VALUE (attrlist);
+ }
+ else
+ {
+ attributes = NULL_TREE;
+ prefix_attributes = NULL_TREE;
+ }
+
+ decl = start_decl (declarator, declspecs, 1,
+ attributes, prefix_attributes);
if (decl)
{
/* Look for __unused__ attribute */
if (TREE_CODE (fns) == LOOKUP_EXPR)
fns = TREE_OPERAND (fns, 0);
- if (TREE_CODE (fns) == IDENTIFIER_NODE)
- dname = fns;
- else if (is_overloaded_fn (fns))
- dname = DECL_NAME (get_first_fn (fns));
- else
- my_friendly_abort (0);
+ dname = fns;
+ if (TREE_CODE (dname) == COMPONENT_REF)
+ dname = TREE_OPERAND (dname, 1);
+ if (TREE_CODE (dname) != IDENTIFIER_NODE)
+ {
+ my_friendly_assert (is_overloaded_fn (dname),
+ 19990331);
+ dname = DECL_NAME (get_first_fn (dname));
+ }
}
/* Fall through. */
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
if (RIDBIT_SETP (RID_UNSIGNED, specbits)
- || (bitfield && ! flag_signed_bitfields
- && (explicit_int || defaulted_int || explicit_char
- /* A typedef for plain `int' without `signed'
- can be controlled just like plain `int'. */
- || ! (typedef_decl != NULL_TREE
- && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
- && TREE_CODE (type) != ENUMERAL_TYPE
- && RIDBIT_NOTSETP (RID_SIGNED, specbits)))
+ /* [class.bit]
+
+ It is implementation-defined whether a plain (neither
+ explicitly signed or unsigned) char, short, int, or long
+ bit-field is signed or unsigned.
+
+ Naturally, we extend this to long long as well. Note that
+ this does not include wchar_t. */
+ || (bitfield && !flag_signed_bitfields
+ && RIDBIT_NOTSETP (RID_SIGNED, specbits)
+ /* A typedef for plain `int' without `signed' can be
+ controlled just like plain `int', but a typedef for
+ `signed int' cannot be so controlled. */
+ && !(typedef_decl
+ && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
+ && (TREE_CODE (type) == INTEGER_TYPE
+ || TREE_CODE (type) == CHAR_TYPE)
+ && !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
{
if (longlong)
type = long_long_unsigned_type_node;
/* Static anonymous unions are dealt with here. */
if (staticp && decl_context == TYPENAME
&& TREE_CODE (declspecs) == TREE_LIST
- && ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
+ && ANON_AGGR_TYPE_P (TREE_VALUE (declspecs)))
decl_context = FIELD;
/* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual'
if (type == error_mark_node)
continue;
+ /* VC++ spells a zero-sized array with []. */
+ if (size == NULL_TREE && decl_context == FIELD && ! staticp
+ && ! RIDBIT_SETP (RID_TYPEDEF, specbits))
+ size = integer_zero_node;
+
if (size)
{
/* Must suspend_momentary here because the index
= fold (build_binary_op (MINUS_EXPR,
cp_convert (index_type, size),
cp_convert (index_type,
- integer_one_node), 1));
+ integer_one_node)));
if (! TREE_CONSTANT (itype))
itype = variable_size (itype);
else if (TREE_OVERFLOW (itype))
push_nested_class used to push into class scope for
parsing the argument list of a function decl, in
qualified_id. */
- pop_nested_class (1);
+ pop_nested_class ();
TREE_COMPLEXITY (declarator) = current_class_depth;
}
else
attrlist = build_decl_list (NULL_TREE, inner_attrs);
}
+ /* Now TYPE has the actual type. */
+
if (explicitp == 1)
{
error ("only constructors can be declared `explicit'");
explicitp = 0;
}
- /* Now TYPE has the actual type. */
-
- /* If this is declaring a typedef name, return a TYPE_DECL. */
-
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
if (type_quals & TYPE_QUAL_CONST)
declarator = dname;
}
else
+ /* Unexpected declarator format. */
my_friendly_abort (990210);
+ /* If this is declaring a typedef name, return a TYPE_DECL. */
+
if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
{
tree decl;
if (type != error_mark_node
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))
+ && CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED)
{
- /* FIXME: This is bogus; we should not be doing this for
- cv-qualified types. */
-
- /* For anonymous structs that are cv-qualified, need to use
- TYPE_MAIN_VARIANT so that name will mangle correctly. As
- type not referenced after this block, don't bother
- resetting type to original type, ie. TREE_TYPE (decl). */
- type = TYPE_MAIN_VARIANT (type);
+ tree oldname = TYPE_NAME (type);
+ tree t;
/* Replace the anonymous name with the real name everywhere. */
lookup_tag_reverse (type, declarator);
- TYPE_NAME (type) = decl;
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ if (TYPE_NAME (t) == oldname)
+ TYPE_NAME (t) = decl;
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_ANONYMOUS (type) = 1;
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
? declarator : dname,
declarator,
- virtualp, flags, quals, raises, attrlist,
+ virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
funcdef_flag, template_count, in_namespace);
if (decl == NULL_TREE)
/* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type, declarator, declarator,
- virtualp, flags, quals, raises, attrlist,
+ virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
template_count, in_namespace);
if (decl == NULL_TREE)
}
t = do_friend (ctype, declarator, decl,
- last_function_parms, flags, quals,
+ last_function_parms, attrlist, flags, quals,
funcdef_flag);
}
if (t && funcdef_flag)
|| !RIDBIT_SETP (RID_STATIC, specbits));
decl = grokfndecl (ctype, type, original_name, declarator,
- virtualp, flags, quals, raises, attrlist,
+ virtualp, flags, quals, raises,
1, friendp,
publicp, inlinep, funcdef_flag,
template_count, in_namespace);
if (RIDBIT_SETP (RID_STATIC, specbits))
DECL_THIS_STATIC (decl) = 1;
- /* Record constancy and volatility. */
- /* FIXME: Disallow `restrict' pointer-to-member declarations. */
- c_apply_type_quals_to_decl (type_quals, decl);
+ /* Record constancy and volatility. There's no need to do this
+ when processing a template; we'll do this for the instantiated
+ declaration based on the type of DECL. */
+ if (!processing_template_decl)
+ c_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
if (name == ansi_opname[(int) MODIFY_EXPR]
&& !(DECL_TEMPLATE_INSTANTIATION (decl)
&& is_member_template (DECL_TI_TEMPLATE (decl))))
- TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
+ ;
else if (name == ansi_opname[(int) CALL_EXPR])
TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
else if (name == ansi_opname[(int) ARRAY_REF])
else if (! friendp)
{
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
- char *what = 0;
+ const char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
}
}
\f
-static char *
+static const char *
tag_name (code)
enum tag_types code;
{
enum tree_code code;
int temp = 0;
register tree ref, t;
- struct binding_level *b = inner_binding_level;
+ struct binding_level *b = current_binding_level;
int got_type = 0;
tree attributes = NULL_TREE;
+ tree context = NULL_TREE;
/* If we are called from the parser, code_type_node will sometimes be a
TREE_LIST. This indicates that the user wrote
}
else
{
- if (current_class_type
- && template_class_depth (current_class_type)
- && PROCESSING_REAL_TEMPLATE_DECL_P ())
- /* Since GLOBALIZE is non-zero, we are not looking at a
- definition of this tag. Since, in addition, we are currently
- processing a (member) template declaration of a template
- class, we don't want to do any lookup at all; consider:
-
- template <class X>
- struct S1
-
- template <class U>
- struct S2
- { template <class V>
- friend struct S1; };
-
- Here, the S2::S1 declaration should not be confused with the
- outer declaration. In particular, the inner version should
- have a template parameter of level 2, not level 1. This
- would be particularly important if the member declaration
- were instead:
-
- template <class V = U> friend struct S1;
-
- say, when we should tsubst into `U' when instantiating S2. */
- ref = NULL_TREE;
- else
+ if (t)
{
- if (t)
- {
- if (t != TYPE_MAIN_VARIANT (t))
- cp_pedwarn ("using typedef-name `%D' after `%s'",
- TYPE_NAME (t), tag_name (tag_code));
- ref = t;
- }
- else
- ref = lookup_tag (code, name, b, 0);
+ /* [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 != TYPE_MAIN_VARIANT (t)
+ || (CLASS_TYPE_P (t) && TYPE_WAS_ANONYMOUS (t)))
+ cp_pedwarn ("using typedef-name `%D' after `%s'",
+ TYPE_NAME (t), tag_name (tag_code));
+ else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ cp_error ("using template type parameter `%T' after `%s'",
+ t, tag_name (tag_code));
+
+ ref = t;
+ }
+ else
+ ref = lookup_tag (code, name, b, 0);
- if (! ref)
- {
- /* Try finding it as a type declaration. If that wins,
- use it. */
- ref = lookup_name (name, 1);
-
- if (ref != NULL_TREE
- && processing_template_decl
- && DECL_CLASS_TEMPLATE_P (ref)
- && template_class_depth (current_class_type) == 0)
- /* Since GLOBALIZE is true, we're declaring a global
+ if (! ref)
+ {
+ /* Try finding it as a type declaration. If that wins,
+ use it. */
+ ref = lookup_name (name, 1);
+
+ if (ref != NULL_TREE
+ && processing_template_decl
+ && DECL_CLASS_TEMPLATE_P (ref)
+ && template_class_depth (current_class_type) == 0)
+ /* Since GLOBALIZE is true, we're declaring a global
template, so we want this type. */
- ref = DECL_RESULT (ref);
+ ref = DECL_RESULT (ref);
- if (ref && TREE_CODE (ref) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (ref)) == code)
- ref = TREE_TYPE (ref);
- else
- ref = NULL_TREE;
- }
+ if (ref && TREE_CODE (ref) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (ref)) == code)
+ ref = TREE_TYPE (ref);
+ else
+ ref = NULL_TREE;
+ }
+
+ if (ref && current_class_type
+ && template_class_depth (current_class_type)
+ && PROCESSING_REAL_TEMPLATE_DECL_P ())
+ {
+ /* Since GLOBALIZE is non-zero, we are not looking at a
+ definition of this tag. Since, in addition, we are currently
+ processing a (member) template declaration of a template
+ class, we must be very careful; consider:
+
+ template <class X>
+ struct S1
+
+ template <class U>
+ struct S2
+ { template <class V>
+ friend struct S1; };
+
+ Here, the S2::S1 declaration should not be confused with the
+ outer declaration. In particular, the inner version should
+ have a template parameter of level 2, not level 1. This
+ would be particularly important if the member declaration
+ were instead:
+
+ template <class V = U> friend struct S1;
+
+ say, when we should tsubst into `U' when instantiating
+ S2. On the other hand, when presented with:
+
+ template <class T>
+ struct S1 {
+ template <class U>
+ struct S2 {};
+ template <class U>
+ friend struct S2;
+ };
+
+ we must find the inner binding eventually. We
+ accomplish this by making sure that the new type we
+ create to represent this declaration has the right
+ TYPE_CONTEXT. */
+ context = TYPE_CONTEXT (ref);
+ ref = NULL_TREE;
}
}
struct binding_level *old_b = class_binding_level;
ref = make_lang_type (code);
+ TYPE_CONTEXT (ref) = context;
if (tag_code == signature_type)
{
TREE_TYPE (ref) = attributes;
- if (ref && TYPE_P (ref))
- {
- /* [dcl.type.elab]
-
- If the identifier resolves to a typedef-name or a template
- type-parameter, the elaborated-type-specifier is
- ill-formed. */
- if (TYPE_LANG_SPECIFIC (ref) && TYPE_WAS_ANONYMOUS (ref))
- cp_error ("`%T' is a typedef name", ref);
- else if (TREE_CODE (ref) == TEMPLATE_TYPE_PARM)
- cp_error ("`%T' is a template type paramter", ref);
- }
-
return ref;
}
/* 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 base;
+
int i, len;
enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
len = list_length (binfo);
push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
+ /* First, make sure that any templates in base-classes are
+ instantiated. This ensures that if we call ourselves recursively
+ we do not get confused about which classes are marked and which
+ are not. */
+ for (base = binfo; base; base = TREE_CHAIN (base))
+ complete_type (TREE_VALUE (base));
+
SET_CLASSTYPE_MARKED (ref);
BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
-#if 1
/* This code replaces similar code in layout_basetypes.
We put the complete_type first for implicit `typename'. */
- if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
+ if (TYPE_SIZE (basetype) == NULL_TREE
&& ! (current_template_parms && uses_template_parms (basetype)))
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
}
-#endif
else
{
if (CLASSTYPE_MARKED (basetype))
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. */
+ CLASSTYPE_VBASECLASSES (ref) = get_vbase_types (ref);
+
pop_obstacks ();
}
tree name;
{
register tree enumtype = NULL_TREE;
- struct binding_level *b = inner_binding_level;
+ struct binding_level *b = current_binding_level;
/* We are wasting space here and putting these on the permanent_obstack so
that typeid(local enum) will work correctly. */
TREE_READONLY (decl) = 1;
if (context && context == current_class_type)
- {
- pushdecl_class_level (decl);
- /* In something like `struct S { enum E { i = 7 }; };' we put `i'
- on the TYPE_FIELDS list for `S'. (That's so that you can say
- things like `S::i' later.) */
- finish_member_declaration (decl);
- }
+ /* In something like `struct S { enum E { i = 7 }; };' we put `i'
+ on the TYPE_FIELDS list for `S'. (That's so that you can say
+ things like `S::i' later.) */
+ finish_member_declaration (decl);
else
{
pushdecl (decl);
{
DECL_EXTERNAL (decl1)
= (interface_only
- || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
+ || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines
+ && !DECL_VINDEX (decl1)));
/* For WIN32 we also want to put these in linkonce sections. */
maybe_make_one_only (decl1);
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
}
+ else if (interface_unknown && interface_only
+ && (! DECL_TEMPLATE_INSTANTIATION (decl1)
+ || flag_alt_external_templates))
+ {
+ /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
+ interface, we will have interface_only set but not
+ interface_known. In that case, we don't want to use the normal
+ heuristics because someone will supply a #pragma implementation
+ elsewhere, and deducing it here would produce a conflict. */
+ comdat_linkage (decl1);
+ DECL_EXTERNAL (decl1) = 0;
+ DECL_INTERFACE_KNOWN (decl1) = 1;
+ DECL_DEFER_OUTPUT (decl1) = 1;
+ }
else
{
/* This is a definition, not a reference.
if (fndecl == NULL_TREE)
return;
- if (! nested && function_depth > 1)
+ if (function_depth > 1)
nested = 1;
fntype = TREE_TYPE (fndecl);
if (! ok_to_optimize_dtor)
{
cond = build_binary_op (NE_EXPR,
- current_class_ptr, integer_zero_node, 1);
+ current_class_ptr, integer_zero_node);
expand_start_cond (cond, 0);
}
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
- DECL_RETURNS_FIRST_ARG (fndecl) = 1;
-
if (flag_this_is_variable > 0)
{
cond = build_binary_op (EQ_EXPR,
- current_class_ptr, integer_zero_node, 1);
+ current_class_ptr, integer_zero_node);
thenclause = build_modify_expr (current_class_ptr, NOP_EXPR,
build_new (NULL_TREE, current_class_type, void_type_node, 0));
}
if (current_class_name)
{
ctype = current_class_type;
- pop_nested_class (1);
+ pop_nested_class ();
}
/* Must mark the RESULT_DECL as being in this function. */
tree decl, auto_delete;
{
tree type = TREE_TYPE (decl);
- if (TYPE_NEEDS_DESTRUCTOR (type))
+ if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
{
int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
*argtypes = args;
}
-int
-id_in_current_class (id)
- tree id;
-{
- return !!purpose_member (id, class_binding_level->class_shadowed);
-}
-
struct cp_function
{
int returns_value;