Skip to content

Commit af67478

Browse files
Refactor and fix Lambda prototype instantiation when it's attributed or macro qualified
1 parent 2521e97 commit af67478

File tree

3 files changed

+56
-50
lines changed

3 files changed

+56
-50
lines changed

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,9 @@ namespace {
12031203
// Whether to evaluate the C++20 constraints or simply substitute into them.
12041204
bool EvaluateConstraints = true;
12051205

1206+
// Whether we are in the middle of transforming a lambda expression.
1207+
bool TransformingLambda = false;
1208+
12061209
public:
12071210
typedef TreeTransform<TemplateInstantiator> inherited;
12081211

@@ -1454,8 +1457,9 @@ namespace {
14541457
ExprResult TransformLambdaExpr(LambdaExpr *E) {
14551458
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
14561459
Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this);
1457-
1460+
TransformingLambda = true;
14581461
ExprResult Result = inherited::TransformLambdaExpr(E);
1462+
TransformingLambda = false;
14591463
if (Result.isInvalid())
14601464
return Result;
14611465

@@ -2180,10 +2184,15 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
21802184
CXXRecordDecl *ThisContext,
21812185
Qualifiers ThisTypeQuals,
21822186
Fn TransformExceptionSpec) {
2183-
// We need a local instantiation scope for this function prototype.
2184-
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
2185-
return inherited::TransformFunctionProtoType(
2186-
TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);
2187+
if (TransformingLambda)
2188+
return inherited::TransformFunctionProtoType(
2189+
TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);
2190+
else {
2191+
// We need a local instantiation scope for this function prototype.
2192+
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
2193+
return inherited::TransformFunctionProtoType(
2194+
TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);
2195+
}
21872196
}
21882197

21892198
ParmVarDecl *TemplateInstantiator::TransformFunctionTypeParam(

clang/lib/Sema/TreeTransform.h

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13629,59 +13629,42 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1362913629
// The transformation MUST be done in the CurrentInstantiationScope since
1363013630
// it introduces a mapping of the original to the newly created
1363113631
// transformed parameters.
13632-
TypeSourceInfo *NewCallOpTSI = nullptr;
13633-
{
13634-
auto OldCallOpTypeLoc =
13635-
E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
13636-
13637-
auto TransformFunctionProtoTypeLoc =
13638-
[this](TypeLocBuilder &TLB, FunctionProtoTypeLoc FPTL) -> QualType {
13639-
SmallVector<QualType, 4> ExceptionStorage;
13640-
TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
13641-
return this->TransformFunctionProtoType(
13642-
TLB, FPTL, nullptr, Qualifiers(),
13643-
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
13644-
return This->TransformExceptionSpec(FPTL.getBeginLoc(), ESI,
13645-
ExceptionStorage, Changed);
13646-
});
13647-
};
13632+
auto OldCallOpTypeLoc =
13633+
E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
1364813634

13649-
QualType NewCallOpType;
13650-
TypeLocBuilder NewCallOpTLBuilder;
13635+
TypeLocBuilder NewCallOpTLBuilder;
13636+
QualType NewCallOpType =
13637+
getDerived().TransformType(NewCallOpTLBuilder, OldCallOpTypeLoc);
1365113638

13652-
if (auto ATL = OldCallOpTypeLoc.getAs<AttributedTypeLoc>()) {
13653-
NewCallOpType = this->TransformAttributedType(
13654-
NewCallOpTLBuilder, ATL,
13655-
[&](TypeLocBuilder &TLB, TypeLoc TL) -> QualType {
13656-
return TransformFunctionProtoTypeLoc(
13657-
TLB, TL.castAs<FunctionProtoTypeLoc>());
13658-
});
13659-
} else {
13660-
auto FPTL = OldCallOpTypeLoc.castAs<FunctionProtoTypeLoc>();
13661-
NewCallOpType = TransformFunctionProtoTypeLoc(NewCallOpTLBuilder, FPTL);
13662-
}
13663-
13664-
if (NewCallOpType.isNull())
13665-
return ExprError();
13666-
NewCallOpTSI =
13667-
NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
13668-
}
13639+
if (NewCallOpType.isNull())
13640+
return ExprError();
1366913641

13670-
ArrayRef<ParmVarDecl *> Params;
13671-
if (auto ATL = NewCallOpTSI->getTypeLoc().getAs<AttributedTypeLoc>()) {
13672-
Params = ATL.getModifiedLoc().castAs<FunctionProtoTypeLoc>().getParams();
13673-
} else {
13674-
auto FPTL = NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
13675-
Params = FPTL.getParams();
13676-
}
13642+
TypeSourceInfo *NewCallOpTSI =
13643+
NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
13644+
13645+
auto ExtractParams = [](TypeLoc TL) {
13646+
auto ExtractParamsImpl = [](auto Self,
13647+
TypeLoc TL) -> ArrayRef<ParmVarDecl *> {
13648+
if (auto FPTL = TL.getAs<FunctionProtoTypeLoc>()) {
13649+
return FPTL.getParams();
13650+
} else if (auto ATL = TL.getAs<AttributedTypeLoc>()) {
13651+
return Self(Self, ATL.getModifiedLoc());
13652+
} else if (auto MQTL = TL.getAs<MacroQualifiedTypeLoc>()) {
13653+
return Self(Self, MQTL.getInnerLoc());
13654+
} else {
13655+
llvm_unreachable("Unhandled TypeLoc");
13656+
}
13657+
};
13658+
return ExtractParamsImpl(ExtractParamsImpl, TL);
13659+
};
1367713660

1367813661
getSema().CompleteLambdaCallOperator(
1367913662
NewCallOperator, E->getCallOperator()->getLocation(),
1368013663
E->getCallOperator()->getInnerLocStart(),
1368113664
E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI,
1368213665
E->getCallOperator()->getConstexprKind(),
13683-
E->getCallOperator()->getStorageClass(), Params,
13684-
E->hasExplicitResultType());
13666+
E->getCallOperator()->getStorageClass(),
13667+
ExtractParams(NewCallOpTSI->getTypeLoc()), E->hasExplicitResultType());
1368513668

1368613669
getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
1368713670
getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
1-
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -verify -fsyntax-only %s
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -ast-dump %s | FileCheck %s
22
// expected-no-diagnostics
33

44
namespace GH76521 {
55

6+
#define MYATTR __attribute__((preserve_most))
7+
68
template <typename T>
79
void foo() {
10+
// CHECK: FunctionDecl {{.*}} foo 'void ()'
811
auto l = []() __attribute__((preserve_most)) {};
12+
// CHECK: CXXMethodDecl {{.*}} operator() 'auto () __attribute__((preserve_most)) const' inline
13+
auto l2 = [](T t) __attribute__((preserve_most)) -> T { return t; };
14+
// CHECK: CXXMethodDecl {{.*}} operator() 'auto (int) const -> int __attribute__((preserve_most))':'auto (int) __attribute__((preserve_most)) const -> int' implicit_instantiation inline instantiated_fro
915
}
1016

17+
template <typename T>
1118
void bar() {
19+
// CHECK: FunctionDecl {{.*}} bar 'void ()'
20+
auto l = []() MYATTR {};
21+
// CHECK: CXXMethodDecl {{.*}} operator() 'auto () __attribute__((preserve_most)) const' inline
22+
}
23+
24+
int main() {
1225
foo<int>();
26+
bar<int>();
1327
}
1428

1529
}

0 commit comments

Comments
 (0)