[clang] [Clang] Introduce FunctionParmPackDecl for expanded lambda captures (PR #107995)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 10 05:05:12 PDT 2024
https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/107995
>From c97f213bc412dd2a4d6ee5c8e58a82f04dbbd03b Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 10 Sep 2024 17:23:55 +0800
Subject: [PATCH 1/2] [Clang] Introduce FunctionParmPackDecl for expanded
lambda captures
---
clang/docs/ReleaseNotes.rst | 2 +-
clang/include/clang/AST/DeclTemplate.h | 37 +++++++++++++++++++
clang/include/clang/AST/RecursiveASTVisitor.h | 2 +
clang/include/clang/Basic/DeclNodes.td | 1 +
clang/include/clang/Sema/Template.h | 3 ++
.../include/clang/Serialization/ASTBitCodes.h | 5 ++-
clang/lib/AST/DeclBase.cpp | 1 +
clang/lib/AST/DeclTemplate.cpp | 37 +++++++++++++++++++
clang/lib/CodeGen/CGDecl.cpp | 1 +
clang/lib/Sema/SemaTemplateInstantiate.cpp | 25 ++++++++++++-
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +++
clang/lib/Sema/TreeTransform.h | 14 +++++--
clang/lib/Serialization/ASTCommon.cpp | 1 +
clang/lib/Serialization/ASTReaderDecl.cpp | 11 ++++++
clang/lib/Serialization/ASTWriterDecl.cpp | 10 +++++
.../SemaCXX/fold_lambda_with_variadics.cpp | 31 ++++------------
clang/tools/libclang/CIndex.cpp | 1 +
17 files changed, 157 insertions(+), 30 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 250821a9f9c45c..f39c39f8646d08 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -344,7 +344,7 @@ Bug Fixes to C++ Support
module imports in those situations. (#GH60336)
- Fix init-capture packs having a size of one before being instantiated. (#GH63677)
- Clang now preserves the unexpanded flag in a lambda transform used for pack expansion. (#GH56852), (#GH85667),
- (#GH99877).
+ (#GH99877), (#GH18873).
- Fixed a bug when diagnosing ambiguous explicit specializations of constrained member functions.
- Fixed an assertion failure when selecting a function from an overload set that includes a
specialization of a conversion function template.
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 687715a22e9fd3..3730f5bee09d2a 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -3220,6 +3220,43 @@ class ImplicitConceptSpecializationDecl final
friend class ASTDeclReader;
};
+class FunctionParmPackDecl final
+ : public Decl,
+ private llvm::TrailingObjects<FunctionParmPackDecl, VarDecl *> {
+ friend TrailingObjects;
+ friend class ASTDeclReader;
+
+ /// The function parameter pack which was referenced.
+ NamedDecl *Pattern;
+
+ unsigned NumExpansions;
+
+ FunctionParmPackDecl(DeclContext *DC, SourceLocation StartLoc,
+ NamedDecl *Pattern, ArrayRef<VarDecl *> ExpandedParams);
+
+ void setExpandedParams(ArrayRef<VarDecl *> ExpandedParams);
+
+public:
+ static FunctionParmPackDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ NamedDecl *Pattern,
+ ArrayRef<VarDecl *> ExpandedParams);
+
+ static FunctionParmPackDecl *
+ CreateDeserialized(ASTContext &C, GlobalDeclID ID, unsigned NumExpansions);
+
+ ArrayRef<VarDecl *> getExpandedParams() const {
+ return ArrayRef<VarDecl *>(getTrailingObjects<VarDecl *>(), NumExpansions);
+ }
+
+ unsigned getNumExpansions() const { return NumExpansions; }
+
+ NamedDecl *getPattern() const { return Pattern; }
+
+ static bool classofKind(Kind K) { return K == FunctionParmPack; }
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+};
+
/// A template parameter object.
///
/// Template parameter objects represent values of class type used as template
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 3389670a2ab9d9..3297e9eb009678 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2353,6 +2353,8 @@ DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, {
TRY_TO(TraverseTemplateArguments(D->getTemplateArguments()));
})
+DEF_TRAVERSE_DECL(FunctionParmPackDecl, {})
+
#undef DEF_TRAVERSE_DECL
// ----------------- Stmt traversal -----------------
diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td
index 48396e85c5adac..694d3d8b79a183 100644
--- a/clang/include/clang/Basic/DeclNodes.td
+++ b/clang/include/clang/Basic/DeclNodes.td
@@ -91,6 +91,7 @@ def Named : DeclNode<Decl, "named declarations", 1>;
def ObjCProperty : DeclNode<Named, "Objective-C properties">;
def ObjCCompatibleAlias : DeclNode<Named>;
def ImplicitConceptSpecialization : DeclNode<Decl>;
+def FunctionParmPack : DeclNode<Decl>;
def LinkageSpec : DeclNode<Decl>, DeclContext;
def Export : DeclNode<Decl>, DeclContext;
def ObjCPropertyImpl : DeclNode<Decl>;
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index 0340c23fd170d6..5de4bf0148652c 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -515,6 +515,9 @@ enum class TemplateSubstitutionKind : char {
llvm::PointerUnion<Decl *, DeclArgumentPack *> *
findInstantiationOf(const Decl *D);
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *
+ findInstantiationUnsafe(const Decl *D);
+
void InstantiatedLocal(const Decl *D, Decl *Inst);
void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst);
void MakeInstantiatedLocalArgPack(const Decl *D);
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 4410df296d8efc..3f23cea4591b40 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1493,7 +1493,10 @@ enum DeclCode {
/// An ImplicitConceptSpecializationDecl record.
DECL_IMPLICIT_CONCEPT_SPECIALIZATION,
- DECL_LAST = DECL_IMPLICIT_CONCEPT_SPECIALIZATION
+ /// A FunctionParmPackDecl record.
+ DECL_FUNCTION_PARM_PACK,
+
+ DECL_LAST = DECL_FUNCTION_PARM_PACK
};
/// Record codes for each kind of statement or expression.
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index f42857f20efc44..728b20b39d1635 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -986,6 +986,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case LifetimeExtendedTemporary:
case RequiresExprBody:
case ImplicitConceptSpecialization:
+ case FunctionParmPack:
// Never looked up by name.
return 0;
}
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 976b3a3e1ecedb..34d60298929c2c 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1132,6 +1132,43 @@ void ImplicitConceptSpecializationDecl::setTemplateArguments(
getTrailingObjects<TemplateArgument>());
}
+//===----------------------------------------------------------------------===//
+// FunctionParmPackDecl Implementation
+//===----------------------------------------------------------------------===//
+FunctionParmPackDecl::FunctionParmPackDecl(DeclContext *DC,
+ SourceLocation StartLoc,
+ NamedDecl *Pattern,
+ ArrayRef<VarDecl *> ExpandedParams)
+ : Decl(FunctionParmPack, DC, StartLoc), Pattern(Pattern),
+ NumExpansions(ExpandedParams.size()) {
+ std::uninitialized_copy(ExpandedParams.begin(), ExpandedParams.end(),
+ getTrailingObjects<VarDecl *>());
+}
+
+FunctionParmPackDecl *
+FunctionParmPackDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, NamedDecl *Pattern,
+ ArrayRef<VarDecl *> ExpandedParams) {
+ return new (C, DC, additionalSizeToAlloc<VarDecl *>(ExpandedParams.size()))
+ FunctionParmPackDecl(DC, StartLoc, Pattern, ExpandedParams);
+}
+
+FunctionParmPackDecl *
+FunctionParmPackDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
+ unsigned NumExpansions) {
+ return new (C, ID, additionalSizeToAlloc<VarDecl *>(NumExpansions))
+ FunctionParmPackDecl(/*DC=*/nullptr, SourceLocation(),
+ /*Pattern=*/nullptr,
+ SmallVector<VarDecl *>(NumExpansions, nullptr));
+}
+
+void FunctionParmPackDecl::setExpandedParams(
+ ArrayRef<VarDecl *> ExpandedParams) {
+ assert(ExpandedParams.size() == NumExpansions);
+ std::uninitialized_copy(ExpandedParams.begin(), ExpandedParams.end(),
+ getTrailingObjects<VarDecl *>());
+}
+
//===----------------------------------------------------------------------===//
// ClassTemplatePartialSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 563f728e29d781..8269a2f9e0fb6f 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -134,6 +134,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::ImplicitConceptSpecialization:
case Decl::LifetimeExtendedTemporary:
case Decl::RequiresExprBody:
+ case Decl::FunctionParmPack:
// None of these decls require codegen support.
return;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index c42cc250bb904a..b09e42356a1c9c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1855,6 +1855,21 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
// template parameter.
}
+ if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D);
+ PVD && SemaRef.ArgumentPackSubstitutionIndex == -1) {
+ if (auto *Found =
+ SemaRef.CurrentInstantiationScope->findInstantiationUnsafe(D)) {
+ using DeclArgumentPack = LocalInstantiationScope::DeclArgumentPack;
+ if (auto *Pack = Found->dyn_cast<DeclArgumentPack *>()) {
+ assert(SemaRef.getCurLambda() &&
+ "Only lambdas can hold off an expanded pack expansion");
+ return FunctionParmPackDecl::Create(SemaRef.getASTContext(),
+ PVD->getDeclContext(),
+ PVD->getLocation(), PVD, *Pack);
+ }
+ }
+ }
+
return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
}
@@ -4369,9 +4384,8 @@ static const Decl *getCanonicalParmVarDecl(const Decl *D) {
return D;
}
-
llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
-LocalInstantiationScope::findInstantiationOf(const Decl *D) {
+LocalInstantiationScope::findInstantiationUnsafe(const Decl *D) {
D = getCanonicalParmVarDecl(D);
for (LocalInstantiationScope *Current = this; Current;
Current = Current->Outer) {
@@ -4395,6 +4409,13 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
if (!Current->CombineWithOuterScope)
break;
}
+ return nullptr;
+}
+
+llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
+LocalInstantiationScope::findInstantiationOf(const Decl *D) {
+ if (auto *Result = findInstantiationUnsafe(D))
+ return Result;
// If we're performing a partial substitution during template argument
// deduction, we may not have values for template parameters yet.
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6df412cbb09c83..6f2a301847c317 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4119,6 +4119,11 @@ Decl *TemplateDeclInstantiator::VisitImplicitConceptSpecializationDecl(
llvm_unreachable("Concept specializations cannot reside inside a template");
}
+Decl *
+TemplateDeclInstantiator::VisitFunctionParmPackDecl(FunctionParmPackDecl *D) {
+ llvm_unreachable("Function param packs cannot reside inside a template");
+}
+
Decl *
TemplateDeclInstantiator::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
return RequiresExprBodyDecl::Create(SemaRef.Context, D->getDeclContext(),
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 0daf620b4123e4..f8b7cca66bc83f 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -14722,12 +14722,20 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
}
// Transform the captured variable.
- auto *CapturedVar = cast_or_null<ValueDecl>(
- getDerived().TransformDecl(C->getLocation(), C->getCapturedVar()));
- if (!CapturedVar || CapturedVar->isInvalidDecl()) {
+ Decl *NewCapturedDecl =
+ getDerived().TransformDecl(C->getLocation(), C->getCapturedVar());
+ if (!NewCapturedDecl || NewCapturedDecl->isInvalidDecl()) {
Invalid = true;
continue;
}
+ if (auto *FPPD = dyn_cast<FunctionParmPackDecl>(NewCapturedDecl)) {
+ LSI->ContainsUnexpandedParameterPack = true;
+ for (VarDecl *Expanded : FPPD->getExpandedParams())
+ getSema().tryCaptureVariable(Expanded, C->getLocation(), Kind,
+ EllipsisLoc);
+ continue;
+ }
+ auto *CapturedVar = cast<ValueDecl>(NewCapturedDecl);
// This is not an init-capture; however it contains an unexpanded pack e.g.
// ([Pack] {}(), ...)
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index f30642f513ae4a..151bfbf145c515 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -453,6 +453,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::RequiresExprBody:
case Decl::UnresolvedUsingIfExists:
case Decl::HLSLBuffer:
+ case Decl::FunctionParmPack:
return false;
// These indirectly derive from Redeclarable<T> but are not actually
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 9272e23c7da3fc..c20532601ebbfc 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -389,6 +389,7 @@ class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> {
void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
void VisitDeclaratorDecl(DeclaratorDecl *DD);
void VisitFunctionDecl(FunctionDecl *FD);
+ void VisitFunctionParmPackDecl(FunctionParmPackDecl *D);
void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *GD);
void VisitCXXMethodDecl(CXXMethodDecl *D);
void VisitCXXConstructorDecl(CXXConstructorDecl *D);
@@ -2406,6 +2407,13 @@ void ASTDeclReader::VisitImplicitConceptSpecializationDecl(
D->setTemplateArguments(Args);
}
+void ASTDeclReader::VisitFunctionParmPackDecl(FunctionParmPackDecl *D) {
+ SmallVector<VarDecl *, 4> Expanded;
+ for (unsigned I = 0; I < D->getNumExpansions(); ++I)
+ Expanded.push_back(cast<VarDecl>(Record.readDeclRef()));
+ D->setExpandedParams(Expanded);
+}
+
void ASTDeclReader::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
}
@@ -4158,6 +4166,9 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) {
D = ImplicitConceptSpecializationDecl::CreateDeserialized(Context, ID,
Record.readInt());
break;
+ case DECL_FUNCTION_PARM_PACK:
+ D = FunctionParmPackDecl::CreateDeserialized(Context, ID, Record.readInt());
+ break;
}
assert(D && "Unknown declaration reading AST file");
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 555f6325da646b..a803d8d8c9611e 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -90,6 +90,7 @@ namespace clang {
void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
void VisitDeclaratorDecl(DeclaratorDecl *D);
void VisitFunctionDecl(FunctionDecl *D);
+ void VisitFunctionParmPackDecl(FunctionParmPackDecl *D);
void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D);
void VisitCXXMethodDecl(CXXMethodDecl *D);
void VisitCXXConstructorDecl(CXXConstructorDecl *D);
@@ -1700,6 +1701,15 @@ void ASTDeclWriter::VisitImplicitConceptSpecializationDecl(
Code = serialization::DECL_IMPLICIT_CONCEPT_SPECIALIZATION;
}
+void ASTDeclWriter::VisitFunctionParmPackDecl(FunctionParmPackDecl *D) {
+ Record.push_back(D->getNumExpansions());
+ VisitDecl(D);
+ Record.AddDeclRef(D->getPattern());
+ for (VarDecl *VD : D->getExpandedParams())
+ Record.AddDeclRef(VD);
+ Code = serialization::DECL_FUNCTION_PARM_PACK;
+}
+
void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
Code = serialization::DECL_REQUIRES_EXPR_BODY;
}
diff --git a/clang/test/SemaCXX/fold_lambda_with_variadics.cpp b/clang/test/SemaCXX/fold_lambda_with_variadics.cpp
index 14e242f009dc51..d86cc72ae09249 100644
--- a/clang/test/SemaCXX/fold_lambda_with_variadics.cpp
+++ b/clang/test/SemaCXX/fold_lambda_with_variadics.cpp
@@ -57,28 +57,14 @@ template <class = void> void f() {
})(1);
}(2, 'b');
-#if 0
- // FIXME: https://github.com/llvm/llvm-project/issues/18873
- [](auto ...x) { // #1
- ([&](auto ...y) { // #2
- ([x, y] { }(), ...); // #3
- })(1, 'a'); // #4
- }(2, 'b'); // #5
-
- // We run into another crash for the above lambda because of the absence of a
- // mechanism that rebuilds an unexpanded pack from an expanded Decls.
- //
- // Basically, this happens after `x` at #1 being expanded when the template
- // arguments at #5, deduced as <int, char>, are ready. When we want to
- // instantiate the body of #1, we first instantiate the CallExpr at #4, which
- // boils down to the lambda's instantiation at #2. To that end, we have to
- // instantiate the body of it, which turns out to be #3. #3 is a CXXFoldExpr,
- // and we immediately have to hold off on the expansion because we don't have
- // corresponding template arguments (arguments at #4 are not transformed yet) for it.
- // Therefore, we want to rebuild a CXXFoldExpr, which requires another pattern
- // transformation of the lambda inside #3. Then we need to find an unexpanded form
- // of such a Decl of x at the time of transforming the capture, which is impossible
- // because the instantiated form has been expanded at #1!
+ // https://github.com/llvm/llvm-project/issues/18873
+ static_assert([]<auto... z>(auto ...x) {
+ return [&](auto ...y) {
+ return ([x, y] {
+ return x + y + z;
+ }() + ...);
+ }(1, 'a');
+ }.template operator()<2, 'b'>(3, 'c') == 1 + 'a' + 2 + 'b' + 3 + 'c');
[](auto ...x) { // #outer
([&](auto ...y) { // #inner
@@ -89,7 +75,6 @@ template <class = void> void f() {
// expected-note-re@#instantiate-f {{function template specialization {{.*}} requested here}}
})('a', 'b', 'c');
}(0, 1, 2, 3);
-#endif
}
template void f(); // #instantiate-f
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index e821c5e4c588b6..432c9924e37d1f 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -7068,6 +7068,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::LifetimeExtendedTemporary:
case Decl::RequiresExprBody:
case Decl::UnresolvedUsingIfExists:
+ case Decl::FunctionParmPack:
return C;
// Declaration kinds that don't make any sense here, but are
>From 720d105706800c3b94cda292da5431f27b17483f Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 10 Sep 2024 20:04:55 +0800
Subject: [PATCH 2/2] Fix CI
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index b09e42356a1c9c..89900be295cd18 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1856,7 +1856,8 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
}
if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D);
- PVD && SemaRef.ArgumentPackSubstitutionIndex == -1) {
+ PVD && SemaRef.CurrentInstantiationScope &&
+ SemaRef.ArgumentPackSubstitutionIndex == -1) {
if (auto *Found =
SemaRef.CurrentInstantiationScope->findInstantiationUnsafe(D)) {
using DeclArgumentPack = LocalInstantiationScope::DeclArgumentPack;
More information about the cfe-commits
mailing list