[clang] Support HLSL matrix initializers (PR #160960)

Farzon Lotfi via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 29 08:35:22 PDT 2025


https://github.com/farzonl updated https://github.com/llvm/llvm-project/pull/160960

>From 526c1cd28ff455148c96ab1a39ef68cbf4dcfa7b Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Fri, 26 Sep 2025 14:48:22 -0400
Subject: [PATCH 1/2] Support HLSL matrix initializers

fixes #159434

In HLSL matrices are `matrix_type` in all respects except that they
support a constructor style syntax for initializing matrices. This
change adds a translation of vector constructor arguments into
initializer lists.

This supports the following HLSL syntax:
(1) HLSL matrices support constructor syntax
(2) HLSL matrices are expanded to constituate components in constructor
---
 .../clang/Basic/DiagnosticSemaKinds.td        |   8 +-
 clang/include/clang/Sema/Initialization.h     |  12 +-
 clang/lib/Sema/CheckExprLifetime.cpp          |   1 +
 clang/lib/Sema/SemaInit.cpp                   | 203 ++++++++++-
 clang/test/AST/HLSL/matrix-constructors.hlsl  | 338 ++++++++++++++++++
 .../BuiltIns/matrix-constructors-errors.hlsl  |  24 ++
 6 files changed, 563 insertions(+), 23 deletions(-)
 create mode 100644 clang/test/AST/HLSL/matrix-constructors.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/matrix-constructors-errors.hlsl

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index bd0e53d3086b0..19e4c548d0208 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6543,9 +6543,9 @@ def warn_extern_init : Warning<"'extern' variable has an initializer">,
 def err_variable_object_no_init : Error<
   "variable-sized object may not be initialized">;
 def err_excess_initializers : Error<
-  "excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
+  "excess elements in %select{array|vector|matrix|scalar|union|struct}0 initializer">;
 def ext_excess_initializers : ExtWarn<
-  "excess elements in %select{array|vector|scalar|union|struct}0 initializer">,
+  "excess elements in %select{array|vector|matrix|scalar|union|struct}0 initializer">,
   InGroup<ExcessInitializers>;
 def err_excess_initializers_for_sizeless_type : Error<
   "excess elements in initializer for indivisible sizeless type %0">;
@@ -11086,8 +11086,8 @@ def err_first_argument_to_cwsc_pdtor_call : Error<
 def err_second_argument_to_cwsc_not_pointer : Error<
   "second argument to __builtin_call_with_static_chain must be of pointer type">;
 
-def err_vector_incorrect_num_elements : Error<
-  "%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">;
+def err_tensor_incorrect_num_elements : Error<
+  "%select{too many|too few}0 elements in %select{vector|matrix}1 %select{initialization|operand}4 (expected %2 elements, have %3)">;
 def err_altivec_empty_initializer : Error<"expected initializer">;
 
 def err_vector_incorrect_bit_count : Error<
diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index d7675ea153afb..865b6428f3081 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -91,6 +91,10 @@ class alignas(8) InitializedEntity {
     /// or vector.
     EK_VectorElement,
 
+    /// The entity being initialized is an element of a matrix.
+    /// or matrix.
+    EK_MatrixElement,
+
     /// The entity being initialized is a field of block descriptor for
     /// the copied-in c++ object.
     EK_BlockElement,
@@ -205,8 +209,8 @@ class alignas(8) InitializedEntity {
     /// virtual base.
     llvm::PointerIntPair<const CXXBaseSpecifier *, 1> Base;
 
-    /// When Kind == EK_ArrayElement, EK_VectorElement, or
-    /// EK_ComplexElement, the index of the array or vector element being
+    /// When Kind == EK_ArrayElement, EK_VectorElement, or EK_MatrixElement,
+    /// or EK_ComplexElement, the index of the array or vector element being
     /// initialized.
     unsigned Index;
 
@@ -536,7 +540,7 @@ class alignas(8) InitializedEntity {
   /// element's index.
   unsigned getElementIndex() const {
     assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement ||
-           getKind() == EK_ComplexElement);
+           getKind() == EK_MatrixElement || getKind() == EK_ComplexElement);
     return Index;
   }
 
@@ -544,7 +548,7 @@ class alignas(8) InitializedEntity {
   /// element, sets the element index.
   void setElementIndex(unsigned Index) {
     assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement ||
-           getKind() == EK_ComplexElement);
+           getKind() == EK_MatrixElement || getKind() == EK_ComplexElement);
     this->Index = Index;
   }
 
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp
index e02e00231e58e..d647fbf007838 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -154,6 +154,7 @@ getEntityLifetime(const InitializedEntity *Entity,
   case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
   case InitializedEntity::EK_LambdaCapture:
   case InitializedEntity::EK_VectorElement:
+  case clang::InitializedEntity::EK_MatrixElement:
   case InitializedEntity::EK_ComplexElement:
     return {nullptr, LK_FullExpression};
 
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index c97129336736b..caae8a6889997 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/IgnoreExpr.h"
+#include "clang/AST/TypeBase.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/Specifiers.h"
@@ -403,6 +404,9 @@ class InitListChecker {
                           unsigned &Index,
                           InitListExpr *StructuredList,
                           unsigned &StructuredIndex);
+  void CheckMatrixType(const InitializedEntity &Entity, InitListExpr *IList,
+                       QualType DeclType, unsigned &Index,
+                       InitListExpr *StructuredList, unsigned &StructuredIndex);
   void CheckVectorType(const InitializedEntity &Entity,
                        InitListExpr *IList, QualType DeclType, unsigned &Index,
                        InitListExpr *StructuredList,
@@ -1003,7 +1007,8 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
       return;
 
     if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement ||
-        ElementEntity.getKind() == InitializedEntity::EK_VectorElement)
+        ElementEntity.getKind() == InitializedEntity::EK_VectorElement ||
+        ElementEntity.getKind() == InitializedEntity::EK_MatrixElement)
       ElementEntity.setElementIndex(Init);
 
     if (Init >= NumInits && (ILE->hasArrayFiller() || SkipEmptyInitChecks))
@@ -1273,6 +1278,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
 
   switch (Entity.getKind()) {
   case InitializedEntity::EK_VectorElement:
+  case InitializedEntity::EK_MatrixElement:
   case InitializedEntity::EK_ComplexElement:
   case InitializedEntity::EK_ArrayElement:
   case InitializedEntity::EK_Parameter:
@@ -1372,11 +1378,12 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
       SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
           << T << IList->getInit(Index)->getSourceRange();
     } else {
-      int initKind = T->isArrayType() ? 0 :
-                     T->isVectorType() ? 1 :
-                     T->isScalarType() ? 2 :
-                     T->isUnionType() ? 3 :
-                     4;
+      int initKind = T->isArrayType()    ? 0
+                     : T->isVectorType() ? 1
+                     : T->isMatrixType() ? 2
+                     : T->isScalarType() ? 3
+                     : T->isUnionType()  ? 4
+                                         : 5;
 
       unsigned DK = ExtraInitsIsError ? diag::err_excess_initializers
                                       : diag::ext_excess_initializers;
@@ -1430,6 +1437,9 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
   } else if (DeclType->isVectorType()) {
     CheckVectorType(Entity, IList, DeclType, Index,
                     StructuredList, StructuredIndex);
+  } else if (DeclType->isMatrixType()) {
+    CheckMatrixType(Entity, IList, DeclType, Index, StructuredList,
+                    StructuredIndex);
   } else if (const RecordDecl *RD = DeclType->getAsRecordDecl()) {
     auto Bases =
         CXXRecordDecl::base_class_const_range(CXXRecordDecl::base_class_const_iterator(),
@@ -1877,6 +1887,93 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
     AggrDeductionCandidateParamTypes->push_back(DeclType);
 }
 
+void InitListChecker::CheckMatrixType(const InitializedEntity &Entity,
+                                      InitListExpr *IList, QualType DeclType,
+                                      unsigned &Index,
+                                      InitListExpr *StructuredList,
+                                      unsigned &StructuredIndex) {
+  if (!SemaRef.getLangOpts().HLSL)
+    return;
+
+  const ConstantMatrixType *MT = DeclType->castAs<ConstantMatrixType>();
+  QualType ElemTy = MT->getElementType();
+  const unsigned Rows = MT->getNumRows();
+  const unsigned Cols = MT->getNumColumns();
+  const unsigned MaxElts = Rows * Cols;
+
+  unsigned NumEltsInit = 0;
+  InitializedEntity ElemEnt =
+      InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+  // A Matrix initalizer should be able to take scalars, vectors, and matrices.
+  auto HandleInit = [&](InitListExpr *List, unsigned &Idx) {
+    Expr *Init = List->getInit(Idx);
+    QualType ITy = Init->getType();
+
+    if (ITy->isVectorType()) {
+      const VectorType *IVT = ITy->castAs<VectorType>();
+      unsigned N = IVT->getNumElements();
+      QualType VTy =
+          ITy->isExtVectorType()
+              ? SemaRef.Context.getExtVectorType(ElemTy, N)
+              : SemaRef.Context.getVectorType(ElemTy, N, IVT->getVectorKind());
+      ElemEnt.setElementIndex(Idx);
+      CheckSubElementType(ElemEnt, List, VTy, Idx, StructuredList,
+                          StructuredIndex);
+      NumEltsInit += N;
+      return;
+    }
+
+    if (ITy->isMatrixType()) {
+      const ConstantMatrixType *IMT = ITy->castAs<ConstantMatrixType>();
+      unsigned N = IMT->getNumRows() * IMT->getNumColumns();
+      QualType MTy = SemaRef.Context.getConstantMatrixType(
+          ElemTy, IMT->getNumRows(), IMT->getNumColumns());
+      ElemEnt.setElementIndex(Idx);
+      CheckSubElementType(ElemEnt, List, MTy, Idx, StructuredList,
+                          StructuredIndex);
+      NumEltsInit += N;
+      return;
+    }
+
+    // Scalar element
+    ElemEnt.setElementIndex(Idx);
+    CheckSubElementType(ElemEnt, List, ElemTy, Idx, StructuredList,
+                        StructuredIndex);
+    ++NumEltsInit;
+  };
+
+  // Column-major: each top-level sublist is treated as a column.
+  while (NumEltsInit < MaxElts && Index < IList->getNumInits()) {
+    Expr *Init = IList->getInit(Index);
+
+    if (auto *SubList = dyn_cast<InitListExpr>(Init)) {
+      unsigned SubIdx = 0;
+      unsigned Row = 0;
+      while (Row < Rows && SubIdx < SubList->getNumInits() &&
+             NumEltsInit < MaxElts) {
+        HandleInit(SubList, SubIdx);
+        ++Row;
+      }
+      ++Index; // advance past this column sublist
+      continue;
+    }
+
+    // Not a sublist: just consume directly.
+    HandleInit(IList, Index);
+  }
+
+  // HLSL requires exactly Rows*Cols initializers after flattening.
+  if (NumEltsInit != MaxElts) {
+    if (!VerifyOnly)
+      SemaRef.Diag(IList->getBeginLoc(),
+                   diag::err_tensor_incorrect_num_elements)
+          << (NumEltsInit < MaxElts) << /*matrix*/ 1 << MaxElts << NumEltsInit
+          << /*initialization*/ 0;
+    hadError = true;
+  }
+}
+
 void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
                                       InitListExpr *IList, QualType DeclType,
                                       unsigned &Index,
@@ -2026,9 +2123,9 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
   if (numEltsInit != maxElements) {
     if (!VerifyOnly)
       SemaRef.Diag(IList->getBeginLoc(),
-                   diag::err_vector_incorrect_num_elements)
-          << (numEltsInit < maxElements) << maxElements << numEltsInit
-          << /*initialization*/ 0;
+                   diag::err_tensor_incorrect_num_elements)
+          << (numEltsInit < maxElements) << /*vector*/ 0 << maxElements
+          << numEltsInit << /*initialization*/ 0;
     hadError = true;
   }
 }
@@ -3639,6 +3736,9 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
   } else if (const VectorType *VT = Parent.getType()->getAs<VectorType>()) {
     Kind = EK_VectorElement;
     Type = VT->getElementType();
+  } else if (const MatrixType *MT = Parent.getType()->getAs<MatrixType>()) {
+    Kind = EK_MatrixElement;
+    Type = MT->getElementType();
   } else {
     const ComplexType *CT = Parent.getType()->getAs<ComplexType>();
     assert(CT && "Unexpected type");
@@ -3687,6 +3787,7 @@ DeclarationName InitializedEntity::getName() const {
   case EK_Delegating:
   case EK_ArrayElement:
   case EK_VectorElement:
+  case EK_MatrixElement:
   case EK_ComplexElement:
   case EK_BlockElement:
   case EK_LambdaToBlockConversionBlockElement:
@@ -3720,6 +3821,7 @@ ValueDecl *InitializedEntity::getDecl() const {
   case EK_Delegating:
   case EK_ArrayElement:
   case EK_VectorElement:
+  case EK_MatrixElement:
   case EK_ComplexElement:
   case EK_BlockElement:
   case EK_LambdaToBlockConversionBlockElement:
@@ -3753,6 +3855,7 @@ bool InitializedEntity::allowsNRVO() const {
   case EK_Delegating:
   case EK_ArrayElement:
   case EK_VectorElement:
+  case EK_MatrixElement:
   case EK_ComplexElement:
   case EK_BlockElement:
   case EK_LambdaToBlockConversionBlockElement:
@@ -3792,6 +3895,9 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
   case EK_Delegating: OS << "Delegating"; break;
   case EK_ArrayElement: OS << "ArrayElement " << Index; break;
   case EK_VectorElement: OS << "VectorElement " << Index; break;
+  case EK_MatrixElement:
+    OS << "MatrixElement " << Index;
+    break;
   case EK_ComplexElement: OS << "ComplexElement " << Index; break;
   case EK_BlockElement: OS << "Block"; break;
   case EK_LambdaToBlockConversionBlockElement:
@@ -6026,7 +6132,7 @@ static void TryOrBuildParenListInitialization(
     Sequence.SetFailed(InitializationSequence::FK_ParenthesizedListInitFailed);
     if (!VerifyOnly) {
       QualType T = Entity.getType();
-      int InitKind = T->isArrayType() ? 0 : T->isUnionType() ? 3 : 4;
+      int InitKind = T->isArrayType() ? 0 : T->isUnionType() ? 4 : 5;
       SourceRange ExcessInitSR(Args[EntityIndexToProcess]->getBeginLoc(),
                                Args.back()->getEndLoc());
       S.Diag(Kind.getLocation(), diag::err_excess_initializers)
@@ -6847,6 +6953,67 @@ void InitializationSequence::InitializeFrom(Sema &S,
     return;
   }
 
+  if (S.getLangOpts().HLSL && DestType->isMatrixType() &&
+      (SourceType.isNull() ||
+       !Context.hasSameUnqualifiedType(SourceType, DestType))) {
+
+    llvm::SmallVector<Expr *> InitArgs;
+
+    for (Expr *Arg : Args) {
+      QualType AT = Arg->getType();
+
+      // Expand matrix arguments element-by-element (col-major).
+      if (AT->isMatrixType()) {
+        const auto *MTy = AT->castAs<ConstantMatrixType>();
+        unsigned Rows = MTy->getNumRows();
+        unsigned Cols = MTy->getNumColumns();
+        QualType ElemTy = MTy->getElementType();
+
+        for (unsigned c = 0; c < Cols; ++c) {
+          for (unsigned r = 0; r < Rows; ++r) {
+            // row index literal
+            Expr *RowIdx = IntegerLiteral::Create(
+                Context, llvm::APInt(Context.getIntWidth(Context.IntTy), r),
+                Context.IntTy, Arg->getBeginLoc());
+            // column index literal
+            Expr *ColIdx = IntegerLiteral::Create(
+                Context, llvm::APInt(Context.getIntWidth(Context.IntTy), c),
+                Context.IntTy, Arg->getBeginLoc());
+
+            InitArgs.emplace_back(new (Context) MatrixSubscriptExpr(
+                Arg, RowIdx, ColIdx, ElemTy, Arg->getEndLoc()));
+          }
+        }
+
+        // Keep your vector expansion, in case vectors appear in the argument
+        // list.
+      } else if (AT->isExtVectorType()) {
+        const auto *VTy = AT->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, Arg->getBeginLoc()),
+              VTy->getElementType(), Arg->getValueKind(), Arg->getObjectKind(),
+              Arg->getEndLoc()));
+        }
+
+      } else {
+        // Scalar or other: forward as-is
+        InitArgs.emplace_back(Arg);
+      }
+    }
+
+    InitListExpr *ILE = new (Context) InitListExpr(
+        S.getASTContext(), SourceLocation(), InitArgs, SourceLocation());
+
+    Args[0] = ILE;
+    AddListInitializationStep(DestType);
+    return;
+  }
+
   // The remaining cases all need a source type.
   if (Args.size() > 1) {
     SetFailed(FK_TooManyInitsForScalar);
@@ -6999,6 +7166,7 @@ static AssignmentAction getAssignmentAction(const InitializedEntity &Entity,
   case InitializedEntity::EK_Binding:
   case InitializedEntity::EK_ArrayElement:
   case InitializedEntity::EK_VectorElement:
+  case InitializedEntity::EK_MatrixElement:
   case InitializedEntity::EK_ComplexElement:
   case InitializedEntity::EK_BlockElement:
   case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
@@ -7024,6 +7192,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
   case InitializedEntity::EK_Base:
   case InitializedEntity::EK_Delegating:
   case InitializedEntity::EK_VectorElement:
+  case InitializedEntity::EK_MatrixElement:
   case InitializedEntity::EK_ComplexElement:
   case InitializedEntity::EK_Exception:
   case InitializedEntity::EK_BlockElement:
@@ -7054,6 +7223,7 @@ static bool shouldDestroyEntity(const InitializedEntity &Entity) {
     case InitializedEntity::EK_Base:
     case InitializedEntity::EK_Delegating:
     case InitializedEntity::EK_VectorElement:
+    case InitializedEntity::EK_MatrixElement:
     case InitializedEntity::EK_ComplexElement:
     case InitializedEntity::EK_BlockElement:
     case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
@@ -7107,6 +7277,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
   case InitializedEntity::EK_Base:
   case InitializedEntity::EK_Delegating:
   case InitializedEntity::EK_VectorElement:
+  case InitializedEntity::EK_MatrixElement:
   case InitializedEntity::EK_ComplexElement:
   case InitializedEntity::EK_BlockElement:
   case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
@@ -7858,9 +8029,11 @@ ExprResult InitializationSequence::Perform(Sema &S,
 
   // HLSL allows vector initialization to function like list initialization, but
   // use the syntax of a C++-like constructor.
-  bool IsHLSLVectorInit = S.getLangOpts().HLSL && DestType->isExtVectorType() &&
-                          isa<InitListExpr>(Args[0]);
-  (void)IsHLSLVectorInit;
+  bool IsHLSLVectorOrMatrixInit =
+      S.getLangOpts().HLSL &&
+      (DestType->isExtVectorType() || DestType->isMatrixType()) &&
+      isa<InitListExpr>(Args[0]);
+  (void)IsHLSLVectorOrMatrixInit;
 
   // For initialization steps that start with a single initializer,
   // grab the only argument out the Args and place it into the "current"
@@ -7899,7 +8072,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
   case SK_StdInitializerList:
   case SK_OCLSamplerInit:
   case SK_OCLZeroOpaqueType: {
-    assert(Args.size() == 1 || IsHLSLVectorInit);
+    assert(Args.size() == 1 || IsHLSLVectorOrMatrixInit);
     CurInit = Args[0];
     if (!CurInit.get()) return ExprError();
     break;
@@ -9117,7 +9290,7 @@ bool InitializationSequence::Diagnose(Sema &S,
         << R;
     else
       S.Diag(Kind.getLocation(), diag::err_excess_initializers)
-        << /*scalar=*/2 << R;
+          << /*scalar=*/3 << R;
     break;
   }
 
diff --git a/clang/test/AST/HLSL/matrix-constructors.hlsl b/clang/test/AST/HLSL/matrix-constructors.hlsl
new file mode 100644
index 0000000000000..faee0162a314b
--- /dev/null
+++ b/clang/test/AST/HLSL/matrix-constructors.hlsl
@@ -0,0 +1,338 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s 
+
+typedef float float2x1 __attribute__((matrix_type(2,1)));
+typedef float float2x3 __attribute__((matrix_type(2,3)));
+typedef float float2x2 __attribute__((matrix_type(2,2)));
+typedef float float2 __attribute__((ext_vector_type(2)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+
+[numthreads(1,1,1)]
+void ok() {
+
+  // CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:36> col:12 A 'float2x3':'matrix<float, 2, 3>' cinit
+  // CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:36> 'float2x3':'matrix<float, 2, 3>' functional cast to float2x3 <NoOp>
+  // CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:35> 'float2x3':'matrix<float, 2, 3>'
+  // CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float' <IntegralToFloating>
+  // CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+  // CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:27> 'float' <IntegralToFloating>
+  // CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:27> 'int' 2
+  // CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:29> 'float' <IntegralToFloating>
+  // CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:29> 'int' 3
+  // CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:31> 'float' <IntegralToFloating>
+  // CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:31> 'int' 4
+  // CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:33> 'float' <IntegralToFloating>
+  // CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:33> 'int' 5
+  // CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:35> 'float' <IntegralToFloating>
+  // CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:35> 'int' 6
+  float2x3 A = float2x3(1,2,3,4,5,6);
+
+  // CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:32> col:12 B 'float2x1':'matrix<float, 2, 1>' cinit
+  // CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:32> 'float2x1':'matrix<float, 2, 1>' functional cast to float2x1 <NoOp>
+  // CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:29> 'float2x1':'matrix<float, 2, 1>'
+  // CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'float' 1.000000e+00
+  // CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:29> 'float' 2.000000e+00
+  float2x1 B = float2x1(1.0,2.0);
+
+  // CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:36> col:12 C 'float2x1':'matrix<float, 2, 1>' cinit
+  // CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:36> 'float2x1':'matrix<float, 2, 1>' functional cast to float2x1 <NoOp>
+  // CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:32> 'float2x1':'matrix<float, 2, 1>'
+  // CHECK-NEXT: UnaryOperator 0x{{[0-9a-fA-F]+}} <col:25, col:26> 'float' prefix '-'
+  // CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:26> 'float' 1.000000e+00
+  // CHECK-NEXT: UnaryOperator 0x{{[0-9a-fA-F]+}} <col:31, col:32> 'float' prefix '-'
+  // CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'float' 2.000000e+00
+  float2x1 C = float2x1(-1.0f,-2.0f);
+
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:48> col:12 D 'float2x3':'matrix<float, 2, 3>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:48> 'float2x3':'matrix<float, 2, 3>' functional cast to float2x3 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:47> 'float2x3':'matrix<float, 2, 3>'
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:35> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:35> 'float2':'vector<float, 2>' functional cast to float2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:32, col:34> 'float2':'vector<float, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:32> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 2
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 0
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:35> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:35> 'float2':'vector<float, 2>' functional cast to float2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:32, col:34> 'float2':'vector<float, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:32> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 2
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:38> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:41> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:41> 'int' 4
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:44> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:44> 'int' 5
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:47> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:47> 'int' 6
+  float2x3 D = float2x3(float2(1,2), 3, 4, 5, 6);
+          
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:55> col:12 E 'float2x3':'matrix<float, 2, 3>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:55> 'float2x3':'matrix<float, 2, 3>' functional cast to float2x3 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:54> 'float2x3':'matrix<float, 2, 3>'
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:35> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:35> 'float2':'vector<float, 2>' functional cast to float2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:32, col:34> 'float2':'vector<float, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:32> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 2
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 0
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:35> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:35> 'float2':'vector<float, 2>' functional cast to float2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:32, col:34> 'float2':'vector<float, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:32> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 2
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:38, col:48> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:38, col:48> 'float2':'vector<float, 2>' functional cast to float2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:45, col:47> 'float2':'vector<float, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:45> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:45> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:47> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:47> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 0
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:38, col:48> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:38, col:48> 'float2':'vector<float, 2>' functional cast to float2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:45, col:47> 'float2':'vector<float, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:45> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:45> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:47> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:47> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:51> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:51> 'int' 5
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:54> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:54> 'int' 6
+  float2x3 E = float2x3(float2(1,2), float2(3,4), 5, 6);
+
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:46> col:12 F 'float2x3':'matrix<float, 2, 3>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:46> 'float2x3':'matrix<float, 2, 3>' functional cast to float2x3 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:45> 'float2x3':'matrix<float, 2, 3>'
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:39> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:39> 'float4':'vector<float, 4>' functional cast to float4 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:32, col:38> 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:32> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 2
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:36> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:36> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:38> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 0
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:39> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:39> 'float4':'vector<float, 4>' functional cast to float4 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:32, col:38> 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:32> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 2
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:36> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:36> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:38> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:39> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:39> 'float4':'vector<float, 4>' functional cast to float4 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:32, col:38> 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:32> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 2
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:36> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:36> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:38> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 2
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:39> 'float'
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:39> 'float4':'vector<float, 4>' functional cast to float4 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:32, col:38> 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:32> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 2
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:36> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:36> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:38> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:42> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:42> 'int' 5
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:45> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:45> 'int' 6
+  float2x3 F = float2x3(float4(1,2,3,4), 5, 6);
+
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:48> col:12 G 'float2x3':'matrix<float, 2, 3>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:48> 'float2x3':'matrix<float, 2, 3>' functional cast to float2x3 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:47> 'float2x3':'matrix<float, 2, 3>'
+// CHECK-NEXT: MatrixSubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:41> 'float' matrixcomponent
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:41> 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:34, col:40> 'float2x2':'matrix<float, 2, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:36> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:36> 'int' 2
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:38> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:40> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:40> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 0
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 0
+// CHECK-NEXT: MatrixSubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:41> 'float' matrixcomponent
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:41> 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:34, col:40> 'float2x2':'matrix<float, 2, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:36> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:36> 'int' 2
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:38> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:40> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:40> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 0
+// CHECK-NEXT: MatrixSubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:41> 'float' matrixcomponent
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:41> 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:34, col:40> 'float2x2':'matrix<float, 2, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:36> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:36> 'int' 2
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:38> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:40> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:40> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 0
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+// CHECK-NEXT: MatrixSubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:41> 'float' matrixcomponent
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:41> 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:34, col:40> 'float2x2':'matrix<float, 2, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:34> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:34> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:36> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:36> 'int' 2
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:38> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:38> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:40> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:40> 'int' 4
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:44> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:44> 'int' 5
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:47> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:47> 'int' 6
+  float2x3 G = float2x3(float2x2(1,2,3,4), 5, 6);  
+
+
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:33> col:12 H 'float2x2':'matrix<float, 2, 2>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:33> 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:32> 'float2x2':'matrix<float, 2, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float' lvalue
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float2':'vector<float, 2>' lvalue Var 0x{{[0-9a-fA-F]+}} 'Vec2' 'float2':'vector<float, 2>'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 0
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float' lvalue
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float2':'vector<float, 2>' lvalue Var 0x{{[0-9a-fA-F]+}} 'Vec2' 'float2':'vector<float, 2>'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:30> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:30> 'int' 3
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:32> 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:32> 'int' 4
+  float2 Vec2 = float2(1.0, 2.0);   
+  float2x2 H = float2x2(Vec2,3,4);
+
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:32> col:12 I 'float2x2':'matrix<float, 2, 2>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:32> 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:31> 'float2x2':'matrix<float, 2, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:25> 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:25> 'int' lvalue Var 0x{{[0-9a-fA-F]+}} 'i' 'int'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:27> 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:27> 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:27> 'int' lvalue Var 0x{{[0-9a-fA-F]+}} 'j' 'int'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:29> 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:29> 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:29> 'int' lvalue Var 0x{{[0-9a-fA-F]+}} 'k' 'int'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:31> 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:31> 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:31> 'int' lvalue Var 0x{{[0-9a-fA-F]+}} 'l' 'int'
+  int i = 1, j = 2, k = 3, l = 4;
+  float2x2 I = float2x2(i,j,k,l);
+
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:38> col:12 J 'float2x2':'matrix<float, 2, 2>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:38> 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:37> 'float2x2':'matrix<float, 2, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:27> 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:27> 'float' lvalue
+// CHECK-NEXT: MemberExpr 0x{{[0-9a-fA-F]+}} <col:25, col:27> 'float2':'vector<float, 2>' lvalue .f 0x{{[0-9a-fA-F]+}}
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:25> 'struct S' lvalue Var 0x{{[0-9a-fA-F]+}} 's' 'struct S'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 0
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:25, col:27> 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9a-fA-F]+}} <col:25, col:27> 'float' lvalue
+// CHECK-NEXT: MemberExpr 0x{{[0-9a-fA-F]+}} <col:25, col:27> 'float2':'vector<float, 2>' lvalue .f 0x{{[0-9a-fA-F]+}}
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:25> 'struct S' lvalue Var 0x{{[0-9a-fA-F]+}} 's' 'struct S'
+// CHECK-NEXT: IntegerLiteral 0x{{[0-9a-fA-F]+}} <col:25> 'int' 1
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:30, col:32> 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr 0x{{[0-9a-fA-F]+}} <col:30, col:32> 'float' lvalue .a 0x{{[0-9a-fA-F]+}}
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:30> 'struct S' lvalue Var 0x{{[0-9a-fA-F]+}} 's' 'struct S'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:35, col:37> 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr 0x{{[0-9a-fA-F]+}} <col:35, col:37> 'float' lvalue .a 0x{{[0-9a-fA-F]+}}
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:35> 'struct S' lvalue Var 0x{{[0-9a-fA-F]+}} 's' 'struct S'
+  struct S { float2 f;  float a;} s;
+  float2x2 J = float2x2(s.f, s.a, s.a);
+
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:32> col:12 K 'float2x2':'matrix<float, 2, 2>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:32> 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:25, col:31> 'float2x2':'matrix<float, 2, 2>'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float' <UserDefinedConversion>
+// CHECK-NEXT: CXXMemberCallExpr 0x{{[0-9a-fA-F]+}} <col:25> 'float'
+// CHECK-NEXT: MemberExpr 0x{{[0-9a-fA-F]+}} <col:25> '<bound member function type>' .operator float 0x{{[0-9a-fA-F]+}}
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:25> 'const T' lvalue <NoOp>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:25> 'struct T' lvalue Var 0x{{[0-9a-fA-F]+}} 't' 'struct T'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:27> 'float' <UserDefinedConversion>
+// CHECK-NEXT: CXXMemberCallExpr 0x{{[0-9a-fA-F]+}} <col:27> 'float'
+// CHECK-NEXT: MemberExpr 0x{{[0-9a-fA-F]+}} <col:27> '<bound member function type>' .operator float 0x{{[0-9a-fA-F]+}}
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:27> 'const T' lvalue <NoOp>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:27> 'struct T' lvalue Var 0x{{[0-9a-fA-F]+}} 't' 'struct T'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:29> 'float' <UserDefinedConversion>
+// CHECK-NEXT: CXXMemberCallExpr 0x{{[0-9a-fA-F]+}} <col:29> 'float'
+// CHECK-NEXT: MemberExpr 0x{{[0-9a-fA-F]+}} <col:29> '<bound member function type>' .operator float 0x{{[0-9a-fA-F]+}}
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:29> 'const T' lvalue <NoOp>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:29> 'struct T' lvalue Var 0x{{[0-9a-fA-F]+}} 't' 'struct T'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:31> 'float' <UserDefinedConversion>
+// CHECK-NEXT: CXXMemberCallExpr 0x{{[0-9a-fA-F]+}} <col:31> 'float'
+// CHECK-NEXT: MemberExpr 0x{{[0-9a-fA-F]+}} <col:31> '<bound member function type>' .operator float 0x{{[0-9a-fA-F]+}}
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-fA-F]+}} <col:31> 'const T' lvalue <NoOp>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-fA-F]+}} <col:31> 'struct T' lvalue Var 0x{{[0-9a-fA-F]+}} 't' 'struct T'
+  struct T {
+    operator float() const { return 1.0f; }
+  } t;
+  float2x2 K = float2x2(t,t,t,t);
+
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:63> col:28 L 'second_level_of_typedefs':'matrix<float, 2, 2>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:32, col:63> 'float2x2':'matrix<float, 2, 2>' functional cast to float2x2 <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:41, col:59> 'float2x2':'matrix<float, 2, 2>'
+// CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:41> 'float' 1.000000e+00
+// CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:47> 'float' 2.000000e+00
+// CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:53> 'float' 3.000000e+00
+// CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:59> 'float' 4.000000e+00
+  typedef float2x2 second_level_of_typedefs;
+  second_level_of_typedefs L = float2x2(1.0f, 2.0f, 3.0f, 4.0f);
+
+// CHECK: VarDecl 0x{{[0-9a-fA-F]+}} <col:3, col:63> col:12 M 'float2x2':'matrix<float, 2, 2>' cinit
+// CHECK-NEXT: CXXFunctionalCastExpr 0x{{[0-9a-fA-F]+}} <col:16, col:63> 'second_level_of_typedefs':'matrix<float, 2, 2>' functional cast to second_level_of_typedefs <NoOp>
+// CHECK-NEXT: InitListExpr 0x{{[0-9a-fA-F]+}} <col:41, col:59> 'second_level_of_typedefs':'matrix<float, 2, 2>'
+// CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:41> 'float' 1.000000e+00
+// CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:47> 'float' 2.000000e+00
+// CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:53> 'float' 3.000000e+00
+// CHECK-NEXT: FloatingLiteral 0x{{[0-9a-fA-F]+}} <col:59> 'float' 4.000000e+00
+  float2x2 M = second_level_of_typedefs(1.0f, 2.0f, 3.0f, 4.0f);
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/matrix-constructors-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/matrix-constructors-errors.hlsl
new file mode 100644
index 0000000000000..099136dc85de8
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/matrix-constructors-errors.hlsl
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify %s
+
+typedef float float2x1 __attribute__((matrix_type(2,1)));
+typedef float float2x2 __attribute__((matrix_type(2,2)));
+typedef float float2 __attribute__((ext_vector_type(2)));
+
+struct S { float f; };
+struct S2 { float2 f;};
+
+[numthreads(1,1,1)]
+void entry() {
+ float2x1 LilMat = float2x1(1.0, 2.0);
+ float2x1 BrokenMat = float2x1(1.0, 2.0, 3.0); // expected-error{{excess elements in matrix initializer}}
+ float2x2 NormieMat = float2x2(LilMat, 3.0, 4.0, 5.0); // expected-error{{excess elements in matrix initializer}}
+ float2x2 BrokenNormie = float2x2(3.0, 4.0); // expected-error{{too few elements in matrix initialization (expected 4 elements, have 2)}}
+ float2x1 OverwhemledNormie = float2x1(3.0, 4.0, 5.0, 6.0); // expected-error{{excess elements in matrix initializer}}
+
+  // These _should_ work in HLSL but aren't yet supported.
+  S s;
+  float2x1 GettingStrange = float2x1(s, s); // expected-error{{no viable conversion from 'S' to 'float'}} expected-error{{no viable conversion from 'S' to 'float'}}
+
+  S2 s2;
+  float2x2 GettingStrange2 = float2x2(s2, s2); // expected-error{{no viable conversion from 'S2' to 'float'}} expected-error{{no viable conversion from 'S2' to 'float'}} expected-error{{too few elements in matrix initialization (expected 4 elements, have 2)}}
+}

>From 6928df6e067e3fd4ac2990321afafeffd4d87f5c Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Mon, 29 Sep 2025 11:35:07 -0400
Subject: [PATCH 2/2] fix test failures

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 19e4c548d0208..430ebed2133d4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2420,9 +2420,9 @@ def err_init_conversion_failed : Error<
   "cannot initialize %select{a variable|a parameter|template parameter|"
   "return object|statement expression result|an "
   "exception object|a member subobject|an array element|a new value|a value|a "
-  "base class|a constructor delegation|a vector element|a block element|a "
-  "block element|a complex element|a lambda capture|a compound literal "
-  "initializer|a related result|a parameter of CF audited function|a "
+  "base class|a constructor delegation|a vector element|a matrix element|a "
+  "block element|a block element|a complex element|a lambda capture|a compound"
+  " literal initializer|a related result|a parameter of CF audited function|a "
   "structured binding|a member subobject}0 "
   "%diff{of type $ with an %select{rvalue|lvalue}2 of type $|"
   "with an %select{rvalue|lvalue}2 of incompatible type}1,3"



More information about the cfe-commits mailing list