Commit dfb5c523 by Mark Mitchell Committed by Mark Mitchell

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
parent 606145e4
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> 2004-12-21 Mark Mitchell <mark@codesourcery.com>
PR c++/18378 PR c++/18378
......
...@@ -2333,10 +2333,18 @@ any_strictly_viable (struct z_candidate *cands) ...@@ -2333,10 +2333,18 @@ any_strictly_viable (struct z_candidate *cands)
return false; 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 static tree
build_this (tree obj) 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); return build_unary_op (ADDR_EXPR, obj, 0);
} }
......
...@@ -334,17 +334,19 @@ cp_genericize (tree fndecl) ...@@ -334,17 +334,19 @@ cp_genericize (tree fndecl)
/* Fix up the types of parms passed by invisible reference. */ /* Fix up the types of parms passed by invisible reference. */
for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
{ if (TREE_ADDRESSABLE (TREE_TYPE (t)))
gcc_assert (!DECL_BY_REFERENCE (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
gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); argument will be a pointer type, so we will never get
TREE_TYPE (t) = DECL_ARG_TYPE (t); here. */
DECL_BY_REFERENCE (t) = 1; gcc_assert (!DECL_BY_REFERENCE (t));
TREE_ADDRESSABLE (t) = 0; gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
relayout_decl (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. */ /* Do the same for the return value. */
if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
......
...@@ -909,9 +909,43 @@ convert_to_void (tree expr, const char *implicit) ...@@ -909,9 +909,43 @@ convert_to_void (tree expr, const char *implicit)
if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr))) if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr)))
{ {
if (implicit && warn_unused_value if (implicit && warn_unused_value && !TREE_NO_WARNING (expr))
&& !TREE_SIDE_EFFECTS (expr) && !TREE_NO_WARNING (expr)) {
warning ("%s has no effect", implicit); /* 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); expr = build1 (CONVERT_EXPR, void_type_node, expr);
} }
return expr; return expr;
......
...@@ -1345,22 +1345,32 @@ emit_support_tinfos (void) ...@@ -1345,22 +1345,32 @@ emit_support_tinfos (void)
for (ix = 0; fundamentals[ix]; ix++) for (ix = 0; fundamentals[ix]; ix++)
{ {
tree bltn = *fundamentals[ix]; tree bltn = *fundamentals[ix];
tree bltn_ptr = build_pointer_type (bltn); tree types[3] = {
tree bltn_const_ptr = build_pointer_type bltn,
(build_qualified_type (bltn, TYPE_QUAL_CONST)); build_pointer_type (bltn),
tree tinfo; build_pointer_type (build_qualified_type (bltn, TYPE_QUAL_CONST))
};
tinfo = get_tinfo_decl (bltn); int i;
TREE_USED (tinfo) = 1;
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1; for (i = 0; i < 3; ++i)
{
tinfo = get_tinfo_decl (bltn_ptr); tree tinfo;
TREE_USED (tinfo) = 1; tinfo = get_tinfo_decl (types[i]);
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1; TREE_USED (tinfo) = 1;
mark_needed (tinfo);
tinfo = get_tinfo_decl (bltn_const_ptr); /* The C++ ABI requires that these objects be COMDAT. But,
TREE_USED (tinfo) = 1; On systems without weak symbols, initialized COMDAT
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1; 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) ...@@ -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 for certain kinds of expressions which are not really lvalues
but which we can accept as 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 tree
unary_complex_lvalue (enum tree_code code, tree arg) 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". */ /* Handle (a, b) used as an "lvalue". */
if (TREE_CODE (arg) == COMPOUND_EXPR) if (TREE_CODE (arg) == COMPOUND_EXPR)
{ {
......
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> 2004-12-22 Janis Johnson <janis187@us.ibm.com>
* lib/gcc-dg.exp (dg-xfail-if): Fix the flags compared against. * lib/gcc-dg.exp (dg-xfail-if): Fix the flags compared against.
......
// 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 ){}
// PR c++/18464
struct A
{
A(int);
operator void*() const;
};
template<int> void foo(const A& x) { 0 ? x : (x ? x : 0); }
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment