Extend this test and make it a bit clearer which cases Clang is getting wrong.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 16 Oct 2016 06:23:29 +0000 (06:23 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 16 Oct 2016 06:23:29 +0000 (06:23 +0000)
llvm-svn: 284331

clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp

index 4dca820..b45ed96 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only %s
+// RUN: %clang_cc1 -fsyntax-only %s -verify
 
 struct AnyT {
   template<typename T>
@@ -11,34 +11,54 @@ void test_cvqual_ref(AnyT any) {
 
 struct AnyThreeLevelPtr {
   template<typename T>
-  operator T***() const
-  {
-    T x = 0;
-    // FIXME: looks like we get this wrong, too!
-    // x = 0; // will fail if T is deduced to a const type
-           // (EDG and GCC get this wrong)
-    return 0;
+  operator T***() const {
+    T x = 0; // expected-note 2{{declared const here}}
+    x = 0; // expected-error 2{{const-qualified type}}
+    T ***p;
+    return p;
   }
 };
 
 struct X { };
 
 void test_deduce_with_qual(AnyThreeLevelPtr a3) {
-  int * const * const * const ip = a3;
+  int * const * const * const ip1 = a3;
+  // FIXME: This is wrong; we are supposed to deduce 'T = int' here.
+  const int * const * const * const ip2 = a3; // expected-note {{instantiation of}}
+  // This one is correct, though.
+  const double * * * ip3 = a3; // expected-note {{instantiation of}}
 }
 
 struct AnyPtrMem {
   template<typename Class, typename T>
   operator T Class::*() const
   {
-    T x = 0;
-    // FIXME: looks like we get this wrong, too!
-    // x = 0; // will fail if T is deduced to a const type.
-           // (EDG and GCC get this wrong)
+    // This is correct: we don't need a qualification conversion here, so we
+    // deduce 'T = const float'.
+    T x = 0; // expected-note {{declared const here}}
+    x = 0; // expected-error {{const-qualified type}}
     return 0;
   }
 };
 
 void test_deduce_ptrmem_with_qual(AnyPtrMem apm) {
-  const float X::* pm = apm;
+  const float X::* pm = apm; // expected-note {{instantiation of}}
+}
+
+struct TwoLevelPtrMem {
+  template<typename Class1, typename Class2, typename T>
+  operator T Class1::*Class2::*() const
+  {
+    T x = 0; // expected-note 2{{declared const here}}
+    x = 0; // expected-error 2{{const-qualified type}}
+    return 0;
+  }
+};
+
+void test_deduce_two_level_ptrmem_with_qual(TwoLevelPtrMem apm) {
+  // FIXME: This is wrong: we should deduce T = 'float'
+  const float X::* const X::* pm2 = apm; // expected-note {{instantiation of}}
+  // This is correct: we don't need a qualification conversion, so we directly
+  // deduce T = 'const double'
+  const double X::* X::* pm1 = apm; // expected-note {{instantiation of}}
 }