This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
971114 PATCH: check for non-aggregates used as base classes
- To: egcs-bugs at cygnus dot com
- Subject: 971114 PATCH: check for non-aggregates used as base classes
- From: buhr at stat dot wisc dot edu (Kevin Buhr)
- Date: 21 Nov 1997 13:03:05 -0600
The 971114 "gcc/cp/parse.y" doesn't properly identify non-aggregate
types used as base classes.
First, the rule:
base_class: base_class_access_list see_typename base_class.1
uses "IS_AGGR_TYPE" instead of "is_aggr_type" to check "base_class.1",
so no error is reported for code like:
typedef int an_int;
class bar : public an_int {};
The base class is silently ignored. Without the "public" access
specifier, the "base_class: base_class.1" rule is used, so an error
*is* correctly reported. The enclosed patch fixes the problem by
using "is_aggr_type" to report the error.
Second, it's possible for a "typename_sub" to be associated with a
non-aggregate type. Several rules do unchecked "TYPE_MAIN_DECL"s on
"typename_sub"s, which would be NULL for, say, an "INTEGER_TYPE",
causing an internal compiler error:
class foo {
typedef int an_int;
};
class bar : foo::an_int {}; // causes internal compiler error
or, in other cases, some very strange semantics:
#include <iostream.h>
struct foo {
foo(int x) { cerr << "foo's int constructor (" << x << ")\n"; };
};
struct bar : foo {
typedef int an_int;
bar() : bar::an_int(3) {}; // will call foo::foo(3)
};
main() { bar b; }
There was one use of "typename_sub", namely the rule:
structsp: TYPENAME_KEYWORD typename_sub
that I didn't understand. Would a non-aggregate type be valid here?
If not, then "typename_sub" always needs to be aggregate, so a single
check could be made in the "typename_sub" rule. In the enclosed
patch, I instead explicitly checked all the other uses of
"typename_sub" using "is_aggr_type".
Comparing "make g++-check" before and after the patch, there were no
changes, so it hopefully doesn't break anything else.
Kevin <buhr@stat.wisc.edu>
* * *
*** egcs-971114/gcc/cp/parse.y.orig Fri Nov 21 12:57:06 1997
--- egcs-971114/gcc/cp/parse.y Thu Nov 20 17:40:25 1997
***************
*** 820,830 ****
| nonnested_type LEFT_RIGHT
{ expand_member_init (current_class_ref, $1, void_type_node); }
| typename_sub '(' nonnull_exprlist ')'
! { expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
! $3); }
| typename_sub LEFT_RIGHT
! { expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
! void_type_node); }
;
identifier:
--- 820,832 ----
| nonnested_type LEFT_RIGHT
{ expand_member_init (current_class_ref, $1, void_type_node); }
| typename_sub '(' nonnull_exprlist ')'
! { if (is_aggr_type ($1, 1))
! expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
! $3); }
| typename_sub LEFT_RIGHT
! { if (is_aggr_type ($1, 1))
! expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1),
! void_type_node); }
;
identifier:
***************
*** 2476,2482 ****
tree type = TREE_TYPE ($3);
if (current_aggr == signature_type_node)
error ("access and source specifiers not allowed in signature");
! if (! IS_AGGR_TYPE (type))
$$ = NULL_TREE;
else if (current_aggr == signature_type_node
&& (! type) && (! IS_SIGNATURE (type)))
--- 2478,2484 ----
tree type = TREE_TYPE ($3);
if (current_aggr == signature_type_node)
error ("access and source specifiers not allowed in signature");
! if (! is_aggr_type (type, 1))
$$ = NULL_TREE;
else if (current_aggr == signature_type_node
&& (! type) && (! IS_SIGNATURE (type)))
***************
*** 2502,2508 ****
base_class.1:
typename_sub
! { $$ = TYPE_MAIN_DECL ($1); }
| nonnested_type
| SIGOF '(' expr ')'
{
--- 2504,2515 ----
base_class.1:
typename_sub
! {
! if (! is_aggr_type ($1, 1))
! $$ = NULL_TREE;
! else
! $$ = TYPE_MAIN_DECL ($1);
! }
| nonnested_type
| SIGOF '(' expr ')'
{