Commit 4b0d3cbe by Mark Mitchell Committed by Mark Mitchell

re PR c++/11946 (fun and merriment with enums as function arguments)

	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.

	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.

	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.

From-SVN: r70593
parent ccc01444
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 Geoffrey Keating <geoffk@apple.com>
* cpppch.c (cpp_valid_state): Re-add warning about PCH not used
......
......@@ -1969,6 +1969,8 @@ c_common_signed_type (tree type)
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;
......@@ -2001,7 +2003,14 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
if (TYPE_PRECISION (type) == TYPE_PRECISION (intQI_type_node))
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
return type;
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
......
......@@ -654,10 +654,14 @@ extern struct rtx_def *hppa_pic_save_rtx PARAMS ((void));
&& 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) \
(FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2))
#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) \
......
......@@ -349,7 +349,27 @@ convert_to_integer (tree type, tree expr)
we are truncating EXPR. */
else if (outprec >= inprec)
return build1 (NOP_EXPR, type, expr);
{
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
......
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 Andrew Pinski <pinskia@physics.uc.edu>
PR c++/10538, PR c/5582
......
......@@ -750,7 +750,10 @@ add_method (tree type, tree method, int error_p)
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;
{
slot = CLASSTYPE_DESTRUCTOR_SLOT;
TYPE_HAS_DESTRUCTOR (type) = 1;
}
else
{
int have_template_convs_p = 0;
......@@ -1646,16 +1649,12 @@ maybe_warn_about_overly_private_class (tree t)
/* 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))
if (TYPE_HAS_DESTRUCTOR (t)
&& TREE_PRIVATE (CLASSTYPE_DESTRUCTORS (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;
}
warning ("`%#T' only defines a private destructor and has no friends",
t);
return;
}
if (TYPE_HAS_CONSTRUCTOR (t))
......@@ -5485,7 +5484,7 @@ pushclass (tree type)
push_class_binding (id, decl);
if (TREE_CODE (decl) == TYPE_DECL)
set_identifier_type_value (id, TREE_TYPE (decl));
set_identifier_type_value (id, decl);
}
unuse_fields (type);
}
......
......@@ -3695,7 +3695,7 @@ 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 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);
......@@ -3744,6 +3744,7 @@ 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 */
......
......@@ -387,12 +387,6 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
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
......
......@@ -377,7 +377,12 @@ set_namespace_binding (tree name, tree scope, tree val)
if (scope == NULL_TREE)
scope = global_namespace;
b = binding_for_name (NAMESPACE_LEVEL (scope), name);
BINDING_VALUE (b) = val;
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);
}
......
......@@ -1413,7 +1413,7 @@ static tree cp_parser_function_specifier_opt
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);
(cp_parser *, cp_parser_flags, bool);
static tree cp_parser_type_name
(cp_parser *);
static tree cp_parser_elaborated_type_specifier
......@@ -3361,7 +3361,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
cp_parser_parse_tentatively (parser);
/* Look for the simple-type-specifier. */
type = cp_parser_simple_type_specifier (parser,
CP_PARSER_FLAGS_NONE);
CP_PARSER_FLAGS_NONE,
/*identifier_p=*/false);
/* Parse the cast itself. */
if (!cp_parser_error_occurred (parser))
postfix_expression
......@@ -8181,7 +8182,8 @@ cp_parser_type_specifier (cp_parser* parser,
/* 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);
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. */
......@@ -8218,11 +8220,13 @@ cp_parser_type_specifier (cp_parser* parser,
__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. */
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)
cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
bool identifier_p)
{
tree type = NULL_TREE;
cp_token *token;
......@@ -8234,18 +8238,38 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags)
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:
/* Consume the token. */
return cp_lexer_consume_token (parser->lexer)->value;
type = void_type_node;
break;
case RID_TYPEOF:
{
......@@ -8266,6 +8290,16 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags)
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))
{
......@@ -8549,8 +8583,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
check_elaborated_type_specifier
(tag_type,
TREE_TYPE (decl),
(tag_type, decl,
(parser->num_template_parameter_lists
|| DECL_SELF_REFERENCE_P (decl)));
......
......@@ -2674,6 +2674,15 @@ push_template_decl_real (tree decl, int is_friend)
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))
......@@ -5996,7 +6005,8 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
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));
grok_op_properties (r, DECL_FRIEND_P (r),
(complain & tf_error) != 0);
}
break;
......
......@@ -1114,23 +1114,7 @@ build_functional_cast (tree exp, tree parms)
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)
if (TREE_CODE (exp) == TYPE_DECL)
type = TREE_TYPE (exp);
else
type = exp;
......
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.
2003-08-19 Geoffrey Keating <geoffk@apple.com>
* gcc.dg/pch/warn-1.c: New.
......
// { dg-do run }
void abort();
int main()
{
enum { shelf = 4 } t = shelf;
if (!(t & shelf))
abort ();
}
struct A {};
struct B
{
typedef A T;
friend struct T; // { dg-error "" }
};
int operator *(int, ...); // { dg-error "class" }
......@@ -8,5 +8,5 @@ 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" }
friend class td; // { dg-error "typedef" }
};
struct Foo
{
template <int i>
~Foo() {} // { dg-error "" }
};
int main()
{
Foo f;
}
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;
}
......@@ -3,15 +3,13 @@
// 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" }
catch (bad_alloc) { // { dg-error "" }
return 1;
}
return 0;
......
......@@ -3,8 +3,6 @@
// 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 {
......
......@@ -3,15 +3,13 @@
// 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" }
catch (bad_alloc) { // { dg-error "" }
return 1;
}
return 0;
......
......@@ -228,9 +228,7 @@ main (void)
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" } */
if ((u ^= 3) != 1)
abort ();
/* Test comma expressions. */
u = 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment