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:
Mark Mitchell 2004-12-22 18:00:39 +00:00 committed by Mark Mitchell
parent 606145e4e0
commit dfb5c52315
10 changed files with 181 additions and 32 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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))))

View File

@ -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;

View File

@ -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;
}
}
}
}

View File

@ -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)
{

View File

@ -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.

View File

@ -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 ){}

View File

@ -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); }

View File

@ -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;
}