re PR c++/18464 (error message about "non-lvalue in unary '&'" when using ?: operator)
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. 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. From-SVN: r92491
This commit is contained in:
parent
606145e4e0
commit
dfb5c52315
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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))))
|
||||
|
|
40
gcc/cp/cvt.c
40
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 ){}
|
|
@ -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); }
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue