diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fe64da57d5b32790c778a892188d683d21878a98..eba897fe83df64f7f2a8041f2140dbb3459532d3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
 2013-01-09  Jason Merrill  <jason@redhat.com>
 
+	PR c++/55878
+	* rtti.c (build_typeid, get_typeid): Add complain parm.
+	(get_tinfo_decl_dynamic): Likewise.
+	* cp-tree.h, parser.c, pt.c: Adjust.
+
 	PR c++/55893
 	* decl.c (cp_finish_decl): Clear TREE_READONLY if the variable
 	needs destruction.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 810df7de29cd21e6076a646cf0605eb911a2194b..5482923fd3c0899dc055183c45dfecd62c94a340 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5476,9 +5476,9 @@ extern void finish_repo				(void);
 extern GTY(()) vec<tree, va_gc> *unemitted_tinfo_decls;
 
 extern void init_rtti_processing		(void);
-extern tree build_typeid			(tree);
+extern tree build_typeid			(tree, tsubst_flags_t);
 extern tree get_tinfo_decl			(tree);
-extern tree get_typeid				(tree);
+extern tree get_typeid				(tree, tsubst_flags_t);
 extern tree build_headof			(tree);
 extern tree build_dynamic_cast			(tree, tree, tsubst_flags_t);
 extern void emit_support_tinfos			(void);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8a90bec770d80ec7f5c4dcdcd7f517c42c8c0a00..36e9342d0fc37ff186b6eb89360773042ef3340d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5473,7 +5473,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 	/* If all went well, simply lookup the type-id.  */
 	if (cp_parser_parse_definitely (parser))
-	  postfix_expression = get_typeid (type);
+	  postfix_expression = get_typeid (type, tf_warning_or_error);
 	/* Otherwise, fall back to the expression variant.  */
 	else
 	  {
@@ -5482,7 +5482,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	    /* Look for an expression.  */
 	    expression = cp_parser_expression (parser, /*cast_p=*/false, & idk);
 	    /* Compute its typeid.  */
-	    postfix_expression = build_typeid (expression);
+	    postfix_expression = build_typeid (expression, tf_warning_or_error);
 	    /* Look for the `)' token.  */
 	    cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 	  }
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index c55dabef7e2ed149dd5a1d85e2b2c06abdb1b883..6d78dd2b90f8ebae8f5a25bf234e7b170f2835c0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14223,12 +14223,12 @@ tsubst_copy_and_build (tree t,
 	if (TYPE_P (operand_0))
 	  {
 	    operand_0 = tsubst (operand_0, args, complain, in_decl);
-	    RETURN (get_typeid (operand_0));
+	    RETURN (get_typeid (operand_0, complain));
 	  }
 	else
 	  {
 	    operand_0 = RECUR (operand_0);
-	    RETURN (build_typeid (operand_0));
+	    RETURN (build_typeid (operand_0, complain));
 	  }
       }
 
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index de28371c67968b81dbf7f89b0efad3e0dc26e2b1..77fd0460a5009417ec3d1e1e9aca5233fb0136bc 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -108,7 +108,6 @@ static tree tinfo_name (tree, bool);
 static tree build_dynamic_cast_1 (tree, tree, tsubst_flags_t);
 static tree throw_bad_cast (void);
 static tree throw_bad_typeid (void);
-static tree get_tinfo_decl_dynamic (tree);
 static tree get_tinfo_ptr (tree);
 static bool typeid_ok_p (void);
 static int qualifier_flags (tree);
@@ -238,7 +237,7 @@ throw_bad_typeid (void)
    otherwise return the static type of the expression.  */
 
 static tree
-get_tinfo_decl_dynamic (tree exp)
+get_tinfo_decl_dynamic (tree exp, tsubst_flags_t complain)
 {
   tree type;
   tree t;
@@ -257,7 +256,7 @@ get_tinfo_decl_dynamic (tree exp)
   /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics.  */
   if (CLASS_TYPE_P (type) || type == unknown_type_node
       || type == init_list_type_node)
-    type = complete_type_or_else (type, exp);
+    type = complete_type_or_maybe_complain (type, exp, complain);
 
   if (!type)
     return error_mark_node;
@@ -278,7 +277,7 @@ get_tinfo_decl_dynamic (tree exp)
     /* Otherwise return the type_info for the static type of the expr.  */
     t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
 
-  return cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
+  return cp_build_indirect_ref (t, RO_NULL, complain);
 }
 
 static bool
@@ -316,7 +315,7 @@ typeid_ok_p (void)
    an lvalue of type "const std::type_info".  */
 
 tree
-build_typeid (tree exp)
+build_typeid (tree exp, tsubst_flags_t complain)
 {
   tree cond = NULL_TREE, initial_expr = exp;
   int nonnull = 0;
@@ -340,10 +339,10 @@ build_typeid (tree exp)
       exp = mark_lvalue_use (exp);
       exp = stabilize_reference (exp);
       cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0),
-			 tf_warning_or_error);
+			 complain);
     }
 
-  exp = get_tinfo_decl_dynamic (exp);
+  exp = get_tinfo_decl_dynamic (exp, complain);
 
   if (exp == error_mark_node)
     return error_mark_node;
@@ -469,7 +468,7 @@ get_tinfo_ptr (tree type)
 /* Return the type_info object for TYPE.  */
 
 tree
-get_typeid (tree type)
+get_typeid (tree type, tsubst_flags_t complain)
 {
   if (type == error_mark_node || !typeid_ok_p ())
     return error_mark_node;
@@ -489,13 +488,12 @@ get_typeid (tree type)
   /* For UNKNOWN_TYPEs call complete_type_or_else to get diagnostics.  */
   if (CLASS_TYPE_P (type) || type == unknown_type_node
       || type == init_list_type_node)
-    type = complete_type_or_else (type, NULL_TREE);
+    type = complete_type_or_maybe_complain (type, NULL_TREE, complain);
 
   if (!type)
     return error_mark_node;
 
-  return cp_build_indirect_ref (get_tinfo_ptr (type), RO_NULL, 
-                                tf_warning_or_error);
+  return cp_build_indirect_ref (get_tinfo_ptr (type), RO_NULL, complain);
 }
 
 /* Check whether TEST is null before returning RESULT.  If TEST is used in
diff --git a/gcc/testsuite/g++.dg/template/typeid1.C b/gcc/testsuite/g++.dg/template/typeid1.C
new file mode 100644
index 0000000000000000000000000000000000000000..6df5f71ff780e8501ed0bad4ecd6dc14f5bd0d7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typeid1.C
@@ -0,0 +1,17 @@
+// PR c++/55878
+
+#include <typeinfo>
+
+struct S;
+
+template <typename T>
+static bool fn (S *s)
+{
+  return typeid (*s) == typeid (T);
+}
+
+struct S
+{
+};
+
+bool x = fn<S> (__null);