https://github.com/MaxEW707 updated 
https://github.com/llvm/llvm-project/pull/99833

>From c66fee7969fc4bd8b5ce79085f0fc09cbc4147da Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Fri, 21 Jun 2024 20:37:40 -0700
Subject: [PATCH 01/10] Support MSVC lvalue to temporary reference binding

---
 clang/docs/ReleaseNotes.rst                 |   4 +
 clang/include/clang/Basic/LangOptions.def   |   1 +
 clang/include/clang/Driver/Options.td       |  12 +++
 clang/include/clang/Sema/Sema.h             |   2 +
 clang/lib/Driver/ToolChains/Clang.cpp       |   5 +
 clang/lib/Driver/ToolChains/MSVC.cpp        |   1 +
 clang/lib/Sema/SemaInit.cpp                 |  22 +++--
 clang/lib/Sema/SemaOverload.cpp             |  16 ++-
 clang/test/Driver/cl-permissive.c           |   7 ++
 clang/test/Driver/cl-zc.cpp                 |   2 +
 clang/test/SemaCXX/ms-reference-binding.cpp | 102 ++++++++++++++++++++
 11 files changed, 165 insertions(+), 9 deletions(-)
 create mode 100644 clang/test/SemaCXX/ms-reference-binding.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3c2e0282d1c72d..becf12fa62ec00 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -104,6 +104,10 @@ C23 Feature Support
 New Compiler Flags
 ------------------
 
+- ``-fms-reference-binding`` and its clang-cl counterpart 
``/Zc:referenceBinding``.
+  Implements the MSVC extension where expressions that bind a user-defined 
type temporary
+  to a non-const lvalue reference are allowed.
+
 Deprecated Compiler Flags
 -------------------------
 
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 0035092ce0d863..ff350410d598a0 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -307,6 +307,7 @@ LANGOPT(HIPStdParInterposeAlloc, 1, 0, "Replace allocations 
/ deallocations with
 LANGOPT(OpenACC           , 1, 0, "OpenACC Enabled")
 
 LANGOPT(MSVCEnableStdcMacro , 1, 0, "Define __STDC__ with 
'-fms-compatibility'")
+LANGOPT(MSVCReferenceBinding , 1, 0, "Accept expressions that bind a non-const 
lvalue reference to a temporary")
 LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
 LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
 LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are 
unavailable")
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8c56dbb51b28a..53a356d120e3a6 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3034,6 +3034,12 @@ def fms_extensions : Flag<["-"], "fms-extensions">, 
Group<f_Group>,
   Visibility<[ClangOption, CC1Option, CLOption]>,
   HelpText<"Accept some non-standard constructs supported by the Microsoft 
compiler">,
   MarshallingInfoFlag<LangOpts<"MicrosoftExt">>, 
ImpliedByAnyOf<[fms_compatibility.KeyPath]>;
+def fms_reference_binding : Flag<["-"], "fms-reference-binding">, 
Group<f_Group>,
+  Visibility<[ClangOption, CC1Option, CLOption]>,
+  HelpText<"Accept expressions that bind a non-const lvalue reference to a 
user-defined type temporary as supported by the Microsoft Compiler">,
+  MarshallingInfoFlag<LangOpts<"MSVCReferenceBinding">>;
+def fno_ms_reference_binding : Flag<["-"], "fno-ms-reference-binding">, 
Group<f_Group>,
+  Visibility<[ClangOption, CLOption]>;
 defm asm_blocks : BoolFOption<"asm-blocks",
   LangOpts<"AsmBlocks">, Default<fms_extensions.KeyPath>,
   PosFlag<SetTrue, [], [ClangOption, CC1Option]>,
@@ -8492,6 +8498,12 @@ def _SLASH_Zc_wchar_t : CLFlag<"Zc:wchar_t">,
   HelpText<"Enable C++ builtin type wchar_t (default)">;
 def _SLASH_Zc_wchar_t_ : CLFlag<"Zc:wchar_t-">,
   HelpText<"Disable C++ builtin type wchar_t">;
+def _SLASH_Zc_referenceBinding : CLFlag<"Zc:referenceBinding">,
+  HelpText<"Do not accept expressions that bind a non-const lvalue reference 
to a user-defined type temporary">,
+  Alias<fno_ms_reference_binding>;
+def _SLASH_Zc_referenceBinding_ : CLFlag<"Zc:referenceBinding-">,
+  HelpText<"Accept expressions that bind a non-const lvalue reference to a 
user-defined type temporary">,
+  Alias<fms_reference_binding>;
 def _SLASH_Z7 : CLFlag<"Z7">, Alias<g_Flag>,
   HelpText<"Enable CodeView debug information in object files">;
 def _SLASH_ZH_MD5 : CLFlag<"ZH:MD5">,
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2ec6367eccea01..6bd575d105675b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10161,6 +10161,8 @@ class Sema final : public SemaBase {
   CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2,
                                ReferenceConversions *Conv = nullptr);
 
+  bool AllowMSLValueReferenceBinding(Qualifiers Quals, QualType QT);
+
   /// AddOverloadCandidate - Adds the given function to the set of
   /// candidate functions, using the given function call arguments.  If
   /// @p SuppressUserConversions, then don't allow user-defined
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 843d68c85bc592..13867181b21c07 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7111,6 +7111,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
                    IsWindowsMSVC))
     CmdArgs.push_back("-fms-extensions");
 
+  // -fno-ms-reference-binding is the default.
+  if (Args.hasFlag(options::OPT_fms_reference_binding,
+                   options::OPT_fno_ms_reference_binding, false))
+    CmdArgs.push_back("-fms-reference-binding");
+
   // -fms-compatibility=0 is default.
   bool IsMSVCCompat = Args.hasFlag(
       options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility,
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp 
b/clang/lib/Driver/ToolChains/MSVC.cpp
index ca266e3e1d1d3c..63ec69647c364b 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -950,6 +950,7 @@ static void TranslatePermissive(Arg *A, 
llvm::opt::DerivedArgList &DAL,
                                 const OptTable &Opts) {
   DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_));
   DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names));
+  DAL.AddFlagArg(A, Opts.getOption(options::OPT_fms_reference_binding));
 }
 
 static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL,
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 90fd6df782f095..f31e6d4bed28c6 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5216,13 +5216,17 @@ static void TryReferenceInitializationCore(Sema &S,
       Sequence.SetOverloadFailure(
                         InitializationSequence::FK_ReferenceInitOverloadFailed,
                                   ConvOvlResult);
-    else if (!InitCategory.isLValue())
-      Sequence.SetFailed(
-          T1Quals.isAddressSpaceSupersetOf(T2Quals)
-              ? InitializationSequence::
-                    FK_NonConstLValueReferenceBindingToTemporary
-              : InitializationSequence::FK_ReferenceInitDropsQualifiers);
-    else {
+    else if (!InitCategory.isLValue()) {
+      if (T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
+        if (!S.getLangOpts().MSVCReferenceBinding ||
+            !S.AllowMSLValueReferenceBinding(T1Quals, T1))
+          Sequence.SetFailed(InitializationSequence::
+                                 FK_NonConstLValueReferenceBindingToTemporary);
+      } else {
+        Sequence.SetFailed(
+            InitializationSequence::FK_ReferenceInitDropsQualifiers);
+      }
+    } else {
       InitializationSequence::FailureKind FK;
       switch (RefRelationship) {
       case Sema::Ref_Compatible:
@@ -5248,7 +5252,9 @@ static void TryReferenceInitializationCore(Sema &S,
       }
       Sequence.SetFailed(FK);
     }
-    return;
+
+    if (Sequence.Failed())
+      return;
   }
 
   //    - If the initializer expression
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index c5f56ac62b458c..a02a1c4f03ee9e 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -4907,6 +4907,16 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
              : Ref_Incompatible;
 }
 
+bool Sema::AllowMSLValueReferenceBinding(Qualifiers Quals, QualType QT) {
+  if (Quals.hasVolatile())
+    return false;
+  if (Quals.hasConst())
+    return true;
+  if (QT->isBuiltinType() || QT->isArrayType())
+    return false;
+  return true;
+}
+
 /// Look for a user-defined conversion to a value reference-compatible
 ///        with DeclType. Return true if something definite is found.
 static bool
@@ -5139,7 +5149,11 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
   //     -- Otherwise, the reference shall be an lvalue reference to a
   //        non-volatile const type (i.e., cv1 shall be const), or the 
reference
   //        shall be an rvalue reference.
-  if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified())) {
+  const bool CanBindLValueRef =
+      !S.getLangOpts().MSVCReferenceBinding
+          ? (T1.isConstQualified() && !T1.isVolatileQualified())
+          : S.AllowMSLValueReferenceBinding(T1.getQualifiers(), T1);
+  if (!isRValRef && !CanBindLValueRef) {
     if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible)
       ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType);
     return ICS;
diff --git a/clang/test/Driver/cl-permissive.c 
b/clang/test/Driver/cl-permissive.c
index d88746d3a5517f..712bef71a43af1 100644
--- a/clang/test/Driver/cl-permissive.c
+++ b/clang/test/Driver/cl-permissive.c
@@ -3,9 +3,11 @@
 
 // RUN: %clang_cl /permissive -### -- %s 2>&1 | FileCheck 
-check-prefix=PERMISSIVE %s
 // PERMISSIVE: "-fno-operator-names"
+// PERMISSIVE: "-fms-reference-binding"
 // PERMISSIVE: "-fdelayed-template-parsing"
 // RUN: %clang_cl /permissive- -### -- %s 2>&1 | FileCheck 
-check-prefix=PERMISSIVE-MINUS %s
 // PERMISSIVE-MINUS-NOT: "-fno-operator-names"
+// PERMISSIVE-MINUS-NOT: "-fms-reference-binding"
 // PERMISSIVE-MINUS-NOT: "-fdelayed-template-parsing"
 
 // The switches set by permissive may then still be manually enabled or 
disabled
@@ -15,3 +17,8 @@
 // RUN: %clang_cl /permissive- /Zc:twoPhase- -### -- %s 2>&1 | FileCheck 
-check-prefix=PERMISSIVE-MINUS-OVERWRITE %s
 // PERMISSIVE-MINUS-OVERWRITE-NOT: "-fno-operator-names"
 // PERMISSIVE-MINUS-OVERWRITE: "-fdelayed-template-parsing"
+
+// RUN: %clang_cl /permissive -fno-ms-reference-binding -### -- %s 2>&1 | 
FileCheck -check-prefix=PERMISSIVE-OVERWRITE-REF-BINDING %s
+// PERMISSIVE-OVERWRITE-REF-BINDING-NOT: "-fms-reference-binding"
+// RUN: %clang_cl /permissive- -fms-reference-binding -### -- %s 2>&1 | 
FileCheck -check-prefix=PERMISSIVE-MINUS-OVERWRITE-REF-BINDING %s
+// PERMISSIVE-MINUS-OVERWRITE-REF-BINDING: "-fms-reference-binding"
diff --git a/clang/test/Driver/cl-zc.cpp b/clang/test/Driver/cl-zc.cpp
index c7cf5b1b6525be..862d7a6e649c6b 100644
--- a/clang/test/Driver/cl-zc.cpp
+++ b/clang/test/Driver/cl-zc.cpp
@@ -122,6 +122,8 @@
 // RUN: %clang_cl -c -### /Zc:char8_t- -- %s 2>&1 | FileCheck -check-prefix 
CHECK-CHAR8_T_ %s
 // CHECK-CHAR8_T_: "-fno-char8_t"
 
+// RUN: %clang_cl -c -### /Zc:referenceBinding- -- %s 2>&1 | FileCheck 
-check-prefix CHECK-REFERENCE_BINDING_ %s
+// CHECK-REFERENCE_BINDING_: "-fms-reference-binding"
 
 
 // These never warn, but don't have an effect yet.
diff --git a/clang/test/SemaCXX/ms-reference-binding.cpp 
b/clang/test/SemaCXX/ms-reference-binding.cpp
new file mode 100644
index 00000000000000..44e4723fd4fa3a
--- /dev/null
+++ b/clang/test/SemaCXX/ms-reference-binding.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-reference-binding %s
+
+struct A {};
+struct B : A {};
+
+B fB();
+A fA();
+
+A&& fARvalueRef();
+A(&&fARvalueRefArray())[1];
+void fARef(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&) {}
+
+  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));
+  fARef(B());
+
+  NS::fARef(A());
+  NS::fARef(static_cast<A&&>(a1));
+  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 });
+}

>From fb60ef9d43123c86835dae73809eab751f354119 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Sat, 20 Jul 2024 23:47:51 -0700
Subject: [PATCH 02/10] update description of lang opt

---
 clang/include/clang/Basic/LangOptions.def | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index ff350410d598a0..704510f67c6855 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -307,7 +307,7 @@ LANGOPT(HIPStdParInterposeAlloc, 1, 0, "Replace allocations 
/ deallocations with
 LANGOPT(OpenACC           , 1, 0, "OpenACC Enabled")
 
 LANGOPT(MSVCEnableStdcMacro , 1, 0, "Define __STDC__ with 
'-fms-compatibility'")
-LANGOPT(MSVCReferenceBinding , 1, 0, "Accept expressions that bind a non-const 
lvalue reference to a temporary")
+LANGOPT(MSVCReferenceBinding , 1, 0, "Accept expressions that bind a non-const 
lvalue reference to a user-defined type temporary")
 LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
 LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
 LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are 
unavailable")

>From e0462a2b0062795e99718385a2826efe0f25b962 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Mon, 22 Jul 2024 21:44:33 -0700
Subject: [PATCH 03/10] PR Feedback on SemaOverload.cpp if check variable
 scoping

---
 clang/lib/Sema/SemaOverload.cpp | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a02a1c4f03ee9e..cee6d7ff8375ce 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -5149,13 +5149,19 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
   //     -- Otherwise, the reference shall be an lvalue reference to a
   //        non-volatile const type (i.e., cv1 shall be const), or the 
reference
   //        shall be an rvalue reference.
-  const bool CanBindLValueRef =
-      !S.getLangOpts().MSVCReferenceBinding
-          ? (T1.isConstQualified() && !T1.isVolatileQualified())
-          : S.AllowMSLValueReferenceBinding(T1.getQualifiers(), T1);
+  if (!isRValRef) {
+    const bool CanBindLValueRef =
+        !S.getLangOpts().MSVCReferenceBinding
+            ? (T1.isConstQualified() && !T1.isVolatileQualified())
+            : S.AllowMSLValueReferenceBinding(T1.getQualifiers(), T1);
+    if (!CanBindLValueRef) {
+      if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible)
+        ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, 
DeclType);
+      return ICS;
+    }
+  }
+
   if (!isRValRef && !CanBindLValueRef) {
-    if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible)
-      ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType);
     return ICS;
   }
 

>From 7dbe845372540ce363fdf22fe1acf0186bf86afd Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Tue, 23 Jul 2024 20:40:06 -0700
Subject: [PATCH 04/10] Reorder logic around `AllowMSLValueReferenceBinding`

---
 clang/lib/Sema/SemaInit.cpp     |  3 +--
 clang/lib/Sema/SemaOverload.cpp | 26 ++++++--------------------
 2 files changed, 7 insertions(+), 22 deletions(-)

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index f31e6d4bed28c6..d03a8010fe940d 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5218,8 +5218,7 @@ static void TryReferenceInitializationCore(Sema &S,
                                   ConvOvlResult);
     else if (!InitCategory.isLValue()) {
       if (T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
-        if (!S.getLangOpts().MSVCReferenceBinding ||
-            !S.AllowMSLValueReferenceBinding(T1Quals, T1))
+        if (!S.AllowMSLValueReferenceBinding(T1Quals, T1))
           Sequence.SetFailed(InitializationSequence::
                                  FK_NonConstLValueReferenceBindingToTemporary);
       } else {
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index cee6d7ff8375ce..344ac653ff9976 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -4908,13 +4908,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
 }
 
 bool Sema::AllowMSLValueReferenceBinding(Qualifiers Quals, QualType QT) {
-  if (Quals.hasVolatile())
-    return false;
-  if (Quals.hasConst())
-    return true;
-  if (QT->isBuiltinType() || QT->isArrayType())
-    return false;
-  return true;
+  return getLangOpts().MSVCReferenceBinding &&
+         !(Quals.hasVolatile() || QT->isBuiltinType() || QT->isArrayType());
 }
 
 /// Look for a user-defined conversion to a value reference-compatible
@@ -5149,19 +5144,10 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
   //     -- Otherwise, the reference shall be an lvalue reference to a
   //        non-volatile const type (i.e., cv1 shall be const), or the 
reference
   //        shall be an rvalue reference.
-  if (!isRValRef) {
-    const bool CanBindLValueRef =
-        !S.getLangOpts().MSVCReferenceBinding
-            ? (T1.isConstQualified() && !T1.isVolatileQualified())
-            : S.AllowMSLValueReferenceBinding(T1.getQualifiers(), T1);
-    if (!CanBindLValueRef) {
-      if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible)
-        ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, 
DeclType);
-      return ICS;
-    }
-  }
-
-  if (!isRValRef && !CanBindLValueRef) {
+  if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified()) &&
+      !S.AllowMSLValueReferenceBinding(T1.getQualifiers(), T1)) {
+    if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible)
+      ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType);
     return ICS;
   }
 

>From 43d9c2ac844e9a407a5bc4dd5431e4ba4aec195d Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Mon, 29 Jul 2024 08:23:24 -0700
Subject: [PATCH 05/10] PR Feedback on ext warning

---
 clang/docs/LanguageExtensions.rst             | 28 +++++++++++++++++++
 clang/include/clang/Basic/DiagnosticGroups.td |  1 +
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 +++
 clang/lib/Sema/SemaInit.cpp                   |  6 +++-
 clang/test/SemaCXX/ms-reference-binding.cpp   | 18 +++++++++++-
 5 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index a747464582e77d..ef8f783151e09c 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -5821,3 +5821,31 @@ specify the starting offset to begin embedding from. The 
resources is treated
 as being empty if the specified offset is larger than the number of bytes in
 the resource. The offset will be applied *before* any ``limit`` parameters are
 applied.
+
+MSVC Extensions
+===============
+
+Clang supports a number of extensions inorder to imitate MSVC.
+Some of these extensions are behind ``-fms-compatibility`` and 
``-fms-extensions`` which
+are further described in :doc:`MSVCCompatibility`.
+
+MSVC Reference Binding
+----------------------
+
+.. code-block:: c++
+
+  struct A {};
+
+  A& a = A();
+
+Please see the `MSDN 
doc<https://learn.microsoft.com/en-us/cpp/build/reference/zc-referencebinding-enforce-reference-binding-rules>`_
 for more information on this non-conforming C++ extension.
+
+MSVC allows user-defined type temporaries to be bound to non-const lvalue 
references when `/permissive`
+or `/Zc:referenceBinding-` are given on the command line.
+
+The current default behavior as of MSVC 1940 is `/permissive`.
+As of Visual Studio 2017, `/permissive-` is the default for projects meaning 
C++ conformance is enforced when
+building with MSVC in Visual Studio.
+
+This MSVC extension can be enabled with ``-fms-reference-binding`` with the 
clang or cl driver.
+This MSVC extension can be enabled with ``/Zc:referenceBinding-`` with the cl 
driver.
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 19c3f1e0433496..eb38f89f040b5b 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1289,6 +1289,7 @@ def MicrosoftStaticAssert : 
DiagGroup<"microsoft-static-assert">;
 def MicrosoftInitFromPredefined : DiagGroup<"microsoft-init-from-predefined">;
 def MicrosoftStringLiteralFromPredefined : DiagGroup<
     "microsoft-string-literal-from-predefined">;
+def MicrosoftReferenceBinding : DiagGroup<"microsoft-reference-binding">;
 
 // Aliases.
 def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 581434d33c5c9a..c4849306ac960a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2430,6 +2430,10 @@ def note_explicit_ctor_deduction_guide_here : Note<
   "explicit %select{constructor|deduction guide}0 declared here">;
 def note_implicit_deduction_guide : Note<"implicit deduction guide declared as 
'%0'">;
 
+def ext_ms_lvalue_reference_binding : ExtWarn<
+  "binding a user-defined type temporary to a non-const lvalue is a "
+  "Microsoft extension">, InGroup<MicrosoftReferenceBinding>;
+
 // C++11 auto
 def warn_cxx98_compat_auto_type_specifier : Warning<
   "'auto' type specifier is incompatible with C++98">,
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index d03a8010fe940d..6cd1e8282e5308 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5218,9 +5218,13 @@ static void TryReferenceInitializationCore(Sema &S,
                                   ConvOvlResult);
     else if (!InitCategory.isLValue()) {
       if (T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
-        if (!S.AllowMSLValueReferenceBinding(T1Quals, T1))
+        if (S.AllowMSLValueReferenceBinding(T1Quals, T1)) {
+          S.Diag(DeclLoc, diag::ext_ms_lvalue_reference_binding)
+              << Initializer->getSourceRange();
+        } else {
           Sequence.SetFailed(InitializationSequence::
                                  FK_NonConstLValueReferenceBindingToTemporary);
+        }
       } else {
         Sequence.SetFailed(
             InitializationSequence::FK_ReferenceInitDropsQualifiers);
diff --git a/clang/test/SemaCXX/ms-reference-binding.cpp 
b/clang/test/SemaCXX/ms-reference-binding.cpp
index 44e4723fd4fa3a..91e25959a8754b 100644
--- a/clang/test/SemaCXX/ms-reference-binding.cpp
+++ b/clang/test/SemaCXX/ms-reference-binding.cpp
@@ -1,4 +1,18 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -fms-reference-binding %s
+// 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 test() {
+  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}}
+}
+
+#else
 
 struct A {};
 struct B : A {};
@@ -100,3 +114,5 @@ void test4() {
   fIntConstArray({ 1 });
   NS::fIntConstArray({ 1 });
 }
+
+#endif

>From d57340bd723440598d647284362515d0f18833b5 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Mon, 29 Jul 2024 08:25:39 -0700
Subject: [PATCH 06/10] quoting

---
 clang/docs/LanguageExtensions.rst | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index ef8f783151e09c..9ea95006b932b6 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -5840,11 +5840,11 @@ MSVC Reference Binding
 
 Please see the `MSDN 
doc<https://learn.microsoft.com/en-us/cpp/build/reference/zc-referencebinding-enforce-reference-binding-rules>`_
 for more information on this non-conforming C++ extension.
 
-MSVC allows user-defined type temporaries to be bound to non-const lvalue 
references when `/permissive`
-or `/Zc:referenceBinding-` are given on the command line.
+MSVC allows user-defined type temporaries to be bound to non-const lvalue 
references when ``/permissive``
+or ``/Zc:referenceBinding-`` are given on the command line.
 
-The current default behavior as of MSVC 1940 is `/permissive`.
-As of Visual Studio 2017, `/permissive-` is the default for projects meaning 
C++ conformance is enforced when
+The current default behavior as of MSVC 1940 is ``/permissive``.
+As of Visual Studio 2017, ``/permissive-`` is the default for projects meaning 
C++ conformance is enforced when
 building with MSVC in Visual Studio.
 
 This MSVC extension can be enabled with ``-fms-reference-binding`` with the 
clang or cl driver.

>From fa35cf773e5b73bafbd0ed4b7de669f37f20f4f1 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Mon, 29 Jul 2024 18:57:33 -0700
Subject: [PATCH 07/10] Fix doc build

---
 clang/docs/LanguageExtensions.rst | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 9ea95006b932b6..e823fe9ec100ca 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -5838,7 +5838,9 @@ MSVC Reference Binding
 
   A& a = A();
 
-Please see the `MSDN 
doc<https://learn.microsoft.com/en-us/cpp/build/reference/zc-referencebinding-enforce-reference-binding-rules>`_
 for more information on this non-conforming C++ extension.
+Please see the `MSDN doc
+<https://learn.microsoft.com/en-us/cpp/build/reference/zc-referencebinding-enforce-reference-binding-rules>`_
+for more information on this non-conforming C++ extension.
 
 MSVC allows user-defined type temporaries to be bound to non-const lvalue 
references when ``/permissive``
 or ``/Zc:referenceBinding-`` are given on the command line.

>From 5560da802ffdd5ddfe7356eda30cc16840beb65f Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Mon, 29 Jul 2024 21:41:52 -0700
Subject: [PATCH 08/10] Default ms reference binding to on unless C++20 similar
 to delayed-template-parsing

---
 clang/lib/Driver/ToolChains/Clang.cpp | 11 ++++++-----
 clang/lib/Driver/ToolChains/MSVC.cpp  |  1 +
 clang/test/Driver/cl-permissive.c     |  2 +-
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 13867181b21c07..05b7de4bea56ca 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7111,11 +7111,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
                    IsWindowsMSVC))
     CmdArgs.push_back("-fms-extensions");
 
-  // -fno-ms-reference-binding is the default.
-  if (Args.hasFlag(options::OPT_fms_reference_binding,
-                   options::OPT_fno_ms_reference_binding, false))
-    CmdArgs.push_back("-fms-reference-binding");
-
   // -fms-compatibility=0 is default.
   bool IsMSVCCompat = Args.hasFlag(
       options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility,
@@ -7277,6 +7272,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     CmdArgs.push_back("-fdelayed-template-parsing");
   }
 
+  // -fno-ms-reference-binding is the default.
+  if (Args.hasFlag(options::OPT_fms_reference_binding,
+                   options::OPT_fno_ms_reference_binding,
+                   IsWindowsMSVC && !HaveCxx20))
+    CmdArgs.push_back("-fms-reference-binding");
+
   if (Args.hasFlag(options::OPT_fpch_validate_input_files_content,
                    options::OPT_fno_pch_validate_input_files_content, false))
     CmdArgs.push_back("-fvalidate-ast-input-files-content");
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp 
b/clang/lib/Driver/ToolChains/MSVC.cpp
index 63ec69647c364b..897040e262e340 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -957,6 +957,7 @@ static void TranslatePermissiveMinus(Arg *A, 
llvm::opt::DerivedArgList &DAL,
                                      const OptTable &Opts) {
   DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase));
   DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names));
+  DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_ms_reference_binding));
 }
 
 llvm::opt::DerivedArgList *
diff --git a/clang/test/Driver/cl-permissive.c 
b/clang/test/Driver/cl-permissive.c
index 712bef71a43af1..e325fc02d0d50a 100644
--- a/clang/test/Driver/cl-permissive.c
+++ b/clang/test/Driver/cl-permissive.c
@@ -3,8 +3,8 @@
 
 // RUN: %clang_cl /permissive -### -- %s 2>&1 | FileCheck 
-check-prefix=PERMISSIVE %s
 // PERMISSIVE: "-fno-operator-names"
-// PERMISSIVE: "-fms-reference-binding"
 // PERMISSIVE: "-fdelayed-template-parsing"
+// PERMISSIVE: "-fms-reference-binding"
 // RUN: %clang_cl /permissive- -### -- %s 2>&1 | FileCheck 
-check-prefix=PERMISSIVE-MINUS %s
 // PERMISSIVE-MINUS-NOT: "-fno-operator-names"
 // PERMISSIVE-MINUS-NOT: "-fms-reference-binding"

>From 2d082c1eba3fb593aa1700bedadf99f9aed37eb9 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Tue, 30 Jul 2024 20:07:47 -0700
Subject: [PATCH 09/10] remove old comment

---
 clang/lib/Driver/ToolChains/Clang.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 05b7de4bea56ca..37106ceab94699 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7272,7 +7272,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     CmdArgs.push_back("-fdelayed-template-parsing");
   }
 
-  // -fno-ms-reference-binding is the default.
   if (Args.hasFlag(options::OPT_fms_reference_binding,
                    options::OPT_fno_ms_reference_binding,
                    IsWindowsMSVC && !HaveCxx20))

>From af0f9b42b7e56a11447de081fcca6b88f9f0f0c2 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.wink...@gmail.com>
Date: Wed, 31 Jul 2024 21:26:29 -0700
Subject: [PATCH 10/10] Fix overload resolution and only consider msvc binding
 if we are an rvalue

---
 clang/lib/Sema/SemaOverload.cpp               | 32 ++++++++++++++---
 .../test/CodeGenCXX/ms-reference-binding.cpp  | 30 ++++++++++++++++
 clang/test/SemaCXX/ms-reference-binding.cpp   | 35 ++++++++++++++++++-
 3 files changed, 91 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/ms-reference-binding.cpp

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 344ac653ff9976..5939b56af7e1cf 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -4446,6 +4446,24 @@ CompareStandardConversionSequences(Sema &S, 
SourceLocation Loc,
         T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
       if (isa<ArrayType>(T2) && T2Quals)
         T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
+
+      if (S.getLangOpts().MSVCReferenceBinding &&
+          S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType()) &&
+          !SCS1.getFromType().hasQualifiers() && SCS1.BindsToRvalue &&
+          SCS2.BindsToRvalue) {
+
+        // When binding a user-defined type temporary to an lvalue MSVC will
+        // pick `const T&` over `T&` when binding an unqualified `T&&`.
+        // Therefore we want to pick the more qualified const overload in this
+        // specific case.
+        if (!T2.hasQualifiers() &&
+            (T1.isConstQualified() && !T1.isVolatileQualified()))
+          return ImplicitConversionSequence::Better;
+        if (!T1.hasQualifiers() &&
+            (T2.isConstQualified() && !T2.isVolatileQualified()))
+          return ImplicitConversionSequence::Worse;
+      }
+
       if (T2.isMoreQualifiedThan(T1))
         return ImplicitConversionSequence::Better;
       if (T1.isMoreQualifiedThan(T2))
@@ -5144,11 +5162,15 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
   //     -- Otherwise, the reference shall be an lvalue reference to a
   //        non-volatile const type (i.e., cv1 shall be const), or the 
reference
   //        shall be an rvalue reference.
-  if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified()) &&
-      !S.AllowMSLValueReferenceBinding(T1.getQualifiers(), T1)) {
-    if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible)
-      ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType);
-    return ICS;
+  if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified())) {
+    if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible) {
+      if (!S.AllowMSLValueReferenceBinding(T1.getQualifiers(), T1)) {
+        ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, 
DeclType);
+        return ICS;
+      }
+    } else {
+      return ICS;
+    }
   }
 
   //       -- If the initializer expression
diff --git a/clang/test/CodeGenCXX/ms-reference-binding.cpp 
b/clang/test/CodeGenCXX/ms-reference-binding.cpp
new file mode 100644
index 00000000000000..6f8ca371914222
--- /dev/null
+++ b/clang/test/CodeGenCXX/ms-reference-binding.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc %s -emit-llvm -fms-extensions 
-fms-compatibility -fms-reference-binding -o - | FileCheck %s
+
+struct A {};
+struct B : A {};
+
+void fAPickConstRef(A&) {}
+void fAPickConstRef(const A&) {}
+
+void fBPickConstRef(A&) {}
+void fBPickConstRef(const A&) {}
+
+void fAPickRef(A&) {}
+void fAPickRef(const volatile A&) {}
+
+void fAPickRef2(A&) {}
+void fAPickRef2(const volatile A&) {}
+
+void test() {
+  fAPickConstRef(A());
+  // CHECK: call {{.*}} @"?fAPickConstRef@@YAXAEBUA@@@Z"
+
+  fBPickConstRef(B());
+  // CHECK: call {{.*}} @"?fBPickConstRef@@YAXAEBUA@@@Z"
+
+  fAPickRef(A());
+  // CHECK: call {{.*}} @"?fAPickRef@@YAXAEAUA@@@Z"
+
+  fAPickRef2(A());
+  // CHECK: call {{.*}} @"?fAPickRef2@@YAXAEAUA@@@Z"
+}
diff --git a/clang/test/SemaCXX/ms-reference-binding.cpp 
b/clang/test/SemaCXX/ms-reference-binding.cpp
index 91e25959a8754b..27201ef2bf63b7 100644
--- a/clang/test/SemaCXX/ms-reference-binding.cpp
+++ b/clang/test/SemaCXX/ms-reference-binding.cpp
@@ -6,12 +6,28 @@
 struct A {};
 void fARef(A&) {}
 
-void test() {
+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@+2 {{candidate function not viable: 1st argument ('const A') 
would lose const qualifier}}
+// expected-note@+1 {{candidate function not viable: 1st argument ('const A') 
would lose const qualifier}}
+void fARefLoseConstQualifier(A&) {}
+
+void test2() {
+  // This should not warn since `fARef2(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 {};
@@ -22,8 +38,13 @@ A fA();
 
 A&& fARvalueRef();
 A(&&fARvalueRefArray())[1];
+
 void fARef(A&) {}
 
+// expected-note@+2 {{candidate function not viable: expects an lvalue for 1st 
argument}}
+// expected-note@+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}}
 
@@ -36,6 +57,10 @@ void fIntConstArray(const int (&)[1]);
 namespace NS {
   void fARef(A&) {}
 
+  // expected-note@+2 {{passing argument to parameter here}}
+  // expected-note@+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}}
 
@@ -87,10 +112,18 @@ void test3() {
 
   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();

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to