This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Several PRs
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 20 Aug 2003 00:08:38 -0700
- Subject: C++ PATCH: Several PRs
- Reply-to: mark at codesourcery dot com
This patch fixes several PRs:
- c++/19946
The problem was in language-independent code; we were using a
NOP_EXPR where we needed a CONVERT_EXPR. In particular, we were
assuming values were already sign-extended when they were not.
- c++/11684
We were issuing errors about instantiating invalid overloaded
operators during overload resolution; we're not supposed to do so.
- c++/10926
We were allowing member template destructors.
- c++/11036
The bug report had to do with allowing invalid elaborated type
specifiers. The root cause was that we were treating
namespace-scope bindings differently from local and class bindings;
this patch makes things more uniform.
- c++/10717
We had code that served no useful purpose whatsoever, but did cause
a quadratic explosion in the running time.
Bootstrapped and tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2003-08-19 Mark Mitchell <mark@codesourcery.com>
PR c++/11946
* convert.c (convert_to_integer): Use CONVERT_EXPR (instead of
NOP_EXPR) when necessary.
* c-common.c (c_common_signed_or_unsigned_type): Correctly handle
types with precisions other than those given by native machine
modes.
2003-08-19 Mark Mitchell <mark@codesourcery.com>
PR c++/11684
* cp-tree.h (grok_op_properties): Change prototype.
* decl.c (grok_op_properties): Add complain parameter.
(grokfndecl): Pass it.
* pt.c (tsubst_decl): Adjust accordingly.
PR c++/10926
* decl.c (start_method): Return immediately if push_template_decl
does not like the declaration.
* pt.c (push_template_decl_real): Disallow member template
destructors.
PR c++/11036.C
* cp-tree.h (add_binding): Add prototype.
* class.c (add_method): Set TYPE_HAS_DESTRUCTOR if appropriate.
(maybe_warn_about_overly_private_class): Use
CLASSTYPE_DESTRUCTORS.
(pushclass): Adjust call to set_identifier_type_value.
* decl.c (add_binding): Give it external linkage.
(push_local_binding): Adjust call to add_binding.
(push_class_binding): Likewise.
(set_identifier_type_value_with_scope): Change prototype. Use
add_binding for global bindings.
(set_identifier_type_value): Adjust accordingly.
(pushtag): Likewise.
(pushdecl): Use set_identifier_type_value, not
set_identifier_type_value_with_scope.
(pushdecl_namespace_level): Adjust calls to
SET_IDENTIFIER_TYPE_VALUE to pass a DECL.
(pushdecl_class_level): Likewise.
(lookup_tag): Use select_decl.
(select_decl): Improve comment.
(record_builtin_type): Do not call pushdecl.
(cxx_init_decl_processing): Do not call xref_tag for bad_alloc.
(cp_finish_decl): Adjust call to set_identifier_type_value.
(check_elaborated_type_specifier): Improve checks for invalid uses
of typedefs.
(xref_tag): Adjust call to check_elaborated_type_specifier.
* decl2.c (grokclassfn): Do not set TYPE_HAS_DESTRUCTOR.
* name-lookup.c (set_namespace_binding): Use add_binding.
* parser.c (cp_parser_simple_type_specifier): Return a TYPE_DECL,
rather than an IDENTIFIER_NODE, to represent built-in types, if
requested by the caller.
(cp_parser_postfix_expression): Adjust call.
(cp_parser_type_specifier): Likewise.
(cp_parser_elaborated_type_specifier): Adjust call to
check_elaborated_type_specifier.
* typeck2.c (build_functional_cast): Do not perform name lookups.
PR c++/10717
* decl.c (expand_static_init): Remove unncessary code.
2003-08-19 Mark Mitchell <mark@codesourcery.com>
PR c++/10926
* g++.dg/template/dtor2.C: New test.
PR c++/11684
* g++.dg/template/operator1.C: New test.
* g++.dg/parse/operator4.C: New test.
PR c++/11946.C
* g++.dg/expr/enum1.C: New test.
* gcc.dg/c99-bool-1.c: Remove bogus warning.
PR c++/11036.C
* g++.dg/parse/elab2.C: New test.
* g++.dg/parse/typedef4.C: Change error message.
* g++.old-deja/g++.robertl/eb133.C: Remove bogus error markers.
* g++.old-deja/g++.robertl/eb133a.C: Remove bogus error markers.
* g++.old-deja/g++.robertl/eb133b.C: Remove bogus error markers.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.447
diff -c -5 -p -r1.447 c-common.c
*** c-common.c 19 Aug 2003 21:04:37 -0000 1.447
--- c-common.c 20 Aug 2003 06:59:20 -0000
*************** c_common_signed_type (tree type)
*** 1967,1976 ****
--- 1967,1978 ----
signed according to UNSIGNEDP. */
tree
c_common_signed_or_unsigned_type (int unsignedp, tree type)
{
+ tree new_type;
+
if (! INTEGRAL_TYPE_P (type)
|| TREE_UNSIGNED (type) == unsignedp)
return type;
if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
*************** c_common_signed_or_unsigned_type (int un
*** 1999,2009 ****
if (TYPE_PRECISION (type) == TYPE_PRECISION (intHI_type_node))
return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
if (TYPE_PRECISION (type) == TYPE_PRECISION (intQI_type_node))
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
! return type;
}
/* Return the minimum number of bits needed to represent VALUE in a
signed or unsigned type, UNSIGNEDP says which. */
--- 2001,2018 ----
if (TYPE_PRECISION (type) == TYPE_PRECISION (intHI_type_node))
return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
if (TYPE_PRECISION (type) == TYPE_PRECISION (intQI_type_node))
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
! new_type = (unsignedp
! ? make_unsigned_type (TYPE_PRECISION (type))
! : make_signed_type (TYPE_PRECISION (type)));
! TYPE_SIZE (new_type) = TYPE_SIZE (type);
! TYPE_SIZE_UNIT (new_type) = TYPE_SIZE_UNIT (type);
! TYPE_MODE (new_type) = TYPE_MODE (type);
!
! return new_type;
}
/* Return the minimum number of bits needed to represent VALUE in a
signed or unsigned type, UNSIGNEDP says which. */
Index: convert.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/convert.c,v
retrieving revision 1.32
diff -c -5 -p -r1.32 convert.c
*** convert.c 28 Jul 2003 15:42:16 -0000 1.32
--- convert.c 20 Aug 2003 06:59:20 -0000
*************** convert_to_integer (tree type, tree expr
*** 347,357 ****
/* If we are widening the type, put in an explicit conversion.
Similarly if we are not changing the width. After this, we know
we are truncating EXPR. */
else if (outprec >= inprec)
! return build1 (NOP_EXPR, type, expr);
/* If TYPE is an enumeral type or a type with a precision less
than the number of bits in its mode, do the conversion to the
type corresponding to its mode, then do a nop conversion
to TYPE. */
--- 347,377 ----
/* If we are widening the type, put in an explicit conversion.
Similarly if we are not changing the width. After this, we know
we are truncating EXPR. */
else if (outprec >= inprec)
! {
! enum tree_code code;
!
! /* If the precision of the EXPR's type is K bits and the
! destination mode has more bits, and the sign is changing,
! it is not safe to use a NOP_EXPR. For example, suppose
! that EXPR's type is a 3-bit unsigned integer type, the
! TYPE is a 3-bit signed integer type, and the machine mode
! for the types is 8-bit QImode. In that case, the
! conversion necessitates an explicit sign-extension. In
! the signed-to-unsigned case the high-order bits have to
! be cleared. */
! if (TREE_UNSIGNED (type) != TREE_UNSIGNED (TREE_TYPE (expr))
! && (TYPE_PRECISION (TREE_TYPE (expr))
! != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (expr)))))
! code = CONVERT_EXPR;
! else
! code = NOP_EXPR;
!
! return build1 (code, type, expr);
! }
/* If TYPE is an enumeral type or a type with a precision less
than the number of bits in its mode, do the conversion to the
type corresponding to its mode, then do a nop conversion
to TYPE. */
Index: config/pa/pa.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa.h,v
retrieving revision 1.200
diff -c -5 -p -r1.200 pa.h
*** config/pa/pa.h 8 Aug 2003 02:57:48 -0000 1.200
--- config/pa/pa.h 20 Aug 2003 06:59:20 -0000
*************** extern struct rtx_def *hppa_pic_save_rtx
*** 652,665 ****
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
((CLASS == BASE_REG_CLASS && GET_CODE (IN) == REG \
&& REGNO (IN) < FIRST_PSEUDO_REGISTER) \
? NO_REGS : secondary_reload_class (CLASS, MODE, IN))
/* On the PA it is not possible to directly move data between
GENERAL_REGS and FP_REGS. */
! #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
! (FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2))
/* Return the stack location to use for secondary memory needed reloads. */
#define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
gen_rtx_MEM (MODE, gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-16)))
--- 652,669 ----
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
((CLASS == BASE_REG_CLASS && GET_CODE (IN) == REG \
&& REGNO (IN) < FIRST_PSEUDO_REGISTER) \
? NO_REGS : secondary_reload_class (CLASS, MODE, IN))
+ #define MAYBE_FP_REG_CLASS_P(CLASS) \
+ reg_classes_intersect_p ((CLASS), FP_REGS)
+
/* On the PA it is not possible to directly move data between
GENERAL_REGS and FP_REGS. */
! #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
! (MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2) \
! || MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1))
/* Return the stack location to use for secondary memory needed reloads. */
#define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
gen_rtx_MEM (MODE, gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-16)))
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.563
diff -c -5 -p -r1.563 class.c
*** cp/class.c 12 Aug 2003 22:26:20 -0000 1.563
--- cp/class.c 20 Aug 2003 06:59:21 -0000
*************** add_method (tree type, tree method, int
*** 748,758 ****
/* Constructors and destructors go in special slots. */
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
slot = CLASSTYPE_CONSTRUCTOR_SLOT;
else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
! slot = CLASSTYPE_DESTRUCTOR_SLOT;
else
{
int have_template_convs_p = 0;
/* See if we already have an entry with this name. */
--- 748,761 ----
/* Constructors and destructors go in special slots. */
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
slot = CLASSTYPE_CONSTRUCTOR_SLOT;
else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
! {
! slot = CLASSTYPE_DESTRUCTOR_SLOT;
! TYPE_HAS_DESTRUCTOR (type) = 1;
! }
else
{
int have_template_convs_p = 0;
/* See if we already have an entry with this name. */
*************** maybe_warn_about_overly_private_class (t
*** 1644,1663 ****
}
/* Even if some of the member functions are non-private, the class
won't be useful for much if all the constructors or destructors
are private: such an object can never be created or destroyed. */
! if (TYPE_HAS_DESTRUCTOR (t))
{
! tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1);
!
! if (TREE_PRIVATE (dtor))
! {
! warning ("`%#T' only defines a private destructor and has no friends",
! t);
! return;
! }
}
if (TYPE_HAS_CONSTRUCTOR (t))
{
int nonprivate_ctor = 0;
--- 1647,1662 ----
}
/* Even if some of the member functions are non-private, the class
won't be useful for much if all the constructors or destructors
are private: such an object can never be created or destroyed. */
! if (TYPE_HAS_DESTRUCTOR (t)
! && TREE_PRIVATE (CLASSTYPE_DESTRUCTORS (t)))
{
! warning ("`%#T' only defines a private destructor and has no friends",
! t);
! return;
}
if (TYPE_HAS_CONSTRUCTOR (t))
{
int nonprivate_ctor = 0;
*************** pushclass (tree type)
*** 5483,5493 ****
tree id = TREE_PURPOSE (item);
tree decl = TREE_TYPE (item);
push_class_binding (id, decl);
if (TREE_CODE (decl) == TYPE_DECL)
! set_identifier_type_value (id, TREE_TYPE (decl));
}
unuse_fields (type);
}
cxx_remember_type_decls (CLASSTYPE_NESTED_UTDS (type));
--- 5482,5492 ----
tree id = TREE_PURPOSE (item);
tree decl = TREE_TYPE (item);
push_class_binding (id, decl);
if (TREE_CODE (decl) == TYPE_DECL)
! set_identifier_type_value (id, decl);
}
unuse_fields (type);
}
cxx_remember_type_decls (CLASSTYPE_NESTED_UTDS (type));
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.903
diff -c -5 -p -r1.903 cp-tree.h
*** cp/cp-tree.h 18 Aug 2003 12:55:03 -0000 1.903
--- cp/cp-tree.h 20 Aug 2003 06:59:21 -0000
*************** extern tree build_ptrmem_type
*** 3693,3703 ****
/* the grokdeclarator prototype is in decl.h */
extern int copy_fn_p (tree);
extern tree get_scope_of_declarator (tree);
extern void grok_special_member_properties (tree);
extern int grok_ctor_properties (tree, tree);
! extern void grok_op_properties (tree, int);
extern tree xref_tag (enum tag_types, tree, tree, bool, bool);
extern tree xref_tag_from_type (tree, tree, int);
extern void xref_basetypes (tree, tree);
extern tree start_enum (tree);
extern void finish_enum (tree);
--- 3693,3703 ----
/* the grokdeclarator prototype is in decl.h */
extern int copy_fn_p (tree);
extern tree get_scope_of_declarator (tree);
extern void grok_special_member_properties (tree);
extern int grok_ctor_properties (tree, tree);
! extern bool grok_op_properties (tree, int, bool);
extern tree xref_tag (enum tag_types, tree, tree, bool, bool);
extern tree xref_tag_from_type (tree, tree, int);
extern void xref_basetypes (tree, tree);
extern tree start_enum (tree);
extern void finish_enum (tree);
*************** extern int nonstatic_local_decl_p
*** 3742,3751 ****
--- 3742,3752 ----
extern tree declare_global_var (tree, tree);
extern void register_dtor_fn (tree);
extern tmpl_spec_kind current_tmpl_spec_kind (int);
extern tree cp_fname_init (const char *);
extern tree check_elaborated_type_specifier (enum tag_types, tree, bool);
+ extern int add_binding (cxx_binding *, tree);
extern bool have_extern_spec;
/* in decl2.c */
extern bool check_java_method (tree);
extern int grok_method_quals (tree, tree, tree);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1113
diff -c -5 -p -r1.1113 decl.c
*** cp/decl.c 18 Aug 2003 12:38:04 -0000 1.1113
--- cp/decl.c 20 Aug 2003 06:59:21 -0000
*************** static tree maybe_process_template_type_
*** 90,100 ****
(tree, int, struct cp_binding_level*);
static void check_for_uninitialized_const_var (tree);
static hashval_t typename_hash (const void *);
static int typename_compare (const void *, const void *);
static void push_binding (tree, tree, struct cp_binding_level*);
- static int add_binding (tree, tree);
static void pop_binding (tree, tree);
static tree local_variable_p_walkfn (tree *, int *, void *);
static tree select_decl (cxx_binding *, int);
static int lookup_flags (int, int);
static tree qualify_lookup (tree, int);
--- 90,99 ----
*************** push_binding (tree id, tree decl, cxx_sc
*** 916,929 ****
additional binding for ID in the same scope. This is the `struct
stat' hack whereby a non-typedef class-name or enum-name can be
bound at the same level as some other kind of entity. It's the
responsibility of the caller to check that inserting this name is
valid here. Returns nonzero if the new binding was successful. */
! static int
! add_binding (tree id, tree decl)
{
- cxx_binding *binding = IDENTIFIER_BINDING (id);
tree bval = BINDING_VALUE (binding);
int ok = 1;
timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
--- 915,928 ----
additional binding for ID in the same scope. This is the `struct
stat' hack whereby a non-typedef class-name or enum-name can be
bound at the same level as some other kind of entity. It's the
responsibility of the caller to check that inserting this name is
valid here. Returns nonzero if the new binding was successful. */
!
! int
! add_binding (cxx_binding *binding, tree decl)
{
tree bval = BINDING_VALUE (binding);
int ok = 1;
timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
*************** push_local_binding (tree id, tree decl,
*** 1039,1049 ****
b = b->level_chain;
if (lookup_name_current_level (id))
{
/* Supplement the existing binding. */
! if (!add_binding (id, decl))
/* It didn't work. Something else must be bound at this
level. Do not add DECL to the list of things to pop
later. */
return;
}
--- 1038,1048 ----
b = b->level_chain;
if (lookup_name_current_level (id))
{
/* Supplement the existing binding. */
! if (!add_binding (IDENTIFIER_BINDING (id), decl))
/* It didn't work. Something else must be bound at this
level. Do not add DECL to the list of things to pop
later. */
return;
}
*************** push_class_binding (tree id, tree decl)
*** 1078,1088 ****
other purpose. */
note_name_declared_in_class (id, decl);
if (binding && BINDING_SCOPE (binding) == class_binding_level)
/* Supplement the existing binding. */
! result = add_binding (id, decl);
else
/* Create a new binding. */
push_binding (id, decl, class_binding_level);
/* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
--- 1077,1087 ----
other purpose. */
note_name_declared_in_class (id, decl);
if (binding && BINDING_SCOPE (binding) == class_binding_level)
/* Supplement the existing binding. */
! result = add_binding (IDENTIFIER_BINDING (id), decl);
else
/* Create a new binding. */
push_binding (id, decl, class_binding_level);
/* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
*************** pop_from_top_level (void)
*** 2308,2360 ****
current_function_decl = s->function_decl;
last_function_parms = s->last_parms;
timevar_pop (TV_NAME_LOOKUP);
}
! /* Push a definition of struct, union or enum tag "name".
! into binding_level "b". "type" should be the type node,
! We assume that the tag "name" is not already defined.
!
! Note that the definition may really be just a forward reference.
! In that case, the TYPE_SIZE will be a NULL_TREE.
!
! C++ gratuitously puts all these tags in the name space. */
!
! /* When setting the IDENTIFIER_TYPE_VALUE field of an identifier ID,
! record the shadowed value for this binding contour. TYPE is
! the type that ID maps to. */
static void
set_identifier_type_value_with_scope (tree id,
! tree type,
struct cp_binding_level* b)
{
if (!b->namespace_p)
{
/* Shadow the marker, not the real thing, so that the marker
gets restored later. */
tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
b->type_shadowed
= tree_cons (id, old_type_value, b->type_shadowed);
}
else
{
cxx_binding *binding =
! binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
! BINDING_TYPE (binding) = type;
/* Store marker instead of real type. */
type = global_type_node;
}
SET_IDENTIFIER_TYPE_VALUE (id, type);
}
/* As set_identifier_type_value_with_scope, but using current_binding_level. */
void
! set_identifier_type_value (tree id, tree type)
{
! set_identifier_type_value_with_scope (id, type, current_binding_level);
}
/* Return the type associated with id. */
tree
--- 2307,2361 ----
current_function_decl = s->function_decl;
last_function_parms = s->last_parms;
timevar_pop (TV_NAME_LOOKUP);
}
! /* Push a definition of struct, union or enum tag named ID. into
! binding_level B. DECL is a TYPE_DECL for the type. We assume that
! the tag ID is not already defined. */
static void
set_identifier_type_value_with_scope (tree id,
! tree decl,
struct cp_binding_level* b)
{
+ tree type;
+
if (!b->namespace_p)
{
/* Shadow the marker, not the real thing, so that the marker
gets restored later. */
tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
b->type_shadowed
= tree_cons (id, old_type_value, b->type_shadowed);
+ type = decl ? TREE_TYPE (decl) : NULL_TREE;
}
else
{
cxx_binding *binding =
! binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
! if (decl)
! {
! if (BINDING_VALUE (binding))
! add_binding (binding, decl);
! else
! BINDING_VALUE (binding) = decl;
! }
! else
! abort ();
/* Store marker instead of real type. */
type = global_type_node;
}
SET_IDENTIFIER_TYPE_VALUE (id, type);
}
/* As set_identifier_type_value_with_scope, but using current_binding_level. */
void
! set_identifier_type_value (tree id, tree decl)
{
! set_identifier_type_value_with_scope (id, decl, current_binding_level);
}
/* Return the type associated with id. */
tree
*************** pushtag (tree name, tree type, int globa
*** 2584,2594 ****
TYPE_FOR_JAVA (type) = 1;
d = create_implicit_typedef (name, type);
DECL_CONTEXT (d) = FROB_CONTEXT (context);
if (! in_class)
! set_identifier_type_value_with_scope (name, type, b);
d = maybe_process_template_type_declaration (type,
globalize, b);
if (b->parm_flag == 2)
--- 2585,2595 ----
TYPE_FOR_JAVA (type) = 1;
d = create_implicit_typedef (name, type);
DECL_CONTEXT (d) = FROB_CONTEXT (context);
if (! in_class)
! set_identifier_type_value_with_scope (name, d, b);
d = maybe_process_template_type_declaration (type,
globalize, b);
if (b->parm_flag == 2)
*************** pushdecl (tree x)
*** 3850,3862 ****
}
if (type != error_mark_node
&& TYPE_NAME (type)
&& TYPE_IDENTIFIER (type))
! set_identifier_type_value_with_scope (DECL_NAME (x), type,
! current_binding_level);
!
}
/* Multiple external decls of the same identifier ought to match.
We get warnings about inline functions where they are defined.
--- 3851,3861 ----
}
if (type != error_mark_node
&& TYPE_NAME (type)
&& TYPE_IDENTIFIER (type))
! set_identifier_type_value (DECL_NAME (x), x);
}
/* Multiple external decls of the same identifier ought to match.
We get warnings about inline functions where they are defined.
*************** pushdecl (tree x)
*** 3942,3960 ****
need_new_binding = 0;
}
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
! set_identifier_type_value_with_scope (name, TREE_TYPE (x),
! current_binding_level);
/* Clear out any TYPE_DECL shadowed by a namespace so that
we won't think this is a type. The C struct hack doesn't
go through namespaces. */
if (TREE_CODE (x) == NAMESPACE_DECL)
! set_identifier_type_value_with_scope (name, NULL_TREE,
! current_binding_level);
if (oldlocal)
{
tree d = oldlocal;
--- 3941,3957 ----
need_new_binding = 0;
}
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
! set_identifier_type_value (name, x);
/* Clear out any TYPE_DECL shadowed by a namespace so that
we won't think this is a type. The C struct hack doesn't
go through namespaces. */
if (TREE_CODE (x) == NAMESPACE_DECL)
! set_identifier_type_value (name, NULL_TREE);
if (oldlocal)
{
tree d = oldlocal;
*************** pushdecl_namespace_level (tree x)
*** 4131,4141 ****
newval = TREE_TYPE (x);
if (ptr == (tree *)0)
{
/* @@ This shouldn't be needed. My test case "zstring.cc" trips
up here if this is changed to an assertion. --KR */
! SET_IDENTIFIER_TYPE_VALUE (name, newval);
}
else
{
*ptr = newval;
}
--- 4128,4138 ----
newval = TREE_TYPE (x);
if (ptr == (tree *)0)
{
/* @@ This shouldn't be needed. My test case "zstring.cc" trips
up here if this is changed to an assertion. --KR */
! SET_IDENTIFIER_TYPE_VALUE (name, x);
}
else
{
*ptr = newval;
}
*************** pushdecl_class_level (tree x)
*** 4194,4204 ****
if (name)
{
is_valid = push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
! set_identifier_type_value (name, TREE_TYPE (x));
}
else if (ANON_AGGR_TYPE_P (TREE_TYPE (x)))
{
/* If X is an anonymous aggregate, all of its members are
treated as if they were members of the class containing the
--- 4191,4201 ----
if (name)
{
is_valid = push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
! set_identifier_type_value (name, x);
}
else if (ANON_AGGR_TYPE_P (TREE_TYPE (x)))
{
/* If X is an anonymous aggregate, all of its members are
treated as if they were members of the class containing the
*************** lookup_tag (enum tree_code form, tree na
*** 5190,5210 ****
class declaration, then we use the _TYPE node for the
template. See the example below. */
if (thislevel_only && !allow_template_parms_p
&& binding && BINDING_VALUE (binding)
&& DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
! old = TREE_TYPE (BINDING_VALUE (binding));
else if (binding)
! old = BINDING_TYPE (binding);
else
old = NULL_TREE;
if (old)
{
/* We've found something at this binding level. If it is
a typedef, extract the tag it refers to. Lookup fails
if the typedef doesn't refer to a taggable type. */
old = follow_tag_typedef (old);
if (!old)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
if (TREE_CODE (old) != form
&& (form == ENUMERAL_TYPE
--- 5187,5208 ----
class declaration, then we use the _TYPE node for the
template. See the example below. */
if (thislevel_only && !allow_template_parms_p
&& binding && BINDING_VALUE (binding)
&& DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
! old = BINDING_VALUE (binding);
else if (binding)
! old = select_decl (binding, LOOKUP_PREFER_TYPES);
else
old = NULL_TREE;
if (old)
{
/* We've found something at this binding level. If it is
a typedef, extract the tag it refers to. Lookup fails
if the typedef doesn't refer to a taggable type. */
+ old = TREE_TYPE (old);
old = follow_tag_typedef (old);
if (!old)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
if (TREE_CODE (old) != form
&& (form == ENUMERAL_TYPE
*************** select_decl (cxx_binding *binding, int f
*** 5643,5658 ****
if (val && TREE_CODE (val) == NAMESPACE_DECL)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
! /* If we could have a type and
! we have nothing or we need a type and have none. */
! if (BINDING_TYPE (binding)
! && (!val || ((flags & LOOKUP_PREFER_TYPES)
! && TREE_CODE (val) != TYPE_DECL)))
! val = TYPE_STUB_DECL (BINDING_TYPE (binding));
/* Don't return non-types if we really prefer types. */
else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
&& (TREE_CODE (val) != TEMPLATE_DECL
|| !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
--- 5641,5655 ----
if (val && TREE_CODE (val) == NAMESPACE_DECL)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
! /* If looking for a type, or if there is no non-type binding, select
! the value binding. */
! if (BINDING_TYPE (binding)
! && (!val || (flags & LOOKUP_PREFER_TYPES)))
! val = BINDING_TYPE (binding);
/* Don't return non-types if we really prefer types. */
else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
&& (TREE_CODE (val) != TEMPLATE_DECL
|| !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
*************** lookup_type_current_level (tree name)
*** 6043,6055 ****
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* Push the declarations of builtin types into the namespace.
! RID_INDEX is the index of the builtin type
! in the array RID_POINTERS. NAME is the name used when looking
! up the builtin type. TYPE is the _TYPE node for the builtin type. */
void
record_builtin_type (enum rid rid_index,
const char* name,
tree type)
--- 6040,6052 ----
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* Push the declarations of builtin types into the namespace.
! RID_INDEX is the index of the builtin type in the array
! RID_POINTERS. NAME is the name used when looking up the builtin
! type. TYPE is the _TYPE node for the builtin type. */
void
record_builtin_type (enum rid rid_index,
const char* name,
tree type)
*************** record_builtin_type (enum rid rid_index,
*** 6060,6090 ****
if ((int) rid_index < (int) RID_MAX)
rname = ridpointers[(int) rid_index];
if (name)
tname = get_identifier (name);
if (tname)
{
! tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
! set_identifier_type_value (tname, NULL_TREE);
! if ((int) rid_index < (int) RID_MAX)
! /* Built-in types live in the global namespace. */
SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
}
! if (rname != NULL_TREE)
{
! if (tname != NULL_TREE)
{
! set_identifier_type_value (rname, NULL_TREE);
! SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl);
! }
! else
! {
! tdecl = pushdecl (build_decl (TYPE_DECL, rname, type));
! set_identifier_type_value (rname, NULL_TREE);
}
}
}
/* Record one of the standard Java types.
* Declare it as having the given NAME.
* If SIZE > 0, it is the size of one of the integral types;
--- 6057,6090 ----
if ((int) rid_index < (int) RID_MAX)
rname = ridpointers[(int) rid_index];
if (name)
tname = get_identifier (name);
+ /* The calls to SET_IDENTIFIER_GLOBAL_VALUE below should be
+ eliminated. Built-in types should not be looked up name; their
+ names are keywords that the parser can recognize. However, there
+ is code in c-common.c that uses identifier_global_value to look
+ up built-in types by name. */
if (tname)
{
! tdecl = build_decl (TYPE_DECL, tname, type);
! DECL_ARTIFICIAL (tdecl) = 1;
! if (tname)
SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
}
! if (rname)
{
! if (!tdecl)
{
! tdecl = build_decl (TYPE_DECL, rname, type);
! DECL_ARTIFICIAL (tdecl) = 1;
}
+ SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl);
}
+
+ if (!TYPE_NAME (type))
+ TYPE_NAME (type) = tdecl;
}
/* Record one of the standard Java types.
* Declare it as having the given NAME.
* If SIZE > 0, it is the size of one of the integral types;
*************** cxx_init_decl_processing (void)
*** 6332,6349 ****
/* Now, C++. */
current_lang_name = lang_name_cplusplus;
{
! tree bad_alloc_type_node, newtype, deltype;
tree ptr_ftype_sizetype;
push_namespace (std_identifier);
! bad_alloc_type_node
! = xref_tag (class_type, get_identifier ("bad_alloc"),
! /*attributes=*/NULL_TREE, true, false);
pop_namespace ();
ptr_ftype_sizetype
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
size_type_node,
void_list_node));
--- 6332,6357 ----
/* Now, C++. */
current_lang_name = lang_name_cplusplus;
{
! tree bad_alloc_id;
! tree bad_alloc_type_node;
! tree bad_alloc_decl;
! tree newtype, deltype;
tree ptr_ftype_sizetype;
push_namespace (std_identifier);
! bad_alloc_id = get_identifier ("bad_alloc");
! bad_alloc_type_node = make_aggr_type (RECORD_TYPE);
! TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
! bad_alloc_decl
! = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
! DECL_CONTEXT (bad_alloc_decl) = current_namespace;
! TYPE_STUB_DECL (bad_alloc_type_node) = bad_alloc_decl;
pop_namespace ();
+
ptr_ftype_sizetype
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
size_type_node,
void_list_node));
*************** cp_finish_decl (tree decl, tree init, tr
*** 8062,8072 ****
if (type != error_mark_node
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
warning ("shadowing previous type declaration of `%#D'", decl);
! set_identifier_type_value (DECL_NAME (decl), type);
}
/* If we have installed this as the canonical typedef for this
type, and that type has not been defined yet, delay emitting
the debug information for it, as we will emit it later. */
--- 8070,8080 ----
if (type != error_mark_node
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
warning ("shadowing previous type declaration of `%#D'", decl);
! set_identifier_type_value (DECL_NAME (decl), decl);
}
/* If we have installed this as the canonical typedef for this
type, and that type has not been defined yet, delay emitting
the debug information for it, as we will emit it later. */
*************** register_dtor_fn (tree decl)
*** 8493,8521 ****
and destruction of DECL. */
static void
expand_static_init (tree decl, tree init)
{
- tree oldstatic;
-
my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
my_friendly_assert (TREE_STATIC (decl), 20021010);
/* Some variables require no initialization. */
if (!init
&& !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
! oldstatic = value_member (decl, static_aggregates);
!
! if (oldstatic)
! {
! if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
! error ("multiple initializations given for `%D'", decl);
! }
! else if (! toplevel_bindings_p ())
{
/* Emit code to perform this initialization but once. */
tree if_stmt;
tree then_clause;
tree assignment;
--- 8501,8520 ----
and destruction of DECL. */
static void
expand_static_init (tree decl, tree init)
{
my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
my_friendly_assert (TREE_STATIC (decl), 20021010);
/* Some variables require no initialization. */
if (!init
&& !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
! if (! toplevel_bindings_p ())
{
/* Emit code to perform this initialization but once. */
tree if_stmt;
tree then_clause;
tree assignment;
*************** grokfndecl (tree ctype,
*** 8899,8909 ****
(ctype ? "static " : "non-"), decl, TREE_VALUE (quals));
quals = NULL_TREE;
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
! grok_op_properties (decl, friendp);
if (ctype && decl_function_context (decl))
DECL_NO_STATIC_CHAIN (decl) = 1;
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
--- 8898,8908 ----
(ctype ? "static " : "non-"), decl, TREE_VALUE (quals));
quals = NULL_TREE;
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
! grok_op_properties (decl, friendp, /*complain=*/true);
if (ctype && decl_function_context (decl))
DECL_NO_STATIC_CHAIN (decl) = 1;
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
*************** unary_op_p (enum tree_code code)
*** 12182,12202 ****
|| code == BIT_NOT_EXPR
|| code == COMPONENT_REF
|| code == TYPE_EXPR);
}
! /* Do a little sanity-checking on how they declared their operator. */
! void
! grok_op_properties (tree decl, int friendp)
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree argtype;
int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
tree name = DECL_NAME (decl);
enum tree_code operator_code;
int arity;
/* Count the number of arguments. */
for (argtype = argtypes, arity = 0;
argtype && argtype != void_list_node;
argtype = TREE_CHAIN (argtype))
--- 12181,12207 ----
|| code == BIT_NOT_EXPR
|| code == COMPONENT_REF
|| code == TYPE_EXPR);
}
! /* DECL is a declaration for an overloaded operator. Returns true if
! the declaration is valid; false otherwise. If COMPLAIN is true,
! errors are issued for invalid declarations. */
! bool
! grok_op_properties (tree decl, int friendp, bool complain)
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree argtype;
int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
tree name = DECL_NAME (decl);
enum tree_code operator_code;
int arity;
+ bool ok;
+
+ /* Assume that the declaration is valid. */
+ ok = true;
/* Count the number of arguments. */
for (argtype = argtypes, arity = 0;
argtype && argtype != void_list_node;
argtype = TREE_CHAIN (argtype))
*************** grok_op_properties (tree decl, int frien
*** 12286,12322 ****
|| operator_code == ARRAY_REF
|| operator_code == NOP_EXPR)
error ("`%D' must be a nonstatic member function", decl);
else
{
! tree p = argtypes;
if (DECL_STATIC_FUNCTION_P (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 arg = non_reference (TREE_VALUE (p));
! /* This lets bad template code slip through. */
! if (IS_AGGR_TYPE (arg)
! || TREE_CODE (arg) == ENUMERAL_TYPE
! || TREE_CODE (arg) == TEMPLATE_TYPE_PARM
! || TREE_CODE (arg) == BOUND_TEMPLATE_TEMPLATE_PARM)
! goto foundaggr;
! }
! error
! ("`%D' must have an argument of class or enumerated type",
! decl);
! foundaggr:
! ;
}
}
if (operator_code == CALL_EXPR)
! return; /* No restrictions on args. */
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
tree t = TREE_TYPE (name);
if (! friendp)
--- 12291,12332 ----
|| operator_code == ARRAY_REF
|| operator_code == NOP_EXPR)
error ("`%D' must be a nonstatic member function", decl);
else
{
! tree p;
if (DECL_STATIC_FUNCTION_P (decl))
error ("`%D' must be either a non-static member function or a non-member function", decl);
! for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
! {
! tree arg = non_reference (TREE_VALUE (p));
! /* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used
! because these checks are performed even on
! template functions. */
! if (IS_AGGR_TYPE (arg) || TREE_CODE (arg) == ENUMERAL_TYPE)
! break;
! }
! if (!p || p == void_list_node)
! {
! if (!complain)
! return false;
!
! error ("`%D' must have an argument of class or "
! "enumerated type",
! decl);
! ok = false;
! }
}
}
+ /* There are no restrictions on the arguments to an overloaded
+ "operator ()". */
if (operator_code == CALL_EXPR)
! return ok;
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
tree t = TREE_TYPE (name);
if (! friendp)
*************** grok_op_properties (tree decl, int frien
*** 12495,12504 ****
--- 12505,12516 ----
else
error ("`%D' cannot have default arguments", decl);
}
}
+
+ return ok;
}
static const char *
tag_name (enum tag_types code)
{
*************** tag_name (enum tag_types code)
*** 12516,12564 ****
abort ();
}
}
/* Name lookup in an elaborated-type-specifier (after the keyword
! indicated by TAG_CODE) has found TYPE. If the
elaborated-type-specifier is invalid, issue a diagnostic and return
! error_mark_node; otherwise, return TYPE itself.
If ALLOW_TEMPLATE_P is true, TYPE may be a class template. */
tree
check_elaborated_type_specifier (enum tag_types tag_code,
! tree type,
bool allow_template_p)
{
! tree t = follow_tag_typedef (type);
! /* [dcl.type.elab] If the identifier resolves to a typedef-name or a
! template type-parameter, the elaborated-type-specifier is
! ill-formed. */
! if (!t)
{
! error ("using typedef-name `%T' after `%s'",
! type, tag_name (tag_code));
! t = error_mark_node;
}
! else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
{
error ("using template type parameter `%T' after `%s'",
type, tag_name (tag_code));
! t = error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE
&& tag_code != enum_type)
{
error ("`%T' referred to as `%s'", type, tag_name (tag_code));
! t = error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
&& tag_code == enum_type)
{
error ("`%T' referred to as enum", type);
! t = error_mark_node;
}
else if (!allow_template_p
&& TREE_CODE (type) == RECORD_TYPE
&& CLASSTYPE_IS_TEMPLATE (type))
{
--- 12528,12592 ----
abort ();
}
}
/* Name lookup in an elaborated-type-specifier (after the keyword
! indicated by TAG_CODE) has found the TYPE_DECL DECL. If the
elaborated-type-specifier is invalid, issue a diagnostic and return
! error_mark_node; otherwise, return the *_TYPE to which it referred.
If ALLOW_TEMPLATE_P is true, TYPE may be a class template. */
tree
check_elaborated_type_specifier (enum tag_types tag_code,
! tree decl,
bool allow_template_p)
{
! tree type;
! /* In the case of:
!
! struct S { struct S *p; };
!
! name lookup will find the TYPE_DECL for the implicit "S::S"
! typedef. Adjust for that here. */
! if (DECL_SELF_REFERENCE_P (decl))
! decl = TYPE_NAME (TREE_TYPE (decl));
!
! type = TREE_TYPE (decl);
!
! /* [dcl.type.elab]
!
! If the identifier resolves to a typedef-name or a template
! type-parameter, the elaborated-type-specifier is ill-formed.
!
! In other words, the only legitimate declaration to use in the
! elaborated type specifier is the implicit typedef created when
! the type is declared. */
! if (!DECL_IMPLICIT_TYPEDEF_P (decl))
{
! error ("using typedef-name `%D' after `%s'", decl, tag_name (tag_code));
! return IS_AGGR_TYPE (type) ? type : error_mark_node;
}
!
! if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
{
error ("using template type parameter `%T' after `%s'",
type, tag_name (tag_code));
! return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE
&& tag_code != enum_type)
{
error ("`%T' referred to as `%s'", type, tag_name (tag_code));
! return error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
&& tag_code == enum_type)
{
error ("`%T' referred to as enum", type);
! return error_mark_node;
}
else if (!allow_template_p
&& TREE_CODE (type) == RECORD_TYPE
&& CLASSTYPE_IS_TEMPLATE (type))
{
*************** check_elaborated_type_specifier (enum ta
*** 12571,12584 ****
then the required template argument is missing. */
error ("template argument required for `%s %T'",
tag_name (tag_code),
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
! t = error_mark_node;
}
! return t;
}
/* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
--- 12599,12612 ----
then the required template argument is missing. */
error ("template argument required for `%s %T'",
tag_name (tag_code),
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
! return error_mark_node;
}
! return type;
}
/* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
*************** xref_tag (enum tag_types tag_code, tree
*** 12651,12662 ****
template <class U> class C; // template_header_p is true
template <class T> class C<T>::D {
class C *c2; // DECL_SELF_REFERENCE_P is true
}; */
! t = check_elaborated_type_specifier (tag_code,
! TREE_TYPE (decl),
template_header_p
| DECL_SELF_REFERENCE_P (decl));
if (t == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
--- 12679,12690 ----
template <class U> class C; // template_header_p is true
template <class T> class C<T>::D {
class C *c2; // DECL_SELF_REFERENCE_P is true
}; */
! t = check_elaborated_type_specifier (tag_code,
! decl,
template_header_p
| DECL_SELF_REFERENCE_P (decl));
if (t == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
*************** start_method (tree declspecs, tree decla
*** 14214,14224 ****
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
/* We process method specializations in finish_struct_1. */
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
! fndecl = push_template_decl (fndecl);
if (! DECL_FRIEND_P (fndecl))
{
if (TREE_CHAIN (fndecl))
{
--- 14242,14256 ----
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
/* We process method specializations in finish_struct_1. */
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
! {
! fndecl = push_template_decl (fndecl);
! if (fndecl == error_mark_node)
! return fndecl;
! }
if (! DECL_FRIEND_P (fndecl))
{
if (TREE_CHAIN (fndecl))
{
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.661
diff -c -5 -p -r1.661 decl2.c
*** cp/decl2.c 15 Aug 2003 12:15:56 -0000 1.661
--- cp/decl2.c 20 Aug 2003 06:59:22 -0000
*************** grokclassfn (tree ctype, tree function,
*** 385,400 ****
if (flags == DTOR_FLAG)
DECL_DESTRUCTOR_P (function) = 1;
if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))
maybe_retrofit_in_chrg (function);
-
- if (flags == DTOR_FLAG)
- {
- DECL_DESTRUCTOR_P (function) = 1;
- TYPE_HAS_DESTRUCTOR (ctype) = 1;
- }
}
/* Create an ARRAY_REF, checking for the user doing things backwards
along the way. */
--- 385,394 ----
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.8
diff -c -5 -p -r1.8 name-lookup.c
*** cp/name-lookup.c 6 Jul 2003 23:23:44 -0000 1.8
--- cp/name-lookup.c 20 Aug 2003 06:59:22 -0000
*************** set_namespace_binding (tree name, tree s
*** 375,384 ****
timevar_push (TV_NAME_LOOKUP);
if (scope == NULL_TREE)
scope = global_namespace;
b = binding_for_name (NAMESPACE_LEVEL (scope), name);
! BINDING_VALUE (b) = val;
timevar_pop (TV_NAME_LOOKUP);
}
#include "gt-cp-name-lookup.h"
--- 375,389 ----
timevar_push (TV_NAME_LOOKUP);
if (scope == NULL_TREE)
scope = global_namespace;
b = binding_for_name (NAMESPACE_LEVEL (scope), name);
! if (!BINDING_VALUE (b)
! || TREE_CODE (val) == OVERLOAD
! || val == error_mark_node)
! BINDING_VALUE (b) = val;
! else
! add_binding (b, val);
timevar_pop (TV_NAME_LOOKUP);
}
#include "gt-cp-name-lookup.h"
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.101
diff -c -5 -p -r1.101 parser.c
*** cp/parser.c 18 Aug 2003 12:55:03 -0000 1.101
--- cp/parser.c 20 Aug 2003 06:59:22 -0000
*************** static tree cp_parser_storage_class_spec
*** 1411,1421 ****
static tree cp_parser_function_specifier_opt
(cp_parser *);
static tree cp_parser_type_specifier
(cp_parser *, cp_parser_flags, bool, bool, int *, bool *);
static tree cp_parser_simple_type_specifier
! (cp_parser *, cp_parser_flags);
static tree cp_parser_type_name
(cp_parser *);
static tree cp_parser_elaborated_type_specifier
(cp_parser *, bool, bool);
static tree cp_parser_enum_specifier
--- 1411,1421 ----
static tree cp_parser_function_specifier_opt
(cp_parser *);
static tree cp_parser_type_specifier
(cp_parser *, cp_parser_flags, bool, bool, int *, bool *);
static tree cp_parser_simple_type_specifier
! (cp_parser *, cp_parser_flags, bool);
static tree cp_parser_type_name
(cp_parser *);
static tree cp_parser_elaborated_type_specifier
(cp_parser *, bool, bool);
static tree cp_parser_enum_specifier
*************** cp_parser_postfix_expression (cp_parser
*** 3359,3369 ****
an id-expression. So, we try the functional cast, and if
that doesn't work we fall back to the primary-expression. */
cp_parser_parse_tentatively (parser);
/* Look for the simple-type-specifier. */
type = cp_parser_simple_type_specifier (parser,
! CP_PARSER_FLAGS_NONE);
/* Parse the cast itself. */
if (!cp_parser_error_occurred (parser))
postfix_expression
= cp_parser_functional_cast (parser, type);
/* If that worked, we're done. */
--- 3359,3370 ----
an id-expression. So, we try the functional cast, and if
that doesn't work we fall back to the primary-expression. */
cp_parser_parse_tentatively (parser);
/* Look for the simple-type-specifier. */
type = cp_parser_simple_type_specifier (parser,
! CP_PARSER_FLAGS_NONE,
! /*identifier_p=*/false);
/* Parse the cast itself. */
if (!cp_parser_error_occurred (parser))
postfix_expression
= cp_parser_functional_cast (parser, type);
/* If that worked, we're done. */
*************** cp_parser_type_specifier (cp_parser* par
*** 8179,8189 ****
break;
}
/* If we do not already have a type-specifier, assume we are looking
at a simple-type-specifier. */
! type_spec = cp_parser_simple_type_specifier (parser, flags);
/* If we didn't find a type-specifier, and a type-specifier was not
optional in this context, issue an error message. */
if (!type_spec && !(flags & CP_PARSER_FLAGS_OPTIONAL))
{
--- 8180,8191 ----
break;
}
/* If we do not already have a type-specifier, assume we are looking
at a simple-type-specifier. */
! type_spec = cp_parser_simple_type_specifier (parser, flags,
! /*identifier_p=*/true);
/* If we didn't find a type-specifier, and a type-specifier was not
optional in this context, issue an error message. */
if (!type_spec && !(flags & CP_PARSER_FLAGS_OPTIONAL))
{
*************** cp_parser_type_specifier (cp_parser* par
*** 8216,8230 ****
simple-type-specifier:
__typeof__ unary-expression
__typeof__ ( type-id )
For the various keywords, the value returned is simply the
! TREE_IDENTIFIER representing the keyword. For the first two
! productions, the value returned is the indicated TYPE_DECL. */
static tree
! cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags)
{
tree type = NULL_TREE;
cp_token *token;
/* Peek at the next token. */
--- 8218,8234 ----
simple-type-specifier:
__typeof__ unary-expression
__typeof__ ( type-id )
For the various keywords, the value returned is simply the
! TREE_IDENTIFIER representing the keyword if IDENTIFIER_P is true.
! For the first two productions, and if IDENTIFIER_P is false, the
! value returned is the indicated TYPE_DECL. */
static tree
! cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
! bool identifier_p)
{
tree type = NULL_TREE;
cp_token *token;
/* Peek at the next token. */
*************** cp_parser_simple_type_specifier (cp_pars
*** 8232,8253 ****
/* If we're looking at a keyword, things are easy. */
switch (token->keyword)
{
case RID_CHAR:
case RID_WCHAR:
case RID_BOOL:
case RID_SHORT:
case RID_INT:
case RID_LONG:
case RID_SIGNED:
case RID_UNSIGNED:
case RID_FLOAT:
case RID_DOUBLE:
case RID_VOID:
! /* Consume the token. */
! return cp_lexer_consume_token (parser->lexer)->value;
case RID_TYPEOF:
{
tree operand;
--- 8236,8277 ----
/* If we're looking at a keyword, things are easy. */
switch (token->keyword)
{
case RID_CHAR:
+ type = char_type_node;
+ break;
case RID_WCHAR:
+ type = wchar_type_node;
+ break;
case RID_BOOL:
+ type = boolean_type_node;
+ break;
case RID_SHORT:
+ type = short_integer_type_node;
+ break;
case RID_INT:
+ type = integer_type_node;
+ break;
case RID_LONG:
+ type = long_integer_type_node;
+ break;
case RID_SIGNED:
+ type = integer_type_node;
+ break;
case RID_UNSIGNED:
+ type = unsigned_type_node;
+ break;
case RID_FLOAT:
+ type = float_type_node;
+ break;
case RID_DOUBLE:
+ type = double_type_node;
+ break;
case RID_VOID:
! type = void_type_node;
! break;
case RID_TYPEOF:
{
tree operand;
*************** cp_parser_simple_type_specifier (cp_pars
*** 8264,8273 ****
--- 8288,8307 ----
default:
break;
}
+ /* If the type-specifier was for a built-in type, we're done. */
+ if (type)
+ {
+ tree id;
+
+ /* Consume the token. */
+ id = cp_lexer_consume_token (parser->lexer)->value;
+ return identifier_p ? id : TYPE_NAME (type);
+ }
+
/* The type-specifier must be a user-defined type. */
if (!(flags & CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES))
{
/* Don't gobble tokens or issue error messages if this is an
optional type-specifier. */
*************** cp_parser_elaborated_type_specifier (cp_
*** 8547,8558 ****
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
check_elaborated_type_specifier
! (tag_type,
! TREE_TYPE (decl),
(parser->num_template_parameter_lists
|| DECL_SELF_REFERENCE_P (decl)));
type = TREE_TYPE (decl);
}
--- 8581,8591 ----
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
check_elaborated_type_specifier
! (tag_type, decl,
(parser->num_template_parameter_lists
|| DECL_SELF_REFERENCE_P (decl)));
type = TREE_TYPE (decl);
}
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.760
diff -c -5 -p -r1.760 pt.c
*** cp/pt.c 18 Aug 2003 12:55:03 -0000 1.760
--- cp/pt.c 20 Aug 2003 06:59:23 -0000
*************** push_template_decl_real (tree decl, int
*** 2672,2681 ****
--- 2672,2690 ----
if (current_lang_name == lang_name_c)
error ("template with C linkage");
else if (TREE_CODE (decl) == TYPE_DECL
&& ANON_AGGRNAME_P (DECL_NAME (decl)))
error ("template class without a name");
+ else if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DESTRUCTOR_P (decl))
+ {
+ /* [temp.mem]
+
+ A destructor shall not be a member template. */
+ error ("destructor `%D' declared as member template", decl);
+ return error_mark_node;
+ }
else if ((DECL_IMPLICIT_TYPEDEF_P (decl)
&& CLASS_TYPE_P (TREE_TYPE (decl)))
|| (TREE_CODE (decl) == VAR_DECL && ctx && CLASS_TYPE_P (ctx))
|| TREE_CODE (decl) == FUNCTION_DECL)
/* OK */;
*************** tsubst_decl (tree t, tree args, tree typ
*** 5994,6004 ****
clone_constructors_and_destructors. */
if (PRIMARY_TEMPLATE_P (gen_tmpl))
clone_function_decl (r, /*update_method_vec_p=*/0);
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
! grok_op_properties (r, DECL_FRIEND_P (r));
}
break;
case PARM_DECL:
{
--- 6003,6014 ----
clone_constructors_and_destructors. */
if (PRIMARY_TEMPLATE_P (gen_tmpl))
clone_function_decl (r, /*update_method_vec_p=*/0);
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
! grok_op_properties (r, DECL_FRIEND_P (r),
! (complain & tf_error) != 0);
}
break;
case PARM_DECL:
{
Index: cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.147
diff -c -5 -p -r1.147 typeck2.c
*** cp/typeck2.c 2 Aug 2003 02:07:49 -0000 1.147
--- cp/typeck2.c 20 Aug 2003 06:59:23 -0000
*************** build_functional_cast (tree exp, tree pa
*** 1112,1138 ****
tree type;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
! if (TREE_CODE (exp) == IDENTIFIER_NODE)
! {
! if (IDENTIFIER_HAS_TYPE_VALUE (exp))
! /* Either an enum or an aggregate type. */
! type = IDENTIFIER_TYPE_VALUE (exp);
! else
! {
! type = lookup_name (exp, 1);
! if (!type || TREE_CODE (type) != TYPE_DECL)
! {
! error ("`%T' fails to be a typedef or built-in type", exp);
! return error_mark_node;
! }
! type = TREE_TYPE (type);
! }
! }
! else if (TREE_CODE (exp) == TYPE_DECL)
type = TREE_TYPE (exp);
else
type = exp;
if (processing_template_decl)
--- 1112,1122 ----
tree type;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
! if (TREE_CODE (exp) == TYPE_DECL)
type = TREE_TYPE (exp);
else
type = exp;
if (processing_template_decl)
Index: testsuite/g++.dg/expr/enum1.C
===================================================================
RCS file: testsuite/g++.dg/expr/enum1.C
diff -N testsuite/g++.dg/expr/enum1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/expr/enum1.C 20 Aug 2003 06:59:23 -0000
***************
*** 0 ****
--- 1,10 ----
+ // { dg-do run }
+
+ void abort();
+ int main()
+ {
+ enum { shelf = 4 } t = shelf;
+ if (!(t & shelf))
+ abort ();
+ }
+
Index: testsuite/g++.dg/parse/elab2.C
===================================================================
RCS file: testsuite/g++.dg/parse/elab2.C
diff -N testsuite/g++.dg/parse/elab2.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/elab2.C 20 Aug 2003 06:59:23 -0000
***************
*** 0 ****
--- 1,7 ----
+ struct A {};
+
+ struct B
+ {
+ typedef A T;
+ friend struct T; // { dg-error "" }
+ };
Index: testsuite/g++.dg/parse/operator4.C
===================================================================
RCS file: testsuite/g++.dg/parse/operator4.C
diff -N testsuite/g++.dg/parse/operator4.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/operator4.C 20 Aug 2003 06:59:23 -0000
***************
*** 0 ****
--- 1 ----
+ int operator *(int, ...); // { dg-error "class" }
Index: testsuite/g++.dg/parse/typedef4.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/parse/typedef4.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 typedef4.C
*** testsuite/g++.dg/parse/typedef4.C 1 Aug 2003 15:41:27 -0000 1.1
--- testsuite/g++.dg/parse/typedef4.C 20 Aug 2003 06:59:23 -0000
***************
*** 6,12 ****
template<class T> class smart_ptr2 {
T* real_ptr;
public:
typedef typename T::subT td;
! friend class td; // { dg-error "typename|not name a class" }
};
--- 6,12 ----
template<class T> class smart_ptr2 {
T* real_ptr;
public:
typedef typename T::subT td;
! friend class td; // { dg-error "typedef" }
};
Index: testsuite/g++.dg/template/dtor2.C
===================================================================
RCS file: testsuite/g++.dg/template/dtor2.C
diff -N testsuite/g++.dg/template/dtor2.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/dtor2.C 20 Aug 2003 06:59:23 -0000
***************
*** 0 ****
--- 1,10 ----
+ struct Foo
+ {
+ template <int i>
+ ~Foo() {} // { dg-error "" }
+ };
+
+ int main()
+ {
+ Foo f;
+ }
Index: testsuite/g++.dg/template/operator1.C
===================================================================
RCS file: testsuite/g++.dg/template/operator1.C
diff -N testsuite/g++.dg/template/operator1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/operator1.C 20 Aug 2003 06:59:23 -0000
***************
*** 0 ****
--- 1,49 ----
+ class test
+ {
+ public:
+ float operator[]( int index )
+ {
+ return testFloat[index];
+ }
+ private:
+ float testFloat[3];
+ };
+
+ template < class typeA > float
+ operator*(
+ typeA a,
+ float b
+ )
+ {
+ return a[0] * b;
+ }
+
+ template < class typeB > float
+ operator*(
+ float a,
+ typeB b
+ )
+ {
+ return a * b[0];
+ }
+
+ template < class typeA, class typeB > float
+ operator*(
+ typeA a,
+ typeB b
+ )
+ {
+ return a[0] * b[0];
+ }
+
+ int main( void )
+ {
+ test aTest;
+ float bTest;
+ float result;
+
+ result = aTest * bTest;
+ result = bTest * aTest;
+
+ return 0;
+ }
Index: testsuite/g++.old-deja/g++.robertl/eb133.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.robertl/eb133.C,v
retrieving revision 1.7
diff -c -5 -p -r1.7 eb133.C
*** testsuite/g++.old-deja/g++.robertl/eb133.C 28 Jun 2003 16:23:29 -0000 1.7
--- testsuite/g++.old-deja/g++.robertl/eb133.C 20 Aug 2003 06:59:23 -0000
***************
*** 1,19 ****
// { dg-do assemble }
// Gives ICE 109
// From: Klaus-Georg Adams <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
// Reported against EGCS snaps 98/06/28.
- // { dg-error "forward declaration" "" { target *-*-* } 0 }
-
using namespace std;
int main()
{
try {
}
! catch (bad_alloc) { // { dg-error "invalid use" }
return 1;
}
return 0;
}
--- 1,17 ----
// { dg-do assemble }
// Gives ICE 109
// From: Klaus-Georg Adams <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
// Reported against EGCS snaps 98/06/28.
using namespace std;
int main()
{
try {
}
! catch (bad_alloc) { // { dg-error "" }
return 1;
}
return 0;
}
Index: testsuite/g++.old-deja/g++.robertl/eb133a.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.robertl/eb133a.C,v
retrieving revision 1.3
diff -c -5 -p -r1.3 eb133a.C
*** testsuite/g++.old-deja/g++.robertl/eb133a.C 28 Jun 2003 16:23:28 -0000 1.3
--- testsuite/g++.old-deja/g++.robertl/eb133a.C 20 Aug 2003 06:59:23 -0000
***************
*** 1,12 ****
// { dg-do assemble }
// Gives ICE 109
// From: Klaus-Georg Adams <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
// Reported against EGCS snaps 98/06/28.
- // { dg-error "forward declaration" "" { target *-*-* } 0 }
-
int main()
{
try {
}
catch (std::bad_alloc) { // { dg-error "" } parse error
--- 1,10 ----
Index: testsuite/g++.old-deja/g++.robertl/eb133b.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.robertl/eb133b.C,v
retrieving revision 1.3
diff -c -5 -p -r1.3 eb133b.C
*** testsuite/g++.old-deja/g++.robertl/eb133b.C 28 Jun 2003 16:23:29 -0000 1.3
--- testsuite/g++.old-deja/g++.robertl/eb133b.C 20 Aug 2003 06:59:23 -0000
***************
*** 1,19 ****
// { dg-do assemble }
// Gives ICE 109
// From: Klaus-Georg Adams <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
// Reported against EGCS snaps 98/06/28.
- // { dg-error "forward declaration" "" { target *-*-* } 0 }
-
using namespace std;
int main()
{
try {
}
! catch (bad_alloc) { // { dg-error "invalid use" }
return 1;
}
return 0;
}
--- 1,17 ----
// { dg-do assemble }
// Gives ICE 109
// From: Klaus-Georg Adams <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
// Reported against EGCS snaps 98/06/28.
using namespace std;
int main()
{
try {
}
! catch (bad_alloc) { // { dg-error "" }
return 1;
}
return 0;
}
Index: testsuite/gcc.dg/c99-bool-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/c99-bool-1.c,v
retrieving revision 1.3
diff -c -5 -p -r1.3 c99-bool-1.c
*** testsuite/gcc.dg/c99-bool-1.c 16 Sep 2002 13:29:49 -0000 1.3
--- testsuite/gcc.dg/c99-bool-1.c 20 Aug 2003 06:59:23 -0000
*************** main (void)
*** 226,238 ****
u = 1;
if ((u &= 0) != 0)
abort ();
if ((u |= 2) != 1)
abort ();
! /* ??? A bit queer, since this gets optimized to ((u = (u != 3)) != 1)
! early in semantic analysis, which then yields the warning below. */
! if ((u ^= 3) != 1) /* { dg-warning "always true due to limited range" } */
abort ();
/* Test comma expressions. */
u = 1;
if ((4, u) != 1)
abort ();
--- 226,236 ----
u = 1;
if ((u &= 0) != 0)
abort ();
if ((u |= 2) != 1)
abort ();
! if ((u ^= 3) != 1)
abort ();
/* Test comma expressions. */
u = 1;
if ((4, u) != 1)
abort ();