Skip to content

Commit 157e7f1

Browse files
Refactor and fix Lambda prototype instantiation when it's attributed or macro qualified
1 parent ed7cee9 commit 157e7f1

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,
@@ -7069,11 +7065,11 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
70697065
}
70707066

70717067
template <typename Derived>
7072-
template <typename Fn>
7073-
QualType TreeTransform<Derived>::TransformAttributedType(
7074-
TypeLocBuilder &TLB, AttributedTypeLoc TL, Fn TransformModifiedTypeFn) {
7068+
QualType TreeTransform<Derived>::TransformAttributedType(TypeLocBuilder &TLB,
7069+
AttributedTypeLoc TL) {
7070+
70757071
const AttributedType *oldType = TL.getTypePtr();
7076-
QualType modifiedType = TransformModifiedTypeFn(TLB, TL.getModifiedLoc());
7072+
QualType modifiedType = getDerived().TransformType(TLB, TL.getModifiedLoc());
70777073
if (modifiedType.isNull())
70787074
return QualType();
70797075

@@ -7117,15 +7113,6 @@ QualType TreeTransform<Derived>::TransformAttributedType(
71177113
return result;
71187114
}
71197115

7120-
template <typename Derived>
7121-
QualType TreeTransform<Derived>::TransformAttributedType(TypeLocBuilder &TLB,
7122-
AttributedTypeLoc TL) {
7123-
return getDerived().TransformAttributedType(
7124-
TLB, TL, [&](TypeLocBuilder &TLB, TypeLoc ModifiedLoc) -> QualType {
7125-
return getDerived().TransformType(TLB, ModifiedLoc);
7126-
});
7127-
}
7128-
71297116
template <typename Derived>
71307117
QualType TreeTransform<Derived>::TransformBTFTagAttributedType(
71317118
TypeLocBuilder &TLB, BTFTagAttributedTypeLoc TL) {
@@ -13636,58 +13623,42 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1363613623
// The transformation MUST be done in the CurrentInstantiationScope since
1363713624
// it introduces a mapping of the original to the newly created
1363813625
// 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-
};
13626+
auto OldCallOpTypeLoc =
13627+
E->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
1365413628

13655-
QualType NewCallOpType;
13656-
TypeLocBuilder NewCallOpTLBuilder;
13629+
TypeLocBuilder NewCallOpTLBuilder;
13630+
QualType NewCallOpType =
13631+
getDerived().TransformType(NewCallOpTLBuilder, OldCallOpTypeLoc);
1365713632

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-
}
13633+
if (NewCallOpType.isNull())
13634+
return ExprError();
1367513635

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-
}
13636+
TypeSourceInfo *NewCallOpTSI =
13637+
NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
13638+
13639+
auto ExtractParams = [](TypeLoc TL) {
13640+
auto ExtractParamsImpl = [](auto Self,
13641+
TypeLoc TL) -> ArrayRef<ParmVarDecl *> {
13642+
if (auto FPTL = TL.getAs<FunctionProtoTypeLoc>()) {
13643+
return FPTL.getParams();
13644+
} else if (auto ATL = TL.getAs<AttributedTypeLoc>()) {
13645+
return Self(Self, ATL.getModifiedLoc());
13646+
} else if (auto MQTL = TL.getAs<MacroQualifiedTypeLoc>()) {
13647+
return Self(Self, MQTL.getInnerLoc());
13648+
} else {
13649+
llvm_unreachable("Unhandled TypeLoc");
13650+
}
13651+
};
13652+
return ExtractParamsImpl(ExtractParamsImpl, TL);
13653+
};
1368313654

1368413655
getSema().CompleteLambdaCallOperator(
1368513656
NewCallOperator, E->getCallOperator()->getLocation(),
1368613657
E->getCallOperator()->getInnerLocStart(),
1368713658
E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI,
1368813659
E->getCallOperator()->getConstexprKind(),
13689-
E->getCallOperator()->getStorageClass(), Params,
13690-
E->hasExplicitResultType());
13660+
E->getCallOperator()->getStorageClass(),
13661+
ExtractParams(NewCallOpTSI->getTypeLoc()), E->hasExplicitResultType());
1369113662

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