git: 6d4bc09d9ce4 - main - devel/llvm17: merge upstream llvm fixes

From: Brooks Davis <brooks_at_FreeBSD.org>
Date: Mon, 11 Dec 2023 17:42:36 UTC
The branch main has been updated by brooks:

URL: https://cgit.FreeBSD.org/ports/commit/?id=6d4bc09d9ce42807965de65e0b0739b6308d96b3

commit 6d4bc09d9ce42807965de65e0b0739b6308d96b3
Author:     Brooks Davis <brooks@FreeBSD.org>
AuthorDate: 2023-12-08 23:58:56 +0000
Commit:     Brooks Davis <brooks@FreeBSD.org>
CommitDate: 2023-12-11 17:42:26 +0000

    devel/llvm17: merge upstream llvm fixes
    
    These fixes were merged to the base LLVM compiler:
      158f4f30adb4 [Clang] Do not change the type of captured vars when checking lambda constraints
      3ed9e9e3ace6 [Clang] Add captures to the instantiation scope of lambda call operators
---
 devel/llvm17/Makefile                          |   2 +-
 devel/llvm17/files/patch-backport-158f4f30adb4 | 211 +++++++++++++++
 devel/llvm17/files/patch-backport-3ed9e9e3ace6 | 342 +++++++++++++++++++++++++
 3 files changed, 554 insertions(+), 1 deletion(-)

diff --git a/devel/llvm17/Makefile b/devel/llvm17/Makefile
index b3b68f775d0f..914dc58793b4 100644
--- a/devel/llvm17/Makefile
+++ b/devel/llvm17/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	llvm
 DISTVERSION=	17.0.6
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	devel lang
 MASTER_SITES=	https://github.com/llvm/llvm-project/releases/download/llvmorg-${DISTVERSION:S/rc/-rc/}/ \
 		https://${PRE_}releases.llvm.org/${LLVM_RELEASE}${RCDIR}/
diff --git a/devel/llvm17/files/patch-backport-158f4f30adb4 b/devel/llvm17/files/patch-backport-158f4f30adb4
new file mode 100644
index 000000000000..c7b31bdab7e6
--- /dev/null
+++ b/devel/llvm17/files/patch-backport-158f4f30adb4
@@ -0,0 +1,211 @@
+commit 158f4f30adb4bfd390057742a32934e4344e8fd3
+Author: Corentin Jabot <corentinjabot@gmail.com>
+Date:   Mon Aug 21 18:07:43 2023 +0200
+
+    [Clang] Do not change the type of captured vars when checking lambda constraints
+    
+    When checking the constraint of a lambda, we need to respect the constness
+    of the call operator when establishing the type of capture variables.
+    
+    In D124351, this was done by adding const to the captured variable...
+    However, that would change the type of the variable outside of the scope
+    of the lambda, which is clearly not the desired outcome.
+    
+    Instead, to ensure const-correctness, we need to populate
+    a LambdaScopeInfo with the capture variables before checking the
+    constraints of a generic lambda.
+    
+    There is no changelog as I'd like to tentatively propose we backport
+    this change to RC3 as it is a regression introduced in the Clang 17
+    cycle.
+    
+    Fixes #61267
+    
+    Reviewed By: aaron.ballman, #clang-language-wg
+    
+    Differential Revision: https://reviews.llvm.org/D158433
+
+diff --git clang/include/clang/Sema/Sema.h clang/include/clang/Sema/Sema.h
+index c992e8763057..807a52886ccb 100644
+--- clang/include/clang/Sema/Sema.h
++++ clang/include/clang/Sema/Sema.h
+@@ -7343,6 +7343,8 @@ public:
+                                            CXXConversionDecl *Conv,
+                                            Expr *Src);
+ 
++  sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator);
++
+   /// Check whether the given expression is a valid constraint expression.
+   /// A diagnostic is emitted if it is not, false is returned, and
+   /// PossibleNonPrimary will be set to true if the failure might be due to a
+diff --git clang/lib/Sema/SemaConcept.cpp clang/lib/Sema/SemaConcept.cpp
+index f24b549dd2ef..fa3dadf68229 100644
+--- clang/lib/Sema/SemaConcept.cpp
++++ clang/lib/Sema/SemaConcept.cpp
+@@ -13,12 +13,14 @@
+ #include "clang/Sema/SemaConcept.h"
+ #include "TreeTransform.h"
+ #include "clang/AST/ASTLambda.h"
++#include "clang/AST/DeclCXX.h"
+ #include "clang/AST/ExprConcepts.h"
+ #include "clang/AST/RecursiveASTVisitor.h"
+ #include "clang/Basic/OperatorPrecedence.h"
+ #include "clang/Sema/EnterExpressionEvaluationContext.h"
+ #include "clang/Sema/Initialization.h"
+ #include "clang/Sema/Overload.h"
++#include "clang/Sema/ScopeInfo.h"
+ #include "clang/Sema/Sema.h"
+ #include "clang/Sema/SemaDiagnostic.h"
+ #include "clang/Sema/SemaInternal.h"
+@@ -540,11 +542,6 @@ bool Sema::addInstantiatedCapturesToScope(
+   auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
+                               unsigned Index) {
+     ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
+-    if (cast<CXXMethodDecl>(Function)->isConst()) {
+-      QualType T = CapturedVar->getType();
+-      T.addConst();
+-      CapturedVar->setType(T);
+-    }
+     if (CapturedVar->isInitCapture())
+       Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
+   };
+@@ -714,6 +711,22 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
+     Record = const_cast<CXXRecordDecl *>(Method->getParent());
+   }
+   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
++
++  // When checking the constraints of a lambda, we need to restore a
++  // LambdaScopeInfo populated with correct capture information so that the type
++  // of a variable referring to a capture is correctly const-adjusted.
++  FunctionScopeRAII FuncScope(*this);
++  if (isLambdaCallOperator(FD)) {
++    LambdaScopeInfo *LSI = RebuildLambdaScopeInfo(
++        const_cast<CXXMethodDecl *>(cast<CXXMethodDecl>(FD)));
++    // Constraints are checked from the parent context of the lambda, so we set
++    // AfterParameterList to false, so that `tryCaptureVariable` finds
++    // explicit captures in the appropriate context.
++    LSI->AfterParameterList = false;
++  } else {
++    FuncScope.disable();
++  }
++
+   return CheckConstraintSatisfaction(
+       FD, {FD->getTrailingRequiresClause()}, *MLTAL,
+       SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
+@@ -902,10 +915,13 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
+   }
+   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
+   FunctionScopeRAII FuncScope(*this);
+-  if (isLambdaCallOperator(Decl))
+-    PushLambdaScope();
+-  else
++
++  if (isLambdaCallOperator(Decl)) {
++    LambdaScopeInfo *LSI = RebuildLambdaScopeInfo(cast<CXXMethodDecl>(Decl));
++    LSI->AfterParameterList = false;
++  } else {
+     FuncScope.disable();
++  }
+ 
+   llvm::SmallVector<Expr *, 1> Converted;
+   return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
+diff --git clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDecl.cpp
+index 3925e2a7f338..0d5f696bf040 100644
+--- clang/lib/Sema/SemaDecl.cpp
++++ clang/lib/Sema/SemaDecl.cpp
+@@ -15289,11 +15289,10 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
+   FD->setInvalidDecl();
+ }
+ 
+-static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
+-                                   Sema &S) {
+-  CXXRecordDecl *const LambdaClass = CallOperator->getParent();
++LambdaScopeInfo *Sema::RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator) {
++  CXXRecordDecl *LambdaClass = CallOperator->getParent();
+ 
+-  LambdaScopeInfo *LSI = S.PushLambdaScope();
++  LambdaScopeInfo *LSI = PushLambdaScope();
+   LSI->CallOperator = CallOperator;
+   LSI->Lambda = LambdaClass;
+   LSI->ReturnType = CallOperator->getReturnType();
+@@ -15317,7 +15316,7 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
+     if (C.capturesVariable()) {
+       ValueDecl *VD = C.getCapturedVar();
+       if (VD->isInitCapture())
+-        S.CurrentInstantiationScope->InstantiatedLocal(VD, VD);
++        CurrentInstantiationScope->InstantiatedLocal(VD, VD);
+       const bool ByRef = C.getCaptureKind() == LCK_ByRef;
+       LSI->addCapture(VD, /*IsBlock*/false, ByRef,
+           /*RefersToEnclosingVariableOrCapture*/true, C.getLocation(),
+@@ -15334,6 +15333,7 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
+     }
+     ++I;
+   }
++  return LSI;
+ }
+ 
+ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
+@@ -15437,7 +15437,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
+     assert(inTemplateInstantiation() &&
+            "There should be an active template instantiation on the stack "
+            "when instantiating a generic lambda!");
+-    RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D), *this);
++    RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D));
+   } else {
+     // Enter a new function scope
+     PushFunctionScope();
+diff --git clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaExpr.cpp
+index 34284a8d9381..ac6c3ba6b357 100644
+--- clang/lib/Sema/SemaExpr.cpp
++++ clang/lib/Sema/SemaExpr.cpp
+@@ -19722,13 +19722,6 @@ bool Sema::tryCaptureVariable(
+         FunctionScopesIndex == MaxFunctionScopesIndex && VarDC == DC)
+       return true;
+ 
+-    // When evaluating some attributes (like enable_if) we might refer to a
+-    // function parameter appertaining to the same declaration as that
+-    // attribute.
+-    if (const auto *Parm = dyn_cast<ParmVarDecl>(Var);
+-        Parm && Parm->getDeclContext() == DC)
+-      return true;
+-
+     // Only block literals, captured statements, and lambda expressions can
+     // capture; other scopes don't work.
+     DeclContext *ParentDC =
+@@ -19756,6 +19749,14 @@ bool Sema::tryCaptureVariable(
+       CSI->getCapture(Var).markUsed(BuildAndDiagnose);
+       break;
+     }
++
++    // When evaluating some attributes (like enable_if) we might refer to a
++    // function parameter appertaining to the same declaration as that
++    // attribute.
++    if (const auto *Parm = dyn_cast<ParmVarDecl>(Var);
++        Parm && Parm->getDeclContext() == DC)
++      return true;
++
+     // If we are instantiating a generic lambda call operator body,
+     // we do not want to capture new variables.  What was captured
+     // during either a lambdas transformation or initial parsing
+diff --git clang/test/SemaCXX/lambda-capture-type-deduction.cpp clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+index e524d3bc20ab..9855122c9627 100644
+--- clang/test/SemaCXX/lambda-capture-type-deduction.cpp
++++ clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+@@ -246,3 +246,17 @@ void check_params_tpl() {
+     static_assert(is_same<int&, decltype((ap))>);
+   };
+ }
++
++namespace GH61267 {
++template <typename> concept C = true;
++
++template<typename>
++void f(int) {
++  int i;
++  [i]<C P>(P) {}(0);
++  i = 4;
++}
++
++void test() { f<int>(0);  }
++
++}
diff --git a/devel/llvm17/files/patch-backport-3ed9e9e3ace6 b/devel/llvm17/files/patch-backport-3ed9e9e3ace6
new file mode 100644
index 000000000000..420be920ab90
--- /dev/null
+++ b/devel/llvm17/files/patch-backport-3ed9e9e3ace6
@@ -0,0 +1,342 @@
+commit 3ed9e9e3ace6f9ce320cf4e75cffa04a7c7241b5
+Author: Corentin Jabot <corentinjabot@gmail.com>
+Date:   Tue Aug 29 19:53:19 2023 +0200
+
+    [Clang] Add captures to the instantiation scope of lambda call operators
+    
+    Like concepts checking, a trailing return type of a lambda
+    in a dependent context may refer to captures in which case
+    they may need to be rebuilt, so the map of local decl
+    should include captures.
+    
+    This patch reveal a pre-existing issue.
+    `this` is always recomputed by TreeTransform.
+    
+    `*this` (like all captures) only become `const`
+    after the parameter list.
+    
+    However, if try to recompute the value of `this` (in a parameter)
+    during template instantiation while determining the type of the call operator,
+    we will determine  it to be const (unless the lambda is mutable).
+    
+    There is no good way to know at that point that we are in a parameter
+    or not, the easiest/best solution is to transform the type of this.
+    
+    Note that doing so break a handful of HLSL tests.
+    So this is a prototype at this point.
+    
+    Fixes #65067
+    Fixes #63675
+    
+    Reviewed By: erichkeane
+    
+    Differential Revision: https://reviews.llvm.org/D159126
+
+diff --git clang/docs/ReleaseNotes.rst clang/docs/ReleaseNotes.rst
+index 2d0302c399fb..6a3a6bb8ad42 100644
+--- clang/docs/ReleaseNotes.rst
++++ clang/docs/ReleaseNotes.rst
+@@ -270,6 +270,11 @@ Bug Fixes to C++ Support
+ - Fix crash when parsing the requires clause of some generic lambdas.
+   (`#64689 <https://github.com/llvm/llvm-project/issues/64689>`_)
+ 
++- Fix crash when the trailing return type of a generic and dependent
++  lambda refers to an init-capture.
++  (`#65067 <https://github.com/llvm/llvm-project/issues/65067>`_` and
++   `#63675 <https://github.com/llvm/llvm-project/issues/63675>`_`)
++
+ Bug Fixes to AST Handling
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
+ - Fixed an import failure of recursive friend class template.
+diff --git clang/include/clang/Sema/Sema.h clang/include/clang/Sema/Sema.h
+index 1bb096c667e3..566655818a85 100644
+--- clang/include/clang/Sema/Sema.h
++++ clang/include/clang/Sema/Sema.h
+@@ -7365,6 +7365,14 @@ public:
+ 
+   sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator);
+ 
++  class LambdaScopeForCallOperatorInstantiationRAII
++      : private FunctionScopeRAII {
++  public:
++    LambdaScopeForCallOperatorInstantiationRAII(
++        Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
++        LocalInstantiationScope &Scope);
++  };
++
+   /// Check whether the given expression is a valid constraint expression.
+   /// A diagnostic is emitted if it is not, false is returned, and
+   /// PossibleNonPrimary will be set to true if the failure might be due to a
+diff --git clang/lib/Sema/SemaConcept.cpp clang/lib/Sema/SemaConcept.cpp
+index fa3dadf68229..d1fa8e783122 100644
+--- clang/lib/Sema/SemaConcept.cpp
++++ clang/lib/Sema/SemaConcept.cpp
+@@ -600,11 +600,6 @@ bool Sema::SetupConstraintScope(
+       if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
+                                            Scope, MLTAL))
+         return true;
+-      // Make sure the captures are also added to the instantiation scope.
+-      if (isLambdaCallOperator(FD) &&
+-          addInstantiatedCapturesToScope(FD, FromMemTempl->getTemplatedDecl(),
+-                                         Scope, MLTAL))
+-        return true;
+     }
+ 
+     return false;
+@@ -629,11 +624,6 @@ bool Sema::SetupConstraintScope(
+     // child-function.
+     if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
+       return true;
+-
+-    // Make sure the captures are also added to the instantiation scope.
+-    if (isLambdaCallOperator(FD) &&
+-        addInstantiatedCapturesToScope(FD, InstantiatedFrom, Scope, MLTAL))
+-      return true;
+   }
+ 
+   return false;
+@@ -712,20 +702,8 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
+   }
+   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
+ 
+-  // When checking the constraints of a lambda, we need to restore a
+-  // LambdaScopeInfo populated with correct capture information so that the type
+-  // of a variable referring to a capture is correctly const-adjusted.
+-  FunctionScopeRAII FuncScope(*this);
+-  if (isLambdaCallOperator(FD)) {
+-    LambdaScopeInfo *LSI = RebuildLambdaScopeInfo(
+-        const_cast<CXXMethodDecl *>(cast<CXXMethodDecl>(FD)));
+-    // Constraints are checked from the parent context of the lambda, so we set
+-    // AfterParameterList to false, so that `tryCaptureVariable` finds
+-    // explicit captures in the appropriate context.
+-    LSI->AfterParameterList = false;
+-  } else {
+-    FuncScope.disable();
+-  }
++  LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
++      *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope);
+ 
+   return CheckConstraintSatisfaction(
+       FD, {FD->getTrailingRequiresClause()}, *MLTAL,
+@@ -913,15 +891,10 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
+     ThisQuals = Method->getMethodQualifiers();
+     Record = Method->getParent();
+   }
+-  CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
+-  FunctionScopeRAII FuncScope(*this);
+ 
+-  if (isLambdaCallOperator(Decl)) {
+-    LambdaScopeInfo *LSI = RebuildLambdaScopeInfo(cast<CXXMethodDecl>(Decl));
+-    LSI->AfterParameterList = false;
+-  } else {
+-    FuncScope.disable();
+-  }
++  CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
++  LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
++      *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
+ 
+   llvm::SmallVector<Expr *, 1> Converted;
+   return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
+diff --git clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDecl.cpp
+index 027c6c3e4222..998060542609 100644
+--- clang/lib/Sema/SemaDecl.cpp
++++ clang/lib/Sema/SemaDecl.cpp
+@@ -15382,6 +15382,10 @@ LambdaScopeInfo *Sema::RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator) {
+   LSI->CallOperator = CallOperator;
+   LSI->Lambda = LambdaClass;
+   LSI->ReturnType = CallOperator->getReturnType();
++  // This function in calls in situation where the context of the call operator
++  // is not entered, so we set AfterParameterList to false, so that
++  // `tryCaptureVariable` finds explicit captures in the appropriate context.
++  LSI->AfterParameterList = false;
+   const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault();
+ 
+   if (LCD == LCD_None)
+diff --git clang/lib/Sema/SemaLambda.cpp clang/lib/Sema/SemaLambda.cpp
+index 5256d91a19a0..1702ddb3ee0f 100644
+--- clang/lib/Sema/SemaLambda.cpp
++++ clang/lib/Sema/SemaLambda.cpp
+@@ -20,6 +20,7 @@
+ #include "clang/Sema/ScopeInfo.h"
+ #include "clang/Sema/SemaInternal.h"
+ #include "clang/Sema/SemaLambda.h"
++#include "clang/Sema/Template.h"
+ #include "llvm/ADT/STLExtras.h"
+ #include <optional>
+ using namespace clang;
+@@ -2254,3 +2255,34 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
+ 
+   return BuildBlock;
+ }
++
++Sema::LambdaScopeForCallOperatorInstantiationRAII::
++    LambdaScopeForCallOperatorInstantiationRAII(
++        Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
++        LocalInstantiationScope &Scope)
++    : FunctionScopeRAII(SemasRef) {
++  if (!isLambdaCallOperator(FD)) {
++    FunctionScopeRAII::disable();
++    return;
++  }
++
++  if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
++    FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
++    if (const auto *FromMemTempl =
++            PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
++      SemasRef.addInstantiatedCapturesToScope(
++          FD, FromMemTempl->getTemplatedDecl(), Scope, MLTAL);
++    }
++  }
++
++  else if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
++           FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {
++    FunctionDecl *InstantiatedFrom =
++        FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization
++            ? FD->getInstantiatedFromMemberFunction()
++            : FD->getInstantiatedFromDecl();
++    SemasRef.addInstantiatedCapturesToScope(FD, InstantiatedFrom, Scope, MLTAL);
++  }
++
++  SemasRef.RebuildLambdaScopeInfo(cast<CXXMethodDecl>(FD));
++}
+diff --git clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+index 63f022d5c2ff..37a7d6204413 100644
+--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
++++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+@@ -2426,6 +2426,9 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
+       cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+   LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
+ 
++  Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
++      SemaRef, const_cast<CXXMethodDecl *>(D), TemplateArgs, Scope);
++
+   // Instantiate enclosing template arguments for friends.
+   SmallVector<TemplateParameterList *, 4> TempParamLists;
+   unsigned NumTempParamLists = 0;
+diff --git clang/lib/Sema/TreeTransform.h clang/lib/Sema/TreeTransform.h
+index 7323140bc336..603a23275889 100644
+--- clang/lib/Sema/TreeTransform.h
++++ clang/lib/Sema/TreeTransform.h
+@@ -12325,7 +12325,16 @@ TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
+ template<typename Derived>
+ ExprResult
+ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
+-  QualType T = getSema().getCurrentThisType();
++
++  // In lambdas, the qualifiers of the type depends of where in
++  // the call operator `this` appear, and we do not have a good way to
++  // rebuild this information, so we transform the type.
++  //
++  // In other contexts, the type of `this` may be overrided
++  // for type deduction, so we need to recompute it.
++  QualType T = getSema().getCurLambda() ?
++                   getDerived().TransformType(E->getType())
++                 : getSema().getCurrentThisType();
+ 
+   if (!getDerived().AlwaysRebuild() && T == E->getType()) {
+     // Mark it referenced in the new context regardless.
+diff --git clang/test/SemaCXX/lambda-capture-type-deduction.cpp clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+index 9855122c9627..7bf36a6a9cab 100644
+--- clang/test/SemaCXX/lambda-capture-type-deduction.cpp
++++ clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+@@ -260,3 +260,40 @@ void f(int) {
+ void test() { f<int>(0);  }
+ 
+ }
++
++namespace GH65067 {
++
++template <typename> class a {
++public:
++  template <typename b> void c(b f) { d<int>(f)(0); }
++  template <typename, typename b> auto d(b f) {
++    return [f = f](auto arg) -> a<decltype(f(arg))> { return {}; };
++  }
++};
++a<void> e;
++auto fn1() {
++  e.c([](int) {});
++}
++
++}
++
++namespace GH63675 {
++
++template <class _Tp> _Tp __declval();
++struct __get_tag {
++  template <class _Tag> void operator()(_Tag);
++};
++template <class _ImplFn> struct __basic_sender {
++  using __tag_t = decltype(__declval<_ImplFn>()(__declval<__get_tag>()));
++  _ImplFn __impl_;
++};
++auto __make_basic_sender = []<class... _Children>(
++                               _Children... __children) {
++  return __basic_sender{[... __children = __children]<class _Fun>(
++                     _Fun __fun) -> decltype(__fun(__children...)) {}};
++};
++void __trans_tmp_1() {
++  __make_basic_sender(__trans_tmp_1);
++}
++
++}
+diff --git clang/test/SemaCXX/this-type-deduction-concept.cpp clang/test/SemaCXX/this-type-deduction-concept.cpp
+new file mode 100644
+index 000000000000..a0c1f605ccef
+--- /dev/null
++++ clang/test/SemaCXX/this-type-deduction-concept.cpp
+@@ -0,0 +1,54 @@
++
++// This test case came up in the review of
++// https://reviews.llvm.org/D159126
++// when transforming `this` within a
++// requires expression, we need to make sure
++// the type of this (and its qualifiers) is respected.
++namespace D159126 {
++
++template <class _Tp>
++concept __member_begin = requires(_Tp __t) {
++  __t.begin();
++};
++
++struct {
++  template <class _Tp>
++  requires __member_begin<_Tp>
++  auto operator()(_Tp &&) {}
++} inline begin;
++
++template <class>
++concept range = requires {
++  begin;
++};
++
++template <class _Tp>
++concept __can_compare_begin = requires(_Tp __t) {
++  begin(__t);
++};
++
++struct {
++  template <__can_compare_begin _Tp> void operator()(_Tp &&);
++} empty;
++
++template <range _Rp> struct owning_view {
++  _Rp __r_;
++public:
++  void empty() const requires requires { empty(__r_); };
++};
++
++template <class T>
++concept HasEmpty = requires(T t) {
++  t.empty();
++};
++
++struct ComparableIters {
++    void begin();
++};
++
++static_assert(HasEmpty<owning_view<ComparableIters&>>);
++static_assert(HasEmpty<owning_view<ComparableIters&&>>);
++static_assert(!HasEmpty<owning_view<const ComparableIters&>>);
++static_assert(!HasEmpty<owning_view<const ComparableIters&&>>);
++
++}