[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