diff --git a/contrib/llvm-project/clang/include/clang/Sema/Sema.h b/contrib/llvm-project/clang/include/clang/Sema/Sema.h index 3752a23faa85..28a5f17d0dd5 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Sema.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Sema.h @@ -7315,6 +7315,16 @@ class Sema final { CXXConversionDecl *Conv, Expr *Src); + 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 a/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp b/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp index f24b549dd2ef..d1fa8e783122 100755 --- a/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp +++ b/contrib/llvm-project/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(Function)->isConst()) { - QualType T = CapturedVar->getType(); - T.addConst(); - CapturedVar->setType(T); - } if (CapturedVar->isInitCapture()) Scope.InstantiatedLocal(CapturedPattern, CapturedVar); }; @@ -603,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; @@ -632,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; @@ -714,6 +701,10 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, Record = const_cast(Method->getParent()); } CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); + + LambdaScopeForCallOperatorInstantiationRAII LambdaScope( + *this, const_cast(FD), *MLTAL, Scope); + return CheckConstraintSatisfaction( FD, {FD->getTrailingRequiresClause()}, *MLTAL, SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), @@ -900,12 +891,10 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints( ThisQuals = Method->getMethodQualifiers(); Record = Method->getParent(); } + CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); - FunctionScopeRAII FuncScope(*this); - if (isLambdaCallOperator(Decl)) - PushLambdaScope(); - else - FuncScope.disable(); + LambdaScopeForCallOperatorInstantiationRAII LambdaScope( + *this, const_cast(Decl), *MLTAL, Scope); llvm::SmallVector Converted; return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL, diff --git a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp index 21b5781a71cd..fab2865ec5a1 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp @@ -15172,14 +15172,17 @@ 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(); + // 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) @@ -15200,7 +15203,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(), @@ -15217,6 +15220,7 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, } ++I; } + return LSI; } Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, @@ -15320,7 +15324,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(D), *this); + RebuildLambdaScopeInfo(cast(D)); } else { // Enter a new function scope PushFunctionScope(); diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp index 3a5e302cc03a..63b00d640a9c 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp @@ -19619,13 +19619,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(Var); - Parm && Parm->getDeclContext() == DC) - return true; - // Only block literals, captured statements, and lambda expressions can // capture; other scopes don't work. DeclContext *ParentDC = @@ -19653,6 +19646,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(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 a/contrib/llvm-project/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm-project/clang/lib/Sema/SemaLambda.cpp index 06fc53591a76..ccc5111d1e31 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaLambda.cpp +++ b/contrib/llvm-project/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 using namespace clang; @@ -2222,3 +2223,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(FD)); +} diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f78d46f59503..332004055b58 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2426,6 +2426,9 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( cast(Owner)->isDefinedOutsideFunctionOrMethod()); LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); + Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope( + SemaRef, const_cast(D), TemplateArgs, Scope); + // Instantiate enclosing template arguments for friends. SmallVector TempParamLists; unsigned NumTempParamLists = 0; diff --git a/contrib/llvm-project/clang/lib/Sema/TreeTransform.h b/contrib/llvm-project/clang/lib/Sema/TreeTransform.h index 097e81ea7d45..b51741d5e8b2 100644 --- a/contrib/llvm-project/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm-project/clang/lib/Sema/TreeTransform.h @@ -12285,7 +12285,16 @@ TreeTransform::TransformCXXNullPtrLiteralExpr( template ExprResult TreeTransform::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.