Skip to content

Commit 2f95a8f

Browse files
Refactor and fix Lambda prototype instantiation when it's attributed or macro qualified
1 parent d3cd1ce commit 2f95a8f

File tree

3 files changed

+56
-49
lines changed

3 files changed

+56
-49
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

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

21872196
ParmVarDecl *TemplateInstantiator::TransformFunctionTypeParam(

clang/lib/Sema/TreeTransform.h

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13636,58 +13636,42 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1363613636
// The transformation MUST be done in the CurrentInstantiationScope since
1363713637
// it introduces a mapping of the original to the newly created
1363813638
// transformed parameters.
13639-
TypeSourceInfo *NewCallOpTSI = nullptr;
13640-
{
13641-
auto OldCallOpTypeLoc =
13642-
E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
13643-
13644-
auto TransformFunctionProtoTypeLoc =
13645-
[this](TypeLocBuilder &TLB, FunctionProtoTypeLoc FPTL) -> QualType {
13646-
SmallVector<QualType, 4> ExceptionStorage;
13647-
return this->TransformFunctionProtoType(
13648-
TLB, FPTL, nullptr, Qualifiers(),
13649-
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
13650-
return TransformExceptionSpec(FPTL.getBeginLoc(), ESI,
13651-
ExceptionStorage, Changed);
13652-
});
13653-
};
13639+
auto OldCallOpTypeLoc =
13640+
E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
1365413641

13655-
QualType NewCallOpType;
13656-
TypeLocBuilder NewCallOpTLBuilder;
13642+
TypeLocBuilder NewCallOpTLBuilder;
13643+
QualType NewCallOpType =
13644+
getDerived().TransformType(NewCallOpTLBuilder, OldCallOpTypeLoc);
1365713645

13658-
if (auto ATL = OldCallOpTypeLoc.getAs<AttributedTypeLoc>()) {
13659-
NewCallOpType = this->TransformAttributedType(
13660-
NewCallOpTLBuilder, ATL,
13661-
[&](TypeLocBuilder &TLB, TypeLoc TL) -> QualType {
13662-
return TransformFunctionProtoTypeLoc(
13663-
TLB, TL.castAs<FunctionProtoTypeLoc>());
13664-
});
13665-
} else {
13666-
auto FPTL = OldCallOpTypeLoc.castAs<FunctionProtoTypeLoc>();
13667-
NewCallOpType = TransformFunctionProtoTypeLoc(NewCallOpTLBuilder, FPTL);
13668-
}
13669-
13670-
if (NewCallOpType.isNull())
13671-
return ExprError();
13672-
NewCallOpTSI =
13673-
NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
13674-
}
13646+
if (NewCallOpType.isNull())
13647+
return ExprError();
1367513648

13676-
ArrayRef<ParmVarDecl *> Params;
13677-
if (auto ATL = NewCallOpTSI->getTypeLoc().getAs<AttributedTypeLoc>()) {
13678-
Params = ATL.getModifiedLoc().castAs<FunctionProtoTypeLoc>().getParams();
13679-
} else {
13680-
auto FPTL = NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
13681-
Params = FPTL.getParams();
13682-
}
13649+
TypeSourceInfo *NewCallOpTSI =
13650+
NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
13651+
13652+
auto ExtractParams = [](TypeLoc TL) {
13653+
auto ExtractParamsImpl = [](auto Self,
13654+
TypeLoc TL) -> ArrayRef<ParmVarDecl *> {
13655+
if (auto FPTL = TL.getAs<FunctionProtoTypeLoc>()) {
13656+
return FPTL.getParams();
13657+
} else if (auto ATL = TL.getAs<AttributedTypeLoc>()) {
13658+
return Self(Self, ATL.getModifiedLoc());
13659+
} else if (auto MQTL = TL.getAs<MacroQualifiedTypeLoc>()) {
13660+
return Self(Self, MQTL.getInnerLoc());
13661+
} else {
13662+
llvm_unreachable("Unhandled TypeLoc");
13663+
}
13664+
};
13665+
return ExtractParamsImpl(ExtractParamsImpl, TL);
13666+
};
1368313667

1368413668
getSema().CompleteLambdaCallOperator(
1368513669
NewCallOperator, E->getCallOperator()->getLocation(),
1368613670
E->getCallOperator()->getInnerLocStart(),
1368713671
E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI,
1368813672
E->getCallOperator()->getConstexprKind(),
13689-
E->getCallOperator()->getStorageClass(), Params,
13690-
E->hasExplicitResultType());
13673+
E->getCallOperator()->getStorageClass(),
13674+
ExtractParams(NewCallOpTSI->getTypeLoc()), E->hasExplicitResultType());
1369113675

1369213676
getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
1369313677
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)