/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001 Free Software Foundation, Inc.
+ 2001, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
#include "ggc.h"
#include "tm_p.h"
#include "target.h"
+#include "c-common.h"
+#include "c-pragma.h"
+#include "diagnostic.h"
extern const struct attribute_spec *lang_attribute_table;
static void set_identifier_type_value_with_scope
PARAMS ((tree, tree, struct binding_level *));
static void record_unknown_type PARAMS ((tree, const char *));
+static tree builtin_function_1 PARAMS ((const char *, tree, tree, int,
+ enum built_in_class, const char *));
static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree));
static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
static void save_function_data PARAMS ((tree));
static void check_function_type PARAMS ((tree, tree));
static void destroy_local_var PARAMS ((tree));
+static void begin_constructor_body PARAMS ((void));
static void finish_constructor_body PARAMS ((void));
+static void begin_destructor_body PARAMS ((void));
static void finish_destructor_body PARAMS ((void));
static tree create_array_type_for_decl PARAMS ((tree, tree, tree));
static tree get_atexit_node PARAMS ((void));
static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
static void store_parm_decls PARAMS ((tree));
static int cp_missing_noreturn_ok_p PARAMS ((tree));
-static void shadow_warning PARAMS ((const char *, tree, tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PARAMS ((void));
\f
/* C and C++ flags are in decl2.c. */
-/* Flag used when debugging spew.c */
-
-extern int spew_debug;
-
/* A expression of value 0 with the same precision as a sizetype
node, but signed. */
tree signed_size_zero_node;
(Zero if we are at namespace scope, one inside the body of a
function, two inside the body of a function in a local class, etc.) */
int function_depth;
+
+/* States indicating how grokdeclarator() should handle declspecs marked
+ with __attribute__((deprecated)). An object declared as
+ __attribute__((deprecated)) suppresses warnings of uses of other
+ deprecated items. */
+
+enum deprecated_states {
+ DEPRECATED_NORMAL,
+ DEPRECATED_SUPPRESS
+};
+
+static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+
+/* Set by add_implicitly_declared_members() to keep those members from
+ being flagged as deprecated or reported as using deprecated
+ types. */
+int adding_implicit_members = 0;
\f
/* For each binding contour we allocate a binding_level structure
which records the names defined in that contour.
/* The binding level which this one is contained in (inherits from). */
struct binding_level *level_chain;
- /* List of decls in `names' that have incomplete
- structure or union types. */
- tree incomplete;
-
/* List of VAR_DECLS saved from a previous for statement.
These would be dead in ISO-conforming code, but might
be referenced in ARM-era code. These are stored in a
static int keep_next_level_flag;
+/* A TREE_LIST of VAR_DECLs. The TREE_PURPOSE is a RECORD_TYPE or
+ UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the
+ time the VAR_DECL was declared, the type was incomplete. */
+
+static tree incomplete_vars;
+
#if defined(DEBUG_CP_BINDING_LEVELS)
static int binding_depth = 0;
static int is_class_level = 0;
{
/* Cannot pop a level, if there are none left to pop. */
if (current_binding_level == global_binding_level)
- my_friendly_abort (123);
+ abort ();
}
/* Pop the current level, and free the structure for reuse. */
#if defined(DEBUG_CP_BINDING_LEVELS)
{
/* Cannot suspend a level, if there are none left to suspend. */
if (current_binding_level == global_binding_level)
- my_friendly_abort (123);
+ abort ();
}
/* Suspend the current level. */
#if defined(DEBUG_CP_BINDING_LEVELS)
newlevel = make_binding_level ();
push_binding_level (newlevel, tag_transparent, keep_next_level_flag);
- GNU_xref_start_scope ((size_t) newlevel);
keep_next_level_flag = 0;
}
break;
default:
- my_friendly_abort (20000309);
+ abort ();
}
}
/* For a binding between a name and an entity at a block scope,
this is the `struct binding_level' for the block. */
#define BINDING_LEVEL(NODE) \
- (((struct tree_binding*)NODE)->scope.level)
+ (((struct tree_binding*)(NODE))->scope.level)
/* A free list of CPLUS_BINDING nodes, connected by their
TREE_CHAINs. */
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))))
+ && (same_type_p (TREE_TYPE (decl),
+ TREE_TYPE (BINDING_VALUE (binding)))
+ /* If either type involves template parameters, we must
+ wait until instantiation. */
+ || uses_template_parms (TREE_TYPE (decl))
+ || uses_template_parms (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:
}
else
{
- cp_error ("declaration of `%#D'", decl);
+ error ("declaration of `%#D'", decl);
cp_error_at ("conflicts with previous declaration `%#D'",
BINDING_VALUE (binding));
ok = 0;
else if (BINDING_TYPE (binding) == decl)
BINDING_TYPE (binding) = NULL_TREE;
else
- my_friendly_abort (0);
+ abort ();
if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
{
rather than the end. This hack is no longer used. */
my_friendly_assert (keep == 0 || keep == 1, 0);
- GNU_xref_end_scope ((size_t) current_binding_level,
- (size_t) current_binding_level->level_chain,
- current_binding_level->parm_flag,
- current_binding_level->keep);
-
if (current_binding_level->keep == 1)
keep = 1;
else if (TREE_CODE (decl) == OVERLOAD)
pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
else
- my_friendly_abort (0);
+ abort ();
}
}
shadowed = TREE_CHAIN (shadowed))
pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));
- GNU_xref_end_scope ((size_t) class_binding_level,
- (size_t) class_binding_level->level_chain,
- class_binding_level->parm_flag,
- class_binding_level->keep);
-
/* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
#if defined(DEBUG_CP_BINDING_LEVELS)
ggc_mark_tree (lvl->shadowed_labels);
ggc_mark_tree (lvl->blocks);
ggc_mark_tree (lvl->this_class);
- ggc_mark_tree (lvl->incomplete);
ggc_mark_tree (lvl->dead_vars_from_for);
}
}
int i = 0, len;
fprintf (stderr, " blocks=");
fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
- fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d",
- list_length (lvl->incomplete), lvl->parm_flag, lvl->keep);
if (lvl->tag_transparent)
fprintf (stderr, " tag-transparent");
if (lvl->more_cleanups_ok)
need_new = 0;
if (DECL_NAMESPACE_ALIAS (d))
{
- cp_error ("namespace alias `%D' not allowed here, assuming `%D'",
+ error ("namespace alias `%D' not allowed here, assuming `%D'",
d, DECL_NAMESPACE_ALIAS (d));
d = DECL_NAMESPACE_ALIAS (d);
}
ggc_mark_tree (t->x_previous_class_type);
ggc_mark_tree (t->x_previous_class_values);
ggc_mark_tree (t->x_saved_tree);
- ggc_mark_tree (t->incomplete);
ggc_mark_tree (t->lookups);
mark_stmt_tree (&t->x_stmt_tree);
s->bindings = b;
s->need_pop_function_context = need_pop;
s->function_decl = current_function_decl;
+ s->last_parms = last_function_parms;
scope_chain = s;
current_function_decl = NULL_TREE;
if (s->need_pop_function_context)
pop_function_context_from (NULL_TREE);
current_function_decl = s->function_decl;
+ last_function_parms = s->last_parms;
free (s);
}
return;
name = DECL_ASSEMBLER_NAME (newdecl);
- cp_pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
+ pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
? implicit_extern_static_warning
: explicit_extern_static_warning, newdecl);
cp_pedwarn_at ("previous declaration of `%D'", olddecl);
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
+ /* Avoid warnings redeclaring anticipated built-ins. */
+ if (DECL_ANTICIPATED (olddecl))
+ return 0;
+
/* If you declare a built-in or predefined function name as static,
the old definition is overridden, but optionally warn this was a
bad choice of name. */
if (! TREE_PUBLIC (newdecl))
{
if (warn_shadow)
- cp_warning ("shadowing %s function `%#D'",
+ warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
/* Discard the old built-in function. */
/* If the built-in is not ansi, then programs can override
it even globally without an error. */
else if (! DECL_BUILT_IN (olddecl))
- cp_warning ("library function `%#D' redeclared as non-function `%#D'",
+ warning ("library function `%#D' redeclared as non-function `%#D'",
olddecl, newdecl);
else
{
- cp_error ("declaration of `%#D'", newdecl);
- cp_error ("conflicts with built-in declaration `%#D'",
+ error ("declaration of `%#D'", newdecl);
+ error ("conflicts with built-in declaration `%#D'",
olddecl);
}
return 0;
}
else if (!types_match)
{
- if ((DECL_EXTERN_C_P (newdecl)
+ /* Avoid warnings redeclaring anticipated built-ins. */
+ if (DECL_ANTICIPATED (olddecl))
+ ; /* Do nothing yet. */
+ else if ((DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl))
|| compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
if (TREE_PUBLIC (newdecl))
{
- cp_warning ("new declaration `%#D'", newdecl);
- cp_warning ("ambiguates built-in declaration `%#D'",
+ warning ("new declaration `%#D'", newdecl);
+ warning ("ambiguates built-in declaration `%#D'",
olddecl);
}
else if (warn_shadow)
- cp_warning ("shadowing %s function `%#D'",
+ warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
}
else
/* Discard the old built-in function. */
return 0;
+
+ /* Replace the old RTL to avoid problems with inlining. */
+ SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
will be banished. */
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
- COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
- SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (newdecl),
- newdecl);
}
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
return 0;
- cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
+ error ("`%#D' redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
cp_error_at ("previous declaration of `%#D'", olddecl);
if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
|| TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
{
- cp_error ("declaration of template `%#D'", newdecl);
+ error ("declaration of template `%#D'", newdecl);
cp_error_at ("conflicts with previous declaration `%#D'",
olddecl);
}
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
{
- cp_error ("new declaration `%#D'", newdecl);
+ error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
return 0;
{
if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
{
- cp_error ("declaration of C function `%#D' conflicts with",
+ error ("declaration of C function `%#D' conflicts with",
newdecl);
cp_error_at ("previous declaration `%#D' here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
- cp_error ("new declaration `%#D'", newdecl);
+ error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
else
else if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
{
- cp_error ("conflicting types for `%#D'", newdecl);
+ error ("conflicting types for `%#D'", newdecl);
cp_error_at ("previous declaration as `%#D'", olddecl);
}
}
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
- cp_error (errmsg, newdecl);
+ error (errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
&& namespace_bindings_p ())
? "`%#D' previously defined here"
: "`%#D' previously declared here", olddecl);
+ return 0;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != NULL_TREE
{
cp_error_at ("previous declaration of `%#D' with %L linkage",
olddecl, DECL_LANGUAGE (olddecl));
- cp_error ("conflicts with new declaration with %L linkage",
+ error ("conflicts with new declaration with %L linkage",
DECL_LANGUAGE (newdecl));
}
}
if (1 == simple_cst_equal (TREE_PURPOSE (t1),
TREE_PURPOSE (t2)))
{
- if (pedantic)
- {
- cp_pedwarn ("default argument given for parameter %d of `%#D'",
- i, newdecl);
- cp_pedwarn_at ("after previous specification in `%#D'",
- olddecl);
- }
+ pedwarn ("default argument given for parameter %d of `%#D'",
+ i, newdecl);
+ cp_pedwarn_at ("after previous specification in `%#D'",
+ olddecl);
}
else
{
- cp_error ("default argument given for parameter %d of `%#D'",
+ error ("default argument given for parameter %d of `%#D'",
i, newdecl);
cp_error_at ("after previous specification in `%#D'",
olddecl);
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& TREE_ADDRESSABLE (olddecl) && warn_inline)
{
- cp_warning ("`%#D' was used before it was declared inline",
+ warning ("`%#D' was used before it was declared inline",
newdecl);
cp_warning_at ("previous non-inline declaration here",
olddecl);
/* Don't warn about friends, let add_friend take care of it. */
&& ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
{
- cp_warning ("redundant redeclaration of `%D' in same scope", newdecl);
+ warning ("redundant redeclaration of `%D' in same scope", newdecl);
cp_warning_at ("previous declaration of `%D'", olddecl);
}
}
except for any that we copy here from the old type. */
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
+ decl_attributes (&newdecl, DECL_ATTRIBUTES (newdecl), 0);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
tree newtype;
/* Merge the data types specified in the two decls. */
- newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
+ newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
- /* If common_type produces a non-typedef type, just use the old type. */
+ /* If merge_types produces a non-typedef type, just use the old type. */
if (TREE_CODE (newdecl) == TYPE_DECL
&& newtype == DECL_ORIGINAL_TYPE (newdecl))
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
- /* Do this after calling `common_type' so that default
+ /* Do this after calling `merge_types' so that default
parameters don't confuse us. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
&& !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
{
- cp_error ("declaration of `%F' throws different exceptions",
+ error ("declaration of `%F' throws different exceptions",
newdecl);
cp_error_at ("than previous declaration `%F'", olddecl);
}
{
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
- DECL_NO_CHECK_MEMORY_USAGE (newdecl)
- |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
DECL_NO_LIMIT_STACK (newdecl)
|= DECL_NO_LIMIT_STACK (olddecl);
}
that specialization that would cause an implicit
instantiation to take place, in every translation unit in
which such a use occurs. */
- cp_error ("explicit specialization of %D after first use",
+ error ("explicit specialization of %D after first use",
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common)
- + tree_code_length [(int)TREE_CODE (newdecl)] * sizeof (char *));
+ + TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
}
DECL_UID (olddecl) = olddecl_uid;
return 1;
}
-/* Output a -Wshadow warning MSGID, if non-NULL, and give the location
- of the previous declaration. */
-static void
-shadow_warning (msgid, name, decl)
- const char *msgid;
- tree name, decl;
-{
- warning ("declaration of `%s' shadows %s", IDENTIFIER_POINTER (name), msgid);
- warning_with_file_and_line (DECL_SOURCE_FILE (decl),
- DECL_SOURCE_LINE (decl),
- "shadowed declaration is here");
-}
-
-
/* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same
name already seen in the same scope).
else if (t == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
- cp_pedwarn ("redeclaration of `wchar_t' as `%T'",
+ pedwarn ("redeclaration of `wchar_t' as `%T'",
TREE_TYPE (x));
/* Throw away the redeclaration. */
This function shall not be overloaded. */
cp_error_at ("invalid redeclaration of `%D'", t);
- cp_error ("as `%D'", x);
+ error ("as `%D'", x);
/* We don't try to push this declaration since that
causes a crash. */
return x;
&& TREE_CODE (decl) == TREE_CODE (x)
&& !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
{
- cp_pedwarn ("type mismatch with previous external decl", x);
+ pedwarn ("type mismatch with previous external decl", x);
cp_pedwarn_at ("previous external decl of `%#D'", decl);
}
}
/* If this real decl matches the implicit, don't complain. */
&& ! (TREE_CODE (x) == FUNCTION_DECL
&& TREE_TYPE (TREE_TYPE (x)) == integer_type_node))
- cp_warning
+ warning
("`%D' was previously implicitly declared to return `int'", x);
/* If new decl is `static' and an `extern' was seen previously,
/* OK */;
else
{
- cp_warning ("extern declaration of `%#D' doesn't match", x);
+ warning ("extern declaration of `%#D' doesn't match", x);
cp_warning_at ("global declaration `%#D'", oldglobal);
}
}
them there. */
struct binding_level *b = current_binding_level->level_chain;
- if (cleanup_label)
- b = b->level_chain;
-
/* ARM $8.3 */
if (b->parm_flag == 1)
{
- cp_error ("declaration of `%#D' shadows a parameter",
+ error ("declaration of `%#D' shadows a parameter",
name);
err = true;
}
if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
&& current_class_ptr
&& !TREE_STATIC (name))
- cp_warning ("declaration of `%s' shadows a member of `this'",
+ warning ("declaration of `%s' shadows a member of `this'",
IDENTIFIER_POINTER (name));
else if (oldlocal != NULL_TREE
&& TREE_CODE (oldlocal) == VAR_DECL)
if (TREE_CODE (x) == FUNCTION_DECL)
check_default_args (x);
- /* Keep count of variables in this level with incomplete type. */
- if (TREE_CODE (x) == VAR_DECL
- && TREE_TYPE (x) != error_mark_node
- && ((!COMPLETE_TYPE_P (TREE_TYPE (x))
- && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
- /* RTTI TD entries are created while defining the type_info. */
- || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
- && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
- {
- if (namespace_bindings_p ())
- namespace_scope_incomplete
- = tree_cons (NULL_TREE, x, namespace_scope_incomplete);
- else
- current_binding_level->incomplete
- = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
- }
+ if (TREE_CODE (x) == VAR_DECL)
+ maybe_register_incomplete_var (x);
}
if (need_new_binding)
if (IS_AGGR_TYPE (t) && warn_shadow
&& (! DECL_IN_SYSTEM_HEADER (decl)
|| ! DECL_IN_SYSTEM_HEADER (old)))
- cp_warning ("`%#D' hides constructor for `%#T'", decl, t);
+ warning ("`%#D' hides constructor for `%#T'", decl, t);
old = NULL_TREE;
}
else if (is_overloaded_fn (old))
&& !(flags & PUSH_USING)
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
TYPE_ARG_TYPES (TREE_TYPE (decl))))
- cp_error ("`%#D' conflicts with previous using declaration `%#D'",
+ error ("`%#D' conflicts with previous using declaration `%#D'",
decl, fn);
if (duplicate_decls (decl, fn))
else
{
cp_error_at ("previous non-function declaration `%#D'", old);
- cp_error ("conflicts with function declaration `%#D'", decl);
+ error ("conflicts with function declaration `%#D'", decl);
return decl;
}
}
}
/* We should always find a previous binding in this case. */
- my_friendly_abort (0);
+ abort ();
}
/* Install the new binding. */
/* Only one warning per identifier. */
&& IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE)
{
- cp_pedwarn ("implicit declaration of function `%#D'", decl);
+ pedwarn ("implicit declaration of function `%#D'", decl);
}
SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
if (! identified)
{
if (decl)
- cp_pedwarn ("jump to label `%D'", decl);
+ pedwarn ("jump to label `%D'", decl);
else
pedwarn ("jump to case label");
if (! identified)
{
if (decl)
- cp_pedwarn ("jump to label `%D'", decl);
+ pedwarn ("jump to label `%D'", decl);
else
pedwarn ("jump to case label");
p->more_cleanups_ok = 0;
if (name == get_identifier ("wchar_t"))
- cp_pedwarn ("label named wchar_t");
+ pedwarn ("label named wchar_t");
if (DECL_INITIAL (decl) != NULL_TREE)
{
- cp_error ("duplicate label `%D'", decl);
+ error ("duplicate label `%D'", decl);
return 0;
}
else
if (high_value)
error ("case label not within a switch statement");
else if (low_value)
- cp_error ("case label `%E' not within a switch statement",
+ error ("case label `%E' not within a switch statement",
low_value);
else
error ("`default' label not within a switch statement");
if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
old = NULL_TREE;
if (old && TREE_CODE (old) != form
- && !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL))
+ && (form == ENUMERAL_TYPE || TREE_CODE (old) == ENUMERAL_TYPE))
{
- cp_error ("`%#D' redeclared as %C", old, form);
+ error ("`%#D' redeclared as %C", old, form);
return NULL_TREE;
}
if (old)
if (TREE_PURPOSE (tail) == name)
{
enum tree_code code = TREE_CODE (TREE_VALUE (tail));
- /* Should tighten this up; it'll probably permit
- UNION_TYPE and a struct template, for example. */
+
if (code != form
- && !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL))
+ && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
{
/* Definition isn't the kind we were looking for. */
- cp_error ("`%#D' redeclared as %C", TREE_VALUE (tail),
- form);
+ error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
return NULL_TREE;
}
return TREE_VALUE (tail);
{
/* This happens for A::B where B is a template, and there are no
template arguments. */
- cp_error ("invalid use of `%D'", name);
+ error ("invalid use of `%D'", name);
return error_mark_node;
}
/*in_decl=*/NULL_TREE,
/*context=*/NULL_TREE,
/*entering_scope=*/0,
- /*complain=*/1);
+ tf_error | tf_warning);
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",
+ 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);
- return val;
+
+ /* Ignore built-in functions that haven't been prototyped yet. */
+ if (!val || !DECL_P(val)
+ || !DECL_LANG_SPECIFIC(val)
+ || !DECL_ANTICIPATED (val))
+ return val;
}
- cp_error ("`%D' undeclared in namespace `%D'", name, namespace);
+ error ("`%D' undeclared in namespace `%D'", name, namespace);
return error_mark_node;
}
/* Resolve `typename CONTEXT::NAME'. Returns an appropriate type,
unless an error occurs, in which case error_mark_node is returned.
- If COMPLAIN zero, don't complain about any errors that occur. */
+ If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
+ set, we return that, rather than the _TYPE it corresponds to, in
+ other cases we look through the type decl. If TF_ERROR is set,
+ complain about errors, otherwise be quiet. */
tree
make_typename_type (context, name, complain)
tree context, name;
- int complain;
+ tsubst_flags_t complain;
{
tree fullname;
}
if (TREE_CODE (name) == TEMPLATE_DECL)
{
- cp_error ("`%D' used without template parameters", name);
+ error ("`%D' used without template parameters", name);
return error_mark_node;
}
if (TREE_CODE (name) != IDENTIFIER_NODE)
- my_friendly_abort (2000);
+ abort ();
if (TREE_CODE (context) == NAMESPACE_DECL)
{
/* We can get here from typename_sub0 in the explicit_template_type
expansion. Just fail. */
- if (complain)
- cp_error ("no class template named `%#T' in `%#T'",
+ if (complain & tf_error)
+ error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
tmpl = lookup_field (context, name, 0, 0);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
- if (complain)
- cp_error ("no class template named `%#T' in `%#T'",
+ if (complain & tf_error)
+ error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
TREE_OPERAND (fullname, 1),
NULL_TREE, context,
/*entering_scope=*/0,
- /*complain=*/1);
+ tf_error | tf_warning);
}
else
{
if (!IS_AGGR_TYPE (context))
{
- if (complain)
- cp_error ("no type named `%#T' in `%#T'", name, context);
+ if (complain & tf_error)
+ 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 (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
+ t = TREE_TYPE (t);
+ return t;
+ }
}
}
there now or its never going to be. */
if (!uses_template_parms (context))
{
- if (complain)
- cp_error ("no type named `%#T' in `%#T'", name, context);
+ if (complain & tf_error)
+ error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
/* Resolve `CONTEXT::template NAME'. Returns an appropriate type,
unless an error occurs, in which case error_mark_node is returned.
- If COMPLAIN zero, don't complain about any errors that occur. */
+ If we locate a TYPE_DECL, we return that, rather than the _TYPE it
+ corresponds to. If COMPLAIN zero, don't complain about any errors
+ that occur. */
tree
make_unbound_class_template (context, name, complain)
else if (DECL_P (name))
name = DECL_NAME (name);
if (TREE_CODE (name) != IDENTIFIER_NODE)
- my_friendly_abort (20010902);
+ abort ();
if (!uses_template_parms (context)
|| currently_open_class (context))
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain)
- cp_error ("no class template named `%#T' in `%#T'", name, context);
+ error ("no class template named `%#T' in `%#T'", name, context);
return error_mark_node;
}
tree val;
val = BINDING_VALUE (binding);
- /* When we implicitly declare some builtin entity, we mark it
- DECL_ANTICIPATED, so that we know to ignore it until it is
- really declared. */
- if (val && DECL_P (val)
- && DECL_LANG_SPECIFIC (val)
- && DECL_ANTICIPATED (val))
- return NULL_TREE;
-
if (LOOKUP_NAMESPACES_ONLY (flags))
{
/* We are not interested in types. */
*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
val = binding_for_name (name, scope);
- /* Initialize binding for this context. */
- BINDING_VALUE (b) = BINDING_VALUE (val);
- BINDING_TYPE (b) = BINDING_TYPE (val);
+ /* Ignore anticipated built-in functions. */
+ if (val && BINDING_VALUE (val)
+ && DECL_P (BINDING_VALUE (val))
+ && DECL_LANG_SPECIFIC (BINDING_VALUE (val))
+ && DECL_ANTICIPATED (BINDING_VALUE (val)))
+ {
+ BINDING_VALUE (b) = NULL_TREE;
+ BINDING_TYPE (b) = NULL_TREE;
+ }
+ else
+ {
+ /* Initialize binding for this context. */
+ BINDING_VALUE (b) = BINDING_VALUE (val);
+ BINDING_TYPE (b) = BINDING_TYPE (val);
+ }
/* Add all _DECLs seen through local using-directives. */
for (level = current_binding_level;
&& ! (TREE_CODE (binding) == TYPE_DECL
&& same_type_p (TREE_TYPE (binding), subtype)))
{
- cp_warning ("lookup of `%D' finds `%#D'",
+ warning ("lookup of `%D' finds `%#D'",
name, binding);
- cp_warning (" instead of `%D' from dependent base class",
+ warning (" instead of `%D' from dependent base class",
typename);
- cp_warning (" (use `typename %T::%D' if that's what you meant)",
+ warning (" (use `typename %T::%D' if that's what you meant)",
constructor_name (current_class_type), name);
}
}
if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL
&& TREE_CODE (val) == TYPE_DECL
&& ! same_type_p (TREE_TYPE (from_obj), TREE_TYPE (val)))
- cp_pedwarn ("\
+ pedwarn ("\
lookup of `%D' in the scope of `%#T' (`%#D') \
does not match lookup in the current scope (`%#D')",
name, got_object, from_obj, val);
flag_inline_functions = 0;
}
- /* In C++, we never create builtin functions whose name does not
- begin with `__'. Users should be using headers to get prototypes
- in C++. It would be nice if we could warn when `-fbuiltin' is
- used explicitly, but we do not have that information. */
- flag_no_builtin = 1;
-
/* Initially, C. */
current_lang_name = lang_name_c;
/* Perform other language dependent initializations. */
init_class_processing ();
- init_init_processing ();
init_search_processing ();
init_rtti_processing ();
flag_const_strings = 0;
/* Add GC roots for all of our global variables. */
- ggc_add_tree_root (c_global_trees, sizeof c_global_trees / sizeof(tree));
- ggc_add_tree_root (cp_global_trees, sizeof cp_global_trees / sizeof(tree));
+ ggc_add_tree_root (c_global_trees, ARRAY_SIZE (c_global_trees));
+ ggc_add_tree_root (cp_global_trees, ARRAY_SIZE (cp_global_trees));
ggc_add_tree_root (&integer_three_node, 1);
ggc_add_tree_root (&integer_two_node, 1);
ggc_add_tree_root (&signed_size_zero_node, 1);
ggc_add_tree_root (¤t_lang_name, 1);
ggc_add_tree_root (&static_aggregates, 1);
ggc_add_tree_root (&free_bindings, 1);
+ ggc_add_tree_root (&incomplete_vars, 1);
}
/* Generate an initializer for a function naming variable from
return decl;
}
-/* Entry point for the benefit of c_common_nodes_and_builtins.
-
- Make a definition for a builtin function named NAME and whose data type
- is TYPE. TYPE should be a function type with argument types.
+/* Make a definition for a builtin function named NAME in the current
+ namespace, whose data type is TYPE and whose context is CONTEXT.
+ TYPE should be a function type with argument types.
CLASS and CODE tell later passes how to compile calls to this function.
See tree.h for possible values.
If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
the name to be called if we can't opencode the function. */
-tree
-builtin_function (name, type, code, class, libname)
+static tree
+builtin_function_1 (name, type, context, code, class, libname)
const char *name;
tree type;
+ tree context;
int code;
enum built_in_class class;
const char *libname;
tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = code;
+ DECL_CONTEXT (decl) = context;
- my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
+ /* The return builtins leave the current function. */
+ if (code == BUILT_IN_RETURN || code == BUILT_IN_EH_RETURN)
+ TREE_THIS_VOLATILE (decl) = 1;
- /* All builtins that don't begin with an `_' should go in the `std'
- namespace. */
- if (name[0] != '_')
- {
- push_namespace (std_identifier);
- DECL_CONTEXT (decl) = std_node;
- }
pushdecl (decl);
- if (name[0] != '_')
- pop_namespace ();
/* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
we cannot change DECL_ASSEMBLER_NAME until we have installed this
return decl;
}
+/* Entry point for the benefit of c_common_nodes_and_builtins.
+
+ Make a defintion for a builtin function named NAME and whose data type
+ is TYPE. TYPE should be a function type with argument types. This
+ function places the anticipated declaration in the global namespace
+ and additionally in the std namespace if appropriate.
+
+ CLASS and CODE tell later passes how to compile calls to this function.
+ See tree.h for possible values.
+
+ If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
+ the name to be called if we can't opencode the function. */
+
+tree
+builtin_function (name, type, code, class, libname)
+ const char *name;
+ tree type;
+ int code;
+ enum built_in_class class;
+ const char *libname;
+{
+ /* All builtins that don't begin with an '_' should additionally
+ go in the 'std' namespace. */
+ if (name[0] != '_')
+ {
+ push_namespace (std_identifier);
+ builtin_function_1 (name, type, std_node, code, class, libname);
+ pop_namespace ();
+ }
+
+ return builtin_function_1 (name, type, NULL_TREE, code, class, libname);
+}
+
/* Generate a FUNCTION_DECL with the typical flags for a runtime library
function. Not called directly. */
attributes. */
void
-insert_default_attributes (decl)
+cxx_insert_default_attributes (decl)
tree decl;
{
if (!DECL_EXTERN_C_FUNCTION_P (decl))
if (found_type == 2 && TREE_CODE (value) == IDENTIFIER_NODE)
{
if (! in_system_header)
- cp_pedwarn ("redeclaration of C++ built-in type `%T'", value);
+ pedwarn ("redeclaration of C++ built-in type `%T'", value);
return NULL_TREE;
}
{
if (ob_modifier == ridpointers[(int) RID_INLINE]
|| ob_modifier == ridpointers[(int) RID_VIRTUAL])
- cp_error ("`%D' can only be specified for functions", ob_modifier);
+ error ("`%D' can only be specified for functions", ob_modifier);
else if (ob_modifier == ridpointers[(int) RID_FRIEND])
- cp_error ("`%D' can only be specified inside a class", ob_modifier);
+ error ("`%D' can only be specified inside a class", ob_modifier);
else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
- cp_error ("`%D' can only be specified for constructors",
+ error ("`%D' can only be specified for constructors",
ob_modifier);
else
- cp_error ("`%D' can only be specified for objects and functions",
+ error ("`%D' can only be specified for objects and functions",
ob_modifier);
}
groktypename (typename)
tree typename;
{
+ tree specs, attrs;
+ tree type;
if (TREE_CODE (typename) != TREE_LIST)
return typename;
- return grokdeclarator (TREE_VALUE (typename),
- TREE_PURPOSE (typename),
- TYPENAME, 0, NULL);
+ split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+ type = grokdeclarator (TREE_VALUE (typename), specs,
+ TYPENAME, 0, &attrs);
+ if (attrs)
+ cplus_decl_attributes (&type, attrs, 0);
+ return type;
}
/* Decode a declarator in an ordinary declaration or data definition.
used_extern_spec = 1;
}
+ /* An object declared as __attribute__((deprecated)) suppresses
+ warnings of uses of other deprecated items. */
+ if (lookup_attribute ("deprecated", attributes))
+ deprecated_state = DEPRECATED_SUPPRESS;
+
attributes = chainon (attributes, prefix_attributes);
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
&attributes);
+ deprecated_state = DEPRECATED_NORMAL;
+
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
Any other case of an initialization in a TYPE_DECL is an error. */
if (pedantic || list_length (declspecs) > 1)
{
- cp_error ("typedef `%D' is initialized", decl);
+ error ("typedef `%D' is initialized", decl);
initialized = 0;
}
break;
case FUNCTION_DECL:
- cp_error ("function `%#D' is initialized like a variable", decl);
+ error ("function `%#D' is initialized like a variable", decl);
initialized = 0;
break;
{
if (! toplevel_bindings_p ()
&& DECL_EXTERNAL (decl))
- cp_warning ("declaration of `%#D' has `extern' and is initialized",
+ warning ("declaration of `%#D' has `extern' and is initialized",
decl);
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
/* Set attributes here so if duplicate decl, will have proper attributes. */
cplus_decl_attributes (&decl, attributes, 0);
+ /* If #pragma weak was used, mark the decl weak now. */
+ if (current_binding_level == global_binding_level)
+ maybe_apply_pragma_weak (decl);
+
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
{
tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
- cp_error ("`%#D' is not a static member of `%#T'", decl, context);
+ error ("`%#D' is not a static member of `%#T'", decl, context);
else
{
if (DECL_CONTEXT (field) != context)
{
- cp_pedwarn ("ISO C++ does not permit `%T::%D' to be defined as `%T::%D'",
+ pedwarn ("ISO C++ does not permit `%T::%D' to be defined as `%T::%D'",
DECL_CONTEXT (field), DECL_NAME (decl),
context, DECL_NAME (decl));
DECL_CONTEXT (decl) = DECL_CONTEXT (field);
initialization. Thus, duplicate_decls won't warn
about this situation, and so we check here. */
if (DECL_INITIAL (decl) && DECL_INITIAL (field))
- cp_error ("duplicate initialization of %D", decl);
+ error ("duplicate initialization of %D", decl);
if (duplicate_decls (decl, field))
decl = field;
}
}
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
- cp_pedwarn ("declaration of `%#D' outside of class is not definition",
+ pedwarn ("declaration of `%#D' outside of class is not definition",
decl);
}
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
- cp_error ("variable `%#D' has initializer but incomplete type",
+ error ("variable `%#D' has initializer but incomplete type",
decl);
initialized = 0;
type = TREE_TYPE (decl) = error_mark_node;
else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
{
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
- cp_error ("elements of array `%#D' have incomplete type", decl);
+ error ("elements of array `%#D' have incomplete type", decl);
/* else we already gave an error in start_decl. */
initialized = 0;
}
if ((! processing_template_decl || ! uses_template_parms (type))
&& !COMPLETE_TYPE_P (complete_type (type)))
{
- cp_error ("aggregate `%#D' has incomplete type and cannot be initialized",
+ error ("aggregate `%#D' has incomplete type and cannot be defined",
decl);
/* Change the type so that assemble_variable will give
DECL an rtl we can live with: (mem (const_int 0)). */
if ((DECL_LANG_SPECIFIC (decl) == 0
|| DECL_IN_AGGR_P (decl) == 0)
&& ! DECL_THIS_EXTERN (decl))
- cp_error ("`%D' declared as reference but not initialized", decl);
+ error ("`%D' declared as reference but not initialized", decl);
return NULL_TREE;
}
if (TREE_CODE (init) == CONSTRUCTOR)
{
- cp_error ("ISO C++ forbids use of initializer list to initialize reference `%D'", decl);
+ error ("ISO C++ forbids use of initializer list to initialize reference `%D'", decl);
return NULL_TREE;
}
return NULL_TREE;
else if (tmp == NULL_TREE)
{
- cp_error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init));
+ error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init));
return NULL_TREE;
}
int failure = complete_array_type (type, initializer, do_default);
if (failure == 1)
- cp_error ("initializer fails to determine size of `%D'", decl);
+ error ("initializer fails to determine size of `%D'", decl);
if (failure == 2)
{
if (do_default)
- cp_error ("array size missing in `%D'", decl);
+ error ("array size missing in `%D'", decl);
/* If a `static' var's size isn't known, make it extern as
well as static, so it does not get allocated. If it's not
`static', then don't mark it extern; finish_incomplete_decl
if (pedantic && TYPE_DOMAIN (type) != NULL_TREE
&& tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
integer_zero_node))
- cp_error ("zero-size array `%D'", decl);
+ error ("zero-size array `%D'", decl);
layout_decl (decl, 0);
}
/* An automatic variable with an incomplete type: that is an error.
Don't talk about array types here, since we took care of that
message in grokdeclarator. */
- cp_error ("storage size of `%D' isn't known", decl);
+ error ("storage size of `%D' isn't known", decl);
TREE_TYPE (decl) = error_mark_node;
}
#if 0
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
- cp_error ("storage size of `%D' isn't constant", decl);
+ error ("storage size of `%D' isn't constant", decl);
}
if (TREE_STATIC (decl)
&& CP_TYPE_CONST_P (type)
&& !TYPE_NEEDS_CONSTRUCTING (type)
&& !DECL_INITIAL (decl))
- cp_error ("uninitialized const `%D'", decl);
+ error ("uninitialized const `%D'", decl);
}
/* Verify INIT (the initializer for DECL), and record the
init = NULL_TREE;
else if (COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
{
- cp_error ("variable-sized object `%D' may not be initialized", decl);
+ error ("variable-sized object `%D' may not be initialized", decl);
init = NULL_TREE;
}
else if (TREE_CODE (type) == ARRAY_TYPE
&& !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
{
- cp_error ("elements of array `%#D' have incomplete type", decl);
+ error ("elements of array `%#D' have incomplete type", decl);
init = NULL_TREE;
}
else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
- cp_error ("`%D' has incomplete type", decl);
+ error ("`%D' has incomplete type", decl);
TREE_TYPE (decl) = error_mark_node;
init = NULL_TREE;
}
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
- cp_error ("`%D' must be initialized by constructor, not by `{...}'",
+ error ("`%D' must be initialized by constructor, not by `{...}'",
decl);
init = error_mark_node;
}
if (! TYPE_NEEDS_CONSTRUCTING (core_type))
{
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
- cp_error ("structure `%D' with uninitialized const members", decl);
+ error ("structure `%D' with uninitialized const members", decl);
if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
- cp_error ("structure `%D' with uninitialized reference members",
+ error ("structure `%D' with uninitialized reference members",
decl);
}
DECL_STMT is expanded. */
defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl);
- /* We try to defer namespace-scope static constants so that they are
- not emitted into the object file unncessarily. */
- if (!DECL_VIRTUAL_P (decl)
- && TREE_READONLY (decl)
- && DECL_INITIAL (decl) != NULL_TREE
- && DECL_INITIAL (decl) != error_mark_node
- && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))
- && toplev
- && !TREE_PUBLIC (decl))
- {
- /* Fool with the linkage according to #pragma interface. */
- if (!interface_unknown)
+ /* We try to defer namespace-scope static constants and template
+ instantiations so that they are not emitted into the object file
+ unnecessarily. */
+ if ((!DECL_VIRTUAL_P (decl)
+ && TREE_READONLY (decl)
+ && DECL_INITIAL (decl) != NULL_TREE
+ && DECL_INITIAL (decl) != error_mark_node
+ && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))
+ && toplev
+ && !TREE_PUBLIC (decl))
+ || DECL_COMDAT (decl))
+ {
+ /* Fool with the linkage of static consts according to #pragma
+ interface. */
+ if (!interface_unknown && !TREE_PUBLIC (decl))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = interface_only;
return;
/* Compute the cleanup. */
- cleanup = maybe_build_cleanup (decl);
+ cleanup = cxx_maybe_build_cleanup (decl);
/* Record the cleanup required for this declaration. */
- if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node
- && cleanup)
+ if (DECL_SIZE (decl) && cleanup)
finish_decl_cleanup (decl, cleanup);
}
}
/* If a name was specified, get the string. */
+ if (current_binding_level == global_binding_level)
+ asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
- asmspec = TREE_STRING_POINTER (asmspec_tree);
+ asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init && TREE_CODE (init) == NAMESPACE_DECL)
{
- cp_error ("cannot initialize `%D' to namespace `%D'",
+ error ("cannot initialize `%D' to namespace `%D'",
decl, init);
init = NULL_TREE;
}
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
- cp_warning ("shadowing previous type declaration of `%#D'", decl);
+ warning ("shadowing previous type declaration of `%#D'", decl);
set_identifier_type_value (DECL_NAME (decl), type);
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
- GNU_xref_decl (current_function_decl, decl);
/* If we have installed this as the canonical typedef for this
type, and that type has not been defined yet, delay emitting
init = check_initializer (decl, init);
maybe_deduce_size_from_array_init (decl, init);
- GNU_xref_decl (current_function_decl, decl);
-
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a
reference temp is added before the DECL_STMT for the reference itself. */
DECL_ARTIFICIAL (fndecl) = 1;
/* Make the function `inline' so that it is only emitted if it is
actually needed. It is unlikely that it will be inlined, since
- it is only called via a function pointer, but we avoid unncessary
+ it is only called via a function pointer, but we avoid unnecessary
emissions this way. */
DECL_INLINE (fndecl) = 1;
/* Build the parameter. */
pushdecl (fndecl);
start_function (/*specs=*/NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED);
- do_pushlevel ();
interface_unknown = old_interface_unknown;
static void
end_cleanup_fn ()
{
- do_poplevel ();
-
expand_body (finish_function (0));
pop_from_top_level ();
end_cleanup_fn ();
/* Call atexit with the cleanup function. */
- mark_addressable (cleanup);
+ cxx_mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
if (flag_use_cxa_atexit)
{
if (oldstatic)
{
if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
- cp_error ("multiple initializations given for `%D'", decl);
+ error ("multiple initializations given for `%D'", decl);
}
else if (! toplevel_bindings_p ())
{
if (ctype && ctype != cur_type)
{
if (flags == DTOR_FLAG)
- cp_error ("destructor for alien class `%T' cannot be a member",
+ error ("destructor for alien class `%T' cannot be a member",
ctype);
else
- cp_error ("constructor for alien class `%T' cannot be a member",
+ error ("constructor for alien class `%T' cannot be a member",
ctype);
return 0;
}
int virtualp, quals, friendp, raises, inlinep;
{
if (virtualp)
- cp_error ("`%D' declared as a `virtual' %s", object, type);
+ error ("`%D' declared as a `virtual' %s", object, type);
if (inlinep)
- cp_error ("`%D' declared as an `inline' %s", object, type);
+ error ("`%D' declared as an `inline' %s", object, type);
if (quals)
- cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration",
+ error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration",
object, type);
if (friendp)
cp_error_at ("`%D' declared as a friend", object);
if (raises
&& (TREE_CODE (object) == TYPE_DECL
|| (!TYPE_PTRFN_P (TREE_TYPE (object))
+ && !TYPE_REFFN_P (TREE_TYPE (object))
&& !TYPE_PTRMEMFUNC_P (TREE_TYPE (object)))))
cp_error_at ("`%D' declared with an exception specification", object);
}
tree t;
if (raises)
- {
- type = build_exception_variant (type, raises);
- }
+ type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
/* Propagate volatile out from type to decl. */
/* Allow this; it's pretty common in C. */;
else
{
- cp_pedwarn ("non-local function `%#D' uses anonymous type",
+ pedwarn ("non-local function `%#D' uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
cp_pedwarn_at ("\
}
}
else
- cp_pedwarn ("non-local function `%#D' uses local type `%T'",
+ pedwarn ("non-local function `%#D' uses local type `%T'",
decl, t);
}
}
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
{
- cp_error ("%smember function `%D' cannot have `%T' method qualifier",
+ error ("%smember function `%D' cannot have `%T' method qualifier",
(ctype ? "static " : "non-"), decl, TREE_VALUE (quals));
quals = NULL_TREE;
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
- grok_op_properties (decl, virtualp, check < 0);
+ grok_op_properties (decl, friendp);
if (ctype && decl_function_context (decl))
DECL_NO_STATIC_CHAIN (decl) = 1;
&& TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
{
if (funcdef_flag)
- cp_error
+ error
("defining explicit specialization `%D' in friend declaration",
orig_declarator);
else
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
{
/* Something like `template <class T> friend void f<T>()'. */
- cp_error ("invalid use of template-id `%D' in declaration of primary template",
+ error ("invalid use of template-id `%D' in declaration of primary template",
orig_declarator);
return NULL_TREE;
}
if (has_default_arg)
{
- cp_error ("default arguments are not allowed in declaration of friend template specialization `%D'",
+ 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'",
+ error ("`inline' is not allowed in declaration of friend template specialization `%D'",
decl);
return NULL_TREE;
}
last_function_parms = TREE_CHAIN (last_function_parms);
}
if (old_decl && DECL_ARTIFICIAL (old_decl))
- cp_error ("definition of implicitly-declared `%D'", old_decl);
+ error ("definition of implicitly-declared `%D'", old_decl);
if (old_decl)
{
/* Attempt to merge the declarations. This can fail, in
the case of some illegal specialization declarations. */
if (!duplicate_decls (decl, old_decl))
- cp_error ("no `%#D' member function declared in class `%T'",
+ error ("no `%#D' member function declared in class `%T'",
decl, ctype);
return old_decl;
}
if (TYPE_ANONYMOUS_P (t))
/* Ignore for now; `enum { foo } e' is pretty common. */;
else
- cp_pedwarn ("non-local variable `%#D' uses local type `%T'",
+ pedwarn ("non-local variable `%#D' uses local type `%T'",
decl, t);
}
}
required. */
if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
{
- cp_error ("invalid in-class initialization of static data member of non-integral type `%T'",
+ error ("invalid 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
return 1;
}
else if (!CP_TYPE_CONST_P (type))
- cp_error ("ISO C++ forbids in-class initialization of non-const static member `%D'",
+ error ("ISO C++ forbids in-class initialization of non-const static member `%D'",
decl);
else if (pedantic && !INTEGRAL_TYPE_P (type))
- cp_pedwarn ("ISO C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+ pedwarn ("ISO C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
return 0;
}
&& TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
{
if (name)
- cp_error ("size of array `%D' has non-integer type", name);
+ error ("size of array `%D' has non-integer type", name);
else
- cp_error ("size of array has non-integer type");
+ error ("size of array has non-integer type");
size = integer_one_node;
}
if (INT_CST_LT (size, integer_zero_node))
{
if (name)
- cp_error ("size of array `%D' is negative", name);
+ error ("size of array `%D' is negative", name);
else
- cp_error ("size of array is negative");
+ error ("size of array is negative");
size = integer_one_node;
}
/* Except that an extension we allow zero-sized arrays. We
else if (integer_zerop (size) && pedantic && !in_system_header)
{
if (name)
- cp_pedwarn ("ISO C++ forbids zero-size array `%D'", name);
+ pedwarn ("ISO C++ forbids zero-size array `%D'", name);
else
- cp_pedwarn ("ISO C++ forbids zero-size array");
+ pedwarn ("ISO C++ forbids zero-size array");
}
}
else if (TREE_CONSTANT (size))
{
/* `(int) &fn' is not a valid array bound. */
if (name)
- cp_error ("size of array `%D' is not an integral constant-expression",
+ error ("size of array `%D' is not an integral constant-expression",
name);
else
- cp_error ("size of array is not an integral constant-expression");
+ error ("size of array is not an integral constant-expression");
}
/* Compute the index of the largest element in the array. It is
if (pedantic)
{
if (name)
- cp_pedwarn ("ISO C++ forbids variable-size array `%D'",
+ pedwarn ("ISO C++ forbids variable-size array `%D'",
name);
else
- cp_pedwarn ("ISO C++ forbids variable-size array");
+ pedwarn ("ISO C++ forbids variable-size array");
}
/* Create a variable-sized array index type. */
if (error_msg)
{
if (name)
- cp_error ("declaration of `%D' as %s", name, error_msg);
+ error ("declaration of `%D' as %s", name, error_msg);
else
- cp_error ("creating %s", error_msg);
+ error ("creating %s", error_msg);
return error_mark_node;
}
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
{
if (name)
- cp_error ("declaration of `%D' as multidimensional array must have bounds for all dimensions except the first",
+ error ("declaration of `%D' as multidimensional array must have bounds for all dimensions except the first",
name);
else
- cp_error ("multidimensional array must have bounds for all dimensions except the first");
+ error ("multidimensional array must have bounds for all dimensions except the first");
return error_mark_node;
}
{
case sfk_constructor:
if (type)
- cp_error ("return type specification for constructor invalid");
+ error ("return type specification for constructor invalid");
type = void_type_node;
break;
case sfk_destructor:
if (type)
- cp_error ("return type specification for destructor invalid");
+ error ("return type specification for destructor invalid");
type = void_type_node;
break;
case sfk_conversion:
if (type && !same_type_p (type, optype))
- cp_error ("operator `%T' declared to return `%T'", optype, type);
+ error ("operator `%T' declared to return `%T'", optype, type);
else if (type)
- cp_pedwarn ("return type specified for `operator %T'", optype);
+ pedwarn ("return type specified for `operator %T'", optype);
type = optype;
break;
default:
- my_friendly_abort (20000408);
+ abort ();
break;
}
tree spec;
tree type = NULL_TREE;
int longlong = 0;
- int constp;
- int restrictp;
- int volatilep;
int type_quals;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
+ int extern_langp = 0;
+ tree dependant_name = NULL_TREE;
+
tree typedef_decl = NULL_TREE;
const char *name;
tree typedef_type = NULL_TREE;
if (rename)
{
- cp_error ("destructor `%T' must match class name `%T'",
+ error ("destructor `%T' must match class name `%T'",
name, rename);
TREE_OPERAND (decl, 0) = rename;
}
finish_decl (decl, init, NULL_TREE);
}
else
- cp_error ("invalid declarator");
+ error ("invalid declarator");
return 0;
}
innermost_code = TREE_CODE (decl);
if (C_IS_RESERVED_WORD (dname))
{
- cp_error ("declarator-id missing; using reserved word `%D'",
+ error ("declarator-id missing; using reserved word `%D'",
dname);
name = IDENTIFIER_POINTER (dname);
}
else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
|| TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
- cp_error ("`%T::%D' is not a valid declarator", cname,
- TREE_OPERAND (decl, 1));
- cp_error (" perhaps you want `typename %T::%D' to make it a type",
- cname, TREE_OPERAND (decl, 1));
- return void_type_node;
+ /* This might be declaring a member of a template
+ parm to be a friend. */
+ ctype = cname;
+ dependant_name = TREE_OPERAND (decl, 1);
}
else if (ctype == NULL_TREE)
ctype = cname;
{
if (! UNIQUELY_DERIVED_FROM_P (cname, ctype))
{
- cp_error ("type `%T' is not derived from type `%T'",
+ error ("type `%T' is not derived from type `%T'",
cname, ctype);
TREE_OPERAND (decl, 0) = NULL_TREE;
}
case TYPE_DECL:
/* Parse error puts this typespec where
a declarator should go. */
- cp_error ("`%T' specified as declarator-id", DECL_NAME (decl));
+ error ("`%T' specified as declarator-id", DECL_NAME (decl));
if (TREE_TYPE (decl) == current_class_type)
- cp_error (" perhaps you want `%T' for a constructor",
+ error (" perhaps you want `%T' for a constructor",
current_class_name);
dname = DECL_NAME (decl);
name = IDENTIFIER_POINTER (dname);
break;
default:
- cp_compiler_error ("`%D' as declarator", decl);
- return 0; /* We used to do a 155 abort here. */
+ internal_error ("`%D' as declarator", decl);
}
}
}
&& innermost_code != CALL_EXPR
&& ! (ctype && declspecs == NULL_TREE))
{
- cp_error ("declaration of `%D' as non-function", dname);
+ error ("declaration of `%D' as non-function", dname);
return void_type_node;
}
id = TREE_VALUE (spec);
+ /* If the entire declaration is itself tagged as deprecated then
+ suppress reports of deprecated items. */
+ if (!adding_implicit_members && id && TREE_DEPRECATED (id))
+ {
+ if (deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (id);
+ }
+
if (TREE_CODE (id) == IDENTIFIER_NODE)
{
if (id == ridpointers[(int) RID_INT]
if (id == ridpointers[(int) RID_BOOL])
error ("`bool' is now a keyword");
else
- cp_error ("extraneous `%T' ignored", id);
+ error ("extraneous `%T' ignored", id);
}
else
{
if (IDENTIFIER_HAS_TYPE_VALUE (id))
{
if (type)
- cp_error ("multiple declarations `%T' and `%T'", type, id);
+ error ("multiple declarations `%T' and `%T'", type, id);
else
type = IDENTIFIER_TYPE_VALUE (id);
goto found;
}
else if (RIDBIT_SETP (i, specbits))
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+ if (i == (int)RID_EXTERN
+ && TREE_PURPOSE (spec) == error_mark_node)
+ /* This extern was part of a language linkage. */
+ extern_langp = 1;
RIDBIT_SET (i, specbits);
goto found;
}
}
}
- /* C++ aggregate types. */
else if (TREE_CODE (id) == TYPE_DECL)
{
if (type)
- cp_error ("multiple declarations `%T' and `%T'", type,
+ error ("multiple declarations `%T' and `%T'", type,
TREE_TYPE (id));
else
{
type = TREE_TYPE (id);
TREE_VALUE (spec) = type;
+ typedef_decl = id;
}
goto found;
}
else
{
type = TREE_TYPE (t);
-#if 0
- /* See the code below that used this. */
- decl_attr = DECL_ATTRIBUTES (id);
-#endif
typedef_decl = t;
}
}
found: ;
}
+#if 0
+ /* See the code below that used this. */
+ if (typedef_decl)
+ decl_attr = DECL_ATTRIBUTES (typedef_decl);
+#endif
typedef_type = type;
/* No type at all: default to `int', and set DEFAULTED_INT
common. With no options, it is allowed. With -Wreturn-type,
it is a warning. It is only an error with -pedantic-errors. */
is_main = (funcdef_flag
- && MAIN_NAME_P (dname)
+ && dname && MAIN_NAME_P (dname)
&& ctype == NULL_TREE
&& in_namespace == NULL_TREE
&& current_namespace == global_namespace);
if (in_system_header || flag_ms_extensions)
/* Allow it, sigh. */;
else if (pedantic || ! is_main)
- cp_pedwarn ("ISO C++ forbids declaration of `%s' with no type",
+ pedwarn ("ISO C++ forbids declaration of `%s' with no type",
name);
else if (warn_return_type)
- cp_warning ("ISO C++ forbids declaration of `%s' with no type",
+ warning ("ISO C++ forbids declaration of `%s' with no type",
name);
type = integer_type_node;
}
+
+ if (type && IMPLICIT_TYPENAME_P (type))
+ {
+ /* The implicit typename extension is deprecated and will be
+ removed. Warn about its use now. */
+ warning ("`%T' is implicitly a typename", type);
+ cp_deprecated ("implicit typename");
+
+ /* Now remove its implicitness, so that we don't warn again.
+ For instance this might be a typedef, and we do not want to
+ warn on uses of the typedef itself. Simply clearing the
+ TREE_TYPE is insufficient. */
+ type = copy_node (type);
+ TREE_TYPE (type) = NULL_TREE;
+ }
ctype = NULL_TREE;
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
- type = unsigned_type (type);
+ type = c_common_unsigned_type (type);
else
type = unsigned_type_node;
}
type = build_complex_type (type);
}
- if (sfk == sfk_conversion
- && (RIDBIT_SETP (RID_CONST, specbits)
- || RIDBIT_SETP (RID_VOLATILE, specbits)
- || RIDBIT_SETP (RID_RESTRICT, specbits)))
- cp_error ("qualifiers are not allowed on declaration of `operator %T'",
+ type_quals = TYPE_UNQUALIFIED;
+ if (RIDBIT_SETP (RID_CONST, specbits))
+ type_quals |= TYPE_QUAL_CONST;
+ if (RIDBIT_SETP (RID_VOLATILE, specbits))
+ type_quals |= TYPE_QUAL_VOLATILE;
+ if (RIDBIT_SETP (RID_RESTRICT, specbits))
+ type_quals |= TYPE_QUAL_RESTRICT;
+ if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
+ error ("qualifiers are not allowed on declaration of `operator %T'",
ctor_return_type);
- /* Set CONSTP if this declaration is `const', whether by
- explicit specification or via a typedef.
- Likewise for VOLATILEP. */
-
- constp = !! RIDBIT_SETP (RID_CONST, specbits) + CP_TYPE_CONST_P (type);
- restrictp =
- !! RIDBIT_SETP (RID_RESTRICT, specbits) + CP_TYPE_RESTRICT_P (type);
- volatilep =
- !! RIDBIT_SETP (RID_VOLATILE, specbits) + CP_TYPE_VOLATILE_P (type);
- type_quals = ((constp ? TYPE_QUAL_CONST : 0)
- | (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
- type = cp_build_qualified_type (type, type_quals);
+ type_quals |= cp_type_quals (type);
+ type = cp_build_qualified_type_real
+ (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
+ ? tf_ignore_bad_quals : 0) | tf_error | tf_warning));
+ /* We might have ignored or rejected some of the qualifiers. */
+ type_quals = cp_type_quals (type);
+
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
if (virtualp && staticp == 2)
{
- cp_error ("member `%D' cannot be declared both virtual and static",
+ error ("member `%D' cannot be declared both virtual and static",
dname);
staticp = 0;
}
friendp = RIDBIT_SETP (RID_FRIEND, specbits);
RIDBIT_RESET (RID_FRIEND, specbits);
+ if (dependant_name && !friendp)
+ {
+ error ("`%T::%D' is not a valid declarator", ctype, dependant_name);
+ return void_type_node;
+ }
+
/* Warn if two storage classes are given. Default to `auto'. */
if (RIDBIT_ANY_SET (specbits))
{
if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
- if (RIDBIT_SETP (RID_EXTERN, specbits)) nclasses++;
+ if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
if (decl_context == PARM && nclasses > 0)
error ("storage class specifiers invalid in parameter declarations");
if (RIDBIT_SETP (RID_TYPEDEF, specbits))
}
if (RIDBIT_SETP (RID_AUTO, specbits)) nclasses++;
if (RIDBIT_SETP (RID_REGISTER, specbits)) nclasses++;
+ if (!nclasses && !friendp && extern_langp)
+ nclasses++;
}
/* Give error if `virtual' is used outside of class declaration. */
&& TYPE_DOMAIN (type) != NULL_TREE
&& !TREE_CONSTANT (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
{
- cp_error ("size of member `%D' is not constant", dname);
+ error ("size of member `%D' is not constant", dname);
/* Proceed with arbitrary constant size, so that offset
computations don't get confused. */
type = create_array_type_for_decl (dname, TREE_TYPE (type),
error ("destructor cannot be static member function");
if (quals)
{
- cp_error ("destructors may not be `%s'",
+ error ("destructors may not be `%s'",
IDENTIFIER_POINTER (TREE_VALUE (quals)));
quals = NULL_TREE;
}
}
if (quals)
{
- cp_error ("constructors may not be `%s'",
+ error ("constructors may not be `%s'",
IDENTIFIER_POINTER (TREE_VALUE (quals)));
quals = NULL_TREE;
}
if (decl_context == NORMAL)
error ("friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
- cp_error ("can't define friend function `%s' in a local class definition",
+ error ("can't define friend function `%s' in a local class definition",
name);
}
if (arg_types != void_list_node)
{
- cp_error ("destructors may not have parameters");
+ error ("destructors may not have parameters");
arg_types = void_list_node;
last_function_parms = NULL_TREE;
}
&& (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE
|| TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE))
{
- cp_error ("cannot declare pointer to `%#T' member",
+ error ("cannot declare pointer to `%#T' member",
TREE_TYPE (type));
type = TREE_TYPE (type);
}
{
register tree typemodlist;
int erred = 0;
-
- constp = 0;
- volatilep = 0;
- restrictp = 0;
+ int constp = 0;
+ int volatilep = 0;
+ int restrictp = 0;
+
for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
tree qualifier = TREE_VALUE (typemodlist);
if (qualifier == ridpointers[(int) RID_CONST])
- constp++;
+ {
+ constp++;
+ type_quals |= TYPE_QUAL_CONST;
+ }
else if (qualifier == ridpointers[(int) RID_VOLATILE])
- volatilep++;
+ {
+ volatilep++;
+ type_quals |= TYPE_QUAL_VOLATILE;
+ }
else if (qualifier == ridpointers[(int) RID_RESTRICT])
- restrictp++;
+ {
+ restrictp++;
+ type_quals |= TYPE_QUAL_RESTRICT;
+ }
else if (!erred)
{
erred = 1;
pedwarn ("duplicate `volatile'");
if (restrictp > 1)
pedwarn ("duplicate `restrict'");
-
- type_quals = ((constp ? TYPE_QUAL_CONST : 0)
- | (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
- if (TREE_CODE (declarator) == ADDR_EXPR
- && (constp || volatilep))
- {
- if (constp)
- pedwarn ("discarding `const' applied to a reference");
- if (volatilep)
- pedwarn ("discarding `volatile' applied to a reference");
- type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
- }
type = cp_build_qualified_type (type, type_quals);
+ type_quals = cp_type_quals (type);
}
declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
&& uses_template_parms (current_class_type))
{
tree args = current_template_args ();
- type = tsubst (type, args, /*complain=*/1, NULL_TREE);
+ type = tsubst (type, args, tf_error | tf_warning,
+ NULL_TREE);
}
/* This pop_nested_class corresponds to the
TREE_COMPLEXITY (declarator) = current_class_depth;
}
else
- my_friendly_abort (16);
+ abort ();
if (TREE_OPERAND (declarator, 0) == NULL_TREE)
{
Is this ill-formed? */
if (pedantic)
- cp_pedwarn ("extra qualification `%T::' on member `%s' ignored",
+ pedwarn ("extra qualification `%T::' on member `%s' ignored",
ctype, name);
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
TYPE_ARG_TYPES (type));
else
{
- cp_error ("cannot declare member function `%T::%s' within `%T'",
+ error ("cannot declare member function `%T::%s' within `%T'",
ctype, name, current_class_type);
return void_type_node;
}
if (current_class_type)
{
- cp_error ("cannot declare member `%T::%s' within `%T'",
+ error ("cannot declare member `%T::%s' within `%T'",
ctype, name, current_class_type);
return void_type_node;
}
declarator = sname;
}
else if (TREE_CODE (sname) == SCOPE_REF)
- my_friendly_abort (17);
+ abort ();
else
{
done_scoping:
break;
default:
- my_friendly_abort (158);
+ abort ();
}
}
&& TREE_OVERFLOW (TYPE_SIZE (type)))
{
error ("size of array `%s' is too large", name);
- /* If we proceed with the array type as it is, we'll eventully
+ /* If we proceed with the array type as it is, we'll eventually
crash in tree_low_cst(). */
type = error_mark_node;
}
else if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
- RIDBIT_RESET (RID_MUTABLE, specbits);
+ RIDBIT_RESET (RID_MUTABLE, specbits);
}
}
/* OK */;
else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
{
- cp_error ("template-id `%D' used as a declarator", declarator);
+ error ("template-id `%D' used as a declarator", declarator);
declarator = dname;
}
else
/* Unexpected declarator format. */
- my_friendly_abort (990210);
+ abort ();
/* If this is declaring a typedef name, return a TYPE_DECL. */
if (decl_context == FIELD)
{
if (declarator == constructor_name (current_class_type))
- cp_pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
+ pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
declarator);
decl = build_lang_decl (TYPE_DECL, declarator, type);
}
/* Detect the case of an array type of unspecified size
which came, as such, direct from a typedef name.
- We must copy the type, so that each identifier gets
- a distinct type, so that each identifier's size can be
- controlled separately by its own initializer. */
+ We must copy the type, so that the array's domain can be
+ individually set by the object's initializer. */
- if (type != 0 && typedef_type != 0
- && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
+ if (type && typedef_type
+ && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
- {
- type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type));
- }
+ type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
/* Detect where we're using a typedef of function type to declare a
function. last_function_parms will not be set, so we must create
{
if (type_quals != TYPE_UNQUALIFIED)
{
- cp_error ("type qualifiers specified for friend class declaration");
+ error ("type qualifiers specified for friend class declaration");
type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
- cp_error ("`inline' specified for friend class declaration");
+ error ("`inline' specified for friend class declaration");
inlinep = 0;
}
|| IMPLICIT_TYPENAME_P (type)))
{
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
- cp_pedwarn ("template parameters cannot be friends");
+ pedwarn ("template parameters cannot be friends");
else if (TREE_CODE (type) == TYPENAME_TYPE)
- cp_pedwarn ("\
+ pedwarn ("\
friend declaration requires class-key, i.e. `friend class %T::%T'",
constructor_name (current_class_type),
TYPE_IDENTIFIER (type));
else
- cp_pedwarn ("\
+ pedwarn ("\
friend declaration requires class-key, i.e. `friend %#T'",
type);
}
/* Only try to do this stuff if we didn't already give up. */
if (type != integer_type_node)
{
- /* DR 209. The friendly class does not need to be accessible
- in the scope of the class granting friendship. */
- skip_type_access_control ();
+ decl_type_access_control (TYPE_NAME (type));
/* A friendly class? */
if (current_class_type)
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
else
- cp_error ("trying to make class `%T' a friend of global scope",
+ error ("trying to make class `%T' a friend of global scope",
type);
type = void_type_node;
if (ctype == NULL_TREE)
{
if (TREE_CODE (type) != METHOD_TYPE)
- cp_error ("invalid qualifiers on non-member function type");
+ error ("invalid qualifiers on non-member function type");
else
ctype = TYPE_METHOD_BASETYPE (type);
}
&& TREE_CODE (type) != UNION_TYPE
&& ! bitfield)
{
- cp_error ("abstract declarator `%T' used as declaration", type);
+ error ("abstract declarator `%T' used as declaration", type);
declarator = make_anon_name ();
}
else if (TREE_CODE (declarator) == IDENTIFIER_NODE)
{
if (IDENTIFIER_OPNAME_P (declarator))
- my_friendly_abort (356);
+ abort ();
else
error ("variable or field `%s' declared void", name);
}
else if (in_namespace && !friendp)
{
/* Something like struct S { int N::j; }; */
- cp_error ("invalid use of `::'");
+ error ("invalid use of `::'");
decl = NULL_TREE;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
typedefs. */
if (friendp && declarator == ridpointers[(int) RID_SIGNED])
{
- cp_error ("function `%D' cannot be declared friend",
+ error ("function `%D' cannot be declared friend",
declarator);
friendp = 0;
}
if (ctype == NULL_TREE)
{
- cp_error ("can't make `%D' into a method -- not in a class",
+ error ("can't make `%D' into a method -- not in a class",
declarator);
return void_type_node;
}
ARM 9.5 */
if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
{
- cp_error ("function `%D' declared virtual inside a union",
+ error ("function `%D' declared virtual inside a union",
declarator);
return void_type_node;
}
{
if (virtualp)
{
- cp_error ("`%D' cannot be declared virtual, since it is always static",
+ error ("`%D' cannot be declared virtual, since it is always static",
declarator);
virtualp = 0;
}
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
if (declarator)
- cp_error ("field `%D' has incomplete type", declarator);
+ error ("field `%D' has incomplete type", declarator);
else
- cp_error ("name `%T' has incomplete type", type);
+ error ("name `%T' has incomplete type", type);
/* If we're instantiating a template, tell them which
instantiation made the field's type be incomplete. */
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))
&& declspecs && TREE_VALUE (declspecs)
&& TREE_TYPE (TREE_VALUE (declspecs)) == type)
- cp_error (" in instantiation of template `%T'",
+ error (" in instantiation of template `%T'",
current_class_type);
type = error_mark_node;
if (friendp)
{
/* Friends are treated specially. */
- tree t = NULL_TREE;
-
- /* DR 209. The friend does not need to be accessible at this
- point. */
- skip_type_access_control ();
-
if (ctype == current_class_type)
warning ("member functions are implicitly friends of their class");
-
- if (decl && DECL_NAME (decl))
- {
- if (template_class_depth (current_class_type) == 0)
- {
- decl = check_explicit_specialization
- (declarator, decl,
- template_count, 2 * (funcdef_flag != 0) + 4);
- if (decl == error_mark_node)
- return error_mark_node;
- }
-
- t = do_friend (ctype, declarator, decl,
- last_function_parms, *attrlist, flags, quals,
- funcdef_flag);
- }
- if (t && funcdef_flag)
- return t;
- return void_type_node;
+ else
+ {
+ tree t = NULL_TREE;
+ if (decl && DECL_NAME (decl))
+ {
+ if (template_class_depth (current_class_type) == 0)
+ {
+ decl
+ = check_explicit_specialization
+ (declarator, decl,
+ template_count, 2 * (funcdef_flag != 0) + 4);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ }
+
+ t = do_friend (ctype, declarator, decl,
+ last_function_parms, *attrlist,
+ flags, quals, funcdef_flag);
+ }
+ if (t && funcdef_flag)
+ return t;
+
+ return void_type_node;
+ }
}
/* Structure field. It may not be a function, except for C++ */
the rest of the compiler does not correctly
handle the initialization unless the member is
static so we make it static below. */
- cp_pedwarn ("ISO C++ forbids initialization of member `%D'",
+ pedwarn ("ISO C++ forbids initialization of member `%D'",
declarator);
- cp_pedwarn ("making `%D' static", declarator);
+ pedwarn ("making `%D' static", declarator);
staticp = 1;
}
to change that in TC 1 so that they are allowed in
classes with no user-defined constructors. */
&& staticp)
- cp_pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
+ pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
declarator);
if (staticp)
declaring main to be static. */
if (TREE_CODE (type) == METHOD_TYPE)
{
- cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl);
+ pedwarn ("cannot declare member function `%D' to have static linkage", decl);
illegal_static = 1;
}
else if (current_function_decl)
DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
- cp_pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
+ pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits);
}
if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl))
{
- cp_error ("static member `%D' declared `register'", decl);
+ error ("static member `%D' declared `register'", decl);
RIDBIT_RESET (RID_REGISTER, specbits);
}
if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic)
{
- cp_pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
+ pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
decl);
RIDBIT_RESET (RID_EXTERN, specbits);
}
|| !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
{
if (decl)
- cp_error ("default argument for `%#D' has type `%T'",
+ error ("default argument for `%#D' has type `%T'",
decl, TREE_TYPE (arg));
else
- cp_error ("default argument for parameter of type `%T' has type `%T'",
+ error ("default argument for parameter of type `%T' has type `%T'",
decl_type, TREE_TYPE (arg));
return error_mark_node;
NULL);
if (var)
{
- cp_error ("default argument `%E' uses local variable `%D'",
+ error ("default argument `%E' uses local variable `%D'",
arg, var);
return error_mark_node;
}
for (parm = first_parm; parm != NULL_TREE; parm = chain)
{
tree type = NULL_TREE;
- register tree decl = TREE_VALUE (parm);
+ tree decl = TREE_VALUE (parm);
tree init = TREE_PURPOSE (parm);
+ tree specs, attrs;
chain = TREE_CHAIN (parm);
/* @@ weak defense against parse errors. */
{
/* Give various messages as the need arises. */
if (TREE_CODE (decl) == STRING_CST)
- cp_error ("invalid string constant `%E'", decl);
+ error ("invalid string constant `%E'", decl);
else if (TREE_CODE (decl) == INTEGER_CST)
error ("invalid integer constant in parameter list, did you forget to give parameter name?");
continue;
if (parm == void_list_node)
break;
- decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl),
- PARM, init != NULL_TREE, NULL);
+ split_specs_attrs (TREE_PURPOSE (decl), &specs, &attrs);
+ decl = grokdeclarator (TREE_VALUE (decl), specs,
+ PARM, init != NULL_TREE, &attrs);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
+ if (attrs)
+ cplus_decl_attributes (&decl, attrs, 0);
+
type = TREE_TYPE (decl);
if (VOID_TYPE_P (type))
{
type = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (type) == METHOD_TYPE)
{
- cp_error ("parameter `%D' invalidly declared method type", decl);
+ error ("parameter `%D' invalidly declared method type", decl);
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
else if (TREE_CODE (type) == OFFSET_TYPE)
{
- cp_error ("parameter `%D' invalidly declared offset type", decl);
+ error ("parameter `%D' invalidly declared offset type", decl);
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
t = TREE_TYPE (t);
}
if (TREE_CODE (t) == ARRAY_TYPE)
- cp_error ("parameter `%D' includes %s to array of unknown bound `%T'",
+ error ("parameter `%D' includes %s to array of unknown bound `%T'",
decl, ptr ? "pointer" : "reference", t);
}
}
\f
-/* D is a constructor or overloaded `operator='. Returns non-zero if
- D's arguments allow it to be a copy constructor, or copy assignment
+/* D is a constructor or overloaded `operator='.
+
+ Let T be the class in which D is declared. Then, this function
+ returns:
+
+ -1 if D's is an ill-formed constructor or copy assignment operator
+ whose first parameter is of type `T'.
+ 0 if D is not a copy constructor or copy assignment
+ operator.
+ 1 if D is a copy constructor or copy assignment operator whose
+ first parameter is a reference to const qualified T.
+ 2 if D is a copy constructor or copy assignment operator whose
+ first parameter is a reference to non-const qualified T.
+
+ This function can be used as a predicate. Positive values indicate
+ a copy constructor and non-zero values indicate a copy assignment
operator. */
int
-copy_args_p (d)
+copy_fn_p (d)
tree d;
{
- tree t;
+ tree args;
+ tree arg_type;
+ int result = 1;
+
+ my_friendly_assert (DECL_FUNCTION_MEMBER_P (d), 20011208);
+
+ if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (d)))
+ /* Instantiations of template member functions are never copy
+ functions. Note that member functions of templated classes are
+ represented as template functions internally, and we must
+ accept those as copy functions. */
+ return 0;
+
+ args = FUNCTION_FIRST_USER_PARMTYPE (d);
+ if (!args)
+ return 0;
+
+ arg_type = TREE_VALUE (args);
- if (!DECL_FUNCTION_MEMBER_P (d))
+ if (TYPE_MAIN_VARIANT (arg_type) == DECL_CONTEXT (d))
+ {
+ /* Pass by value copy assignment operator. */
+ result = -1;
+ }
+ else if (TREE_CODE (arg_type) == REFERENCE_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
+ {
+ if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
+ result = 2;
+ }
+ else
return 0;
+
+ args = TREE_CHAIN (args);
- t = FUNCTION_FIRST_USER_PARMTYPE (d);
- if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
- && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t)))
- == DECL_CONTEXT (d))
- && (TREE_CHAIN (t) == NULL_TREE
- || TREE_CHAIN (t) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (t))))
- return 1;
- return 0;
+ if (args && args != void_list_node && !TREE_PURPOSE (args))
+ /* There are more non-optional args. */
+ return 0;
+
+ return result;
}
-/* These memoizing functions keep track of special properties which
- a class may have. `grok_ctor_properties' notices whether a class
- has a constructor of the form X(X&), and also complains
- if the class has a constructor of the form X(X).
- `grok_op_properties' takes notice of the various forms of
- operator= which are defined, as well as what sorts of type conversion
- may apply. Both functions take a FUNCTION_DECL as an argument. */
+/* Remember any special properties of member function DECL. */
+
+void grok_special_member_properties (decl)
+ tree decl;
+{
+ if (!DECL_NONSTATIC_MEMBER_FUNCTION_P(decl))
+ ; /* Not special. */
+ else if (DECL_CONSTRUCTOR_P (decl))
+ {
+ int ctor = copy_fn_p (decl);
+
+ if (ctor > 0)
+ {
+ /* [class.copy]
+
+ A non-template constructor for class X is a copy
+ constructor if its first parameter is of type X&, const
+ X&, volatile X& or const volatile X&, and either there
+ are no other parameters or else all other parameters have
+ default arguments. */
+ TYPE_HAS_INIT_REF (DECL_CONTEXT (decl)) = 1;
+ if (ctor > 1)
+ TYPE_HAS_CONST_INIT_REF (DECL_CONTEXT (decl)) = 1;
+ }
+ else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (DECL_CONTEXT (decl)) = 1;
+ }
+ else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
+ {
+ /* [class.copy]
+
+ A non-template assignment operator for class X is a copy
+ assignment operator if its parameter is of type X, X&, const
+ X&, volatile X& or const volatile X&. */
+
+ int assop = copy_fn_p (decl);
+
+ if (assop)
+ {
+ TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
+ if (assop != 1)
+ TYPE_HAS_CONST_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
+ if (DECL_PURE_VIRTUAL_P (decl))
+ TYPE_HAS_ABSTRACT_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
+ }
+ }
+}
+
+/* Check a constructor DECL has the correct form. Complains
+ if the class has a constructor of the form X(X). */
int
grok_ctor_properties (ctype, decl)
tree ctype, decl;
{
- tree parmtypes = FUNCTION_FIRST_USER_PARMTYPE (decl);
- tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
-
- /* [class.copy]
-
- A non-template constructor for class X is a copy constructor if
- its first parameter is of type X&, const X&, volatile X& or const
- volatile X&, and either there are no other parameters or else all
- other parameters have default arguments. */
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
- && sufficient_parms_p (TREE_CHAIN (parmtypes))
- && !(DECL_TEMPLATE_INSTANTIATION (decl)
- && is_member_template (DECL_TI_TEMPLATE (decl))))
- {
- TYPE_HAS_INIT_REF (ctype) = 1;
- if (CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
- TYPE_HAS_CONST_INIT_REF (ctype) = 1;
- }
- /* [class.copy]
-
- A declaration of a constructor for a class X is ill-formed if its
- first parameter is of type (optionally cv-qualified) X and either
- there are no other parameters or else all other parameters have
- default arguments.
-
- We *don't* complain about member template instantiations that
- have this form, though; they can occur as we try to decide what
- constructor to use during overload resolution. Since overload
- resolution will never prefer such a constructor to the
- non-template copy constructor (which is either explicitly or
- implicitly defined), there's no need to worry about their
- existence. Theoretically, they should never even be
- instantiated, but that's hard to forestall. */
- else if (TYPE_MAIN_VARIANT (parmtype) == ctype
- && sufficient_parms_p (TREE_CHAIN (parmtypes))
- && !(DECL_TEMPLATE_INSTANTIATION (decl)
- && is_member_template (DECL_TI_TEMPLATE (decl))))
- {
- cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
+ int ctor_parm = copy_fn_p (decl);
+
+ if (ctor_parm < 0)
+ {
+ /* [class.copy]
+
+ A declaration of a constructor for a class X is ill-formed if
+ its first parameter is of type (optionally cv-qualified) X
+ and either there are no other parameters or else all other
+ parameters have default arguments.
+
+ We *don't* complain about member template instantiations that
+ have this form, though; they can occur as we try to decide
+ what constructor to use during overload resolution. Since
+ overload resolution will never prefer such a constructor to
+ the non-template copy constructor (which is either explicitly
+ or implicitly defined), there's no need to worry about their
+ existence. Theoretically, they should never even be
+ instantiated, but that's hard to forestall. */
+ error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype);
SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
return 0;
}
- else if (TREE_CODE (parmtype) == VOID_TYPE
- || TREE_PURPOSE (parmtypes) != NULL_TREE)
- TYPE_HAS_DEFAULT_CONSTRUCTOR (ctype) = 1;
-
+
return 1;
}
/* Do a little sanity-checking on how they declared their operator. */
void
-grok_op_properties (decl, virtualp, friendp)
+grok_op_properties (decl, friendp)
tree decl;
- int virtualp, friendp;
+ int friendp;
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree argtype;
#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \
if (ansi_opname (CODE) == name) \
{ \
- operator_code = CODE; \
+ operator_code = (CODE); \
break; \
} \
else if (ansi_assopname (CODE) == name) \
{ \
- operator_code = CODE; \
+ operator_code = (CODE); \
DECL_ASSIGNMENT_OPERATOR_P (decl) = 1; \
break; \
}
#include "operators.def"
#undef DEF_OPERATOR
- my_friendly_abort (20000527);
+ abort ();
}
while (0);
my_friendly_assert (operator_code != LAST_CPLUS_TREE_CODE, 20000526);
|| operator_code == COMPONENT_REF
|| operator_code == ARRAY_REF
|| operator_code == NOP_EXPR)
- cp_error ("`%D' must be a nonstatic member function", decl);
+ error ("`%D' must be a nonstatic member function", decl);
else
{
tree p = argtypes;
if (DECL_STATIC_FUNCTION_P (decl))
- cp_error ("`%D' must be either a non-static member function or a non-member function", decl);
+ error ("`%D' must be either a non-static member function or a non-member function", decl);
if (p)
for (; TREE_CODE (TREE_VALUE (p)) != VOID_TYPE ; p = TREE_CHAIN (p))
|| TREE_CODE (arg) == BOUND_TEMPLATE_TEMPLATE_PARM)
goto foundaggr;
}
- cp_error
+ error
("`%D' must have an argument of class or enumerated type",
decl);
foundaggr:
ref ? "a reference to " : "", what);
}
}
-
- if (DECL_ASSIGNMENT_OPERATOR_P (decl)
- && operator_code == NOP_EXPR)
- {
- tree parmtype;
-
- if (arity != 2 && methodp)
- {
- cp_error ("`%D' must take exactly one argument", decl);
- return;
- }
- parmtype = TREE_VALUE (TREE_CHAIN (argtypes));
-
- /* [class.copy]
-
- A user-declared copy assignment operator X::operator= is
- a non-static non-template member function of class X with
- exactly one parameter of type X, X&, const X&, volatile
- X& or const volatile X&. */
- if (copy_assignment_arg_p (parmtype, virtualp)
- && !(DECL_TEMPLATE_INSTANTIATION (decl)
- && is_member_template (DECL_TI_TEMPLATE (decl)))
- && ! friendp)
- {
- TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
- if (TREE_CODE (parmtype) != REFERENCE_TYPE
- || CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
- TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
- }
- }
- else if (operator_code == COND_EXPR)
+ if (operator_code == COND_EXPR)
{
/* 13.4.0.3 */
- cp_error ("ISO C++ prohibits overloading operator ?:");
+ error ("ISO C++ prohibits overloading operator ?:");
}
else if (ambi_op_p (operator_code))
{
break;
default:
- my_friendly_abort (20000527);
+ abort ();
}
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
&& ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
if (methodp)
- cp_error ("postfix `%D' must take `int' as its argument",
+ error ("postfix `%D' must take `int' as its argument",
decl);
else
- cp_error
+ error
("postfix `%D' must take `int' as its second argument",
decl);
}
else
{
if (methodp)
- cp_error ("`%D' must take either zero or one argument", decl);
+ error ("`%D' must take either zero or one argument", decl);
else
- cp_error ("`%D' must take either one or two arguments", decl);
+ error ("`%D' must take either one or two arguments", decl);
}
/* More Effective C++ rule 6. */
if (TREE_CODE (ret) != REFERENCE_TYPE
|| !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
arg))
- cp_warning ("prefix `%D' should return `%T'", decl,
+ warning ("prefix `%D' should return `%T'", decl,
build_reference_type (arg));
}
else
{
if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
- cp_warning ("postfix `%D' should return `%T'", decl, arg);
+ warning ("postfix `%D' should return `%T'", decl, arg);
}
}
}
if (arity != 1)
{
if (methodp)
- cp_error ("`%D' must take `void'", decl);
+ error ("`%D' must take `void'", decl);
else
- cp_error ("`%D' must take exactly one argument", decl);
+ error ("`%D' must take exactly one argument", decl);
}
}
else /* if (binary_op_p (operator_code)) */
if (arity != 2)
{
if (methodp)
- cp_error ("`%D' must take exactly one argument", decl);
+ error ("`%D' must take exactly one argument", decl);
else
- cp_error ("`%D' must take exactly two arguments", decl);
+ error ("`%D' must take exactly two arguments", decl);
}
/* More Effective C++ rule 7. */
&& (operator_code == TRUTH_ANDIF_EXPR
|| operator_code == TRUTH_ORIF_EXPR
|| operator_code == COMPOUND_EXPR))
- cp_warning ("user-defined `%D' always evaluates both arguments",
+ warning ("user-defined `%D' always evaluates both arguments",
decl);
}
|| operator_code == TRUNC_DIV_EXPR
|| operator_code == MULT_EXPR)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
- cp_warning ("`%D' should return by value", decl);
+ warning ("`%D' should return by value", decl);
- /* 13.4.0.8 */
+ /* [over.oper]/8 */
for (; argtypes && argtypes != void_list_node;
argtypes = TREE_CHAIN (argtypes))
if (TREE_PURPOSE (argtypes))
|| operator_code == POSTDECREMENT_EXPR)
{
if (pedantic)
- cp_pedwarn ("`%D' cannot have default arguments", decl);
+ pedwarn ("`%D' cannot have default arguments", decl);
}
else
- cp_error ("`%D' cannot have default arguments", decl);
+ error ("`%D' cannot have default arguments", decl);
}
}
case enum_type:
return "enum";
default:
- my_friendly_abort (981122);
+ abort ();
}
}
code = ENUMERAL_TYPE;
break;
default:
- my_friendly_abort (18);
+ abort ();
}
/* If a cross reference is requested, look up the type
static int explained;
tree shadowed;
- cp_warning ("`%s %T' declares a new type at namespace scope",
+ warning ("`%s %T' declares a new type at namespace scope",
tag_name (tag_code), name);
if (!explained++)
- cp_warning (" names from dependent base classes are not visible to unqualified name lookup - to refer to the inherited type, say `%s %T::%T'",
+ warning (" names from dependent base classes are not visible to unqualified name lookup - to refer to the inherited type, say `%s %T::%T'",
tag_name (tag_code),
constructor_name (current_class_type),
TYPE_IDENTIFIER (t));
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'",
+ 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'",
+ error ("using template type parameter `%T' after `%s'",
t, tag_name (tag_code));
ref = t;
the forward-reference will be altered into a real type. */
if (code == ENUMERAL_TYPE)
{
- cp_error ("use of enum `%#D' without previous declaration", name);
+ error ("use of enum `%#D' without previous declaration", name);
ref = make_node (ENUMERAL_TYPE);
redeclare_class_template (ref, current_template_parms);
}
- /* Until the type is defined, tentatively accept whatever
- structure tag the user hands us. */
- if (!COMPLETE_TYPE_P (ref)
- && ref != current_class_type
- /* Have to check this, in case we have contradictory tag info. */
- && IS_AGGR_TYPE_CODE (TREE_CODE (ref)))
- {
- if (tag_code == class_type)
- CLASSTYPE_DECLARED_CLASS (ref) = 1;
- else if (tag_code == record_type)
- CLASSTYPE_DECLARED_CLASS (ref) = 0;
- }
-
- TREE_TYPE (ref) = attributes;
+ TYPE_ATTRIBUTES (ref) = attributes;
return ref;
}
void
xref_basetypes (code_type_node, name, ref, binfo)
tree code_type_node;
- tree name, ref;
+ tree name ATTRIBUTE_UNUSED;
+ tree ref;
tree binfo;
{
/* In the declaration `A : X, Y, ... Z' we mark all the types
tree base;
int i, len;
+ enum tag_types tag_code;
/* If we are called from the parser, code_type_node will sometimes be a
TREE_LIST. This indicates that the user wrote
if (TREE_CODE (code_type_node) == TREE_LIST)
code_type_node = TREE_VALUE (code_type_node);
- enum tag_types tag_code = (enum tag_types) tree_low_cst (code_type_node, 1);
+ tag_code = (enum tag_types) tree_low_cst (code_type_node, 1);
if (tag_code == union_type)
{
- cp_error ("derived union `%T' invalid", ref);
+ error ("derived union `%T' invalid", ref);
return;
}
&& TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
&& TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
{
- cp_error ("base type `%T' fails to be a struct or class type",
+ error ("base type `%T' fails to be a struct or class type",
TREE_VALUE (binfo));
continue;
}
- GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
-
/* This code replaces similar code in layout_basetypes.
We put the complete_type first for implicit `typename'. */
if (!COMPLETE_TYPE_P (basetype)
&& ! (current_template_parms && uses_template_parms (basetype)))
{
- cp_error ("base class `%T' has incomplete type", basetype);
+ error ("base class `%T' has incomplete type", basetype);
continue;
}
else
if (CLASSTYPE_MARKED (basetype))
{
if (basetype == ref)
- cp_error ("recursive type `%T' undefined", basetype);
+ error ("recursive type `%T' undefined", basetype);
else
- cp_error ("duplicate base type `%T' invalid", basetype);
+ error ("duplicate base type `%T' invalid", basetype);
continue;
}
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
{
- cp_error ("multiple definition of `%#T'", enumtype);
+ error ("multiple definition of `%#T'", enumtype);
cp_error_at ("previous definition here", enumtype);
/* Clear out TYPE_VALUES, and start again. */
TYPE_VALUES (enumtype) = NULL_TREE;
pushtag (name, enumtype, 0);
}
- if (current_class_type)
- TREE_ADDRESSABLE (b->tags) = 1;
-
- GNU_xref_decl (current_function_decl, enumtype);
return enumtype;
}
if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
/* Use the width of the narrowest normal C type which is wide
enough. */
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (c_common_type_for_size
(precision, 1));
else
TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
}
else
{
- cp_error ("enumerator value for `%D' not integer constant", name);
+ error ("enumerator value for `%D' not integer constant", name);
value = NULL_TREE;
}
}
integer_one_node);
if (tree_int_cst_lt (value, prev_value))
- cp_error ("overflow in enumeration values at `%D'", name);
+ error ("overflow in enumeration values at `%D'", name);
}
else
value = integer_zero_node;
things like `S::i' later.) */
finish_member_declaration (decl);
else
- {
- pushdecl (decl);
- GNU_xref_decl (current_function_decl, decl);
- }
+ pushdecl (decl);
/* Add this enumeration constant to the list for this type. */
TYPE_VALUES (enumtype) = tree_cons (name, decl, TYPE_VALUES (enumtype));
if (!COMPLETE_OR_VOID_TYPE_P (return_type))
{
- cp_error ("return type `%#T' is incomplete", TREE_TYPE (fntype));
+ error ("return type `%#T' is incomplete", TREE_TYPE (fntype));
/* Make it return void instead, but don't change the
type of the DECL_RESULT, in case we have a named return value. */
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
- if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
+ if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
+ return 0;
+
+ cplus_decl_attributes (&decl1, attrs, 0);
+
+ /* If #pragma weak was used, mark the decl weak now. */
+ if (current_binding_level == global_binding_level)
+ maybe_apply_pragma_weak (decl1);
fntype = TREE_TYPE (decl1);
restype = TREE_TYPE (fntype);
if (CLASS_TYPE_P (restype) && !CLASSTYPE_GOT_SEMICOLON (restype))
{
- cp_error ("semicolon missing after declaration of `%#T'", restype);
+ error ("semicolon missing after declaration of `%#T'", restype);
shadow_tag (build_tree_list (NULL_TREE, restype));
CLASSTYPE_GOT_SEMICOLON (restype) = 1;
if (TREE_CODE (fntype) == FUNCTION_TYPE)
if (warn_ecpp
&& DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
&& TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
- cp_warning ("`operator=' should return a reference to `*this'");
+ warning ("`operator=' should return a reference to `*this'");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in poplevel) with the BLOCK. */
/* Build the return declaration for the function. */
restype = TREE_TYPE (fntype);
- if (!processing_template_decl)
+ /* Promote the value to int before returning it. */
+ if (c_promoting_integer_type_p (restype))
+ restype = type_promotes_to (restype);
+ if (DECL_RESULT (decl1) == NULL_TREE)
{
- if (!DECL_RESULT (decl1))
- {
- DECL_RESULT (decl1)
- = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
- c_apply_type_quals_to_decl (cp_type_quals (restype),
- DECL_RESULT (decl1));
- }
+ DECL_RESULT (decl1)
+ = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
+ c_apply_type_quals_to_decl (cp_type_quals (restype),
+ DECL_RESULT (decl1));
}
- else
- /* Just use `void'. Nobody will ever look at this anyhow. */
- DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, void_type_node);
/* Initialize RTL machinery. We cannot do this until
CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this
pushlevel (0);
current_binding_level->parm_flag = 1;
- cplus_decl_attributes (&decl1, attrs, 0);
-
- /* Promote the value to int before returning it. */
- if (c_promoting_integer_type_p (restype))
- restype = type_promotes_to (restype);
-
- if (DECL_RESULT (decl1) == NULL_TREE)
- {
- DECL_RESULT (decl1)
- = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
- TREE_READONLY (DECL_RESULT (decl1)) = CP_TYPE_CONST_P (restype);
- TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = CP_TYPE_VOLATILE_P (restype);
- }
-
++function_depth;
if (DECL_DESTRUCTOR_P (decl1))
{
register tree fndecl = current_function_decl;
register tree parm;
- int parms_have_cleanups = 0;
- tree cleanups = NULL_TREE;
/* This is a chain of any other decls that came in among the parm
declarations. If a parm is declared with enum {foo, bar} x;
next = TREE_CHAIN (parm);
if (TREE_CODE (parm) == PARM_DECL)
{
- tree cleanup;
-
if (DECL_NAME (parm) == NULL_TREE
|| TREE_CODE (parm) != VOID_TYPE)
pushdecl (parm);
else
- cp_error ("parameter `%D' declared void", parm);
-
- cleanup = (processing_template_decl
- ? NULL_TREE
- : maybe_build_cleanup (parm));
-
- if (cleanup)
- cleanups = tree_cons (parm, cleanup, cleanups);
+ error ("parameter `%D' declared void", parm);
}
else
{
DECL_ARGUMENTS is not modified. */
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
- /* Now that we have initialized the parms, we can start their
- cleanups. We cannot do this before, since expand_decl_cleanup
- should not be called before the parm can be used. */
- while (cleanups)
- {
- finish_decl_cleanup (TREE_PURPOSE (cleanups),
- TREE_VALUE (cleanups));
- cleanups = TREE_CHAIN (cleanups);
- }
-
- /* Create a binding contour which can be used to catch
- cleanup-generated temporaries. */
- if (parms_have_cleanups)
- pushlevel (0);
-
/* Do the starting of the exception specifications, if we have any. */
if (flag_exceptions && !processing_template_decl
&& flag_enforce_eh_specs
}
}
-/* At the end of every constructor we generate to code to return
- `this'. Do that now. */
+/* Add a note to mark the beginning of the main body of the constructor.
+ This is used to set up the data structures for the cleanup regions for
+ fully-constructed bases and members. */
static void
-finish_constructor_body ()
+begin_constructor_body ()
{
- /* Any return from a constructor will end up here. */
- if (ctor_label)
- add_stmt (build_stmt (LABEL_STMT, ctor_label));
+}
+
+/* Add a note to mark the end of the main body of the constructor. This is
+ used to end the cleanup regions for fully-constructed bases and
+ members. */
- /* Clear CTOR_LABEL so that finish_return_stmt knows to really
- generate the return, rather than a goto to CTOR_LABEL. */
- ctor_label = NULL_TREE;
- /* In check_return_expr we translate an empty return from a
- constructor to a return of `this'. */
- finish_return_stmt (NULL_TREE);
- /* Mark the end of the constructor. */
- add_stmt (build_stmt (CTOR_STMT));
+static void
+finish_constructor_body ()
+{
}
-/* At the end of every destructor we generate code to restore virtual
- function tables to the values desired by base classes and to call
- to base class destructors. Do that now. */
+/* Do all the processing for the beginning of a destructor; set up the
+ vtable pointers and cleanups for bases and members. */
static void
-finish_destructor_body ()
+begin_destructor_body ()
{
+ tree if_stmt;
tree compound_stmt;
- tree exprstmt;
- /* Create a block to contain all the extra code. */
+ /* If the dtor is empty, and we know there is not any possible
+ way we could use any vtable entries, before they are possibly
+ set by a base class dtor, we don't have to setup the vtables,
+ as we know that any base class dtor will set up any vtables
+ it needs. We avoid MI, because one base class dtor can do a
+ virtual dispatch to an overridden function that would need to
+ have a non-related vtable set up, we cannot avoid setting up
+ vtables in that case. We could change this to see if there
+ is just one vtable.
+
+ ??? In the destructor for a class, the vtables are set
+ appropriately for that class. There will be no non-related
+ vtables. jason 2001-12-11. */
+ if_stmt = begin_if_stmt ();
+
+ /* If it is not safe to avoid setting up the vtables, then
+ someone will change the condition to be boolean_true_node.
+ (Actually, for now, we do not have code to set the condition
+ appropriately, so we just assume that we always need to
+ initialize the vtables.) */
+ finish_if_stmt_cond (boolean_true_node, if_stmt);
+ current_vcalls_possible_p = &IF_COND (if_stmt);
+
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
- /* Any return from a destructor will end up here. */
- add_stmt (build_stmt (LABEL_STMT, dtor_label));
-
- /* Generate the code to call destructor on base class. If this
- destructor belongs to a class with virtual functions, then set
- the virtual function table pointer to represent the type of our
- base class. */
-
- /* This side-effect makes call to `build_delete' generate the code
- we have to have at the end of this destructor. `build_delete'
- will set the flag again. */
- TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
-
- exprstmt = build_delete (current_class_type,
- current_class_ref,
- sfk_base_destructor,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
- 0);
-
- if (exprstmt != error_mark_node
- && (TREE_CODE (exprstmt) != NOP_EXPR
- || TREE_OPERAND (exprstmt, 0) != integer_zero_node
- || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
- {
- if (exprstmt != void_zero_node)
- /* Don't call `expand_expr_stmt' if we're not going to do
- anything, since -Wall will give a diagnostic. */
- finish_expr_stmt (exprstmt);
-
- /* Run destructors for all virtual baseclasses. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- {
- tree vbases;
- tree if_stmt;
-
- if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
- current_in_charge_parm,
- integer_two_node),
- if_stmt);
-
- vbases = CLASSTYPE_VBASECLASSES (current_class_type);
- /* The CLASSTYPE_VBASECLASSES list is in initialization
- order, so we have to march through it in reverse order. */
- for (vbases = nreverse (copy_list (vbases));
- vbases;
- vbases = TREE_CHAIN (vbases))
- {
- tree vbase = TREE_VALUE (vbases);
- tree base_type = BINFO_TYPE (vbase);
+ /* Make all virtual function table pointers in non-virtual base
+ classes point to CURRENT_CLASS_TYPE's virtual function
+ tables. */
+ initialize_vtbl_ptrs (current_class_ptr);
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
- {
- tree base_ptr_type = build_pointer_type (base_type);
- tree expr = current_class_ptr;
-
- /* Convert to the basetype here, as we know the layout is
- fixed. What is more, if we let build_method_call do it,
- it will use the vtable, which may have been clobbered
- by the deletion of our primary base. */
-
- expr = build1 (NOP_EXPR, base_ptr_type, expr);
- expr = build (PLUS_EXPR, base_ptr_type, expr,
- BINFO_OFFSET (vbase));
- expr = build_indirect_ref (expr, NULL);
- expr = build_method_call (expr, base_dtor_identifier,
- NULL_TREE, vbase,
- LOOKUP_NORMAL);
- finish_expr_stmt (expr);
- }
- }
+ finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
+ finish_then_clause (if_stmt);
+ finish_if_stmt ();
- finish_then_clause (if_stmt);
- finish_if_stmt ();
- }
- }
+ /* And insert cleanups for our bases and members so that they
+ will be properly destroyed if we throw. */
+ push_base_cleanups ();
+}
+
+/* At the end of every destructor we generate code to delete the object if
+ necessary. Do that now. */
+
+static void
+finish_destructor_body ()
+{
+ tree exprstmt;
/* In a virtual destructor, we must call delete. */
if (DECL_VIRTUAL_P (current_function_decl))
/* [class.dtor]
- At the point of definition of a virtual destructor (including
- an implicit definition), non-placement operator delete shall
- be looked up in the scope of the destructor's class and if
- found shall be accessible and unambiguous. */
+ At the point of definition of a virtual destructor (including
+ an implicit definition), non-placement operator delete shall
+ be looked up in the scope of the destructor's class and if
+ found shall be accessible and unambiguous. */
exprstmt = build_op_delete_call
(DELETE_EXPR, current_class_ptr, virtual_size,
LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
finish_then_clause (if_stmt);
finish_if_stmt ();
}
+}
- /* Close the block we started above. */
- finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
+/* Do the necessary processing for the beginning of a function body, which
+ in this case includes member-initializers, but not the catch clauses of
+ a function-try-block. Currently, this means opening a binding level
+ for the member-initializers (in a ctor) and member cleanups (in a dtor).
+ In other functions, this isn't necessary, but it doesn't hurt. */
+
+tree
+begin_function_body ()
+{
+ tree stmt;
+
+ if (processing_template_decl)
+ /* Do nothing now. */;
+ else
+ /* Always keep the BLOCK node associated with the outermost pair of
+ curly braces of a function. These are needed for correct
+ operation of dwarfout.c. */
+ keep_next_level (1);
+
+ stmt = begin_compound_stmt (0);
+ COMPOUND_STMT_BODY_BLOCK (stmt) = 1;
+
+ if (processing_template_decl)
+ /* Do nothing now. */;
+ else if (DECL_CONSTRUCTOR_P (current_function_decl))
+ begin_constructor_body ();
+ else if (DECL_DESTRUCTOR_P (current_function_decl))
+ begin_destructor_body ();
+
+ return stmt;
}
+/* Do the processing for the end of a function body. Currently, this means
+ closing out the cleanups for fully-constructed bases and members, and in
+ the case of the destructor, deleting the object if desired. Again, this
+ is only meaningful for [cd]tors, since they are the only functions where
+ there is a significant distinction between the main body and any
+ function catch clauses. Handling, say, main() return semantics here
+ would be wrong, as flowing off the end of a function catch clause for
+ main() would also need to return 0. */
+
+void
+finish_function_body (compstmt)
+ tree compstmt;
+{
+ if (processing_template_decl)
+ /* Do nothing now. */;
+ else if (DECL_DESTRUCTOR_P (current_function_decl))
+ /* Any return from a destructor will end up here. Put it before the
+ cleanups so that an explicit return doesn't duplicate them. */
+ add_stmt (build_stmt (LABEL_STMT, dtor_label));
+
+ /* Close the block; in a destructor, run the member cleanups. */
+ finish_compound_stmt (0, compstmt);
+
+ if (processing_template_decl)
+ /* Do nothing now. */;
+ else if (DECL_CONSTRUCTOR_P (current_function_decl))
+ finish_constructor_body ();
+ else if (DECL_DESTRUCTOR_P (current_function_decl))
+ finish_destructor_body ();
+}
+
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
for the function definition.
FLAGS is a bitwise or of the following values:
- 1 - CALL_POPLEVEL
- An extra call to poplevel (and expand_end_bindings) must be
- made to take care of the binding contour for the base
- initializers. This is only relevant for constructors.
2 - INCLASS_INLINE
We just finished processing the body of an in-class inline
function definition. (This processing will have taken place
{
register tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE;
- int call_poplevel = (flags & 1) != 0;
int inclass_inline = (flags & 2) != 0;
int nested;
there's no need to add any extra bits. */
if (!DECL_CLONED_FUNCTION_P (fndecl))
{
- if (DECL_CONSTRUCTOR_P (fndecl))
- {
- finish_constructor_body ();
- if (call_poplevel)
- do_poplevel ();
- }
- else if (DECL_DESTRUCTOR_P (fndecl) && !processing_template_decl)
- finish_destructor_body ();
- else if (DECL_MAIN_P (fndecl))
+ if (DECL_MAIN_P (current_function_decl))
{
/* Make it so that `main' always returns 0 by default. */
-#ifdef VMS
+#ifdef VMS_TARGET
finish_return_stmt (integer_one_node);
#else
finish_return_stmt (integer_zero_node);
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
this function's blocks. */
+
+ /* If the current binding level isn't the outermost binding level
+ for this function, either there is a bug, or we have experienced
+ syntax errors and the statement tree is malformed. */
if (current_binding_level->parm_flag != 1)
- my_friendly_abort (122);
+ {
+ /* Make sure we have already experienced errors. */
+ if (errorcount == 0)
+ abort ();
+
+ /* Throw away the broken statement tree and extra binding
+ levels. */
+ DECL_SAVED_TREE (fndecl) = build_stmt (COMPOUND_STMT, NULL_TREE);
+
+ while (current_binding_level->parm_flag != 1)
+ {
+ if (current_binding_level->parm_flag == 2)
+ pop_nested_class ();
+ else
+ poplevel (0, 0, 0);
+ }
+ }
poplevel (1, 0, 1);
/* Set up the named return value optimization, if we can. Here, we
if (!processing_template_decl && calls_setjmp_p (fndecl))
DECL_UNINLINABLE (fndecl) = 1;
+ /* Complain if there's just no return statement. */
+ if (warn_return_type
+ && !processing_template_decl
+ && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
+ && !current_function_returns_value && !current_function_returns_null
+ /* Don't complain if we abort or throw. */
+ && !current_function_returns_abnormally
+ && !DECL_NAME (DECL_RESULT (fndecl))
+ /* Normally, with -Wreturn-type, flow will complain. Unless we're an
+ inline function, as we might never be compiled separately. */
+ && DECL_INLINE (fndecl))
+ warning ("no return statement in function returning non-void");
+
/* Clear out memory we no longer need. */
free_after_parsing (cfun);
/* Since we never call rest_of_compilation, we never clear
if (fndecl == NULL_TREE)
return NULL_TREE;
+ if (attrlist)
+ cplus_decl_attributes (&fndecl, attrlist, 0);
+
/* Pass friends other than inline friend functions back. */
if (fndecl == void_type_node)
return fndecl;
{
if (DECL_CONTEXT (fndecl)
&& TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
- cp_error ("`%D' is already defined in class `%T'", fndecl,
+ error ("`%D' is already defined in class `%T'", fndecl,
DECL_CONTEXT (fndecl));
}
return void_type_node;
fndecl = copy_node (fndecl);
TREE_CHAIN (fndecl) = NULL_TREE;
}
-
- if (DECL_CONSTRUCTOR_P (fndecl))
- {
- if (! grok_ctor_properties (current_class_type, fndecl))
- return void_type_node;
- }
- else if (IDENTIFIER_OPNAME_P (DECL_NAME (fndecl)))
- grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl), 0);
+ grok_special_member_properties (fndecl);
}
cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
DECL_CONTEXT (link) = NULL_TREE;
}
- GNU_xref_end_scope ((size_t) current_binding_level,
- (size_t) current_binding_level->level_chain,
- current_binding_level->parm_flag,
- current_binding_level->keep);
-
poplevel (0, 0, 0);
DECL_INITIAL (fndecl) = old_initial;
return decl;
}
\f
-/* Called when a new struct TYPE is defined.
- If this structure or union completes the type of any previous
- variable declaration, lay it out and output its rtl. */
+
+/* VAR is a VAR_DECL. If its type is incomplete, remember VAR so that
+ we can lay it out later, when and if its type becomes complete. */
void
-hack_incomplete_structures (type)
- tree type;
+maybe_register_incomplete_var (var)
+ tree var;
{
- tree *list;
- struct binding_level *level;
-
- if (!type) /* Don't do this for class templates. */
- return;
+ my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406);
- if (namespace_bindings_p ())
+ /* Keep track of variables with incomplete types. */
+ if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
+ && DECL_EXTERNAL (var))
{
- level = 0;
- list = &namespace_scope_incomplete;
- }
- else
- {
- level = innermost_nonclass_level ();
- list = &level->incomplete;
+ tree inner_type = TREE_TYPE (var);
+
+ while (TREE_CODE (inner_type) == ARRAY_TYPE)
+ inner_type = TREE_TYPE (inner_type);
+ inner_type = TYPE_MAIN_VARIANT (inner_type);
+
+ if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type))
+ /* RTTI TD entries are created while defining the type_info. */
+ || (TYPE_LANG_SPECIFIC (inner_type)
+ && TYPE_BEING_DEFINED (inner_type)))
+ incomplete_vars = tree_cons (inner_type, var, incomplete_vars);
}
+}
- while (1)
- {
- while (*list)
- {
- tree decl = TREE_VALUE (*list);
- if ((decl && TREE_TYPE (decl) == type)
- || (TREE_TYPE (decl)
- && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (decl)) == type))
- {
- int toplevel = toplevel_bindings_p ();
- if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (decl)) == type)
- layout_type (TREE_TYPE (decl));
- layout_decl (decl, 0);
- rest_of_decl_compilation (decl, NULL, toplevel, 0);
- if (! toplevel)
- {
- tree cleanup;
- expand_decl (decl);
- cleanup = maybe_build_cleanup (decl);
- expand_decl_init (decl);
- if (! expand_decl_cleanup (decl, cleanup))
- cp_error ("parser lost in parsing declaration of `%D'",
- decl);
- }
- *list = TREE_CHAIN (*list);
- }
- else
- list = &TREE_CHAIN (*list);
- }
+/* Called when a class type (given by TYPE) is defined. If there are
+ any existing VAR_DECLs whose type hsa been completed by this
+ declaration, update them now. */
+
+void
+complete_vars (type)
+ tree type;
+{
+ tree *list = &incomplete_vars;
- /* Keep looking through artificial binding levels generated
- for local variables. */
- if (level && level->keep == 2)
+ my_friendly_assert (CLASS_TYPE_P (type), 20020406);
+ while (*list)
+ {
+ if (same_type_p (type, TREE_PURPOSE (*list)))
{
- level = level->level_chain;
- list = &level->incomplete;
+ tree var = TREE_VALUE (*list);
+ /* Make sure that the type of the VAR has been laid out. It
+ might not have been if the type of VAR is an array. */
+ layout_type (TREE_TYPE (var));
+ /* Lay out the variable itself. */
+ layout_decl (var, 0);
+ /* Remove this entry from the list. */
+ *list = TREE_CHAIN (*list);
}
else
- break;
+ list = &TREE_CHAIN (*list);
}
}
here. */
tree
-maybe_build_cleanup (decl)
+cxx_maybe_build_cleanup (decl)
tree decl;
{
tree type = TREE_TYPE (decl);
rval = decl;
else
{
- mark_addressable (decl);
+ cxx_mark_addressable (decl);
rval = build_unary_op (ADDR_EXPR, decl, 0);
}
return rval;
}
- return 0;
+ return NULL_TREE;
}
\f
/* When a stmt has been parsed, this function is called. */
if (cp_type_quals (TREE_TYPE (TREE_VALUE (args)))
!= TYPE_UNQUALIFIED)
- cp_error ("static member function `%#D' declared with type qualifiers",
+ error ("static member function `%#D' declared with type qualifiers",
decl);
args = TREE_CHAIN (args);
mark_c_language_function (&p->base);
- ggc_mark_tree (p->x_ctor_label);
ggc_mark_tree (p->x_dtor_label);
ggc_mark_tree (p->x_current_class_ptr);
ggc_mark_tree (p->x_current_class_ref);
mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
mark_binding_level (&p->bindings);
+ mark_pending_inlines (&p->unparsed_inlines);
}
/* Mark the language-specific data in F for GC. */
}
void
-lang_mark_tree (t)
+cxx_mark_tree (t)
tree t;
{
enum tree_code code = TREE_CODE (t);