commit a18ad4a33d12b2dc4a76034baeddb8d74cc83388
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Apr 11 18:41:30 2013 -0400

    	PR c++/48665
    	* rtti.c (get_typeid): Diagnose qualified function type.
    	* pt.c (tsubst) [POINTER_TYPE]: Likewise.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 77329a4..6ce2770 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11521,6 +11521,21 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
 	    return error_mark_node;
 	  }
+	else if (TREE_CODE (type) == FUNCTION_TYPE
+		 && (type_memfn_quals (type) != TYPE_UNQUALIFIED
+		     || type_memfn_rqual (type) != REF_QUAL_NONE))
+	  {
+	    if (complain & tf_error)
+	      {
+		if (code == POINTER_TYPE)
+		  error ("forming pointer to qualified function type %qT",
+			 type);
+		else
+		  error ("forming reference to qualified function type %qT",
+			 type);
+	      }
+	    return error_mark_node;
+	  }
 	else if (code == POINTER_TYPE)
 	  {
 	    r = build_pointer_type (type);
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index b3c6687..4e73165 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -477,6 +477,16 @@ get_typeid (tree type, tsubst_flags_t complain)
      referenced type.  */
   type = non_reference (type);
 
+  /* This is not one of the uses of a qualified function type in 8.3.5.  */
+  if (TREE_CODE (type) == FUNCTION_TYPE
+      && (type_memfn_quals (type) != TYPE_UNQUALIFIED
+	  || type_memfn_rqual (type) != REF_QUAL_NONE))
+    {
+      if (complain & tf_error)
+	error ("typeid of qualified function type %qT", type);
+      return error_mark_node;
+    }
+
   /* The top-level cv-qualifiers of the lvalue expression or the type-id
      that is the operand of typeid are always ignored.  */
   type = TYPE_MAIN_VARIANT (type);
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype40.C b/gcc/testsuite/g++.dg/cpp0x/decltype40.C
index 7933c95..55258f4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype40.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype40.C
@@ -68,7 +68,7 @@ static_assert(sizeof(g<void(&)()>(0)) == 2, "Ouch");
 static_assert(sizeof(g<void(&&)()>(0)) == 2, "Ouch");
 static_assert(sizeof(f<void, void>(0)) == 2, "Ouch");
 static_assert(sizeof(f<void(), void()>(0)) == 2, "Ouch");
-static_assert(sizeof(f<void() const, void() const>(0)) == 2, "Ouch");
+//static_assert(sizeof(f<void() const, void() const>(0)) == 2, "Ouch");
 static_assert(sizeof(f<int, void>(0)) == 2, "Ouch");
 static_assert(sizeof(f<void, int>(0)) == 2, "Ouch");
 static_assert(sizeof(f<C, void>(0)) == 2, "Ouch");
@@ -90,7 +90,7 @@ static_assert(sizeof(g2<void(&)()>(0)) == 2, "Ouch");
 static_assert(sizeof(g2<void(&&)()>(0)) == 2, "Ouch");
 static_assert(sizeof(f2<void, void>(0)) == 2, "Ouch");
 static_assert(sizeof(f2<void(), void()>(0)) == 2, "Ouch");
-static_assert(sizeof(f2<void() const, void() const>(0)) == 2, "Ouch");
+//static_assert(sizeof(f2<void() const, void() const>(0)) == 2, "Ouch");
 static_assert(sizeof(f2<int, void>(0)) == 2, "Ouch");
 static_assert(sizeof(f2<void, int>(0)) == 2, "Ouch");
 static_assert(sizeof(f2<C, void>(0)) == 2, "Ouch");
diff --git a/gcc/testsuite/g++.dg/rtti/fn-quals.C b/gcc/testsuite/g++.dg/rtti/fn-quals.C
new file mode 100644
index 0000000..75d24f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/rtti/fn-quals.C
@@ -0,0 +1,12 @@
+// PR c++/48665
+
+#include <typeinfo>
+extern "C" void abort();
+
+template<class A,class B> void f() {
+  if (typeid(A)==typeid(B)) abort(); // { dg-error "qualified function" }
+  if (typeid(A*)==typeid(B*)) abort(); // { dg-error "qualified function" }
+}
+int main() {
+  f<void()const,void()>();
+}
diff --git a/libstdc++-v3/testsuite/20_util/is_assignable/value.cc b/libstdc++-v3/testsuite/20_util/is_assignable/value.cc
index eade406..8d45671 100644
--- a/libstdc++-v3/testsuite/20_util/is_assignable/value.cc
+++ b/libstdc++-v3/testsuite/20_util/is_assignable/value.cc
@@ -277,8 +277,8 @@ static_assert(!std::is_assignable<DelAnyAssign&, int&>::value, "Error");
 static_assert(!std::is_assignable<DelAnyAssign&, const int&>::value, "Error");
 static_assert(!std::is_assignable<DelAnyAssign&, void>::value, "Error");
 static_assert(!std::is_assignable<DelAnyAssign&, void()>::value, "Error");
-static_assert(!std::is_assignable<DelAnyAssign&, void()
-const>::value, "Error");
+// static_assert(!std::is_assignable<DelAnyAssign&, void()
+// const>::value, "Error");
 static_assert(!std::is_assignable<DelAnyAssign&, void(&)()>::value, "Error");
 static_assert(!std::is_assignable<DelAnyAssign&, void(&&)()>::value, "Error");
 static_assert(!std::is_assignable<DelAnyAssign&,
@@ -600,7 +600,7 @@ static_assert(std::is_assignable<UAssignAll&,
 std::nullptr_t&>::value, "Error");
 static_assert(std::is_assignable<UAssignAll&, void()>::value, "Error");
 static_assert(std::is_assignable<UAssignAll&, void(&)()>::value, "Error");
-static_assert(std::is_assignable<UAssignAll&, void() const>::value, "Error");
+//static_assert(std::is_assignable<UAssignAll&, void() const>::value, "Error");
 static_assert(std::is_assignable<UAssignAll&, void(*)()>::value, "Error");
 static_assert(std::is_assignable<UAssignAll&, void(*&)()>::value, "Error");
 static_assert(std::is_assignable<UAssignAll&, int*>::value, "Error");
@@ -636,8 +636,8 @@ static_assert(!std::is_assignable<UDelAssignAll&,
 std::nullptr_t&>::value, "Error");
 static_assert(!std::is_assignable<UDelAssignAll&, void()>::value, "Error");
 static_assert(!std::is_assignable<UDelAssignAll&, void(&)()>::value, "Error");
-static_assert(!std::is_assignable<UDelAssignAll&, void()
-const>::value, "Error");
+// static_assert(!std::is_assignable<UDelAssignAll&, void()
+// const>::value, "Error");
 static_assert(!std::is_assignable<UDelAssignAll&, void(*)()>::value, "Error");
 static_assert(!std::is_assignable<UDelAssignAll&, void(*&)()>::value, "Error");
 static_assert(!std::is_assignable<UDelAssignAll&, int*>::value, "Error");
diff --git a/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc b/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc
index ba6ffab..f311911 100644
--- a/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc
+++ b/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc
@@ -72,8 +72,8 @@ static_assert(!std::is_constructible<DelEllipsis, SE>::value, "Error");
 static_assert(!std::is_constructible<DelEllipsis, OpE>::value, "Error");
 static_assert(!std::is_constructible<DelEllipsis, OpSE>::value, "Error");
 static_assert(!std::is_constructible<DelEllipsis, void()>::value, "Error");
-static_assert(!std::is_constructible<DelEllipsis, void() const>::value,
-	      "Error");
+// static_assert(!std::is_constructible<DelEllipsis, void() const>::value,
+// 	      "Error");
 static_assert(!std::is_constructible<DelEllipsis, int[1]>::value, "Error");
 static_assert(!std::is_constructible<DelEllipsis, int[]>::value, "Error");
 static_assert(!std::is_constructible<DelEllipsis, int*>::value, "Error");
@@ -461,20 +461,20 @@ static_assert(!std::is_constructible<OpSE, void()>::value, "Error");
 static_assert(!std::is_constructible<int[], void()>::value, "Error");
 static_assert(!std::is_constructible<int[1], void()>::value, "Error");
 
-static_assert(!std::is_constructible<void(int) const,
-	      void() const>::value, "Error");
-static_assert(!std::is_constructible<int, void() const>::value, "Error");
-static_assert(!std::is_constructible<Abstract, void() const>::value, "Error");
-static_assert(!std::is_constructible<std::nullptr_t, void() const>::value,
-	      "Error");
-static_assert(!std::is_constructible<Empty, void() const>::value, "Error");
-static_assert(!std::is_constructible<U, void() const>::value, "Error");
-static_assert(!std::is_constructible<E, void() const>::value, "Error");
-static_assert(!std::is_constructible<SE, void() const>::value, "Error");
-static_assert(!std::is_constructible<OpE, void() const>::value, "Error");
-static_assert(!std::is_constructible<OpSE, void() const>::value, "Error");
-static_assert(!std::is_constructible<int[], void() const>::value, "Error");
-static_assert(!std::is_constructible<int[1], void() const>::value, "Error");
+// static_assert(!std::is_constructible<void(int) const,
+// 	      void() const>::value, "Error");
+// static_assert(!std::is_constructible<int, void() const>::value, "Error");
+// static_assert(!std::is_constructible<Abstract, void() const>::value, "Error");
+// static_assert(!std::is_constructible<std::nullptr_t, void() const>::value,
+// 	      "Error");
+// static_assert(!std::is_constructible<Empty, void() const>::value, "Error");
+// static_assert(!std::is_constructible<U, void() const>::value, "Error");
+// static_assert(!std::is_constructible<E, void() const>::value, "Error");
+// static_assert(!std::is_constructible<SE, void() const>::value, "Error");
+// static_assert(!std::is_constructible<OpE, void() const>::value, "Error");
+// static_assert(!std::is_constructible<OpSE, void() const>::value, "Error");
+// static_assert(!std::is_constructible<int[], void() const>::value, "Error");
+// static_assert(!std::is_constructible<int[1], void() const>::value, "Error");
 
 static_assert(!std::is_constructible<void, int, int>::value, "Error");
 static_assert(!std::is_constructible<void, Empty, B>::value, "Error");
@@ -488,8 +488,8 @@ static_assert(!std::is_constructible<void, int[], int[]>::value, "Error");
 static_assert(!std::is_constructible<void, void, int>::value, "Error");
 static_assert(!std::is_constructible<void, void, void>::value, "Error");
 static_assert(!std::is_constructible<void, void(), void()>::value, "Error");
-static_assert(!std::is_constructible<void, void() const,
-	      void() volatile>::value, "Error");
+// static_assert(!std::is_constructible<void, void() const,
+// 	      void() volatile>::value, "Error");
 
 static_assert(!std::is_constructible<int, int, int>::value, "Error");
 static_assert(!std::is_constructible<const int, int, int>::value, "Error");
@@ -651,13 +651,13 @@ static_assert(!std::is_constructible<void(), void, void>::value, "Error");
 static_assert(!std::is_constructible<void(), void(), int>::value, "Error");
 static_assert(!std::is_constructible<void(), void(), void()>::value, "Error");
 
-static_assert(!std::is_constructible<void() const, int, int>::value, "Error");
-static_assert(!std::is_constructible<void() const, void, int>::value, "Error");
-static_assert(!std::is_constructible<void() const, void, void>::value, "Error");
-static_assert(!std::is_constructible<void() const, void() volatile,
-	      int>::value, "Error");
-static_assert(!std::is_constructible<void() const, void() volatile const,
-	      void() const>::value, "Error");
+// static_assert(!std::is_constructible<void() const, int, int>::value, "Error");
+// static_assert(!std::is_constructible<void() const, void, int>::value, "Error");
+// static_assert(!std::is_constructible<void() const, void, void>::value, "Error");
+// static_assert(!std::is_constructible<void() const, void() volatile,
+// 	      int>::value, "Error");
+// static_assert(!std::is_constructible<void() const, void() volatile const,
+// 	      void() const>::value, "Error");
 
 static_assert(!std::is_constructible<FromArgs<int>, int, int>::value, "Error");
 static_assert(!std::is_constructible<const FromArgs<int>, int, int>::value,
diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/result_type.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/result_type.cc
index 24cd6b9..e849a5d 100644
--- a/libstdc++-v3/testsuite/20_util/reference_wrapper/result_type.cc
+++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/result_type.cc
@@ -27,9 +27,9 @@ using namespace std;
 struct T;
 
 reference_wrapper<int(float, ...)>::result_type                       i01;
-reference_wrapper<int(float, ...) const>::result_type                 i02;
-reference_wrapper<int(float, ...) volatile>::result_type              i03;
-reference_wrapper<int(float, ...) const volatile>::result_type        i04;
+// reference_wrapper<int(float, ...) const>::result_type                 i02;
+// reference_wrapper<int(float, ...) volatile>::result_type              i03;
+// reference_wrapper<int(float, ...) const volatile>::result_type        i04;
 
 reference_wrapper<int(*)(float, ...)>::result_type                    i05;
 reference_wrapper<int(* const)(float, ...)>::result_type              i06;
diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-2.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-2.cc
index 89dcd3b..e0f7231 100644
--- a/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-2.cc
+++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-2.cc
@@ -25,13 +25,13 @@
 using namespace std;
 
 reference_wrapper<int(float)>::argument_type                               i01;
-reference_wrapper<int(float) const>::argument_type                         i02;
-reference_wrapper<int(float) volatile>::argument_type                      i03;
-reference_wrapper<int(float) const volatile>::argument_type                i04;
+// reference_wrapper<int(float) const>::argument_type                         i02;
+// reference_wrapper<int(float) volatile>::argument_type                      i03;
+// reference_wrapper<int(float) const volatile>::argument_type                i04;
 reference_wrapper<int(float)>::result_type                                 i05;
-reference_wrapper<int(float) const>::result_type                           i06;
-reference_wrapper<int(float) volatile>::result_type                        i07;
-reference_wrapper<int(float) const volatile>::result_type                  i08;
+// reference_wrapper<int(float) const>::result_type                           i06;
+// reference_wrapper<int(float) volatile>::result_type                        i07;
+// reference_wrapper<int(float) const volatile>::result_type                  i08;
 
 reference_wrapper<int(*)(float)>::argument_type                            i09;
 reference_wrapper<int(* const)(float)>::argument_type                      i10;
@@ -43,17 +43,17 @@ reference_wrapper<int(* volatile)(float)>::result_type                     i15;
 reference_wrapper<int(* const volatile)(float)>::result_type               i16;
 
 reference_wrapper<int(float, char)>::first_argument_type                   i17;
-reference_wrapper<int(float, char) const>::first_argument_type             i18;
-reference_wrapper<int(float, char) volatile>::first_argument_type          i19;
-reference_wrapper<int(float, char) const volatile>::first_argument_type    i20;
+// reference_wrapper<int(float, char) const>::first_argument_type             i18;
+// reference_wrapper<int(float, char) volatile>::first_argument_type          i19;
+// reference_wrapper<int(float, char) const volatile>::first_argument_type    i20;
 reference_wrapper<int(float, char)>::second_argument_type                  i21;
-reference_wrapper<int(float, char) const>::second_argument_type            i22;
-reference_wrapper<int(float, char) volatile>::second_argument_type         i23;
-reference_wrapper<int(float, char) const volatile>::second_argument_type   i24;
+// reference_wrapper<int(float, char) const>::second_argument_type            i22;
+// reference_wrapper<int(float, char) volatile>::second_argument_type         i23;
+// reference_wrapper<int(float, char) const volatile>::second_argument_type   i24;
 reference_wrapper<int(float, char)>::result_type                           i25;
-reference_wrapper<int(float, char) const>::result_type                     i26;
-reference_wrapper<int(float, char) volatile>::result_type                  i27;
-reference_wrapper<int(float, char) const volatile>::result_type            i28;
+// reference_wrapper<int(float, char) const>::result_type                     i26;
+// reference_wrapper<int(float, char) volatile>::result_type                  i27;
+// reference_wrapper<int(float, char) const volatile>::result_type            i28;
 
 reference_wrapper<int(*)(float, char)>::first_argument_type                i29;
 reference_wrapper<int(* const)(float, char)>::first_argument_type          i30;
