diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 202e416cb571d4d70a317934f8bf61f52acce7cf..696349f7be88c9cce58d99cd4d264d56b3611ecb 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2004-12-09  Alexandre Oliva  <aoliva@redhat.com>
+
+	PR c++/18757
+	* parser.c (cp_parser_template_id): Don't create a CPP_TEMPLATE_ID
+	if parsing failed.
+
 2004-12-09  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
 	PR c++/18073
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index dae68f36578e16025c9cb1cb8ddcd9702cfde462..ce3c7a6838daeb588ea86a41abd1f5f0602d6c3b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8416,8 +8416,9 @@ cp_parser_template_id (cp_parser *parser,
      should we re-parse the token stream, we will not have to repeat
      the effort required to do the parse, nor will we issue duplicate
      error messages about problems during instantiation of the
-     template.  */
-  if (start_of_id)
+     template.  Do so only if parsing succeeded, otherwise we may
+     silently accept template arguments with syntax errors.  */
+  if (start_of_id && !cp_parser_error_occurred (parser))
     {
       cp_token *token = cp_lexer_token_at (parser->lexer, start_of_id);
       
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 54b1dfe9da3d51c28605172e5b06c8f8b3933c17..51d6be53469aa79700fd87684fafb29a56fce916 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2004-12-09  Alexandre Oliva  <aoliva@redhat.com>
+
+	* g++.dg/parse/typename5.C: Adjust for new error.
+	* g++.dg/parse/typename7.C: New.
+
 2004-12-09  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
 	PR c++/18073
diff --git a/gcc/testsuite/g++.dg/parse/typename5.C b/gcc/testsuite/g++.dg/parse/typename5.C
index 6b2ed894a86d5bf735fa6da15aa12fc1b7fa5644..36647519fe61b3de710066237c60f6105e849de5 100644
--- a/gcc/testsuite/g++.dg/parse/typename5.C
+++ b/gcc/testsuite/g++.dg/parse/typename5.C
@@ -8,5 +8,5 @@ template <typename> struct A {};
 
 template <typename> struct B
 {
-    typedef A<typename X::Y> C; // { dg-error "declared|invalid|no type" }
+    typedef A<typename X::Y> C; // { dg-error "declared|invalid|no type|expected" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/typename7.C b/gcc/testsuite/g++.dg/parse/typename7.C
new file mode 100644
index 0000000000000000000000000000000000000000..211931781394c037c071e58ad304e3edf99054b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/typename7.C
@@ -0,0 +1,31 @@
+// { dg-do compile }
+
+// Origin: Volker Reichelt <reichelt@igpm.rwth-aachen.de> and
+// Alexandre Oliva <aoliva@redhat.com>
+
+// PR c++/18757: ICE in get_innermost_template_args
+
+struct A
+{
+  template<typename>   void foo(int);
+  template<typename T> void bar(T t) {
+    this->foo<typename T>(t); } // { dg-error "expected" }
+  template<typename T> void bad(T t) {
+    foo<typename T>(t); } // { dg-error "expected" }
+};
+
+template <typename T>
+struct B
+{
+  void bar(T t) {
+    A().bar<typename T>(t); } // { dg-error "expected" }
+  void bad(T t) {
+    B<typename T>::bar(t); } // { dg-error "invalid|not a template" }
+};
+
+void baz()
+{
+    A().bar(0);
+    A().bad(0);
+    B<int>().bar(0);
+}