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