diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8f6462414b1d1f6a20e7864b545b89ac03b02652..b6cf53af8f859a664a79124fce7dbca30617a0d2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2009-11-19  Jason Merrill  <jason@redhat.com>
+
+	* dwarf2out.c (get_context_die): Take TYPE_MAIN_VARIANT.
+
 2009-11-19  Basile Starynkevitch  <basile@starynkevitch.net>
             Rafael Avila de Espindola  <espindola@google.com>
 
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6a30b67bdfdfc7bda8a87ac8cc22fd760a94e762..c25d360eaf0c0b3b887fb39be719b8836a0c4f43 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,14 @@
 2009-11-19  Jason Merrill  <jason@redhat.com>
 
+	DR 176 permissiveness
+	* class.c (build_self_reference): Call set_underlying_type.
+	* decl.c (check_elaborated_type_specifier): Don't complain about
+	injected-class-name.
+	(type_is_deprecated): Use TYPE_MAIN_VARIANT.
+	* pt.c (convert_template_argument): Handle injected-class-name used
+	as template template argument.
+	* typeck2.c (abstract_virtuals_error): Use TYPE_MAIN_VARIANT.
+
 	PR c++/561
 	* decl.c (static_fn_type): Split out...
 	(revert_static_member_fn): ...from here.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3cf15fb0fa6af2983dd898a489f93bf9a50bbdac..38eb73f400445cb3e0bffa81083c8b5b3bdd271f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6513,6 +6513,7 @@ build_self_reference (void)
   DECL_CONTEXT (value) = current_class_type;
   DECL_ARTIFICIAL (value) = 1;
   SET_DECL_SELF_REFERENCE_P (value);
+  set_underlying_type (value);
 
   if (processing_template_decl)
     value = push_template_decl (value);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 29e32c8062419ca3f345684885098beddf166f31..7f5a688873bd3943c5b00ed3a1320b437b3f6ddd 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9787,6 +9787,10 @@ type_is_deprecated (tree type)
       && TREE_DEPRECATED (TYPE_NAME (type)))
     return type;
 
+  /* Do warn about using typedefs to a deprecated class.  */
+  if (TAGGED_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type))
+    return type_is_deprecated (TYPE_MAIN_VARIANT (type));
+
   code = TREE_CODE (type);
 
   if (code == POINTER_TYPE || code == REFERENCE_TYPE
@@ -10608,6 +10612,7 @@ check_elaborated_type_specifier (enum tag_types tag_code,
      elaborated type specifier is the implicit typedef created when
      the type is declared.  */
   else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+	   && !DECL_SELF_REFERENCE_P (decl)
 	   && tag_code != typename_type)
     {
       error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9c82e3c19a5885d658680a88e9198388e5129f6d..c3b0f0e668f346795d18583f090ebee9eba2bc29 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5370,6 +5370,22 @@ convert_template_argument (tree parm,
   if (TREE_CODE (arg) == TYPE_PACK_EXPANSION)
     arg = PACK_EXPANSION_PATTERN (arg);
 
+  /* Deal with an injected-class-name used as a template template arg.  */
+  if (requires_tmpl_type && CLASS_TYPE_P (arg))
+    {
+      tree t = maybe_get_template_decl_from_type_decl (TYPE_NAME (arg));
+      if (TREE_CODE (t) == TEMPLATE_DECL)
+	{
+	  if (complain & tf_warning_or_error)
+	    pedwarn (input_location, OPT_pedantic, "injected-class-name %qD"
+		     " used as template template argument", TYPE_NAME (arg));
+	  else if (flag_pedantic_errors)
+	    t = arg;
+
+	  arg = t;
+	}
+    }
+
   is_tmpl_type = 
     ((TREE_CODE (arg) == TEMPLATE_DECL
       && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 6cb115202b291e81f051edc5e58a892fcaac0295..a296caae26e4a48cbe7a91780c8e8af0ec16443b 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -236,6 +236,7 @@ abstract_virtuals_error (tree decl, tree type)
      be abstract.  */
   if (!CLASS_TYPE_P (type))
     return 0;
+  type = TYPE_MAIN_VARIANT (type);
 
   /* If the type is incomplete, we register it within a hash table,
      so that we can check again once it is completed. This makes sense
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 3db2092b4ee6b87815742e6aba0d61cd7f632c8e..0394114e1d6954d8e111158f4d7cd1b5756f8bea 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -19089,7 +19089,7 @@ get_context_die (tree context)
     {
       /* Find die that represents this context.  */
       if (TYPE_P (context))
-	return force_type_die (context);
+	return force_type_die (TYPE_MAIN_VARIANT (context));
       else
 	return force_decl_die (context);
     }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0a42693a3ec40e2e37b78c5a6d7198fb3fff3f7f..5a56a9c5fbb34991faa0f0ed4e0a9da765ad3b57 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2009-11-19  Jason Merrill  <jason@redhat.com>
+
+	DR 176 permissiveness
+	* g++.dg/ext/injected-ttp.C: New.
+	* g++.old-deja/g++.pt/niklas01a.C: Adjust.
+	* g++.old-deja/g++.pt/ttp41.C: Adjust.
+
 2009-11-19  Andy Hutchinson  <hutchinsonandy@gcc.gnu.org>
 
 	* gcc.c-torture/compile/pr40204.c: Test only for int32 target.
diff --git a/gcc/testsuite/g++.dg/ext/injected-ttp.C b/gcc/testsuite/g++.dg/ext/injected-ttp.C
new file mode 100644
index 0000000000000000000000000000000000000000..405bee88cdfb7ce2b163b56dfd1f3339957e310a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/injected-ttp.C
@@ -0,0 +1,15 @@
+// Test for doing the right thing with injected-class-name used as template
+// type argument.  This is an extension from DR 176.
+
+// { dg-options "-pedantic" }
+
+template <class T>
+struct A { };
+
+template <template <class> class TTP>
+struct B { };
+
+struct C: A<int>
+{
+  B<A> b;			// { dg-warning "injected-class-name" }
+};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
index 7fe07a2df0ed93e2d92c7e5c100d94c6dd2c54c3..eec11ab003392080e7a4cac6446bb4069449cc57 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
@@ -2,7 +2,7 @@
 // { dg-options "-fshow-column" }
 
 struct A { // { dg-error "" } forward declaration
-  friend struct B : A {		// { dg-error "invalid use of incomplete type 'struct A'" }
+  friend struct B : A {		// { dg-error "invalid use of incomplete type 'struct A" }
     int x;
   };	// { dg-error "class definition may not be declared a friend" ""  { target *-*-* } { 5 } }
   int y;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C
index b260961e813949d9a2f0af448186b5b9e2279837..564294e38404d2da52a98eb1e8dffdfbb94ff68d 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "" }
 template<template<class> class D,class E> class C
 {
 	public:
@@ -13,8 +14,8 @@ template<class T> class D
 
 template<class T> int D<T>::f()
 {
-	C<D,D> c;	// { dg-error "" }
-	return c.g();	// { dg-error "" }
+	C<D,D> c;
+	return c.g();
 }
 
 int main()