diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d28a020523ac7815becb9ccd5c0f8e137e8fae2d..accc1e30296f59f5512a3bb8a32c70597e1837ef 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,21 @@ +2004-12-22 Mark Mitchell <mark@codesourcery.com> + + PR c++/18464 + * call.c (build_this): In templates, do not bother with + build_unary_op. + * typeck.c (unary_complex_lvalue): In a template, always refuse + simplifications. + + PR c++/18492 + * cp-gimplify.c (cp_genericize): Relax assertion. + + PR c++/11224 + * cvt.c (convert_to_void): Warn about unused values. + + PR c++/18257 + * rtti.c (emit_support_tinfos): On systems without weak symbols, + emit the runtime library type-info objects as non-COMDAT. + 2004-12-21 Mark Mitchell <mark@codesourcery.com> PR c++/18378 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 69e06e05d4289df8ee08e7540428c772e42371bb..f94526af85cc17587349440f9a48c4eea3bab8c7 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2333,10 +2333,18 @@ any_strictly_viable (struct z_candidate *cands) return false; } +/* OBJ is being used in an expression like "OBJ.f (...)". In other + words, it is about to become the "this" pointer for a member + function call. Take the address of the object. */ + static tree build_this (tree obj) { - /* Fix this to work on non-lvalues. */ + /* In a template, we are only concerned about the type of the + expression, so we can take a shortcut. */ + if (processing_template_decl) + return build_address (obj); + return build_unary_op (ADDR_EXPR, obj, 0); } diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index d953156b416135bbed85789345323d6adedbfc6c..413a93380104e6d340511d1bf874d583f8ebe899 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -334,17 +334,19 @@ cp_genericize (tree fndecl) /* Fix up the types of parms passed by invisible reference. */ for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) - { - gcc_assert (!DECL_BY_REFERENCE (t)); - if (TREE_ADDRESSABLE (TREE_TYPE (t))) - { - gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); - TREE_TYPE (t) = DECL_ARG_TYPE (t); - DECL_BY_REFERENCE (t) = 1; - TREE_ADDRESSABLE (t) = 0; - relayout_decl (t); - } - } + if (TREE_ADDRESSABLE (TREE_TYPE (t))) + { + /* If a function's arguments are copied to create a thunk, + then DECL_BY_REFERENCE will be set -- but the type of the + argument will be a pointer type, so we will never get + here. */ + gcc_assert (!DECL_BY_REFERENCE (t)); + gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); + TREE_TYPE (t) = DECL_ARG_TYPE (t); + DECL_BY_REFERENCE (t) = 1; + TREE_ADDRESSABLE (t) = 0; + relayout_decl (t); + } /* Do the same for the return value. */ if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 2d73ab8569832154e8ce2f93de47af86152053de..64db10097a200357236bc2d0b5bf93a13141ead2 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -909,9 +909,43 @@ convert_to_void (tree expr, const char *implicit) if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr))) { - if (implicit && warn_unused_value - && !TREE_SIDE_EFFECTS (expr) && !TREE_NO_WARNING (expr)) - warning ("%s has no effect", implicit); + if (implicit && warn_unused_value && !TREE_NO_WARNING (expr)) + { + /* The middle end does not warn about expressions that have + been explicitly cast to void, so we must do so here. */ + if (!TREE_SIDE_EFFECTS (expr)) + warning ("%s has no effect", implicit); + else + { + tree e; + enum tree_code code; + enum tree_code_class class; + + e = expr; + /* We might like to warn about (say) "(int) f()", as the + cast has no effect, but the compiler itself will + generate implicit conversions under some + circmstances. (For example a block copy will be + turned into a call to "__builtin_memcpy", with a + conversion of the return value to an appropriate + type.) So, to avoid false positives, we strip + conversions. */ + STRIP_NOPS (e); + + code = TREE_CODE (e); + class = TREE_CODE_CLASS (code); + if (class == tcc_comparison + || class == tcc_unary + || (class == tcc_binary + && !(code == MODIFY_EXPR + || code == INIT_EXPR + || code == PREDECREMENT_EXPR + || code == PREINCREMENT_EXPR + || code == POSTDECREMENT_EXPR + || code == POSTINCREMENT_EXPR))) + warning ("value computed is not used"); + } + } expr = build1 (CONVERT_EXPR, void_type_node, expr); } return expr; diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index c113e1c349d3750f38f8c64df1877fc8d0743a5e..6c92d19c52880ae85c3d739cbaa8b8b82f7cce78 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -1345,22 +1345,32 @@ emit_support_tinfos (void) for (ix = 0; fundamentals[ix]; ix++) { tree bltn = *fundamentals[ix]; - tree bltn_ptr = build_pointer_type (bltn); - tree bltn_const_ptr = build_pointer_type - (build_qualified_type (bltn, TYPE_QUAL_CONST)); - tree tinfo; - - tinfo = get_tinfo_decl (bltn); - TREE_USED (tinfo) = 1; - TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1; - - tinfo = get_tinfo_decl (bltn_ptr); - TREE_USED (tinfo) = 1; - TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1; - - tinfo = get_tinfo_decl (bltn_const_ptr); - TREE_USED (tinfo) = 1; - TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1; + tree types[3] = { + bltn, + build_pointer_type (bltn), + build_pointer_type (build_qualified_type (bltn, TYPE_QUAL_CONST)) + }; + int i; + + for (i = 0; i < 3; ++i) + { + tree tinfo; + tinfo = get_tinfo_decl (types[i]); + TREE_USED (tinfo) = 1; + mark_needed (tinfo); + /* The C++ ABI requires that these objects be COMDAT. But, + On systems without weak symbols, initialized COMDAT + objects are emitted with internal linkage. (See + comdat_linkage for details.) Since we want these objects + to have external linkage so that copies do not have to be + emitted in code outside the runtime library, we make them + non-COMDAT here. */ + if (!flag_weak) + { + gcc_assert (TREE_PUBLIC (tinfo) && !DECL_COMDAT (tinfo)); + DECL_INTERFACE_KNOWN (tinfo) = 1; + } + } } } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 778e3311b90f14d3db910a27ddea8c6618c0e615..6ce3811bf3fa61ec29cbfc36a6ee1c00a61e5004 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4153,11 +4153,18 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) for certain kinds of expressions which are not really lvalues but which we can accept as lvalues. - If ARG is not a kind of expression we can handle, return zero. */ + If ARG is not a kind of expression we can handle, return + NULL_TREE. */ tree unary_complex_lvalue (enum tree_code code, tree arg) { + /* Inside a template, making these kinds of adjustments is + pointless; we are only concerned with the type of the + expression. */ + if (processing_template_decl) + return NULL_TREE; + /* Handle (a, b) used as an "lvalue". */ if (TREE_CODE (arg) == COMPOUND_EXPR) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5f0074a063b4f8e7f970d6bd96486c1b933e6a97..555353a2d567615f230f6b647461dcf34e88886e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2004-12-22 Mark Mitchell <mark@codesourcery.com> + + PR c++/18464 + * g++.dg/template/cond5.C: New test. + + PR c++/18492 + * g++.dg/inherit/thunk3.C: New test. + + PR c++/11224 + * g++.dg/warn/Wunused-9.C: New test. + 2004-12-22 Janis Johnson <janis187@us.ibm.com> * lib/gcc-dg.exp (dg-xfail-if): Fix the flags compared against. diff --git a/gcc/testsuite/g++.dg/inherit/thunk3.C b/gcc/testsuite/g++.dg/inherit/thunk3.C new file mode 100644 index 0000000000000000000000000000000000000000..9787aa9c6c278390bf59f2cf4808fe8d50e05b2d --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/thunk3.C @@ -0,0 +1,12 @@ +// PR c++/18492 + +struct X{ ~X(); }; +struct B +{ + virtual void a( X ) = 0; +}; +struct D : public virtual B +{ + void a( X ); +}; +void D::a( X ){} diff --git a/gcc/testsuite/g++.dg/template/cond5.C b/gcc/testsuite/g++.dg/template/cond5.C new file mode 100644 index 0000000000000000000000000000000000000000..bba31e6afb282408557eae0d0a3bbc457673bd42 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/cond5.C @@ -0,0 +1,9 @@ +// PR c++/18464 + +struct A +{ + A(int); + operator void*() const; +}; + +template<int> void foo(const A& x) { 0 ? x : (x ? x : 0); } diff --git a/gcc/testsuite/g++.dg/warn/Wunused-9.C b/gcc/testsuite/g++.dg/warn/Wunused-9.C new file mode 100644 index 0000000000000000000000000000000000000000..30e3f6d69555850c1e3bce8d0b749571d68b00de --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wunused-9.C @@ -0,0 +1,38 @@ +// PR c++/11224 +// { dg-options "-Wunused" } + +struct someclass { + + bool isEmpty() const { return true; } +}; + +int main() +{ + bool bOk = false; + someclass foo; + + bOk == foo.isEmpty(); // { dg-warning "not used" } + + return bOk; +} + +int& f(); + +void g() { + f() == 0; // { dg-warning "not used" } + f() != 1; // { dg-warning "not used" } + f() < 2; // { dg-warning "not used" } + f() > 3; // { dg-warning "not used" } + f() <= 4; // { dg-warning "not used" } + f() >= 5; // { dg-warning "not used" } + f() + 6; // { dg-warning "not used" } + f() - 7; // { dg-warning "not used" } + f() * 8; // { dg-warning "not used" } + f() / 9; // { dg-warning "not used" } + +f(); // { dg-warning "not used" "" { xfail *-*-* } } + -f(); // { dg-warning "not used" } + ++f(); + --f(); + f() = 10; + f() <<= 11; +}