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:
parent
692e9bd5d0
commit
90418208f9
24 changed files with 859 additions and 786 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
1415
gcc/cp/parse.c
1415
gcc/cp/parse.c
File diff suppressed because it is too large
Load diff
|
@ -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 }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -502,7 +502,7 @@ operator<<(ostream& o, const SLS& s)
|
|||
SLS gsls;
|
||||
const SLS gcsls;
|
||||
|
||||
int foo()
|
||||
void foo()
|
||||
{
|
||||
const unsigned SIZE = 20;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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>&);
|
||||
|
|
|
@ -17,4 +17,4 @@ private:
|
|||
|
||||
data* user::data1() const {
|
||||
return (_c.contents (_c.first)); // ERROR -
|
||||
} // ERROR - control reaches end
|
||||
}
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ inline void f() {
|
|||
S s;
|
||||
}
|
||||
|
||||
int g()
|
||||
void g()
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
f();
|
||||
|
|
|
@ -6,7 +6,7 @@ struct E
|
|||
int f(int);
|
||||
};
|
||||
|
||||
int ha()
|
||||
void ha()
|
||||
{
|
||||
enum {X = 0};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
31
gcc/testsuite/g++.old-deja/g++.pt/repo3.C
Normal file
31
gcc/testsuite/g++.old-deja/g++.pt/repo3.C
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -23,4 +23,4 @@ bool operator==(const MyInt& a, const MyInt& b)
|
|||
bool f()
|
||||
{
|
||||
return 3 == MyInt(); // ERROR - ambiguous
|
||||
} // ERROR - no return value
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue