Skip to content

Commit efc1fec

Browse files
Refactor and fix Lambda prototype instantiation when it's attributed or macro qualified
1 parent 94166c6 commit efc1fec

File tree

3 files changed

+60
-66
lines changed

3 files changed

+60
-66
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,7 +1457,7 @@ 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);
14591462
if (Result.isInvalid())
14601463
return Result;
@@ -2178,10 +2181,16 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
21782181
CXXRecordDecl *ThisContext,
21792182
Qualifiers ThisTypeQuals,
21802183
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);
2184+
if (TransformingLambda) {
2185+
TransformingLambda = false;
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: 31 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -674,10 +674,6 @@ class TreeTransform {
674674
Qualifiers ThisTypeQuals,
675675
Fn TransformExceptionSpec);
676676

677-
template <typename Fn>
678-
QualType TransformAttributedType(TypeLocBuilder &TLB, AttributedTypeLoc TL,
679-
Fn TransformModifiedType);
680-
681677
bool TransformExceptionSpec(SourceLocation Loc,
682678
FunctionProtoType::ExceptionSpecInfo &ESI,
683679
SmallVectorImpl<QualType> &Exceptions,
@@ -7182,11 +7178,11 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
71827178
}
71837179

71847180
template <typename Derived>
7185-
template <typename Fn>
7186-
QualType TreeTransform<Derived>::TransformAttributedType(
7187-
TypeLocBuilder &TLB, AttributedTypeLoc TL, Fn TransformModifiedTypeFn) {
7181+
QualType TreeTransform<Derived>::TransformAttributedType(TypeLocBuilder &TLB,
7182+
AttributedTypeLoc TL) {
7183+
71887184
const AttributedType *oldType = TL.getTypePtr();
7189-
QualType modifiedType = TransformModifiedTypeFn(TLB, TL.getModifiedLoc());
7185+
QualType modifiedType = getDerived().TransformType(TLB, TL.getModifiedLoc());
71907186
if (modifiedType.isNull())
71917187
return QualType();
71927188

@@ -7230,15 +7226,6 @@ QualType TreeTransform<Derived>::TransformAttributedType(
72307226
return result;
72317227
}
72327228

7233-
template <typename Derived>
7234-
QualType TreeTransform<Derived>::TransformAttributedType(TypeLocBuilder &TLB,
7235-
AttributedTypeLoc TL) {
7236-
return getDerived().TransformAttributedType(
7237-
TLB, TL, [&](TypeLocBuilder &TLB, TypeLoc ModifiedLoc) -> QualType {
7238-
return getDerived().TransformType(TLB, ModifiedLoc);
7239-
});
7240-
}
7241-
72427229
template <typename Derived>
72437230
QualType TreeTransform<Derived>::TransformBTFTagAttributedType(
72447231
TypeLocBuilder &TLB, BTFTagAttributedTypeLoc TL) {
@@ -13770,58 +13757,42 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1377013757
// The transformation MUST be done in the CurrentInstantiationScope since
1377113758
// it introduces a mapping of the original to the newly created
1377213759
// transformed parameters.
13773-
TypeSourceInfo *NewCallOpTSI = nullptr;
13774-
{
13775-
auto OldCallOpTypeLoc =
13776-
E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
13777-
13778-
auto TransformFunctionProtoTypeLoc =
13779-
[this](TypeLocBuilder &TLB, FunctionProtoTypeLoc FPTL) -> QualType {
13780-
SmallVector<QualType, 4> ExceptionStorage;
13781-
return this->TransformFunctionProtoType(
13782-
TLB, FPTL, nullptr, Qualifiers(),
13783-
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
13784-
return TransformExceptionSpec(FPTL.getBeginLoc(), ESI,
13785-
ExceptionStorage, Changed);
13786-
});
13787-
};
13760+
auto OldCallOpTypeLoc =
13761+
E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
1378813762

13789-
QualType NewCallOpType;
13790-
TypeLocBuilder NewCallOpTLBuilder;
13763+
TypeLocBuilder NewCallOpTLBuilder;
13764+
QualType NewCallOpType =
13765+
getDerived().TransformType(NewCallOpTLBuilder, OldCallOpTypeLoc);
1379113766

13792-
if (auto ATL = OldCallOpTypeLoc.getAs<AttributedTypeLoc>()) {
13793-
NewCallOpType = this->TransformAttributedType(
13794-
NewCallOpTLBuilder, ATL,
13795-
[&](TypeLocBuilder &TLB, TypeLoc TL) -> QualType {
13796-
return TransformFunctionProtoTypeLoc(
13797-
TLB, TL.castAs<FunctionProtoTypeLoc>());
13798-
});
13799-
} else {
13800-
auto FPTL = OldCallOpTypeLoc.castAs<FunctionProtoTypeLoc>();
13801-
NewCallOpType = TransformFunctionProtoTypeLoc(NewCallOpTLBuilder, FPTL);
13802-
}
13803-
13804-
if (NewCallOpType.isNull())
13805-
return ExprError();
13806-
NewCallOpTSI =
13807-
NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
13808-
}
13767+
if (NewCallOpType.isNull())
13768+
return ExprError();
1380913769

13810-
ArrayRef<ParmVarDecl *> Params;
13811-
if (auto ATL = NewCallOpTSI->getTypeLoc().getAs<AttributedTypeLoc>()) {
13812-
Params = ATL.getModifiedLoc().castAs<FunctionProtoTypeLoc>().getParams();
13813-
} else {
13814-
auto FPTL = NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
13815-
Params = FPTL.getParams();
13816-
}
13770+
TypeSourceInfo *NewCallOpTSI =
13771+
NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
13772+
13773+
auto ExtractParams = [](TypeLoc TL) {
13774+
auto ExtractParamsImpl = [](auto Self,
13775+
TypeLoc TL) -> ArrayRef<ParmVarDecl *> {
13776+
if (auto FPTL = TL.getAs<FunctionProtoTypeLoc>()) {
13777+
return FPTL.getParams();
13778+
} else if (auto ATL = TL.getAs<AttributedTypeLoc>()) {
13779+
return Self(Self, ATL.getModifiedLoc());
13780+
} else if (auto MQTL = TL.getAs<MacroQualifiedTypeLoc>()) {
13781+
return Self(Self, MQTL.getInnerLoc());
13782+
} else {
13783+
llvm_unreachable("Unhandled TypeLoc");
13784+
}
13785+
};
13786+
return ExtractParamsImpl(ExtractParamsImpl, TL);
13787+
};
1381713788

1381813789
getSema().CompleteLambdaCallOperator(
1381913790
NewCallOperator, E->getCallOperator()->getLocation(),
1382013791
E->getCallOperator()->getInnerLocStart(),
1382113792
E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI,
1382213793
E->getCallOperator()->getConstexprKind(),
13823-
E->getCallOperator()->getStorageClass(), Params,
13824-
E->hasExplicitResultType());
13794+
E->getCallOperator()->getStorageClass(),
13795+
ExtractParams(NewCallOpTSI->getTypeLoc()), E->hasExplicitResultType());
1382513796

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