repo.c (repo_get_id): Handle the case where a class with virtual bases has a null TYPE_BINFO_VTABLE.

* repo.c (repo_get_id): Handle the case where a class with virtual
        bases has a null TYPE_BINFO_VTABLE.

        * parse.y (member_init): Just pass in the type.
        * init.c (expand_member_init): Handle getting a type.

        * decl.c (finish_function): Warn if a function has no return
        statement.
        Suggested by Andrew Koenig.
        * typeck.c (check_return_expr): Do set current_function_returns_value
        if we got an error_mark_node.

From-SVN: r34863
This commit is contained in:
Jason Merrill 2000-07-04 03:47:11 -04:00
parent 692e9bd5d0
commit 90418208f9
24 changed files with 859 additions and 786 deletions

View file

@ -1,3 +1,24 @@
2000-07-04 scott snyder <snyder@fnal.gov>
Jason Merrill <jason@redhat.com>
* repo.c (repo_get_id): Handle the case where a class with virtual
bases has a null TYPE_BINFO_VTABLE.
2000-07-04 Kevin Buhr <buhr@stat.wisc.edu>
Jason Merrill <jason@redhat.com>
* parse.y (member_init): Just pass in the type.
* init.c (expand_member_init): Handle getting a type.
2000-07-04 Martin v. Löwis <loewis@informatik.hu-berlin.de>
Jason Merrill <jason@redhat.com>
* decl.c (finish_function): Warn if a function has no return
statement.
Suggested by Andrew Koenig.
* typeck.c (check_return_expr): Do set current_function_returns_value
if we got an error_mark_node.
2000-07-03 Nathan Sidwell <nathan@codesourcery.com>
* decl2.c (push_decl_namespace): Push the original namespace.

View file

@ -7889,7 +7889,6 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
}
/* The old ARM scoping rules injected variables declared in the
initialization statement of a for-statement into the surrounding
scope. We support this usage, in order to be backward-compatible.
@ -8034,7 +8033,6 @@ destroy_local_var (decl)
finish_decl_cleanup (decl, cleanup);
}
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
@ -14484,30 +14482,24 @@ finish_function (flags)
note_debug_info_needed (ctype);
#endif
returns_null |= can_reach_end;
/* Since we don't normally go through c_expand_return for constructors,
this normally gets the wrong value.
Also, named return values have their return codes emitted after
NOTE_INSN_FUNCTION_END, confusing jump.c. */
if (DECL_CONSTRUCTOR_P (fndecl)
|| DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE)
returns_null = 0;
if (DECL_NAME (DECL_RESULT (fndecl)))
returns_value |= can_reach_end;
else
returns_null |= can_reach_end;
if (TREE_THIS_VOLATILE (fndecl) && returns_null)
cp_warning ("`noreturn' function `%D' does return", fndecl);
else if ((warn_return_type || pedantic)
&& returns_null
warning ("`noreturn' function does return");
else if (returns_null
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE)
{
/* If this function returns non-void and control can drop through,
complain. */
cp_warning ("control reaches end of non-void function `%D'", fndecl);
/* Always complain if there's just no return statement. */
if (!returns_value)
warning ("no return statement in function returning non-void");
else if (warn_return_type || pedantic)
/* If this function returns non-void and control can drop through,
complain. */
warning ("control reaches end of non-void function");
}
/* With just -W, complain only if function returns both with
and without a value. */
else if (extra_warnings && returns_value && returns_null)
warning ("this function may return with or without a value");
}
else
{

View file

@ -1043,7 +1043,12 @@ expand_member_init (exp, name, init)
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
if (name && TREE_CODE (name) == TYPE_DECL)
if (name && TYPE_P (name))
{
basetype = name;
name = TYPE_IDENTIFIER (name);
}
else if (name && TREE_CODE (name) == TYPE_DECL)
{
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
name = DECL_NAME (name);

File diff suppressed because it is too large Load diff

View file

@ -930,12 +930,9 @@ member_init:
{ $$ = 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); }
{ $$ = expand_member_init (current_class_ref, $1, $3); }
| typename_sub LEFT_RIGHT
{ $$ = expand_member_init (current_class_ref,
TYPE_MAIN_DECL ($1),
{ $$ = expand_member_init (current_class_ref, $1,
void_type_node); }
| error
{ $$ = NULL_TREE }

View file

@ -97,13 +97,36 @@ repo_get_id (t)
{
if (TYPE_P (t))
{
tree vtable;
/* If we're not done setting up the class, we may not have set up
the vtable, so going ahead would give the wrong answer.
See g++.pt/instantiate4.C. */
if (!COMPLETE_TYPE_P (t) || TYPE_BEING_DEFINED (t))
my_friendly_abort (981113);
t = get_vtbl_decl_for_binfo (TYPE_BINFO (t));
vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (t));
/* If we don't have a primary vtable, try looking for a secondary
vtable. */
if (vtable == NULL_TREE && !flag_new_abi
&& TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
for (i = 0; i < n_baselinks; ++i)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
if (TREE_VIA_VIRTUAL (base_binfo))
{
vtable = get_vtbl_decl_for_binfo (base_binfo);
if (vtable)
break;
}
}
}
t = vtable;
if (t == NULL_TREE)
return t;
}

View file

@ -6750,29 +6750,23 @@ check_return_expr (retval)
warning ("function declared `noreturn' has a `return' statement");
/* Check for various simple errors. */
if (retval == error_mark_node)
{
/* If an error occurred, there's nothing to do. */
current_function_returns_null = 1;
return error_mark_node;
}
else if (dtor_label)
if (dtor_label)
{
if (retval)
error ("returning a value from a destructor");
return NULL_TREE;
}
else if (in_function_try_handler
&& DECL_CONSTRUCTOR_P (current_function_decl))
else if (DECL_CONSTRUCTOR_P (current_function_decl))
{
/* If a return statement appears in a handler of the
function-try-block of a constructor, the program is ill-formed. */
error ("cannot return from a handler of a function-try-block of a constructor");
return error_mark_node;
if (in_function_try_handler)
/* If a return statement appears in a handler of the
function-try-block of a constructor, the program is ill-formed. */
error ("cannot return from a handler of a function-try-block of a constructor");
else if (retval)
/* You can't return a value from a constructor. */
error ("returning a value from a constructor");
return NULL_TREE;
}
else if (retval && DECL_CONSTRUCTOR_P (current_function_decl))
/* You can't return a value from a constructor. */
error ("returning a value from a constructor");
/* Under the old ABI, constructors actually always return `this',
even though in C++ you can't return a value from a constructor. */
@ -6819,6 +6813,9 @@ check_return_expr (retval)
/* Remember that this function can sometimes return without a
value. */
current_function_returns_null = 1;
else
/* Remember that this function did return a value. */
current_function_returns_value = 1;
/* Only operator new(...) throw(), can return NULL [expr.new/13]. */
if ((DECL_OVERLOADED_OPERATOR_P (current_function_decl) == NEW_EXPR
@ -6836,8 +6833,8 @@ check_return_expr (retval)
/* We don't need to do any conversions when there's nothing being
returned. */
if (!retval)
return NULL_TREE;
if (!retval || retval == error_mark_node)
return retval;
/* Do any required conversions. */
if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl))
@ -6858,7 +6855,7 @@ check_return_expr (retval)
/* If the conversion failed, treat this just like `return;'. */
if (retval == error_mark_node)
return NULL_TREE;
return retval;
/* We can't initialize a register from a AGGR_INIT_EXPR. */
else if (! current_function_returns_struct
&& TREE_CODE (retval) == TARGET_EXPR
@ -6873,8 +6870,6 @@ check_return_expr (retval)
if (retval && retval != result)
retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
/* All done. Remember that this function did return a value. */
current_function_returns_value = 1;
return retval;
}

View file

@ -5,4 +5,4 @@ int f (int i) {
for (int j = i; j; j--)
;
return j; // error: j should only be in scope inside the body of `for'// ERROR - .*
} // ERROR - non-void
}

View file

@ -12,9 +12,9 @@ protected:
class ccBgaInspection : public ccInspection
{
public:
int reinspect (unsigned long diagFlags);
void reinspect (unsigned long diagFlags);
};
int
void
ccBgaInspection::reinspect (unsigned long diag_flags)
{
ct2d_rigid physTdev;

View file

@ -1,5 +1,5 @@
// This testcase used to cause a crash on the Alpha.
// Special g++ Options:
// Special g++ Options: -w
// Build don't link:
struct A {

View file

@ -10,7 +10,7 @@ typedef int (*fptr)(A *);
typedef void* vptr;
typedef int (A::*pmf)();
int foo (A* ap, pmf fp, int A::* ip)
void foo (A* ap, pmf fp, int A::* ip)
{
fptr p;
vptr q;

View file

@ -502,7 +502,7 @@ operator<<(ostream& o, const SLS& s)
SLS gsls;
const SLS gcsls;
int foo()
void foo()
{
const unsigned SIZE = 20;

View file

@ -29,7 +29,7 @@ char ***spp = &sp;
int foo (int a = (**bar) (s))
{
return doowop<foo>::bar; // ERROR - not a member
} // ERROR - non-void
}
int foo2 (int (*a)(int) = &foo)
{

View file

@ -8,7 +8,7 @@ struct ostream {
template <class T> class foo;
template <class T> ostream& operator<< (ostream& ios, foo<T>&obj) { };
template <class T> ostream& operator<< (ostream& ios, foo<T>&obj) {return ios;}
template <class T> class foo {
friend ostream& operator<<<>(ostream&, foo<T>&);

View file

@ -17,4 +17,4 @@ private:
data* user::data1() const {
return (_c.contents (_c.first)); // ERROR -
} // ERROR - control reaches end
}

View file

@ -107,7 +107,7 @@ warn_return_1 ()
{
foo f;
printf ("returning 1\n");
}
} // WARNING - no return statement
int
warn_return_arg (int arg)
@ -115,7 +115,7 @@ warn_return_arg (int arg)
foo f;
printf ("returning %d\n", arg);
arg;
}
} // WARNING - no return statement
int
warn_return_sum (int x, int y)
@ -123,14 +123,14 @@ warn_return_sum (int x, int y)
foo f;
printf ("returning %d+%d\n", x, y);
x + y;
}
} // WARNING - no return statement
foo
warn_return_foo ()
{
foo f;
printf ("returning foo\n");
}
} // WARNING - no return statement
foo
nowarn_return_named_foo () return f
@ -142,7 +142,7 @@ foo
warn_foo_parm_returns_foo (foo f)
{
f;
}
} // WARNING - no return statement
main ()
{

View file

@ -1,5 +1,5 @@
// Origin: Bryan Scattergood <bryan@fsel.com>
// Special g++ Options: -O -fno-exceptions
// Special g++ Options: -O -fno-exceptions -w
extern "C" void abort();

View file

@ -6,7 +6,7 @@ inline void f() {
S s;
}
int g()
void g()
{
for (int i = 0; i < 2; ++i)
f();

View file

@ -6,7 +6,7 @@ struct E
int f(int);
};
int ha()
void ha()
{
enum {X = 0};

View file

@ -7,7 +7,7 @@ inline unsigned int asize(ARRY &a)
return sizeof(a) / sizeof(a[0]);
}
int f(unsigned int n) {
void f(unsigned int n) {
int x[n];
asize(x); // ERROR - no matching function

View file

@ -0,0 +1,31 @@
// Test that we properly generate the vtable and such for C.
// Contributed by scott snyder <snyder@fnal.gov>
// Build then link:
// Special g++ Options: -frepo
struct A
{
virtual ~A () {}
};
template <typename T>
struct B : virtual public A
{
virtual void foo () {}
};
template <typename T>
struct C : virtual public A
{
};
template <typename T>
struct D : public B<T>, public C<T>
{
};
main ()
{
D<int> x;
}

View file

@ -10,6 +10,7 @@ template <class T, class U, int I>
S<T,I>::X f(T, U)
{
S<T, I>::X();
return S<T, I>::X();
}
template S<int, 3>::X f<int, double, 3>(int, double);

View file

@ -23,4 +23,4 @@ bool operator==(const MyInt& a, const MyInt& b)
bool f()
{
return 3 == MyInt(); // ERROR - ambiguous
} // ERROR - no return value
}

View file

@ -1,9 +1,20 @@
#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)
};
int main() { bar b; }
// Test that g++ complains about referring to a builtin type in a
// mem-initializer.
// Contributed by Kevin Buhr <buhr@stat.wisc.edu>
int r = 0;
struct foo {
foo(int x) { r = 1; } // ERROR - candidate
}; // ERROR - candidate
struct bar : foo {
typedef int an_int;
bar() : bar::an_int(3) {} // ERROR - not a base
};
int
main() {
bar b;
return r;
}