summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-07-11 23:19:41 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-07-11 23:19:41 +0000
commitb884ed186eb705c4c5b5ebfcc864f3cfc8794bbb (patch)
tree29b2a3a1912a6b617c7ecc3992da8572c579322e /clang/test
parentdc7200b486b6c5b5229abcee97c160145cc3d955 (diff)
downloadbcm5719-llvm-b884ed186eb705c4c5b5ebfcc864f3cfc8794bbb.tar.gz
bcm5719-llvm-b884ed186eb705c4c5b5ebfcc864f3cfc8794bbb.zip
Fix deduction for conversion function templates converting to reference
types. We previously tried to use the "parameter is a reference" logic here, but that doesn't work because it gets P and A backwards. Instead, add a separate implementation of the "deduced A can be less qualified than A" rule. This also exposes that we incorrectly stripped cv-qualifiers from the referent of A if it was a reference. However, if we don't do that, we get the wrong results when P is a reference. In an attempt to match what sanity dictates and what other implementations are doing, we now remove cv-qualifiers from A and P unless both are reference types. I've brought this up on the core reflector too, to try to get the standard fixed. llvm-svn: 336867
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
index b45ed96d144..89478ed39f6 100644
--- a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only %s -verify
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify
struct AnyT {
template<typename T>
@@ -62,3 +64,69 @@ void test_deduce_two_level_ptrmem_with_qual(TwoLevelPtrMem apm) {
// deduce T = 'const double'
const double X::* X::* pm1 = apm; // expected-note {{instantiation of}}
}
+
+namespace non_ptr_ref_cv_qual {
+ template<typename Expected>
+ struct ConvToT {
+ template<typename T> operator T() {
+ using Check = T;
+ using Check = Expected;
+ }
+ };
+ const int test_conv_to_t_1 = ConvToT<int>();
+ // We intentionally deviate from [temp.deduct.conv]p4 here, and also remove
+ // the top-level cv-quaifiers from A *after* removing the reference type, if
+ // P is not also a reference type. This matches what other compilers are
+ // doing, and is necessary to support real-world code.
+ const int &test_conv_to_t_2 = ConvToT<int>();
+
+ // Example code that would be broken by the standard's rule.
+ struct Dest {};
+ Dest d1a((ConvToT<Dest>()));
+ Dest d1b = ConvToT<Dest>();
+ Dest &d2 = (d1a = ConvToT<Dest>());
+
+ template<typename Expected>
+ struct ConvToTRef {
+ template<typename T> operator T&() {
+ using Check = T;
+ using Check = Expected;
+ }
+ };
+ const int test_conv_to_t_ref_1 = ConvToTRef<int>();
+ const int &test_conv_to_t_ref_2 = ConvToTRef<const int>();
+
+ Dest d3a((ConvToTRef<const Dest>())); // initialize the copy ctor parameter with 'const Dest&'
+ Dest d3b = ConvToTRef<Dest>(); // convert to non-const T via [over.match.copy]/1.2
+ Dest &d4 = (d3a = ConvToTRef<const Dest>());
+
+ template<typename Expected>
+ struct ConvToConstT {
+ template<typename T> operator const T() {
+ using Check = T;
+ using Check = Expected;
+ }
+ };
+ const int test_conv_to_const_t_1 = ConvToConstT<int>();
+ const int &test_conv_to_const_t_2 = ConvToConstT<int>();
+
+ template<typename Expected>
+ struct ConvToConstTRef {
+ template<typename T> operator const T&() {
+ using Check = T;
+ using Check = Expected;
+ }
+ };
+ const int test_conv_to_const_t_ref_1 = ConvToConstTRef<int>();
+ const int &test_conv_to_const_t_ref_2 = ConvToConstTRef<int>();
+
+ template <typename T, int N> using Arr = T[N];
+ struct ConvToArr {
+ template <int N>
+ operator Arr<int, N> &() {
+ static_assert(N == 3, "");
+ }
+ };
+ int (&test_conv_to_arr_1)[3] = ConvToArr(); // ok
+ const int (&test_conv_to_arr_2)[3] = ConvToArr(); // ok, with qualification conversion
+}
OpenPOWER on IntegriCloud