Skip to content

Commit

Permalink
Revert "[Clang] Add captures to the instantiation scope of lambda cal…
Browse files Browse the repository at this point in the history
…l operators"

The change causes some libcxx regressions

This reverts commit eaf725b.
  • Loading branch information
cor3ntin committed Sep 7, 2023
1 parent edae8f6 commit 98062d8
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 95 deletions.
5 changes: 0 additions & 5 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,6 @@ 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.
Expand Down
8 changes: 0 additions & 8 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -7352,14 +7352,6 @@ class Sema final {

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
Expand Down
37 changes: 32 additions & 5 deletions clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,11 @@ 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;
Expand All @@ -624,6 +629,11 @@ 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;
Expand Down Expand Up @@ -702,8 +712,20 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
}
CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);

LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
*this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope);
// 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,
Expand Down Expand Up @@ -891,10 +913,15 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
ThisQuals = Method->getMethodQualifiers();
Record = Method->getParent();
}

CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
*this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
FunctionScopeRAII FuncScope(*this);

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,
Expand Down
4 changes: 0 additions & 4 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15380,10 +15380,6 @@ 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)
Expand Down
32 changes: 0 additions & 32 deletions clang/lib/Sema/SemaLambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#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;
Expand Down Expand Up @@ -2255,34 +2254,3 @@ 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));
}
3 changes: 0 additions & 3 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2426,9 +2426,6 @@ 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;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -12325,7 +12325,7 @@ TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
QualType T = getDerived().TransformType(E->getType());
QualType T = getSema().getCurrentThisType();

if (!getDerived().AlwaysRebuild() && T == E->getType()) {
// Mark it referenced in the new context regardless.
Expand Down
37 changes: 0 additions & 37 deletions clang/test/SemaCXX/lambda-capture-type-deduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,40 +260,3 @@ 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);
}

}

0 comments on commit 98062d8

Please sign in to comment.