[clang] [Clang] [C++26] Implement P1306R5 Expansion Statements (PR #165195)

via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 27 14:32:53 PDT 2025


================
@@ -2393,9 +2413,13 @@ ExprResult
 TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
                                                        ValueDecl *PD) {
   typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
-  llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
-    = getSema().CurrentInstantiationScope->findInstantiationOf(PD);
-  assert(Found && "no instantiation for parameter pack");
+  llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found =
+      getSema().CurrentInstantiationScope->getInstantiationOfIfExists(PD);
+
+  // This can happen when instantiating an expansion statement that contains
+  // a pack (e.g. `template for (auto x : {{ts...}})`).
+  if (!Found)
+    return E;
----------------
Sirraide wrote:

> Oh man, I spent hours debugging the assertions around this...

I’m definitely not an expert when it comes to our templates implementation, but my understanding of this is that some of the assertions are just ‘no longer correct’, in that they guard against situations that should have been impossible before but are possible now.

> ...I might be misremembering, but this might be to handle something like:
> 
> ```c++
> template <typename... Ts>
> int fn(Ts... ts) {
>   template for (int i : {1, 2, 3}) {
>     return (ts, ...);
>   }
> }
> ```

That seems to work just fine (at least the instantiation does; it crashes in constant evaluation, but I think I just forgot to check for `ESR_Return`); I’ll fix that and that as a test case.

> my approach was to instantiate expansion statements as eagerly as possible to facilitate early diagnosis.

Yes, that’s also what I ended up doing.

https://github.com/llvm/llvm-project/pull/165195


More information about the cfe-commits mailing list