[clang] [HLSL] Fix vector list initialization (PR #161421)

Chris B via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 1 10:55:10 PDT 2025


================
@@ -6817,33 +6820,17 @@ void InitializationSequence::InitializeFrom(Sema &S,
   assert(Args.size() >= 1 && "Zero-argument case handled above");
 
   // For HLSL ext vector types we allow list initialization behavior for C++
-  // constructor syntax. This is accomplished by converting initialization
-  // arguments an InitListExpr late.
+  // functional cast expressions which look like constructor syntax. This is
+  // accomplished by converting initialization arguments an InitListExpr.
   if (S.getLangOpts().HLSL && Args.size() > 1 && DestType->isExtVectorType() &&
       (SourceType.isNull() ||
        !Context.hasSameUnqualifiedType(SourceType, DestType))) {
-
-    llvm::SmallVector<Expr *> InitArgs;
-    for (auto *Arg : Args) {
-      if (Arg->getType()->isExtVectorType()) {
-        const auto *VTy = Arg->getType()->castAs<ExtVectorType>();
-        unsigned Elm = VTy->getNumElements();
-        for (unsigned Idx = 0; Idx < Elm; ++Idx) {
-          InitArgs.emplace_back(new (Context) ArraySubscriptExpr(
-              Arg,
-              IntegerLiteral::Create(
-                  Context, llvm::APInt(Context.getIntWidth(Context.IntTy), Idx),
-                  Context.IntTy, SourceLocation()),
-              VTy->getElementType(), Arg->getValueKind(), Arg->getObjectKind(),
-              SourceLocation()));
-        }
-      } else
-        InitArgs.emplace_back(Arg);
-    }
     InitListExpr *ILE = new (Context) InitListExpr(
-        S.getASTContext(), SourceLocation(), InitArgs, SourceLocation());
+        S.getASTContext(), SourceLocation(), Args, SourceLocation());
----------------
llvm-beanz wrote:

As implemented right now, the code doesn't have the problem you're describing. This `InitListExpr` isn't the final `InitListExpr` placed into the AST, it is translated in SemaHLSL which does pull the source locations from the transformed argument list (see: https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaHLSL.cpp#L4208).

With this PR if you dump the AST for this code (from vector-constructors.hlsl):
```hlsl
  float2 Vec2 = float2(1.0, 2.0);
```

You get:
```
Dumping Vec2:
VarDecl 0x13c04fb00 <vector-constructors.hlsl:9:3, col:32> col:10 used Vec2 'float2':'vector<float, 2>' cinit
`-CXXFunctionalCastExpr 0x13c04fcc8 <col:17, col:32> 'float2':'vector<float, 2>' functional cast to float2 <NoOp>
  `-InitListExpr 0x13c04fc78 <col:24, col:29> 'float2':'vector<float, 2>'
    |-FloatingLiteral 0x13c04fb98 <col:24> 'float' 1.000000e+00
    `-FloatingLiteral 0x13c04fbb8 <col:29> 'float' 2.000000e+00
```

The unfortunate thing here is that the `InitListExpr::getLBraceLoc()` returns the location of the character `1` while the `InitListExpr::getRBraceLoc()` returns the location of the `0` from `2.0`. I'm honestly not sure which is better.

I think there are good odds we'll need to revisit this when we write a refactoring tool to rewrite initializer lists because it may be easier to recognize that braces are missing if we have no location for them than if we have a location that points to the wrong thing. That said, for consistency with HLSL 202y (where we won't be transforming init lists), I'll apply the change here too.

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


More information about the cfe-commits mailing list