[clang] [clang-cl] [Sema] Support MSVC non-const lvalue to user-defined temporary reference (PR #99833)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 19 08:06:07 PDT 2024
================
@@ -0,0 +1,151 @@
+// RUN: %clang_cc1 -fsyntax-only -Wno-microsoft-reference-binding -verify -fms-reference-binding %s
+// RUN: %clang_cc1 -DEXTWARN -fsyntax-only -verify -fms-reference-binding %s
+
+#ifdef EXTWARN
+
+struct A {};
+void fARef(A&) {}
+
+void test1() {
+ A& a1 = A(); // expected-warning{{binding a user-defined type temporary to a non-const lvalue is a Microsoft extension}}
+
+ fARef(A()); // expected-warning{{binding a user-defined type temporary to a non-const lvalue is a Microsoft extension}}
+}
+
+void fARefDoNotWarn(A&) {}
+void fARefDoNotWarn(const A&) {}
+
+// expected-note at +2 {{candidate function not viable: 1st argument ('const A') would lose const qualifier}}
+// expected-note at +1 {{candidate function not viable: 1st argument ('const A') would lose const qualifier}}
+void fARefLoseConstQualifier(A&) {}
+
+void test2() {
+ // This should not warn since `fARefDoNotWarn(const A&)` is a better candidate
+ fARefDoNotWarn(A());
+
+ const A a;
+ fARefLoseConstQualifier(a); // expected-error{{no matching function for call to 'fARefLoseConstQualifier'}}
+ fARefLoseConstQualifier(static_cast<const A&&>(a)); // expected-error{{no matching function for call to 'fARefLoseConstQualifier'}}
+}
+
+#else
+
+struct A {};
+struct B : A {};
+
+B fB();
+A fA();
+
+A&& fARvalueRef();
+A(&&fARvalueRefArray())[1];
+
+void fARef(A&) {}
+
+// expected-note at +2 {{candidate function not viable: expects an lvalue for 1st argument}}
+// expected-note at +1 {{candidate function not viable: expects an lvalue for 1st argument}}
+void fAVolatileRef(volatile A&) {}
+
+void fIntRef(int&) {} // expected-note{{candidate function not viable: expects an lvalue for 1st argument}}
+void fDoubleRef(double&) {} // expected-note{{candidate function not viable: expects an lvalue for 1st argument}}
+
+void fIntConstRef(const int&) {}
+void fDoubleConstRef(const double&) {}
+
+void fIntArray(int (&)[1]); // expected-note{{candidate function not viable: expects an lvalue for 1st argument}}
+void fIntConstArray(const int (&)[1]);
+
+namespace NS {
+ void fARef(A&) {}
+
+ // expected-note at +2 {{passing argument to parameter here}}
+ // expected-note at +1 {{passing argument to parameter here}}
+ void fAVolatileRef(volatile A&) {}
+
+ void fIntRef(int&) {} // expected-note{{passing argument to parameter here}}
+ void fDoubleRef(double&) {} // expected-note{{passing argument to parameter here}}
+
+ void fIntConstRef(const int&) {}
+ void fDoubleConstRef(const double&) {}
+
+ A(&&fARvalueRefArray())[1];
+
+ void fIntArray(int (&)[1]); // expected-note{{passing argument to parameter here}}
+
+ void fIntConstArray(const int (&)[1]);
+}
+
+void test1() {
+ double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}}
+ int& i1 = 0; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
+
+ fIntRef(0); // expected-error{{no matching function for call to 'fIntRef'}}
+ fDoubleRef(0.0); // expected-error{{no matching function for call to 'fDoubleRef'}}
+
+ NS::fIntRef(0); // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
+ NS::fDoubleRef(0.0); // expected-error{{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}}
+
+ int i2 = 2;
+ double& rd3 = i2; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}}
+}
+
+void test2() {
+ fIntConstRef(0);
+ fDoubleConstRef(0.0);
+
+ NS::fIntConstRef(0);
+ NS::fDoubleConstRef(0.0);
+
+ int i = 0;
+ const int ci = 0;
+ volatile int vi = 0;
+ const volatile int cvi = 0;
+ bool b = true;
+
+ const volatile int &cvir1 = b ? ci : vi; // expected-error{{volatile lvalue reference to type 'const volatile int' cannot bind to a temporary of type 'int'}}
+
+ volatile int& vir1 = 0; // expected-error{{volatile lvalue reference to type 'volatile int' cannot bind to a temporary of type 'int'}}
+ const volatile int& cvir2 = 0; // expected-error{{volatile lvalue reference to type 'const volatile int' cannot bind to a temporary of type 'int'}}
+}
+
+void test3() {
+ A& a1 = A();
+
+ fARef(A());
+ fARef(static_cast<A&&>(a1));
+
+ fAVolatileRef(A()); // expected-error{{no matching function for call to 'fAVolatileRef'}}
+ fAVolatileRef(static_cast<A&&>(a1)); // expected-error{{no matching function for call to 'fAVolatileRef'}}
+
+ fARef(B());
+
+ NS::fARef(A());
+ NS::fARef(static_cast<A&&>(a1));
+
+ NS::fAVolatileRef(A()); // expected-error{{volatile lvalue reference to type 'volatile A' cannot bind to a temporary of type 'A'}}
+ NS::fAVolatileRef(static_cast<A&&>(a1)); // expected-error{{volatile lvalue reference to type 'volatile A' cannot bind to a temporary of type 'A'}}
+
+ NS::fARef(B());
+
+ A& a2 = fA();
+
+ A& a3 = fARvalueRef();
+
+ const A& rca = fB();
+ A& ra = fB();
+}
+
+void test4() {
+ A (&array1)[1] = fARvalueRefArray(); // expected-error{{non-const lvalue reference to type 'A[1]' cannot bind to a temporary of type 'A[1]'}}
+ const A (&array2)[1] = fARvalueRefArray();
+
+ A (&array3)[1] = NS::fARvalueRefArray(); // expected-error{{non-const lvalue reference to type 'A[1]' cannot bind to a temporary of type 'A[1]'}}
+ const A (&array4)[1] = NS::fARvalueRefArray();
+
+ fIntArray({ 1 }); // expected-error{{no matching function for call to 'fIntArray'}}
+ NS::fIntArray({ 1 }); // expected-error{{non-const lvalue reference to type 'int[1]' cannot bind to an initializer list temporary}}
+
+ fIntConstArray({ 1 });
+ NS::fIntConstArray({ 1 });
+}
+
+#endif
----------------
AaronBallman wrote:
Some other test coverage to consider:
* Binding to a type that's a `typedef` to a class type
* Dependent types
* Function types
* Attributed types (such as a calling convention on a function type)
https://github.com/llvm/llvm-project/pull/99833
More information about the cfe-commits
mailing list