Implement the suggested resolution to core issue 547, extended to also
allow ref-qualifiers on function types used as template type
arguments. GNU actually allows cv-qualifiers on function types in many
places where it shouldn't, so we currently categorize this as a GNU
extension.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124584 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/SemaCXX/issue547.cpp b/test/SemaCXX/issue547.cpp
new file mode 100644
index 0000000..03c5b7c
--- /dev/null
+++ b/test/SemaCXX/issue547.cpp
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename T>
+struct classify_function {
+  static const unsigned value = 0;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args...)> {
+  static const unsigned value = 1;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args...) const> { // expected-warning{{template argument of 'const' qualified function type is a GNU extension}}
+  static const unsigned value = 2;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args...) volatile> { // expected-warning{{template argument of 'volatile' qualified function type is a GNU extension}}
+  static const unsigned value = 3;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args...) const volatile> { // expected-warning{{template argument of 'const volatile' qualified function type is a GNU extension}}
+  static const unsigned value = 4;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args......)> {
+  static const unsigned value = 5;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args......) const> { // expected-warning{{template argument of 'const' qualified function type is a GNU extension}}
+  static const unsigned value = 6;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args......) volatile> { // expected-warning{{template argument of 'volatile' qualified function type is a GNU extension}}
+  static const unsigned value = 7;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args......) const volatile> { // expected-warning{{template argument of 'const volatile' qualified function type is a GNU extension}}
+  static const unsigned value = 8;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args......) &&> { // expected-warning{{template argument of '&&' qualified function type is a GNU extension}}
+  static const unsigned value = 9;
+};
+
+template<typename R, typename ...Args>
+struct classify_function<R(Args......) const &> { // expected-warning{{template argument of 'const &' qualified function type is a GNU extension}}
+  static const unsigned value = 10;
+};
+
+typedef void f0(int) const;
+typedef void f1(int, float...) const volatile;
+typedef void f2(int, double, ...) &&;
+typedef void f3(int, double, ...) const &;
+
+int check0[classify_function<f0>::value == 2? 1 : -1];
+int check1[classify_function<f1>::value == 8? 1 : -1];
+int check2[classify_function<f2>::value == 9? 1 : -1];
+int check3[classify_function<f3>::value == 10? 1 : -1];