[clang] 761d422 - [HLSL] Implement HLSL intialization list support (#123141)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Feb 15 11:21:40 PST 2025
Author: Chris B
Date: 2025-02-15T13:21:36-06:00
New Revision: 761d422441c0e6822abb233d339fab4f3cf7f60a
URL: https://github.com/llvm/llvm-project/commit/761d422441c0e6822abb233d339fab4f3cf7f60a
DIFF: https://github.com/llvm/llvm-project/commit/761d422441c0e6822abb233d339fab4f3cf7f60a.diff
LOG: [HLSL] Implement HLSL intialization list support (#123141)
This PR implements HLSL's initialization list behvaior as specified in
the draft language specifcation under
[*Decl.Init.Agg*](https://microsoft.github.io/hlsl-specs/specs/hlsl.html#Decl.Init.Agg).
This behavior is a bit unusual for C/C++ because intermediate braces in
initializer lists are ignored and a whole array of additional
conversions occur unintuitively to how initializaiton works in C.
The implementaiton in this PR generates a valid C/C++ initialization
list AST for the HLSL initializer so that there are no changes required
to Clang's CodeGen to support this. This design will also allow us to
use Clang's rewrite to convert HLSL initializers to valid C/C++
initializers that are equivalent. It does have the downside that it will
generate often redundant accesses during codegen. The IR optimizer is
extremely good at eliminating those so this will have no impact on the
final executable performance.
There is some opportunity for optimizing the initializer list generation
that we could consider in subsequent commits. One notable opportunity
would be to identify aggregate objects that occur in the same place in
both initializers and do not require converison, those aggregates could
be initialized as aggregates rather than fully scalarized.
Closes #56067
---------
Co-authored-by: Finn Plummer <50529406+inbelic at users.noreply.github.com>
Co-authored-by: Helena Kotas <hekotas at microsoft.com>
Co-authored-by: Justin Bogner <mail at justinbogner.com>
Added:
clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
clang/test/SemaHLSL/Language/InitListAST.hlsl
clang/test/SemaHLSL/Language/InitLists.hlsl
Modified:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/SemaHLSL.h
clang/lib/AST/DeclCXX.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CGExprAgg.cpp
clang/lib/CodeGen/CGHLSLRuntime.cpp
clang/lib/CodeGen/CGHLSLRuntime.h
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/Sema/SemaChecking.cpp
clang/lib/Sema/SemaHLSL.cpp
clang/lib/Sema/SemaInit.cpp
clang/test/CodeGenHLSL/ArrayTemporary.hlsl
clang/test/SemaHLSL/ArrayTemporary.hlsl
clang/test/SemaHLSL/Language/ElementwiseCast-errors.hlsl
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c4f0fc55b4a38..f10af8f5bd6b2 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12626,6 +12626,9 @@ def err_hlsl_pointers_unsupported : Error<
"%select{pointers|references}0 are unsupported in HLSL">;
def err_hlsl_missing_resource_class : Error<"HLSL resource needs to have [[hlsl::resource_class()]] attribute">;
def err_hlsl_attribute_needs_intangible_type: Error<"attribute %0 can be used only on HLSL intangible type %1">;
+def err_hlsl_incorrect_num_initializers: Error<
+ "too %select{few|many}0 initializers in list for type %1 "
+ "(expected %2 but found %3)">;
def err_hlsl_operator_unsupported : Error<
"the '%select{&|*|->}0' operator is unsupported in HLSL">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index c9266ea50e4bf..4f4bbe95476ee 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -26,6 +26,8 @@
namespace clang {
class AttributeCommonInfo;
class IdentifierInfo;
+class InitializedEntity;
+class InitializationKind;
class ParsedAttr;
class Scope;
class VarDecl;
@@ -149,6 +151,9 @@ class SemaHLSL : public SemaBase {
QualType getInoutParameterType(QualType Ty);
+ bool TransformInitList(const InitializedEntity &Entity,
+ const InitializationKind &Kind, InitListExpr *Init);
+
private:
// HLSL resource type attributes need to be processed all at once.
// This is a list to collect them.
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index e394e0515e599..1aa48f0026335 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1462,6 +1462,18 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal)
data().HasInheritedAssignment = true;
}
+
+ // HLSL: All user-defined data types are aggregates and use aggregate
+ // initialization, meanwhile most, but not all built-in types behave like
+ // aggregates. Resource types, and some other HLSL types that wrap handles
+ // don't behave like aggregates. We can identify these as
diff erent because we
+ // implicitly define "special" member functions, which aren't spellable in
+ // HLSL. This all _needs_ to change in the future. There are two
+ // relevant HLSL feature proposals that will depend on this changing:
+ // * 0005-strict-initializer-lists.md
+ // * https://github.com/microsoft/hlsl-specs/pull/325
+ if (getLangOpts().HLSL)
+ data().Aggregate = data().UserDeclaredSpecialMembers == 0;
}
bool CXXRecordDecl::isLiteral() const {
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 0b0ffd2db853f..191912ca7d800 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5551,6 +5551,12 @@ CodeGenFunction::getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e) {
return EmitAnyExpr(e->getSourceExpr());
}
+bool CodeGenFunction::isOpaqueValueEmitted(const OpaqueValueExpr *E) {
+ if (OpaqueValueMapping::shouldBindAsLValue(E))
+ return OpaqueLValues.contains(E);
+ return OpaqueRValues.contains(E);
+}
+
RValue CodeGenFunction::EmitRValueForField(LValue LV,
const FieldDecl *FD,
SourceLocation Loc) {
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index d25d0f2c2133c..625ca363d9019 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "CGCXXABI.h"
+#include "CGHLSLRuntime.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
@@ -1776,6 +1777,18 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
}
#endif
+ // HLSL initialization lists in the AST are an expansion which can contain
+ // side-effecting expressions wrapped in opaque value expressions. To properly
+ // emit these we need to emit the opaque values before we emit the argument
+ // expressions themselves. This is a little hacky, but it prevents us needing
+ // to do a bigger AST-level change for a language feature that we need
+ // deprecate in the near future. See related HLSL language proposals:
+ // * 0005-strict-initializer-lists.md
+ // * https://github.com/microsoft/hlsl-specs/pull/325
+ if (CGF.getLangOpts().HLSL && isa<InitListExpr>(ExprToVisit))
+ CGF.CGM.getHLSLRuntime().emitInitListOpaqueValues(
+ CGF, cast<InitListExpr>(ExprToVisit));
+
AggValueSlot Dest = EnsureSlot(ExprToVisit->getType());
LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), ExprToVisit->getType());
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 03ddc87d8d3df..856d8b1b2948d 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -14,9 +14,11 @@
#include "CGHLSLRuntime.h"
#include "CGDebugInfo.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
@@ -617,3 +619,33 @@ llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
llvm_unreachable("Convergence token should have been emitted.");
return nullptr;
}
+
+class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
+public:
+ llvm::SmallPtrSet<OpaqueValueExpr *, 8> OVEs;
+ OpaqueValueVisitor() {}
+
+ bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ OVEs.insert(E);
+ return true;
+ }
+};
+
+void CGHLSLRuntime::emitInitListOpaqueValues(CodeGenFunction &CGF,
+ InitListExpr *E) {
+
+ typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
+ OpaqueValueVisitor Visitor;
+ Visitor.TraverseStmt(E);
+ for (auto *OVE : Visitor.OVEs) {
+ if (CGF.isOpaqueValueEmitted(OVE))
+ continue;
+ if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
+ LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
+ OpaqueValueMappingData::bind(CGF, OVE, LV);
+ } else {
+ RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
+ OpaqueValueMappingData::bind(CGF, OVE, RV);
+ }
+ }
+}
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 032b2dee82f21..8767a2ddceb96 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -55,6 +55,7 @@ class StructType;
namespace clang {
class VarDecl;
class ParmVarDecl;
+class InitListExpr;
class HLSLBufferDecl;
class HLSLResourceBindingAttr;
class Type;
@@ -65,6 +66,7 @@ class FunctionDecl;
namespace CodeGen {
class CodeGenModule;
+class CodeGenFunction;
class CGHLSLRuntime {
public:
@@ -161,6 +163,8 @@ class CGHLSLRuntime {
llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB);
+ void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E);
+
private:
void addBufferResourceAnnotation(llvm::GlobalVariable *GV,
llvm::hlsl::ResourceClass RC,
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 64cd8a3ac55e2..8c5362bcc33c4 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3011,6 +3011,10 @@ class CodeGenFunction : public CodeGenTypeCache {
/// otherwise create one.
RValue getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e);
+ /// isOpaqueValueEmitted - Return true if the opaque value expression has
+ /// already been emitted.
+ bool isOpaqueValueEmitted(const OpaqueValueExpr *E);
+
/// Get the index of the current ArrayInitLoopExpr, if any.
llvm::Value *getArrayInitIndex() { return ArrayInitIndex; }
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 66c233de4ef30..aae61f612a4bc 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11679,8 +11679,12 @@ static void AnalyzeImplicitConversions(
// Propagate whether we are in a C++ list initialization expression.
// If so, we do not issue warnings for implicit int-float conversion
// precision loss, because C++11 narrowing already handles it.
- bool IsListInit = Item.IsListInit ||
- (isa<InitListExpr>(OrigE) && S.getLangOpts().CPlusPlus);
+ //
+ // HLSL's initialization lists are special, so they shouldn't observe the C++
+ // behavior here.
+ bool IsListInit =
+ Item.IsListInit || (isa<InitListExpr>(OrigE) &&
+ S.getLangOpts().CPlusPlus && !S.getLangOpts().HLSL);
if (E->isTypeDependent() || E->isValueDependent())
return;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 9a60054a6169e..be45761552290 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2589,17 +2589,20 @@ static void BuildFlattenedTypeList(QualType BaseTy,
continue;
}
if (const auto *RT = dyn_cast<RecordType>(T)) {
- const RecordDecl *RD = RT->getDecl();
- if (RD->isUnion()) {
+ const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
+ assert(RD && "HLSL record types should all be CXXRecordDecls!");
+
+ if (RD->isStandardLayout())
+ RD = RD->getStandardLayoutBaseWithFields();
+
+ // For types that we shouldn't decompose (unions and non-aggregates), just
+ // add the type itself to the list.
+ if (RD->isUnion() || !RD->isAggregate()) {
List.push_back(T);
continue;
}
- const CXXRecordDecl *CXXD = dyn_cast<CXXRecordDecl>(RD);
llvm::SmallVector<QualType, 16> FieldTypes;
- if (CXXD && CXXD->isStandardLayout())
- RD = CXXD->getStandardLayoutBaseWithFields();
-
for (const auto *FD : RD->fields())
FieldTypes.push_back(FD->getType());
// Reverse the newly added sub-range.
@@ -2608,9 +2611,9 @@ static void BuildFlattenedTypeList(QualType BaseTy,
// If this wasn't a standard layout type we may also have some base
// classes to deal with.
- if (CXXD && !CXXD->isStandardLayout()) {
+ if (!RD->isStandardLayout()) {
FieldTypes.clear();
- for (const auto &Base : CXXD->bases())
+ for (const auto &Base : RD->bases())
FieldTypes.push_back(Base.getType());
std::reverse(FieldTypes.begin(), FieldTypes.end());
WorkList.insert(WorkList.end(), FieldTypes.begin(), FieldTypes.end());
@@ -3056,3 +3059,193 @@ void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
}
}
}
+
+static bool CastInitializer(Sema &S, ASTContext &Ctx, Expr *E,
+ llvm::SmallVectorImpl<Expr *> &List,
+ llvm::SmallVectorImpl<QualType> &DestTypes) {
+ if (List.size() >= DestTypes.size()) {
+ List.push_back(E);
+ // This is odd, but it isn't technically a failure due to conversion, we
+ // handle mismatched counts of arguments
diff erently.
+ return true;
+ }
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Ctx, DestTypes[List.size()], false);
+ ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E);
+ if (Res.isInvalid())
+ return false;
+ Expr *Init = Res.get();
+ List.push_back(Init);
+ return true;
+}
+
+static bool BuildInitializerList(Sema &S, ASTContext &Ctx, Expr *E,
+ llvm::SmallVectorImpl<Expr *> &List,
+ llvm::SmallVectorImpl<QualType> &DestTypes) {
+ // If this is an initialization list, traverse the sub initializers.
+ if (auto *Init = dyn_cast<InitListExpr>(E)) {
+ for (auto *SubInit : Init->inits())
+ if (!BuildInitializerList(S, Ctx, SubInit, List, DestTypes))
+ return false;
+ return true;
+ }
+
+ // If this is a scalar type, just enqueue the expression.
+ QualType Ty = E->getType();
+
+ if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))
+ return CastInitializer(S, Ctx, E, List, DestTypes);
+
+ if (auto *VecTy = Ty->getAs<VectorType>()) {
+ uint64_t Size = VecTy->getNumElements();
+
+ QualType SizeTy = Ctx.getSizeType();
+ uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
+ for (uint64_t I = 0; I < Size; ++I) {
+ auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
+ SizeTy, SourceLocation());
+
+ ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr(
+ E, E->getBeginLoc(), Idx, E->getEndLoc());
+ if (ElExpr.isInvalid())
+ return false;
+ if (!CastInitializer(S, Ctx, ElExpr.get(), List, DestTypes))
+ return false;
+ }
+ return true;
+ }
+
+ if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr())) {
+ uint64_t Size = ArrTy->getZExtSize();
+ QualType SizeTy = Ctx.getSizeType();
+ uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);
+ for (uint64_t I = 0; I < Size; ++I) {
+ auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),
+ SizeTy, SourceLocation());
+ ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr(
+ E, E->getBeginLoc(), Idx, E->getEndLoc());
+ if (ElExpr.isInvalid())
+ return false;
+ if (!BuildInitializerList(S, Ctx, ElExpr.get(), List, DestTypes))
+ return false;
+ }
+ return true;
+ }
+
+ if (auto *RTy = Ty->getAs<RecordType>()) {
+ llvm::SmallVector<const RecordType *> RecordTypes;
+ RecordTypes.push_back(RTy);
+ while (RecordTypes.back()->getAsCXXRecordDecl()->getNumBases()) {
+ CXXRecordDecl *D = RecordTypes.back()->getAsCXXRecordDecl();
+ assert(D->getNumBases() == 1 &&
+ "HLSL doesn't support multiple inheritance");
+ RecordTypes.push_back(D->bases_begin()->getType()->getAs<RecordType>());
+ }
+ while (!RecordTypes.empty()) {
+ const RecordType *RT = RecordTypes.back();
+ RecordTypes.pop_back();
+ for (auto *FD : RT->getDecl()->fields()) {
+ DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess());
+ DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc());
+ ExprResult Res = S.BuildFieldReferenceExpr(
+ E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo);
+ if (Res.isInvalid())
+ return false;
+ if (!BuildInitializerList(S, Ctx, Res.get(), List, DestTypes))
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+static Expr *GenerateInitLists(ASTContext &Ctx, QualType Ty,
+ llvm::SmallVectorImpl<Expr *>::iterator &It) {
+ if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType())) {
+ return *(It++);
+ }
+ llvm::SmallVector<Expr *> Inits;
+ assert(!isa<MatrixType>(Ty) && "Matrix types not yet supported in HLSL");
+ Ty = Ty.getDesugaredType(Ctx);
+ if (Ty->isVectorType() || Ty->isConstantArrayType()) {
+ QualType ElTy;
+ uint64_t Size = 0;
+ if (auto *ATy = Ty->getAs<VectorType>()) {
+ ElTy = ATy->getElementType();
+ Size = ATy->getNumElements();
+ } else {
+ auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr());
+ ElTy = VTy->getElementType();
+ Size = VTy->getZExtSize();
+ }
+ for (uint64_t I = 0; I < Size; ++I)
+ Inits.push_back(GenerateInitLists(Ctx, ElTy, It));
+ }
+ if (auto *RTy = Ty->getAs<RecordType>()) {
+ llvm::SmallVector<const RecordType *> RecordTypes;
+ RecordTypes.push_back(RTy);
+ while (RecordTypes.back()->getAsCXXRecordDecl()->getNumBases()) {
+ CXXRecordDecl *D = RecordTypes.back()->getAsCXXRecordDecl();
+ assert(D->getNumBases() == 1 &&
+ "HLSL doesn't support multiple inheritance");
+ RecordTypes.push_back(D->bases_begin()->getType()->getAs<RecordType>());
+ }
+ while (!RecordTypes.empty()) {
+ const RecordType *RT = RecordTypes.back();
+ RecordTypes.pop_back();
+ for (auto *FD : RT->getDecl()->fields()) {
+ Inits.push_back(GenerateInitLists(Ctx, FD->getType(), It));
+ }
+ }
+ }
+ auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),
+ Inits, Inits.back()->getEndLoc());
+ NewInit->setType(Ty);
+ return NewInit;
+}
+
+bool SemaHLSL::TransformInitList(const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ InitListExpr *Init) {
+ // If the initializer is a scalar, just return it.
+ if (Init->getType()->isScalarType())
+ return true;
+ ASTContext &Ctx = SemaRef.getASTContext();
+ llvm::SmallVector<QualType, 16> DestTypes;
+ // An initializer list might be attempting to initialize a reference or
+ // rvalue-reference. When checking the initializer we should look through the
+ // reference.
+ QualType InitTy = Entity.getType().getNonReferenceType();
+ BuildFlattenedTypeList(InitTy, DestTypes);
+
+ llvm::SmallVector<Expr *, 16> ArgExprs;
+ for (unsigned I = 0; I < Init->getNumInits(); ++I) {
+ Expr *E = Init->getInit(I);
+ if (E->HasSideEffects(Ctx)) {
+ QualType Ty = E->getType();
+ if (auto *RTy = Ty->getAs<RecordType>())
+ E = new (Ctx) MaterializeTemporaryExpr(Ty, E, E->isLValue());
+ E = new (Ctx) OpaqueValueExpr(E->getBeginLoc(), Ty, E->getValueKind(),
+ E->getObjectKind(), E);
+ Init->setInit(I, E);
+ }
+ if (!BuildInitializerList(SemaRef, Ctx, E, ArgExprs, DestTypes))
+ return false;
+ }
+
+ if (DestTypes.size() != ArgExprs.size()) {
+ int TooManyOrFew = ArgExprs.size() > DestTypes.size() ? 1 : 0;
+ SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)
+ << TooManyOrFew << InitTy << DestTypes.size() << ArgExprs.size();
+ return false;
+ }
+
+ auto It = ArgExprs.begin();
+ // GenerateInitLists will always return an InitListExpr here, because the
+ // scalar case is handled above.
+ auto *NewInit = cast<InitListExpr>(GenerateInitLists(Ctx, InitTy, It));
+ Init->resizeInits(Ctx, NewInit->getNumInits());
+ for (unsigned I = 0; I < NewInit->getNumInits(); ++I)
+ Init->updateInit(Ctx, I, NewInit->getInit(I));
+ return true;
+}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 18090eb1c9e9a..6a76e6d74a4b0 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -26,6 +26,7 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Ownership.h"
+#include "clang/Sema/SemaHLSL.h"
#include "clang/Sema/SemaObjC.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/FoldingSet.h"
@@ -4787,6 +4788,10 @@ static void TryListInitialization(Sema &S,
bool TreatUnavailableAsInvalid) {
QualType DestType = Entity.getType();
+ if (S.getLangOpts().HLSL &&
+ !S.HLSL().TransformInitList(Entity, Kind, InitList))
+ return;
+
// C++ doesn't allow scalar initialization with more than one argument.
// But C99 complex numbers are scalars and it makes sense there.
if (S.getLangOpts().CPlusPlus && DestType->isScalarType() &&
diff --git a/clang/test/CodeGenHLSL/ArrayTemporary.hlsl b/clang/test/CodeGenHLSL/ArrayTemporary.hlsl
index e5db7eac37a42..91a283554459d 100644
--- a/clang/test/CodeGenHLSL/ArrayTemporary.hlsl
+++ b/clang/test/CodeGenHLSL/ArrayTemporary.hlsl
@@ -1,3 +1,4 @@
+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
void fn(float x[2]) { }
@@ -27,7 +28,7 @@ void fn2(Obj O[4]) { }
// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 32, i1 false)
// CHECK: call void {{.*}}fn2{{.*}}(ptr noundef byval([4 x %struct.Obj]) align 4 [[Tmp]])
void call2() {
- Obj Arr[4] = {};
+ Obj Arr[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
fn2(Arr);
}
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
new file mode 100644
index 0000000000000..a0590162c7087
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BasicFeatures/InitLists.hlsl
@@ -0,0 +1,963 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -disable-llvm-passes -emit-llvm -finclude-default-header -o - %s | FileCheck %s
+
+struct TwoFloats {
+ float X, Y;
+};
+
+struct TwoInts {
+ int Z, W;
+};
+
+struct Doggo {
+ int4 LegState;
+ int TailState;
+ float HairCount;
+ float4 EarDirection[2];
+};
+
+struct AnimalBits {
+ int Legs[4];
+ uint State;
+ int64_t Counter;
+ float4 LeftDir;
+ float4 RightDir;
+};
+
+struct Kitteh {
+ int4 Legs;
+ int TailState;
+ float HairCount;
+ float4 Claws[2];
+};
+
+struct Zoo {
+ Doggo Dogs[2];
+ Kitteh Cats[4];
+};
+
+struct FourFloats : TwoFloats {
+ float Z, W;
+};
+
+struct SlicyBits {
+ int Z : 8;
+ int W : 8;
+};
+
+// Case 1: Extraneous braces get ignored in literal instantiation.
+// CHECK-LABEL: define void @_Z5case1v(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 @__const._Z5case1v.TF1, i32 8, i1 false)
+// CHECK-NEXT: ret void
+//
+TwoFloats case1() {
+ TwoFloats TF1 = {{{1.0, 2}}};
+ return TF1;
+}
+
+// Case 2: Valid C/C++ initializer is handled appropriately.
+// CHECK-LABEL: define void @_Z5case2v(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 @__const._Z5case2v.TF2, i32 8, i1 false)
+// CHECK-NEXT: ret void
+//
+TwoFloats case2() {
+ TwoFloats TF2 = {1, 2};
+ return TF2;
+}
+
+// Case 3: Simple initialization with conversion of an argument.
+// CHECK-LABEL: define void @_Z5case3i(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[VAL:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[VAL_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[VAL]], ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP0]] to float
+// CHECK-NEXT: store float [[CONV]], ptr [[X]], align 4
+// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: store float 2.000000e+00, ptr [[Y]], align 4
+// CHECK-NEXT: ret void
+//
+TwoFloats case3(int Val) {
+ TwoFloats TF3 = {Val, 2};
+ return TF3;
+}
+
+// Case 4: Initialization from a scalarized vector into a structure with element
+// conversions.
+// CHECK-LABEL: define void @_Z5case4Dv2_i(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], <2 x i32> noundef [[TWOVALS:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TWOVALS_ADDR:%.*]] = alloca <2 x i32>, align 8
+// CHECK-NEXT: store <2 x i32> [[TWOVALS]], ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <2 x i32> [[TMP0]], i64 0
+// CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[VECEXT]] to float
+// CHECK-NEXT: store float [[CONV]], ptr [[X]], align 4
+// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT: [[VECEXT1:%.*]] = extractelement <2 x i32> [[TMP1]], i64 1
+// CHECK-NEXT: [[CONV2:%.*]] = sitofp i32 [[VECEXT1]] to float
+// CHECK-NEXT: store float [[CONV2]], ptr [[Y]], align 4
+// CHECK-NEXT: ret void
+//
+TwoFloats case4(int2 TwoVals) {
+ TwoFloats TF4 = {TwoVals};
+ return TF4;
+}
+
+// Case 5: Initialization from a scalarized vector of matching type.
+// CHECK-LABEL: define void @_Z5case5Dv2_i(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOINTS:%.*]]) align 4 [[AGG_RESULT:%.*]], <2 x i32> noundef [[TWOVALS:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TWOVALS_ADDR:%.*]] = alloca <2 x i32>, align 8
+// CHECK-NEXT: store <2 x i32> [[TWOVALS]], ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <2 x i32> [[TMP0]], i64 0
+// CHECK-NEXT: store i32 [[VECEXT]], ptr [[Z]], align 4
+// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[TWOVALS_ADDR]], align 8
+// CHECK-NEXT: [[VECEXT1:%.*]] = extractelement <2 x i32> [[TMP1]], i64 1
+// CHECK-NEXT: store i32 [[VECEXT1]], ptr [[W]], align 4
+// CHECK-NEXT: ret void
+//
+TwoInts case5(int2 TwoVals) {
+ TwoInts TI1 = {TwoVals};
+ return TI1;
+}
+
+// Case 6: Initialization from a scalarized structure of
diff erent type with
+//
diff erent element types.
+// CHECK-LABEL: define void @_Z5case69TwoFloats(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOINTS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS:%.*]]) align 4 [[TF4:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF4]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[TMP0]] to i32
+// CHECK-NEXT: store i32 [[CONV]], ptr [[Z]], align 4
+// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF4]], i32 0, i32 1
+// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[Y]], align 4
+// CHECK-NEXT: [[CONV1:%.*]] = fptosi float [[TMP1]] to i32
+// CHECK-NEXT: store i32 [[CONV1]], ptr [[W]], align 4
+// CHECK-NEXT: ret void
+//
+TwoInts case6(TwoFloats TF4) {
+ TwoInts TI2 = {TF4};
+ return TI2;
+}
+
+// Case 7: Initialization of a complex structure, with bogus braces and element
+// conversions from a collection of scalar values, and structures.
+// CHECK-LABEL: define void @_Z5case77TwoIntsS_i9TwoFloatsS0_S0_S0_(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_DOGGO:%.*]]) align 16 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_TWOINTS:%.*]]) align 4 [[TI1:%.*]], ptr noundef byval([[STRUCT_TWOINTS]]) align 4 [[TI2:%.*]], i32 noundef [[VAL:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS:%.*]]) align 4 [[TF1:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS]]) align 4 [[TF2:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS]]) align 4 [[TF3:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS]]) align 4 [[TF4:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[VAL_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[VAL]], ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT: [[LEGSTATE:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[Z]], align 4
+// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i32 0
+// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[W]], align 4
+// CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <4 x i32> [[VECINIT]], i32 [[TMP1]], i32 1
+// CHECK-NEXT: [[Z2:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI2]], i32 0, i32 0
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[Z2]], align 4
+// CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <4 x i32> [[VECINIT1]], i32 [[TMP2]], i32 2
+// CHECK-NEXT: [[W4:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI2]], i32 0, i32 1
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[W4]], align 4
+// CHECK-NEXT: [[VECINIT5:%.*]] = insertelement <4 x i32> [[VECINIT3]], i32 [[TMP3]], i32 3
+// CHECK-NEXT: store <4 x i32> [[VECINIT5]], ptr [[LEGSTATE]], align 16
+// CHECK-NEXT: [[TAILSTATE:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT: store i32 [[TMP4]], ptr [[TAILSTATE]], align 16
+// CHECK-NEXT: [[HAIRCOUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[AGG_RESULT]], i32 0, i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[VAL_ADDR]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP5]] to float
+// CHECK-NEXT: store float [[CONV]], ptr [[HAIRCOUNT]], align 4
+// CHECK-NEXT: [[EARDIRECTION:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[AGG_RESULT]], i32 0, i32 3
+// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP6:%.*]] = load float, ptr [[X]], align 4
+// CHECK-NEXT: [[VECINIT6:%.*]] = insertelement <4 x float> poison, float [[TMP6]], i32 0
+// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP7:%.*]] = load float, ptr [[Y]], align 4
+// CHECK-NEXT: [[VECINIT7:%.*]] = insertelement <4 x float> [[VECINIT6]], float [[TMP7]], i32 1
+// CHECK-NEXT: [[X8:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF2]], i32 0, i32 0
+// CHECK-NEXT: [[TMP8:%.*]] = load float, ptr [[X8]], align 4
+// CHECK-NEXT: [[VECINIT9:%.*]] = insertelement <4 x float> [[VECINIT7]], float [[TMP8]], i32 2
+// CHECK-NEXT: [[Y10:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF2]], i32 0, i32 1
+// CHECK-NEXT: [[TMP9:%.*]] = load float, ptr [[Y10]], align 4
+// CHECK-NEXT: [[VECINIT11:%.*]] = insertelement <4 x float> [[VECINIT9]], float [[TMP9]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT11]], ptr [[EARDIRECTION]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds <4 x float>, ptr [[EARDIRECTION]], i32 1
+// CHECK-NEXT: [[X12:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF3]], i32 0, i32 0
+// CHECK-NEXT: [[TMP10:%.*]] = load float, ptr [[X12]], align 4
+// CHECK-NEXT: [[VECINIT13:%.*]] = insertelement <4 x float> poison, float [[TMP10]], i32 0
+// CHECK-NEXT: [[Y14:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF3]], i32 0, i32 1
+// CHECK-NEXT: [[TMP11:%.*]] = load float, ptr [[Y14]], align 4
+// CHECK-NEXT: [[VECINIT15:%.*]] = insertelement <4 x float> [[VECINIT13]], float [[TMP11]], i32 1
+// CHECK-NEXT: [[X16:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF4]], i32 0, i32 0
+// CHECK-NEXT: [[TMP12:%.*]] = load float, ptr [[X16]], align 4
+// CHECK-NEXT: [[VECINIT17:%.*]] = insertelement <4 x float> [[VECINIT15]], float [[TMP12]], i32 2
+// CHECK-NEXT: [[Y18:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF4]], i32 0, i32 1
+// CHECK-NEXT: [[TMP13:%.*]] = load float, ptr [[Y18]], align 4
+// CHECK-NEXT: [[VECINIT19:%.*]] = insertelement <4 x float> [[VECINIT17]], float [[TMP13]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT19]], ptr [[ARRAYINIT_ELEMENT]], align 16
+// CHECK-NEXT: ret void
+//
+Doggo case7(TwoInts TI1, TwoInts TI2, int Val, TwoFloats TF1, TwoFloats TF2,
+ TwoFloats TF3, TwoFloats TF4) {
+ Doggo D1 = {TI1, TI2, {Val, Val}, {{TF1, TF2}, {TF3, TF4}}};
+ return D1;
+}
+
+// Case 8: Initialization of a structure from a
diff erent structure with
+// significantly
diff erent element types and grouping.
+// CHECK-LABEL: define void @_Z5case85Doggo(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_ANIMALBITS:%.*]]) align 16 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_DOGGO:%.*]]) align 16 [[D1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[LEGS:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[LEGSTATE:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr [[LEGSTATE]], align 16
+// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <4 x i32> [[TMP0]], i64 0
+// CHECK-NEXT: store i32 [[VECEXT]], ptr [[LEGS]], align 4
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds i32, ptr [[LEGS]], i32 1
+// CHECK-NEXT: [[LEGSTATE1:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[LEGSTATE1]], align 16
+// CHECK-NEXT: [[VECEXT2:%.*]] = extractelement <4 x i32> [[TMP1]], i64 1
+// CHECK-NEXT: store i32 [[VECEXT2]], ptr [[ARRAYINIT_ELEMENT]], align 4
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT3:%.*]] = getelementptr inbounds i32, ptr [[LEGS]], i32 2
+// CHECK-NEXT: [[LEGSTATE4:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr [[LEGSTATE4]], align 16
+// CHECK-NEXT: [[VECEXT5:%.*]] = extractelement <4 x i32> [[TMP2]], i64 2
+// CHECK-NEXT: store i32 [[VECEXT5]], ptr [[ARRAYINIT_ELEMENT3]], align 4
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT6:%.*]] = getelementptr inbounds i32, ptr [[LEGS]], i32 3
+// CHECK-NEXT: [[LEGSTATE7:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i32>, ptr [[LEGSTATE7]], align 16
+// CHECK-NEXT: [[VECEXT8:%.*]] = extractelement <4 x i32> [[TMP3]], i64 3
+// CHECK-NEXT: store i32 [[VECEXT8]], ptr [[ARRAYINIT_ELEMENT6]], align 4
+// CHECK-NEXT: [[STATE:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[TAILSTATE:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TAILSTATE]], align 16
+// CHECK-NEXT: store i32 [[TMP4]], ptr [[STATE]], align 16
+// CHECK-NEXT: [[COUNTER:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 2
+// CHECK-NEXT: [[HAIRCOUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[HAIRCOUNT]], align 4
+// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[TMP5]] to i64
+// CHECK-NEXT: store i64 [[CONV]], ptr [[COUNTER]], align 8
+// CHECK-NEXT: [[LEFTDIR:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 3
+// CHECK-NEXT: [[EARDIRECTION:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION]], i32 0, i32 0
+// CHECK-NEXT: [[TMP6:%.*]] = load <4 x float>, ptr [[ARRAYIDX]], align 16
+// CHECK-NEXT: [[VECEXT9:%.*]] = extractelement <4 x float> [[TMP6]], i64 0
+// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <4 x float> poison, float [[VECEXT9]], i32 0
+// CHECK-NEXT: [[EARDIRECTION10:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION10]], i32 0, i32 0
+// CHECK-NEXT: [[TMP7:%.*]] = load <4 x float>, ptr [[ARRAYIDX11]], align 16
+// CHECK-NEXT: [[VECEXT12:%.*]] = extractelement <4 x float> [[TMP7]], i64 1
+// CHECK-NEXT: [[VECINIT13:%.*]] = insertelement <4 x float> [[VECINIT]], float [[VECEXT12]], i32 1
+// CHECK-NEXT: [[EARDIRECTION14:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION14]], i32 0, i32 0
+// CHECK-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[ARRAYIDX15]], align 16
+// CHECK-NEXT: [[VECEXT16:%.*]] = extractelement <4 x float> [[TMP8]], i64 2
+// CHECK-NEXT: [[VECINIT17:%.*]] = insertelement <4 x float> [[VECINIT13]], float [[VECEXT16]], i32 2
+// CHECK-NEXT: [[EARDIRECTION18:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX19:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION18]], i32 0, i32 0
+// CHECK-NEXT: [[TMP9:%.*]] = load <4 x float>, ptr [[ARRAYIDX19]], align 16
+// CHECK-NEXT: [[VECEXT20:%.*]] = extractelement <4 x float> [[TMP9]], i64 3
+// CHECK-NEXT: [[VECINIT21:%.*]] = insertelement <4 x float> [[VECINIT17]], float [[VECEXT20]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT21]], ptr [[LEFTDIR]], align 16
+// CHECK-NEXT: [[RIGHTDIR:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[AGG_RESULT]], i32 0, i32 4
+// CHECK-NEXT: [[EARDIRECTION22:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX23:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION22]], i32 0, i32 1
+// CHECK-NEXT: [[TMP10:%.*]] = load <4 x float>, ptr [[ARRAYIDX23]], align 16
+// CHECK-NEXT: [[VECEXT24:%.*]] = extractelement <4 x float> [[TMP10]], i64 0
+// CHECK-NEXT: [[VECINIT25:%.*]] = insertelement <4 x float> poison, float [[VECEXT24]], i32 0
+// CHECK-NEXT: [[EARDIRECTION26:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX27:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION26]], i32 0, i32 1
+// CHECK-NEXT: [[TMP11:%.*]] = load <4 x float>, ptr [[ARRAYIDX27]], align 16
+// CHECK-NEXT: [[VECEXT28:%.*]] = extractelement <4 x float> [[TMP11]], i64 1
+// CHECK-NEXT: [[VECINIT29:%.*]] = insertelement <4 x float> [[VECINIT25]], float [[VECEXT28]], i32 1
+// CHECK-NEXT: [[EARDIRECTION30:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX31:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION30]], i32 0, i32 1
+// CHECK-NEXT: [[TMP12:%.*]] = load <4 x float>, ptr [[ARRAYIDX31]], align 16
+// CHECK-NEXT: [[VECEXT32:%.*]] = extractelement <4 x float> [[TMP12]], i64 2
+// CHECK-NEXT: [[VECINIT33:%.*]] = insertelement <4 x float> [[VECINIT29]], float [[VECEXT32]], i32 2
+// CHECK-NEXT: [[EARDIRECTION34:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX35:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION34]], i32 0, i32 1
+// CHECK-NEXT: [[TMP13:%.*]] = load <4 x float>, ptr [[ARRAYIDX35]], align 16
+// CHECK-NEXT: [[VECEXT36:%.*]] = extractelement <4 x float> [[TMP13]], i64 3
+// CHECK-NEXT: [[VECINIT37:%.*]] = insertelement <4 x float> [[VECINIT33]], float [[VECEXT36]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT37]], ptr [[RIGHTDIR]], align 16
+// CHECK-NEXT: ret void
+//
+AnimalBits case8(Doggo D1) {
+ AnimalBits A1 = {D1};
+ return A1;
+}
+
+// Case 9: Everything everywhere all at once... Initializing mismatched
+// structures from
diff erent layouts,
diff erent component groupings, with no
+// top-level bracing separation.
+// CHECK-LABEL: define void @_Z5case95Doggo10AnimalBits(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_ZOO:%.*]]) align 16 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_DOGGO:%.*]]) align 16 [[D1:%.*]], ptr noundef byval([[STRUCT_ANIMALBITS:%.*]]) align 16 [[A1:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[DOGS:%.*]] = getelementptr inbounds nuw [[STRUCT_ZOO]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[LEGSTATE:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[DOGS]], i32 0, i32 0
+// CHECK-NEXT: [[LEGSTATE1:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr [[LEGSTATE1]], align 16
+// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <4 x i32> [[TMP0]], i64 0
+// CHECK-NEXT: [[VECINIT:%.*]] = insertelement <4 x i32> poison, i32 [[VECEXT]], i32 0
+// CHECK-NEXT: [[LEGSTATE2:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[LEGSTATE2]], align 16
+// CHECK-NEXT: [[VECEXT3:%.*]] = extractelement <4 x i32> [[TMP1]], i64 1
+// CHECK-NEXT: [[VECINIT4:%.*]] = insertelement <4 x i32> [[VECINIT]], i32 [[VECEXT3]], i32 1
+// CHECK-NEXT: [[LEGSTATE5:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr [[LEGSTATE5]], align 16
+// CHECK-NEXT: [[VECEXT6:%.*]] = extractelement <4 x i32> [[TMP2]], i64 2
+// CHECK-NEXT: [[VECINIT7:%.*]] = insertelement <4 x i32> [[VECINIT4]], i32 [[VECEXT6]], i32 2
+// CHECK-NEXT: [[LEGSTATE8:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load <4 x i32>, ptr [[LEGSTATE8]], align 16
+// CHECK-NEXT: [[VECEXT9:%.*]] = extractelement <4 x i32> [[TMP3]], i64 3
+// CHECK-NEXT: [[VECINIT10:%.*]] = insertelement <4 x i32> [[VECINIT7]], i32 [[VECEXT9]], i32 3
+// CHECK-NEXT: store <4 x i32> [[VECINIT10]], ptr [[LEGSTATE]], align 16
+// CHECK-NEXT: [[TAILSTATE:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[DOGS]], i32 0, i32 1
+// CHECK-NEXT: [[TAILSTATE11:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[TAILSTATE11]], align 16
+// CHECK-NEXT: store i32 [[TMP4]], ptr [[TAILSTATE]], align 16
+// CHECK-NEXT: [[HAIRCOUNT:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[DOGS]], i32 0, i32 2
+// CHECK-NEXT: [[HAIRCOUNT12:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 2
+// CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[HAIRCOUNT12]], align 4
+// CHECK-NEXT: store float [[TMP5]], ptr [[HAIRCOUNT]], align 4
+// CHECK-NEXT: [[EARDIRECTION:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[DOGS]], i32 0, i32 3
+// CHECK-NEXT: [[EARDIRECTION13:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION13]], i32 0, i32 0
+// CHECK-NEXT: [[TMP6:%.*]] = load <4 x float>, ptr [[ARRAYIDX]], align 16
+// CHECK-NEXT: [[VECEXT14:%.*]] = extractelement <4 x float> [[TMP6]], i64 0
+// CHECK-NEXT: [[VECINIT15:%.*]] = insertelement <4 x float> poison, float [[VECEXT14]], i32 0
+// CHECK-NEXT: [[EARDIRECTION16:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX17:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION16]], i32 0, i32 0
+// CHECK-NEXT: [[TMP7:%.*]] = load <4 x float>, ptr [[ARRAYIDX17]], align 16
+// CHECK-NEXT: [[VECEXT18:%.*]] = extractelement <4 x float> [[TMP7]], i64 1
+// CHECK-NEXT: [[VECINIT19:%.*]] = insertelement <4 x float> [[VECINIT15]], float [[VECEXT18]], i32 1
+// CHECK-NEXT: [[EARDIRECTION20:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX21:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION20]], i32 0, i32 0
+// CHECK-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[ARRAYIDX21]], align 16
+// CHECK-NEXT: [[VECEXT22:%.*]] = extractelement <4 x float> [[TMP8]], i64 2
+// CHECK-NEXT: [[VECINIT23:%.*]] = insertelement <4 x float> [[VECINIT19]], float [[VECEXT22]], i32 2
+// CHECK-NEXT: [[EARDIRECTION24:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX25:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION24]], i32 0, i32 0
+// CHECK-NEXT: [[TMP9:%.*]] = load <4 x float>, ptr [[ARRAYIDX25]], align 16
+// CHECK-NEXT: [[VECEXT26:%.*]] = extractelement <4 x float> [[TMP9]], i64 3
+// CHECK-NEXT: [[VECINIT27:%.*]] = insertelement <4 x float> [[VECINIT23]], float [[VECEXT26]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT27]], ptr [[EARDIRECTION]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds <4 x float>, ptr [[EARDIRECTION]], i32 1
+// CHECK-NEXT: [[EARDIRECTION28:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX29:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION28]], i32 0, i32 1
+// CHECK-NEXT: [[TMP10:%.*]] = load <4 x float>, ptr [[ARRAYIDX29]], align 16
+// CHECK-NEXT: [[VECEXT30:%.*]] = extractelement <4 x float> [[TMP10]], i64 0
+// CHECK-NEXT: [[VECINIT31:%.*]] = insertelement <4 x float> poison, float [[VECEXT30]], i32 0
+// CHECK-NEXT: [[EARDIRECTION32:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX33:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION32]], i32 0, i32 1
+// CHECK-NEXT: [[TMP11:%.*]] = load <4 x float>, ptr [[ARRAYIDX33]], align 16
+// CHECK-NEXT: [[VECEXT34:%.*]] = extractelement <4 x float> [[TMP11]], i64 1
+// CHECK-NEXT: [[VECINIT35:%.*]] = insertelement <4 x float> [[VECINIT31]], float [[VECEXT34]], i32 1
+// CHECK-NEXT: [[EARDIRECTION36:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX37:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION36]], i32 0, i32 1
+// CHECK-NEXT: [[TMP12:%.*]] = load <4 x float>, ptr [[ARRAYIDX37]], align 16
+// CHECK-NEXT: [[VECEXT38:%.*]] = extractelement <4 x float> [[TMP12]], i64 2
+// CHECK-NEXT: [[VECINIT39:%.*]] = insertelement <4 x float> [[VECINIT35]], float [[VECEXT38]], i32 2
+// CHECK-NEXT: [[EARDIRECTION40:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX41:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION40]], i32 0, i32 1
+// CHECK-NEXT: [[TMP13:%.*]] = load <4 x float>, ptr [[ARRAYIDX41]], align 16
+// CHECK-NEXT: [[VECEXT42:%.*]] = extractelement <4 x float> [[TMP13]], i64 3
+// CHECK-NEXT: [[VECINIT43:%.*]] = insertelement <4 x float> [[VECINIT39]], float [[VECEXT42]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT43]], ptr [[ARRAYINIT_ELEMENT]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT44:%.*]] = getelementptr inbounds [[STRUCT_DOGGO]], ptr [[DOGS]], i32 1
+// CHECK-NEXT: [[LEGSTATE45:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[ARRAYINIT_ELEMENT44]], i32 0, i32 0
+// CHECK-NEXT: [[LEGS:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX46:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS]], i32 0, i32 0
+// CHECK-NEXT: [[TMP14:%.*]] = load i32, ptr [[ARRAYIDX46]], align 16
+// CHECK-NEXT: [[VECINIT47:%.*]] = insertelement <4 x i32> poison, i32 [[TMP14]], i32 0
+// CHECK-NEXT: [[LEGS48:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX49:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS48]], i32 0, i32 1
+// CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[ARRAYIDX49]], align 4
+// CHECK-NEXT: [[VECINIT50:%.*]] = insertelement <4 x i32> [[VECINIT47]], i32 [[TMP15]], i32 1
+// CHECK-NEXT: [[LEGS51:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX52:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS51]], i32 0, i32 2
+// CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[ARRAYIDX52]], align 8
+// CHECK-NEXT: [[VECINIT53:%.*]] = insertelement <4 x i32> [[VECINIT50]], i32 [[TMP16]], i32 2
+// CHECK-NEXT: [[LEGS54:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX55:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS54]], i32 0, i32 3
+// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[ARRAYIDX55]], align 4
+// CHECK-NEXT: [[VECINIT56:%.*]] = insertelement <4 x i32> [[VECINIT53]], i32 [[TMP17]], i32 3
+// CHECK-NEXT: store <4 x i32> [[VECINIT56]], ptr [[LEGSTATE45]], align 16
+// CHECK-NEXT: [[TAILSTATE57:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[ARRAYINIT_ELEMENT44]], i32 0, i32 1
+// CHECK-NEXT: [[STATE:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP18:%.*]] = load i32, ptr [[STATE]], align 16
+// CHECK-NEXT: store i32 [[TMP18]], ptr [[TAILSTATE57]], align 16
+// CHECK-NEXT: [[HAIRCOUNT58:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[ARRAYINIT_ELEMENT44]], i32 0, i32 2
+// CHECK-NEXT: [[COUNTER:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 2
+// CHECK-NEXT: [[TMP19:%.*]] = load i64, ptr [[COUNTER]], align 8
+// CHECK-NEXT: [[CONV:%.*]] = sitofp i64 [[TMP19]] to float
+// CHECK-NEXT: store float [[CONV]], ptr [[HAIRCOUNT58]], align 4
+// CHECK-NEXT: [[EARDIRECTION59:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[ARRAYINIT_ELEMENT44]], i32 0, i32 3
+// CHECK-NEXT: [[LEFTDIR:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP20:%.*]] = load <4 x float>, ptr [[LEFTDIR]], align 16
+// CHECK-NEXT: [[VECEXT60:%.*]] = extractelement <4 x float> [[TMP20]], i64 0
+// CHECK-NEXT: [[VECINIT61:%.*]] = insertelement <4 x float> poison, float [[VECEXT60]], i32 0
+// CHECK-NEXT: [[LEFTDIR62:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP21:%.*]] = load <4 x float>, ptr [[LEFTDIR62]], align 16
+// CHECK-NEXT: [[VECEXT63:%.*]] = extractelement <4 x float> [[TMP21]], i64 1
+// CHECK-NEXT: [[VECINIT64:%.*]] = insertelement <4 x float> [[VECINIT61]], float [[VECEXT63]], i32 1
+// CHECK-NEXT: [[LEFTDIR65:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP22:%.*]] = load <4 x float>, ptr [[LEFTDIR65]], align 16
+// CHECK-NEXT: [[VECEXT66:%.*]] = extractelement <4 x float> [[TMP22]], i64 2
+// CHECK-NEXT: [[VECINIT67:%.*]] = insertelement <4 x float> [[VECINIT64]], float [[VECEXT66]], i32 2
+// CHECK-NEXT: [[LEFTDIR68:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP23:%.*]] = load <4 x float>, ptr [[LEFTDIR68]], align 16
+// CHECK-NEXT: [[VECEXT69:%.*]] = extractelement <4 x float> [[TMP23]], i64 3
+// CHECK-NEXT: [[VECINIT70:%.*]] = insertelement <4 x float> [[VECINIT67]], float [[VECEXT69]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT70]], ptr [[EARDIRECTION59]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT71:%.*]] = getelementptr inbounds <4 x float>, ptr [[EARDIRECTION59]], i32 1
+// CHECK-NEXT: [[RIGHTDIR:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP24:%.*]] = load <4 x float>, ptr [[RIGHTDIR]], align 16
+// CHECK-NEXT: [[VECEXT72:%.*]] = extractelement <4 x float> [[TMP24]], i64 0
+// CHECK-NEXT: [[VECINIT73:%.*]] = insertelement <4 x float> poison, float [[VECEXT72]], i32 0
+// CHECK-NEXT: [[RIGHTDIR74:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP25:%.*]] = load <4 x float>, ptr [[RIGHTDIR74]], align 16
+// CHECK-NEXT: [[VECEXT75:%.*]] = extractelement <4 x float> [[TMP25]], i64 1
+// CHECK-NEXT: [[VECINIT76:%.*]] = insertelement <4 x float> [[VECINIT73]], float [[VECEXT75]], i32 1
+// CHECK-NEXT: [[RIGHTDIR77:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP26:%.*]] = load <4 x float>, ptr [[RIGHTDIR77]], align 16
+// CHECK-NEXT: [[VECEXT78:%.*]] = extractelement <4 x float> [[TMP26]], i64 2
+// CHECK-NEXT: [[VECINIT79:%.*]] = insertelement <4 x float> [[VECINIT76]], float [[VECEXT78]], i32 2
+// CHECK-NEXT: [[RIGHTDIR80:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP27:%.*]] = load <4 x float>, ptr [[RIGHTDIR80]], align 16
+// CHECK-NEXT: [[VECEXT81:%.*]] = extractelement <4 x float> [[TMP27]], i64 3
+// CHECK-NEXT: [[VECINIT82:%.*]] = insertelement <4 x float> [[VECINIT79]], float [[VECEXT81]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT82]], ptr [[ARRAYINIT_ELEMENT71]], align 16
+// CHECK-NEXT: [[CATS:%.*]] = getelementptr inbounds nuw [[STRUCT_ZOO]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[LEGS83:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH:%.*]], ptr [[CATS]], i32 0, i32 0
+// CHECK-NEXT: [[LEGSTATE84:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP28:%.*]] = load <4 x i32>, ptr [[LEGSTATE84]], align 16
+// CHECK-NEXT: [[VECEXT85:%.*]] = extractelement <4 x i32> [[TMP28]], i64 0
+// CHECK-NEXT: [[VECINIT86:%.*]] = insertelement <4 x i32> poison, i32 [[VECEXT85]], i32 0
+// CHECK-NEXT: [[LEGSTATE87:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP29:%.*]] = load <4 x i32>, ptr [[LEGSTATE87]], align 16
+// CHECK-NEXT: [[VECEXT88:%.*]] = extractelement <4 x i32> [[TMP29]], i64 1
+// CHECK-NEXT: [[VECINIT89:%.*]] = insertelement <4 x i32> [[VECINIT86]], i32 [[VECEXT88]], i32 1
+// CHECK-NEXT: [[LEGSTATE90:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP30:%.*]] = load <4 x i32>, ptr [[LEGSTATE90]], align 16
+// CHECK-NEXT: [[VECEXT91:%.*]] = extractelement <4 x i32> [[TMP30]], i64 2
+// CHECK-NEXT: [[VECINIT92:%.*]] = insertelement <4 x i32> [[VECINIT89]], i32 [[VECEXT91]], i32 2
+// CHECK-NEXT: [[LEGSTATE93:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP31:%.*]] = load <4 x i32>, ptr [[LEGSTATE93]], align 16
+// CHECK-NEXT: [[VECEXT94:%.*]] = extractelement <4 x i32> [[TMP31]], i64 3
+// CHECK-NEXT: [[VECINIT95:%.*]] = insertelement <4 x i32> [[VECINIT92]], i32 [[VECEXT94]], i32 3
+// CHECK-NEXT: store <4 x i32> [[VECINIT95]], ptr [[LEGS83]], align 16
+// CHECK-NEXT: [[TAILSTATE96:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[CATS]], i32 0, i32 1
+// CHECK-NEXT: [[TAILSTATE97:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP32:%.*]] = load i32, ptr [[TAILSTATE97]], align 16
+// CHECK-NEXT: store i32 [[TMP32]], ptr [[TAILSTATE96]], align 16
+// CHECK-NEXT: [[HAIRCOUNT98:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[CATS]], i32 0, i32 2
+// CHECK-NEXT: [[HAIRCOUNT99:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 2
+// CHECK-NEXT: [[TMP33:%.*]] = load float, ptr [[HAIRCOUNT99]], align 4
+// CHECK-NEXT: store float [[TMP33]], ptr [[HAIRCOUNT98]], align 4
+// CHECK-NEXT: [[CLAWS:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[CATS]], i32 0, i32 3
+// CHECK-NEXT: [[EARDIRECTION100:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX101:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION100]], i32 0, i32 0
+// CHECK-NEXT: [[TMP34:%.*]] = load <4 x float>, ptr [[ARRAYIDX101]], align 16
+// CHECK-NEXT: [[VECEXT102:%.*]] = extractelement <4 x float> [[TMP34]], i64 0
+// CHECK-NEXT: [[VECINIT103:%.*]] = insertelement <4 x float> poison, float [[VECEXT102]], i32 0
+// CHECK-NEXT: [[EARDIRECTION104:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX105:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION104]], i32 0, i32 0
+// CHECK-NEXT: [[TMP35:%.*]] = load <4 x float>, ptr [[ARRAYIDX105]], align 16
+// CHECK-NEXT: [[VECEXT106:%.*]] = extractelement <4 x float> [[TMP35]], i64 1
+// CHECK-NEXT: [[VECINIT107:%.*]] = insertelement <4 x float> [[VECINIT103]], float [[VECEXT106]], i32 1
+// CHECK-NEXT: [[EARDIRECTION108:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX109:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION108]], i32 0, i32 0
+// CHECK-NEXT: [[TMP36:%.*]] = load <4 x float>, ptr [[ARRAYIDX109]], align 16
+// CHECK-NEXT: [[VECEXT110:%.*]] = extractelement <4 x float> [[TMP36]], i64 2
+// CHECK-NEXT: [[VECINIT111:%.*]] = insertelement <4 x float> [[VECINIT107]], float [[VECEXT110]], i32 2
+// CHECK-NEXT: [[EARDIRECTION112:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX113:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION112]], i32 0, i32 0
+// CHECK-NEXT: [[TMP37:%.*]] = load <4 x float>, ptr [[ARRAYIDX113]], align 16
+// CHECK-NEXT: [[VECEXT114:%.*]] = extractelement <4 x float> [[TMP37]], i64 3
+// CHECK-NEXT: [[VECINIT115:%.*]] = insertelement <4 x float> [[VECINIT111]], float [[VECEXT114]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT115]], ptr [[CLAWS]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT116:%.*]] = getelementptr inbounds <4 x float>, ptr [[CLAWS]], i32 1
+// CHECK-NEXT: [[EARDIRECTION117:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX118:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION117]], i32 0, i32 1
+// CHECK-NEXT: [[TMP38:%.*]] = load <4 x float>, ptr [[ARRAYIDX118]], align 16
+// CHECK-NEXT: [[VECEXT119:%.*]] = extractelement <4 x float> [[TMP38]], i64 0
+// CHECK-NEXT: [[VECINIT120:%.*]] = insertelement <4 x float> poison, float [[VECEXT119]], i32 0
+// CHECK-NEXT: [[EARDIRECTION121:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX122:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION121]], i32 0, i32 1
+// CHECK-NEXT: [[TMP39:%.*]] = load <4 x float>, ptr [[ARRAYIDX122]], align 16
+// CHECK-NEXT: [[VECEXT123:%.*]] = extractelement <4 x float> [[TMP39]], i64 1
+// CHECK-NEXT: [[VECINIT124:%.*]] = insertelement <4 x float> [[VECINIT120]], float [[VECEXT123]], i32 1
+// CHECK-NEXT: [[EARDIRECTION125:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX126:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION125]], i32 0, i32 1
+// CHECK-NEXT: [[TMP40:%.*]] = load <4 x float>, ptr [[ARRAYIDX126]], align 16
+// CHECK-NEXT: [[VECEXT127:%.*]] = extractelement <4 x float> [[TMP40]], i64 2
+// CHECK-NEXT: [[VECINIT128:%.*]] = insertelement <4 x float> [[VECINIT124]], float [[VECEXT127]], i32 2
+// CHECK-NEXT: [[EARDIRECTION129:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX130:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION129]], i32 0, i32 1
+// CHECK-NEXT: [[TMP41:%.*]] = load <4 x float>, ptr [[ARRAYIDX130]], align 16
+// CHECK-NEXT: [[VECEXT131:%.*]] = extractelement <4 x float> [[TMP41]], i64 3
+// CHECK-NEXT: [[VECINIT132:%.*]] = insertelement <4 x float> [[VECINIT128]], float [[VECEXT131]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT132]], ptr [[ARRAYINIT_ELEMENT116]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT133:%.*]] = getelementptr inbounds [[STRUCT_KITTEH]], ptr [[CATS]], i32 1
+// CHECK-NEXT: [[LEGS134:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT133]], i32 0, i32 0
+// CHECK-NEXT: [[LEGS135:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX136:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS135]], i32 0, i32 0
+// CHECK-NEXT: [[TMP42:%.*]] = load i32, ptr [[ARRAYIDX136]], align 16
+// CHECK-NEXT: [[VECINIT137:%.*]] = insertelement <4 x i32> poison, i32 [[TMP42]], i32 0
+// CHECK-NEXT: [[LEGS138:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX139:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS138]], i32 0, i32 1
+// CHECK-NEXT: [[TMP43:%.*]] = load i32, ptr [[ARRAYIDX139]], align 4
+// CHECK-NEXT: [[VECINIT140:%.*]] = insertelement <4 x i32> [[VECINIT137]], i32 [[TMP43]], i32 1
+// CHECK-NEXT: [[LEGS141:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX142:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS141]], i32 0, i32 2
+// CHECK-NEXT: [[TMP44:%.*]] = load i32, ptr [[ARRAYIDX142]], align 8
+// CHECK-NEXT: [[VECINIT143:%.*]] = insertelement <4 x i32> [[VECINIT140]], i32 [[TMP44]], i32 2
+// CHECK-NEXT: [[LEGS144:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX145:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS144]], i32 0, i32 3
+// CHECK-NEXT: [[TMP45:%.*]] = load i32, ptr [[ARRAYIDX145]], align 4
+// CHECK-NEXT: [[VECINIT146:%.*]] = insertelement <4 x i32> [[VECINIT143]], i32 [[TMP45]], i32 3
+// CHECK-NEXT: store <4 x i32> [[VECINIT146]], ptr [[LEGS134]], align 16
+// CHECK-NEXT: [[TAILSTATE147:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT133]], i32 0, i32 1
+// CHECK-NEXT: [[STATE148:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP46:%.*]] = load i32, ptr [[STATE148]], align 16
+// CHECK-NEXT: store i32 [[TMP46]], ptr [[TAILSTATE147]], align 16
+// CHECK-NEXT: [[HAIRCOUNT149:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT133]], i32 0, i32 2
+// CHECK-NEXT: [[COUNTER150:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 2
+// CHECK-NEXT: [[TMP47:%.*]] = load i64, ptr [[COUNTER150]], align 8
+// CHECK-NEXT: [[CONV151:%.*]] = sitofp i64 [[TMP47]] to float
+// CHECK-NEXT: store float [[CONV151]], ptr [[HAIRCOUNT149]], align 4
+// CHECK-NEXT: [[CLAWS152:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT133]], i32 0, i32 3
+// CHECK-NEXT: [[LEFTDIR153:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP48:%.*]] = load <4 x float>, ptr [[LEFTDIR153]], align 16
+// CHECK-NEXT: [[VECEXT154:%.*]] = extractelement <4 x float> [[TMP48]], i64 0
+// CHECK-NEXT: [[VECINIT155:%.*]] = insertelement <4 x float> poison, float [[VECEXT154]], i32 0
+// CHECK-NEXT: [[LEFTDIR156:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP49:%.*]] = load <4 x float>, ptr [[LEFTDIR156]], align 16
+// CHECK-NEXT: [[VECEXT157:%.*]] = extractelement <4 x float> [[TMP49]], i64 1
+// CHECK-NEXT: [[VECINIT158:%.*]] = insertelement <4 x float> [[VECINIT155]], float [[VECEXT157]], i32 1
+// CHECK-NEXT: [[LEFTDIR159:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP50:%.*]] = load <4 x float>, ptr [[LEFTDIR159]], align 16
+// CHECK-NEXT: [[VECEXT160:%.*]] = extractelement <4 x float> [[TMP50]], i64 2
+// CHECK-NEXT: [[VECINIT161:%.*]] = insertelement <4 x float> [[VECINIT158]], float [[VECEXT160]], i32 2
+// CHECK-NEXT: [[LEFTDIR162:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP51:%.*]] = load <4 x float>, ptr [[LEFTDIR162]], align 16
+// CHECK-NEXT: [[VECEXT163:%.*]] = extractelement <4 x float> [[TMP51]], i64 3
+// CHECK-NEXT: [[VECINIT164:%.*]] = insertelement <4 x float> [[VECINIT161]], float [[VECEXT163]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT164]], ptr [[CLAWS152]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT165:%.*]] = getelementptr inbounds <4 x float>, ptr [[CLAWS152]], i32 1
+// CHECK-NEXT: [[RIGHTDIR166:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP52:%.*]] = load <4 x float>, ptr [[RIGHTDIR166]], align 16
+// CHECK-NEXT: [[VECEXT167:%.*]] = extractelement <4 x float> [[TMP52]], i64 0
+// CHECK-NEXT: [[VECINIT168:%.*]] = insertelement <4 x float> poison, float [[VECEXT167]], i32 0
+// CHECK-NEXT: [[RIGHTDIR169:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP53:%.*]] = load <4 x float>, ptr [[RIGHTDIR169]], align 16
+// CHECK-NEXT: [[VECEXT170:%.*]] = extractelement <4 x float> [[TMP53]], i64 1
+// CHECK-NEXT: [[VECINIT171:%.*]] = insertelement <4 x float> [[VECINIT168]], float [[VECEXT170]], i32 1
+// CHECK-NEXT: [[RIGHTDIR172:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP54:%.*]] = load <4 x float>, ptr [[RIGHTDIR172]], align 16
+// CHECK-NEXT: [[VECEXT173:%.*]] = extractelement <4 x float> [[TMP54]], i64 2
+// CHECK-NEXT: [[VECINIT174:%.*]] = insertelement <4 x float> [[VECINIT171]], float [[VECEXT173]], i32 2
+// CHECK-NEXT: [[RIGHTDIR175:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP55:%.*]] = load <4 x float>, ptr [[RIGHTDIR175]], align 16
+// CHECK-NEXT: [[VECEXT176:%.*]] = extractelement <4 x float> [[TMP55]], i64 3
+// CHECK-NEXT: [[VECINIT177:%.*]] = insertelement <4 x float> [[VECINIT174]], float [[VECEXT176]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT177]], ptr [[ARRAYINIT_ELEMENT165]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT178:%.*]] = getelementptr inbounds [[STRUCT_KITTEH]], ptr [[CATS]], i32 2
+// CHECK-NEXT: [[LEGS179:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT178]], i32 0, i32 0
+// CHECK-NEXT: [[LEGSTATE180:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP56:%.*]] = load <4 x i32>, ptr [[LEGSTATE180]], align 16
+// CHECK-NEXT: [[VECEXT181:%.*]] = extractelement <4 x i32> [[TMP56]], i64 0
+// CHECK-NEXT: [[VECINIT182:%.*]] = insertelement <4 x i32> poison, i32 [[VECEXT181]], i32 0
+// CHECK-NEXT: [[LEGSTATE183:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP57:%.*]] = load <4 x i32>, ptr [[LEGSTATE183]], align 16
+// CHECK-NEXT: [[VECEXT184:%.*]] = extractelement <4 x i32> [[TMP57]], i64 1
+// CHECK-NEXT: [[VECINIT185:%.*]] = insertelement <4 x i32> [[VECINIT182]], i32 [[VECEXT184]], i32 1
+// CHECK-NEXT: [[LEGSTATE186:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP58:%.*]] = load <4 x i32>, ptr [[LEGSTATE186]], align 16
+// CHECK-NEXT: [[VECEXT187:%.*]] = extractelement <4 x i32> [[TMP58]], i64 2
+// CHECK-NEXT: [[VECINIT188:%.*]] = insertelement <4 x i32> [[VECINIT185]], i32 [[VECEXT187]], i32 2
+// CHECK-NEXT: [[LEGSTATE189:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP59:%.*]] = load <4 x i32>, ptr [[LEGSTATE189]], align 16
+// CHECK-NEXT: [[VECEXT190:%.*]] = extractelement <4 x i32> [[TMP59]], i64 3
+// CHECK-NEXT: [[VECINIT191:%.*]] = insertelement <4 x i32> [[VECINIT188]], i32 [[VECEXT190]], i32 3
+// CHECK-NEXT: store <4 x i32> [[VECINIT191]], ptr [[LEGS179]], align 16
+// CHECK-NEXT: [[TAILSTATE192:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT178]], i32 0, i32 1
+// CHECK-NEXT: [[TAILSTATE193:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP60:%.*]] = load i32, ptr [[TAILSTATE193]], align 16
+// CHECK-NEXT: store i32 [[TMP60]], ptr [[TAILSTATE192]], align 16
+// CHECK-NEXT: [[HAIRCOUNT194:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT178]], i32 0, i32 2
+// CHECK-NEXT: [[HAIRCOUNT195:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 2
+// CHECK-NEXT: [[TMP61:%.*]] = load float, ptr [[HAIRCOUNT195]], align 4
+// CHECK-NEXT: store float [[TMP61]], ptr [[HAIRCOUNT194]], align 4
+// CHECK-NEXT: [[CLAWS196:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT178]], i32 0, i32 3
+// CHECK-NEXT: [[EARDIRECTION197:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX198:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION197]], i32 0, i32 0
+// CHECK-NEXT: [[TMP62:%.*]] = load <4 x float>, ptr [[ARRAYIDX198]], align 16
+// CHECK-NEXT: [[VECEXT199:%.*]] = extractelement <4 x float> [[TMP62]], i64 0
+// CHECK-NEXT: [[VECINIT200:%.*]] = insertelement <4 x float> poison, float [[VECEXT199]], i32 0
+// CHECK-NEXT: [[EARDIRECTION201:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX202:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION201]], i32 0, i32 0
+// CHECK-NEXT: [[TMP63:%.*]] = load <4 x float>, ptr [[ARRAYIDX202]], align 16
+// CHECK-NEXT: [[VECEXT203:%.*]] = extractelement <4 x float> [[TMP63]], i64 1
+// CHECK-NEXT: [[VECINIT204:%.*]] = insertelement <4 x float> [[VECINIT200]], float [[VECEXT203]], i32 1
+// CHECK-NEXT: [[EARDIRECTION205:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX206:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION205]], i32 0, i32 0
+// CHECK-NEXT: [[TMP64:%.*]] = load <4 x float>, ptr [[ARRAYIDX206]], align 16
+// CHECK-NEXT: [[VECEXT207:%.*]] = extractelement <4 x float> [[TMP64]], i64 2
+// CHECK-NEXT: [[VECINIT208:%.*]] = insertelement <4 x float> [[VECINIT204]], float [[VECEXT207]], i32 2
+// CHECK-NEXT: [[EARDIRECTION209:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX210:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION209]], i32 0, i32 0
+// CHECK-NEXT: [[TMP65:%.*]] = load <4 x float>, ptr [[ARRAYIDX210]], align 16
+// CHECK-NEXT: [[VECEXT211:%.*]] = extractelement <4 x float> [[TMP65]], i64 3
+// CHECK-NEXT: [[VECINIT212:%.*]] = insertelement <4 x float> [[VECINIT208]], float [[VECEXT211]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT212]], ptr [[CLAWS196]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT213:%.*]] = getelementptr inbounds <4 x float>, ptr [[CLAWS196]], i32 1
+// CHECK-NEXT: [[EARDIRECTION214:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX215:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION214]], i32 0, i32 1
+// CHECK-NEXT: [[TMP66:%.*]] = load <4 x float>, ptr [[ARRAYIDX215]], align 16
+// CHECK-NEXT: [[VECEXT216:%.*]] = extractelement <4 x float> [[TMP66]], i64 0
+// CHECK-NEXT: [[VECINIT217:%.*]] = insertelement <4 x float> poison, float [[VECEXT216]], i32 0
+// CHECK-NEXT: [[EARDIRECTION218:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX219:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION218]], i32 0, i32 1
+// CHECK-NEXT: [[TMP67:%.*]] = load <4 x float>, ptr [[ARRAYIDX219]], align 16
+// CHECK-NEXT: [[VECEXT220:%.*]] = extractelement <4 x float> [[TMP67]], i64 1
+// CHECK-NEXT: [[VECINIT221:%.*]] = insertelement <4 x float> [[VECINIT217]], float [[VECEXT220]], i32 1
+// CHECK-NEXT: [[EARDIRECTION222:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX223:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION222]], i32 0, i32 1
+// CHECK-NEXT: [[TMP68:%.*]] = load <4 x float>, ptr [[ARRAYIDX223]], align 16
+// CHECK-NEXT: [[VECEXT224:%.*]] = extractelement <4 x float> [[TMP68]], i64 2
+// CHECK-NEXT: [[VECINIT225:%.*]] = insertelement <4 x float> [[VECINIT221]], float [[VECEXT224]], i32 2
+// CHECK-NEXT: [[EARDIRECTION226:%.*]] = getelementptr inbounds nuw [[STRUCT_DOGGO]], ptr [[D1]], i32 0, i32 3
+// CHECK-NEXT: [[ARRAYIDX227:%.*]] = getelementptr inbounds nuw [2 x <4 x float>], ptr [[EARDIRECTION226]], i32 0, i32 1
+// CHECK-NEXT: [[TMP69:%.*]] = load <4 x float>, ptr [[ARRAYIDX227]], align 16
+// CHECK-NEXT: [[VECEXT228:%.*]] = extractelement <4 x float> [[TMP69]], i64 3
+// CHECK-NEXT: [[VECINIT229:%.*]] = insertelement <4 x float> [[VECINIT225]], float [[VECEXT228]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT229]], ptr [[ARRAYINIT_ELEMENT213]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT230:%.*]] = getelementptr inbounds [[STRUCT_KITTEH]], ptr [[CATS]], i32 3
+// CHECK-NEXT: [[LEGS231:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT230]], i32 0, i32 0
+// CHECK-NEXT: [[LEGS232:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX233:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS232]], i32 0, i32 0
+// CHECK-NEXT: [[TMP70:%.*]] = load i32, ptr [[ARRAYIDX233]], align 16
+// CHECK-NEXT: [[VECINIT234:%.*]] = insertelement <4 x i32> poison, i32 [[TMP70]], i32 0
+// CHECK-NEXT: [[LEGS235:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX236:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS235]], i32 0, i32 1
+// CHECK-NEXT: [[TMP71:%.*]] = load i32, ptr [[ARRAYIDX236]], align 4
+// CHECK-NEXT: [[VECINIT237:%.*]] = insertelement <4 x i32> [[VECINIT234]], i32 [[TMP71]], i32 1
+// CHECK-NEXT: [[LEGS238:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX239:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS238]], i32 0, i32 2
+// CHECK-NEXT: [[TMP72:%.*]] = load i32, ptr [[ARRAYIDX239]], align 8
+// CHECK-NEXT: [[VECINIT240:%.*]] = insertelement <4 x i32> [[VECINIT237]], i32 [[TMP72]], i32 2
+// CHECK-NEXT: [[LEGS241:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 0
+// CHECK-NEXT: [[ARRAYIDX242:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[LEGS241]], i32 0, i32 3
+// CHECK-NEXT: [[TMP73:%.*]] = load i32, ptr [[ARRAYIDX242]], align 4
+// CHECK-NEXT: [[VECINIT243:%.*]] = insertelement <4 x i32> [[VECINIT240]], i32 [[TMP73]], i32 3
+// CHECK-NEXT: store <4 x i32> [[VECINIT243]], ptr [[LEGS231]], align 16
+// CHECK-NEXT: [[TAILSTATE244:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT230]], i32 0, i32 1
+// CHECK-NEXT: [[STATE245:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP74:%.*]] = load i32, ptr [[STATE245]], align 16
+// CHECK-NEXT: store i32 [[TMP74]], ptr [[TAILSTATE244]], align 16
+// CHECK-NEXT: [[HAIRCOUNT246:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT230]], i32 0, i32 2
+// CHECK-NEXT: [[COUNTER247:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 2
+// CHECK-NEXT: [[TMP75:%.*]] = load i64, ptr [[COUNTER247]], align 8
+// CHECK-NEXT: [[CONV248:%.*]] = sitofp i64 [[TMP75]] to float
+// CHECK-NEXT: store float [[CONV248]], ptr [[HAIRCOUNT246]], align 4
+// CHECK-NEXT: [[CLAWS249:%.*]] = getelementptr inbounds nuw [[STRUCT_KITTEH]], ptr [[ARRAYINIT_ELEMENT230]], i32 0, i32 3
+// CHECK-NEXT: [[LEFTDIR250:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP76:%.*]] = load <4 x float>, ptr [[LEFTDIR250]], align 16
+// CHECK-NEXT: [[VECEXT251:%.*]] = extractelement <4 x float> [[TMP76]], i64 0
+// CHECK-NEXT: [[VECINIT252:%.*]] = insertelement <4 x float> poison, float [[VECEXT251]], i32 0
+// CHECK-NEXT: [[LEFTDIR253:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP77:%.*]] = load <4 x float>, ptr [[LEFTDIR253]], align 16
+// CHECK-NEXT: [[VECEXT254:%.*]] = extractelement <4 x float> [[TMP77]], i64 1
+// CHECK-NEXT: [[VECINIT255:%.*]] = insertelement <4 x float> [[VECINIT252]], float [[VECEXT254]], i32 1
+// CHECK-NEXT: [[LEFTDIR256:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP78:%.*]] = load <4 x float>, ptr [[LEFTDIR256]], align 16
+// CHECK-NEXT: [[VECEXT257:%.*]] = extractelement <4 x float> [[TMP78]], i64 2
+// CHECK-NEXT: [[VECINIT258:%.*]] = insertelement <4 x float> [[VECINIT255]], float [[VECEXT257]], i32 2
+// CHECK-NEXT: [[LEFTDIR259:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 3
+// CHECK-NEXT: [[TMP79:%.*]] = load <4 x float>, ptr [[LEFTDIR259]], align 16
+// CHECK-NEXT: [[VECEXT260:%.*]] = extractelement <4 x float> [[TMP79]], i64 3
+// CHECK-NEXT: [[VECINIT261:%.*]] = insertelement <4 x float> [[VECINIT258]], float [[VECEXT260]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT261]], ptr [[CLAWS249]], align 16
+// CHECK-NEXT: [[ARRAYINIT_ELEMENT262:%.*]] = getelementptr inbounds <4 x float>, ptr [[CLAWS249]], i32 1
+// CHECK-NEXT: [[RIGHTDIR263:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP80:%.*]] = load <4 x float>, ptr [[RIGHTDIR263]], align 16
+// CHECK-NEXT: [[VECEXT264:%.*]] = extractelement <4 x float> [[TMP80]], i64 0
+// CHECK-NEXT: [[VECINIT265:%.*]] = insertelement <4 x float> poison, float [[VECEXT264]], i32 0
+// CHECK-NEXT: [[RIGHTDIR266:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP81:%.*]] = load <4 x float>, ptr [[RIGHTDIR266]], align 16
+// CHECK-NEXT: [[VECEXT267:%.*]] = extractelement <4 x float> [[TMP81]], i64 1
+// CHECK-NEXT: [[VECINIT268:%.*]] = insertelement <4 x float> [[VECINIT265]], float [[VECEXT267]], i32 1
+// CHECK-NEXT: [[RIGHTDIR269:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP82:%.*]] = load <4 x float>, ptr [[RIGHTDIR269]], align 16
+// CHECK-NEXT: [[VECEXT270:%.*]] = extractelement <4 x float> [[TMP82]], i64 2
+// CHECK-NEXT: [[VECINIT271:%.*]] = insertelement <4 x float> [[VECINIT268]], float [[VECEXT270]], i32 2
+// CHECK-NEXT: [[RIGHTDIR272:%.*]] = getelementptr inbounds nuw [[STRUCT_ANIMALBITS]], ptr [[A1]], i32 0, i32 4
+// CHECK-NEXT: [[TMP83:%.*]] = load <4 x float>, ptr [[RIGHTDIR272]], align 16
+// CHECK-NEXT: [[VECEXT273:%.*]] = extractelement <4 x float> [[TMP83]], i64 3
+// CHECK-NEXT: [[VECINIT274:%.*]] = insertelement <4 x float> [[VECINIT271]], float [[VECEXT273]], i32 3
+// CHECK-NEXT: store <4 x float> [[VECINIT274]], ptr [[ARRAYINIT_ELEMENT262]], align 16
+// CHECK-NEXT: ret void
+//
+Zoo case9(Doggo D1, AnimalBits A1) {
+ Zoo Z1 = {D1, A1, D1, A1, D1, A1};
+ return Z1;
+}
+
+// Case 10: Initialize an object with a base class from two objects.
+// CHECK-LABEL: define void @_Z6case109TwoFloatsS_(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FOURFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS:%.*]]) align 4 [[TF1:%.*]], ptr noundef byval([[STRUCT_TWOFLOATS]]) align 4 [[TF2:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[X1:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF1]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X1]], align 4
+// CHECK-NEXT: store float [[TMP0]], ptr [[X]], align 4
+// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[Y2:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF1]], i32 0, i32 1
+// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[Y2]], align 4
+// CHECK-NEXT: store float [[TMP1]], ptr [[Y]], align 4
+// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[X3:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF2]], i32 0, i32 0
+// CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[X3]], align 4
+// CHECK-NEXT: store float [[TMP2]], ptr [[Z]], align 4
+// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 2
+// CHECK-NEXT: [[Y4:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[TF2]], i32 0, i32 1
+// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[Y4]], align 4
+// CHECK-NEXT: store float [[TMP3]], ptr [[W]], align 4
+// CHECK-NEXT: ret void
+//
+FourFloats case10(TwoFloats TF1, TwoFloats TF2) {
+ FourFloats FF1 = {TF1, TF2};
+ return FF1;
+}
+
+// Case 11: Initialize an object with a base class from a vector splat.
+// CHECK-LABEL: define void @_Z6case11f(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FOURFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4
+// CHECK-NEXT: [[REF_TMP:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[REF_TMP1:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[REF_TMP4:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[REF_TMP7:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4
+// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS:%.*]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_ADDR]], align 4
+// CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x float> poison, float [[TMP0]], i64 0
+// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x float> [[CAST_SPLAT]], <1 x float> poison, <4 x i32> zeroinitializer
+// CHECK-NEXT: store <4 x float> [[TMP1]], ptr [[REF_TMP]], align 16
+// CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[REF_TMP]], align 16
+// CHECK-NEXT: [[VECEXT:%.*]] = extractelement <4 x float> [[TMP2]], i64 0
+// CHECK-NEXT: store float [[VECEXT]], ptr [[X]], align 4
+// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[F_ADDR]], align 4
+// CHECK-NEXT: [[CAST_SPLAT2:%.*]] = insertelement <1 x float> poison, float [[TMP3]], i64 0
+// CHECK-NEXT: [[TMP4:%.*]] = shufflevector <1 x float> [[CAST_SPLAT2]], <1 x float> poison, <4 x i32> zeroinitializer
+// CHECK-NEXT: store <4 x float> [[TMP4]], ptr [[REF_TMP1]], align 16
+// CHECK-NEXT: [[TMP5:%.*]] = load <4 x float>, ptr [[REF_TMP1]], align 16
+// CHECK-NEXT: [[VECEXT3:%.*]] = extractelement <4 x float> [[TMP5]], i64 1
+// CHECK-NEXT: store float [[VECEXT3]], ptr [[Y]], align 4
+// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[TMP6:%.*]] = load float, ptr [[F_ADDR]], align 4
+// CHECK-NEXT: [[CAST_SPLAT5:%.*]] = insertelement <1 x float> poison, float [[TMP6]], i64 0
+// CHECK-NEXT: [[TMP7:%.*]] = shufflevector <1 x float> [[CAST_SPLAT5]], <1 x float> poison, <4 x i32> zeroinitializer
+// CHECK-NEXT: store <4 x float> [[TMP7]], ptr [[REF_TMP4]], align 16
+// CHECK-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[REF_TMP4]], align 16
+// CHECK-NEXT: [[VECEXT6:%.*]] = extractelement <4 x float> [[TMP8]], i64 2
+// CHECK-NEXT: store float [[VECEXT6]], ptr [[Z]], align 4
+// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 2
+// CHECK-NEXT: [[TMP9:%.*]] = load float, ptr [[F_ADDR]], align 4
+// CHECK-NEXT: [[CAST_SPLAT8:%.*]] = insertelement <1 x float> poison, float [[TMP9]], i64 0
+// CHECK-NEXT: [[TMP10:%.*]] = shufflevector <1 x float> [[CAST_SPLAT8]], <1 x float> poison, <4 x i32> zeroinitializer
+// CHECK-NEXT: store <4 x float> [[TMP10]], ptr [[REF_TMP7]], align 16
+// CHECK-NEXT: [[TMP11:%.*]] = load <4 x float>, ptr [[REF_TMP7]], align 16
+// CHECK-NEXT: [[VECEXT9:%.*]] = extractelement <4 x float> [[TMP11]], i64 3
+// CHECK-NEXT: store float [[VECEXT9]], ptr [[W]], align 4
+// CHECK-NEXT: ret void
+//
+FourFloats case11(float F) {
+ FourFloats FF1 = {F.xxxx};
+ return FF1;
+}
+
+// Case 12: Initialize bitfield from two integers.
+// CHECK-LABEL: define void @_Z6case12ii(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_SLICYBITS:%.*]]) align 4 [[AGG_RESULT:%.*]], i32 noundef [[I:%.*]], i32 noundef [[J:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[J_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4
+// CHECK-NEXT: store i32 [[J]], ptr [[J_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i16
+// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[AGG_RESULT]], align 4
+// CHECK-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP1]], 255
+// CHECK-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD]], -256
+// CHECK-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_VALUE]]
+// CHECK-NEXT: store i16 [[BF_SET]], ptr [[AGG_RESULT]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[J_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
+// CHECK-NEXT: [[BF_LOAD1:%.*]] = load i16, ptr [[AGG_RESULT]], align 4
+// CHECK-NEXT: [[BF_VALUE2:%.*]] = and i16 [[TMP3]], 255
+// CHECK-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_VALUE2]], 8
+// CHECK-NEXT: [[BF_CLEAR3:%.*]] = and i16 [[BF_LOAD1]], 255
+// CHECK-NEXT: [[BF_SET4:%.*]] = or i16 [[BF_CLEAR3]], [[BF_SHL]]
+// CHECK-NEXT: store i16 [[BF_SET4]], ptr [[AGG_RESULT]], align 4
+// CHECK-NEXT: ret void
+//
+SlicyBits case12(int I, int J) {
+ SlicyBits SB = {I, J};
+ return SB;
+}
+
+// Case 13: Initialize bitfield from a struct of two ints.
+// CHECK-LABEL: define void @_Z6case137TwoInts(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_SLICYBITS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_TWOINTS:%.*]]) align 4 [[TI:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[Z]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i16
+// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[AGG_RESULT]], align 4
+// CHECK-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP1]], 255
+// CHECK-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD]], -256
+// CHECK-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_VALUE]]
+// CHECK-NEXT: store i16 [[BF_SET]], ptr [[AGG_RESULT]], align 4
+// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[TI]], i32 0, i32 1
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[W]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
+// CHECK-NEXT: [[BF_LOAD1:%.*]] = load i16, ptr [[AGG_RESULT]], align 4
+// CHECK-NEXT: [[BF_VALUE2:%.*]] = and i16 [[TMP3]], 255
+// CHECK-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_VALUE2]], 8
+// CHECK-NEXT: [[BF_CLEAR3:%.*]] = and i16 [[BF_LOAD1]], 255
+// CHECK-NEXT: [[BF_SET4:%.*]] = or i16 [[BF_CLEAR3]], [[BF_SHL]]
+// CHECK-NEXT: store i16 [[BF_SET4]], ptr [[AGG_RESULT]], align 4
+// CHECK-NEXT: ret void
+//
+SlicyBits case13(TwoInts TI) {
+ SlicyBits SB = {TI};
+ return SB;
+}
+
+// Case 14: Initialize struct of ints from struct with bitfields.
+// CHECK-LABEL: define void @_Z6case149SlicyBits(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOINTS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_SLICYBITS:%.*]]) align 4 [[SB:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[SB]], align 4
+// CHECK-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_LOAD]], 8
+// CHECK-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8
+// CHECK-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32
+// CHECK-NEXT: store i32 [[BF_CAST]], ptr [[Z]], align 4
+// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOINTS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[BF_LOAD1:%.*]] = load i16, ptr [[SB]], align 4
+// CHECK-NEXT: [[BF_ASHR2:%.*]] = ashr i16 [[BF_LOAD1]], 8
+// CHECK-NEXT: [[BF_CAST3:%.*]] = sext i16 [[BF_ASHR2]] to i32
+// CHECK-NEXT: store i32 [[BF_CAST3]], ptr [[W]], align 4
+// CHECK-NEXT: ret void
+//
+TwoInts case14(SlicyBits SB) {
+ TwoInts TI = {SB};
+ return TI;
+}
+
+// Case 15: Initialize struct of floats from struct with bitfields.
+// CHECK-LABEL: define void @_Z6case159SlicyBits(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noundef byval([[STRUCT_SLICYBITS:%.*]]) align 4 [[SB:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[SB]], align 4
+// CHECK-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_LOAD]], 8
+// CHECK-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8
+// CHECK-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32
+// CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[BF_CAST]] to float
+// CHECK-NEXT: store float [[CONV]], ptr [[X]], align 4
+// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[BF_LOAD1:%.*]] = load i16, ptr [[SB]], align 4
+// CHECK-NEXT: [[BF_ASHR2:%.*]] = ashr i16 [[BF_LOAD1]], 8
+// CHECK-NEXT: [[BF_CAST3:%.*]] = sext i16 [[BF_ASHR2]] to i32
+// CHECK-NEXT: [[CONV4:%.*]] = sitofp i32 [[BF_CAST3]] to float
+// CHECK-NEXT: store float [[CONV4]], ptr [[Y]], align 4
+// CHECK-NEXT: ret void
+//
+TwoFloats case15(SlicyBits SB) {
+ TwoFloats TI = {SB};
+ return TI;
+}
+
+// Case 16: Side-effecting initialization list arguments. The important thing
+// here is that case16 only has _one_ call to makeTwo.
+// CHECK-LABEL: define void @_Z7makeTwoRf(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_TWOFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr noalias noundef nonnull align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: store ptr [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[X1:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[TMP0]], align 4
+// CHECK-NEXT: store float [[TMP1]], ptr [[X1]], align 4
+// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[TMP2]], align 4
+// CHECK-NEXT: [[MUL:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP3]], 1.500000e+00
+// CHECK-NEXT: store float [[MUL]], ptr [[Y]], align 4
+// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[TMP4]], align 4
+// CHECK-NEXT: [[MUL2:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP5]], 2.000000e+00
+// CHECK-NEXT: store float [[MUL2]], ptr [[TMP4]], align 4
+// CHECK-NEXT: ret void
+//
+TwoFloats makeTwo(inout float X) {
+ TwoFloats TF = {X, X*1.5};
+ X *= 2;
+ return TF;
+}
+
+// CHECK-LABEL: define void @_Z6case16v(
+// CHECK-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_FOURFLOATS:%.*]]) align 4 [[AGG_RESULT:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[X:%.*]] = alloca float, align 4
+// CHECK-NEXT: [[REF_TMP:%.*]] = alloca [[STRUCT_TWOFLOATS:%.*]], align 4
+// CHECK-NEXT: [[TMP:%.*]] = alloca float, align 4
+// CHECK-NEXT: store float 0.000000e+00, ptr [[X]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X]], align 4
+// CHECK-NEXT: store float [[TMP0]], ptr [[TMP]], align 4
+// CHECK-NEXT: call void @_Z7makeTwoRf(ptr dead_on_unwind writable sret([[STRUCT_TWOFLOATS]]) align 4 [[REF_TMP]], ptr noalias noundef nonnull align 4 dereferenceable(4) [[TMP]]) #[[ATTR2:[0-9]+]]
+// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[TMP]], align 4
+// CHECK-NEXT: store float [[TMP1]], ptr [[X]], align 4
+// CHECK-NEXT: [[X1:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 0
+// CHECK-NEXT: store float 0.000000e+00, ptr [[X1]], align 4
+// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[X2:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[REF_TMP]], i32 0, i32 0
+// CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[X2]], align 4
+// CHECK-NEXT: store float [[TMP2]], ptr [[Y]], align 4
+// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 1
+// CHECK-NEXT: [[Y3:%.*]] = getelementptr inbounds nuw [[STRUCT_TWOFLOATS]], ptr [[REF_TMP]], i32 0, i32 1
+// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[Y3]], align 4
+// CHECK-NEXT: store float [[TMP3]], ptr [[Z]], align 4
+// CHECK-NEXT: [[W:%.*]] = getelementptr inbounds nuw [[STRUCT_FOURFLOATS]], ptr [[AGG_RESULT]], i32 0, i32 2
+// CHECK-NEXT: store float 3.000000e+00, ptr [[W]], align 4
+// CHECK-NEXT: ret void
+//
+FourFloats case16() {
+ float X = 0;
+ FourFloats FF = {0, makeTwo(X), 3};
+ return FF;
+}
diff --git a/clang/test/SemaHLSL/ArrayTemporary.hlsl b/clang/test/SemaHLSL/ArrayTemporary.hlsl
index 0266a198e7ec9..3d713a89adf3b 100644
--- a/clang/test/SemaHLSL/ArrayTemporary.hlsl
+++ b/clang/test/SemaHLSL/ArrayTemporary.hlsl
@@ -25,7 +25,7 @@ void fn2(Obj O[4]) { }
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'Obj[4]' <HLSLArrayRValue>
void call2() {
- Obj Arr[4] = {};
+ Obj Arr[4] = {0, 0, 0, 0, 0, 0, 0, 0};
fn2(Arr);
}
diff --git a/clang/test/SemaHLSL/Language/ElementwiseCast-errors.hlsl b/clang/test/SemaHLSL/Language/ElementwiseCast-errors.hlsl
index b7085bc69547b..9417249383469 100644
--- a/clang/test/SemaHLSL/Language/ElementwiseCast-errors.hlsl
+++ b/clang/test/SemaHLSL/Language/ElementwiseCast-errors.hlsl
@@ -43,7 +43,9 @@ export void cantCast4() {
int2 A = {1,2};
R r = R(A);
// expected-error at -1 {{no matching conversion for functional-style cast from 'int2' (aka 'vector<int, 2>') to 'R'}}
- R r2 = {1, 2};
+ R r2;
+ r2.A = 1;
+ r2.F = 2.0;
int2 B = (int2)r2;
// expected-error at -1 {{cannot convert 'R' to 'int2' (aka 'vector<int, 2>') without a conversion operator}}
}
diff --git a/clang/test/SemaHLSL/Language/InitListAST.hlsl b/clang/test/SemaHLSL/Language/InitListAST.hlsl
new file mode 100644
index 0000000000000..d58582f9029fe
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/InitListAST.hlsl
@@ -0,0 +1,983 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -disable-llvm-passes -finclude-default-header -ast-dump -ast-dump-filter=case %s | FileCheck %s
+
+struct TwoFloats {
+ float X, Y;
+};
+
+struct TwoInts {
+ int Z, W;
+};
+
+struct Doggo {
+ int4 LegState;
+ int TailState;
+ float HairCount;
+ float4 EarDirection[2];
+};
+
+struct AnimalBits {
+ int Legs[4];
+ uint State;
+ int64_t Counter;
+ float4 LeftDir;
+ float4 RightDir;
+};
+
+struct Kitteh {
+ int4 Legs;
+ int TailState;
+ float HairCount;
+ float4 Claws[2];
+};
+
+struct Zoo {
+ Doggo Dogs[2];
+ Kitteh Cats[4];
+};
+
+struct FourFloats : TwoFloats {
+ float Z, W;
+};
+
+struct SlicyBits {
+ int Z : 8;
+ int W : 8;
+};
+
+// Case 1: Extraneous braces get ignored in literal instantiation.
+// CHECK-LABEL: Dumping case1
+// CHECK: VarDecl {{.*}} used TF1 'TwoFloats' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats'
+// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 1.000000e+00
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2
+TwoFloats case1() {
+ TwoFloats TF1 = {{{1.0, 2}}};
+ return TF1;
+}
+
+// Case 2: Valid C/C++ initializer is handled appropriately.
+//CHECK-LABEL: Dumping case2
+//CHECK: VarDecl {{.*}} used TF2 'TwoFloats' nrvo cinit
+//CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats'
+//CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+//CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
+//CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+//CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2
+TwoFloats case2() {
+ TwoFloats TF2 = {1, 2};
+ return TF2;
+}
+
+// Case 3: Simple initialization with conversion of an argument.
+// CHECK-LABEL: Dumping case3
+// CHECK: VarDecl {{.*}} used TF3 'TwoFloats' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'Val' 'int'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2
+TwoFloats case3(int Val) {
+ TwoFloats TF3 = {Val, 2};
+ return TF3;
+}
+
+// Case 4: Initialization from a scalarized vector into a structure with element
+// conversions.
+// CHECK-LABEL: Dumping case4
+// CHECK: VarDecl {{.*}} used TF4 'TwoFloats' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}}'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'TwoVals' 'int2':'vector<int, 2>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'TwoVals' 'int2':'vector<int, 2>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+TwoFloats case4(int2 TwoVals) {
+ TwoFloats TF4 = {TwoVals};
+ return TF4;
+}
+
+// Case 5: Initialization from a scalarized vector of matching type.
+// CHECK-LABEL: Dumping case5
+// CHECK: VarDecl {{.*}} used TI1 'TwoInts' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoInts'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'TwoVals' 'int2':'vector<int, 2>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'TwoVals' 'int2':'vector<int, 2>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+TwoInts case5(int2 TwoVals) {
+ TwoInts TI1 = {TwoVals};
+ return TI1;
+}
+
+// Case 6: Initialization from a scalarized structure of
diff erent type with
+//
diff erent element types.
+// CHECK-LABEL: Dumping case6
+// CHECK: VarDecl {{.*}} used TI2 'TwoInts' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoInts'
+// CHECK-NEXT: ImplicitCastExpr {{.*}}'int' <FloatingToIntegral>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .X {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF4' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <FloatingToIntegral>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .Y {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF4' 'TwoFloats'
+TwoInts case6(TwoFloats TF4) {
+ TwoInts TI2 = {TF4};
+ return TI2;
+}
+
+// Case 7: Initialization of a complex structure, with bogus braces and element
+// conversions from a collection of scalar values, and structures.
+// CHECK-LABEL: Dumping case7
+// CHECK: VarDecl {{.*}} used D1 'Doggo' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'Doggo'
+// CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector<int, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .Z {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoInts' lvalue ParmVar {{.*}} 'TI1' 'TwoInts'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .W {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoInts' lvalue ParmVar {{.*}} 'TI1' 'TwoInts'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .Z {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoInts' lvalue ParmVar {{.*}} 'TI2' 'TwoInts'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .W {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoInts' lvalue ParmVar {{.*}} 'TI2' 'TwoInts'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'Val' 'int'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'Val' 'int'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4[2]'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .X {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF1' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .Y {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF1' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .X {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF2' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .Y {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF2' 'TwoFloats'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .X {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF3' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .Y {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF3' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .X {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF4' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .Y {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF4' 'TwoFloats'
+Doggo case7(TwoInts TI1, TwoInts TI2, int Val, TwoFloats TF1, TwoFloats TF2,
+ TwoFloats TF3, TwoFloats TF4) {
+ Doggo D1 = {TI1, TI2, {Val, Val}, {{TF1, TF2}, {TF3, TF4}}};
+ return D1;
+}
+
+// Case 8: Initialization of a structure from a
diff erent structure with
+// significantly
diff erent element types and grouping.
+// CHECK-LABEL: Dumping case8
+// CHECK: VarDecl {{.*}} used A1 'AnimalBits' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'AnimalBits'
+// CHECK-NEXT: InitListExpr {{.*}} 'int[4]'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int' <IntegralCast>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .TailState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'long' <FloatingToIntegral>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .HairCount {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+AnimalBits case8(Doggo D1) {
+ AnimalBits A1 = {D1};
+ return A1;
+}
+
+// Case 9: Everything everywhere all at once... Initializing mismatched
+// structures from
diff erent layouts,
diff erent component groupings, with no
+// top-level bracing separation.
+// CHECK-LABEL: Dumping case9
+// CHECK: VarDecl {{.*}} used Z1 'Zoo' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'Zoo'
+// CHECK-NEXT: InitListExpr {{.*}} 'Doggo[2]'
+// CHECK-NEXT: InitListExpr {{.*}} 'Doggo'
+// CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector<int, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .TailState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .HairCount {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4[2]'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'Doggo'
+// CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector<int, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <IntegralCast>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'uint':'unsigned int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'uint':'unsigned int' lvalue .State {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t':'long' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int64_t':'long' lvalue .Counter {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4[2]'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'Kitteh[4]'
+// CHECK-NEXT: InitListExpr {{.*}} 'Kitteh'
+// CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector<int, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .TailState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .HairCount {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4[2]'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'Kitteh'
+// CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector<int, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <IntegralCast>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'uint':'unsigned int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'uint':'unsigned int' lvalue .State {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t':'long' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int64_t':'long' lvalue .Counter {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4[2]'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'Kitteh'
+// CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector<int, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'int4':'vector<int, 4>' lvalue .LegState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .TailState {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .HairCount {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4[2]'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float4':'vector<float, 4>' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4 *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'float4[2]' lvalue .EarDirection {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'Doggo' lvalue ParmVar {{.*}} 'D1' 'Doggo'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'Kitteh'
+// CHECK-NEXT: InitListExpr {{.*}} 'int4':'vector<int, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'int' lvalue
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int *' <ArrayToPointerDecay>
+// CHECK-NEXT: MemberExpr {{.*}} 'int[4]' lvalue .Legs {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <IntegralCast>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'uint':'unsigned int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'uint':'unsigned int' lvalue .State {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t':'long' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int64_t':'long' lvalue .Counter {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4[2]'
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .LeftDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+// CHECK-NEXT: InitListExpr {{.*}} 'float4':'vector<float, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' lvalue vectorcomponent
+// CHECK-NEXT: MemberExpr {{.*}} 'float4':'vector<float, 4>' lvalue .RightDir {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'AnimalBits' lvalue ParmVar {{.*}} 'A1' 'AnimalBits'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+Zoo case9(Doggo D1, AnimalBits A1) {
+ Zoo Z1 = {D1, A1, D1, A1, D1, A1};
+ return Z1;
+}
+
+// Case 10: Initialize an object with a base class from two objects.
+// CHECK-LABEL: Dumping case10
+// CHECK: | `-VarDecl {{.*}} used FF1 'FourFloats' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'FourFloats'
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .X {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF1' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .Y {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF1' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .X {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF2' 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .Y {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoFloats' lvalue ParmVar {{.*}} 'TF2' 'TwoFloats'
+FourFloats case10(TwoFloats TF1, TwoFloats TF2) {
+ FourFloats FF1 = {TF1, TF2};
+ return FF1;
+}
+
+// Case 11: Initialize an object with a base class from a vector splat.
+// CHECK-LABEL: Dumping case11
+// CHECK: VarDecl {{.*}} used FF1 'FourFloats' nrvo cinit
+// CHECK-NEXT: ExprWithCleanups {{.*}} 'FourFloats'
+// CHECK-NEXT: InitListExpr {{.*}} 'FourFloats'
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' xvalue vectorcomponent
+// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'vector<float, 4>' xvalue
+// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'vector<float, 4>' xxxx
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 1>' lvalue <VectorSplat>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'F' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' xvalue vectorcomponent
+// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'vector<float, 4>' xvalue
+// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'vector<float, 4>' xxxx
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 1>' lvalue <VectorSplat>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'F' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' xvalue vectorcomponent
+// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'vector<float, 4>' xvalue
+// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'vector<float, 4>' xxxx
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 1>' lvalue <VectorSplat>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'F' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'float' xvalue vectorcomponent
+// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'vector<float, 4>' xvalue
+// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'vector<float, 4>' xxxx
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 1>' lvalue <VectorSplat>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'F' 'float'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 3
+FourFloats case11(float F) {
+ FourFloats FF1 = {F.xxxx};
+ return FF1;
+}
+
+// Case 12: Initialize bitfield from two integers.
+// CHECK-LABEL: Dumping case12
+// CHECK: VarDecl {{.*}} used SB 'SlicyBits' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'SlicyBits'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'I' 'int'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'J' 'int'
+SlicyBits case12(int I, int J) {
+ SlicyBits SB = {I, J};
+ return SB;
+}
+
+// Case 13: Initialize bitfield from a struct of two ints.
+// CHECK-LABEL: Dumping case13
+// CHECK: VarDecl {{.*}} used SB 'SlicyBits' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'SlicyBits'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .Z {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoInts' lvalue ParmVar {{.*}} 'TI' 'TwoInts'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue .W {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'TwoInts' lvalue ParmVar {{.*}} 'TI' 'TwoInts'
+SlicyBits case13(TwoInts TI) {
+ SlicyBits SB = {TI};
+ return SB;
+}
+
+// Case 14: Initialize struct of ints from struct with bitfields.
+// CHECK-LABEL: Dumping case14
+// CHECK: VarDecl {{.*}} used TI 'TwoInts' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoInts'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue bitfield .Z {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'SlicyBits' lvalue ParmVar {{.*}} 'SB' 'SlicyBits'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue bitfield .W {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'SlicyBits' lvalue ParmVar {{.*}} 'SB' 'SlicyBits'
+TwoInts case14(SlicyBits SB) {
+ TwoInts TI = {SB};
+ return TI;
+}
+
+// Case 15: Initialize struct of floats from struct with bitfields.
+// CHECK-LABEL: Dumping case15
+// CHECK: VarDecl {{.*}} used TI 'TwoFloats' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue bitfield .Z {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'SlicyBits' lvalue ParmVar {{.*}} 'SB' 'SlicyBits'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'int' lvalue bitfield .W {{.*}}
+// CHECK-NEXT: DeclRefExpr {{.*}} 'SlicyBits' lvalue ParmVar {{.*}} 'SB' 'SlicyBits'
+TwoFloats case15(SlicyBits SB) {
+ TwoFloats TI = {SB};
+ return TI;
+}
+
+// Case 16: Side-effecting initialization list arguments. The important thing
+// here is that case16 only has _one_ call to makeTwo.
+TwoFloats makeTwo(inout float X) {
+ TwoFloats TF = {X, X*1.5};
+ X *= 2;
+ return TF;
+}
+
+// CHECK-LABEL: Dumping case16
+// CHECK: VarDecl {{.*}} used FF 'FourFloats' nrvo cinit
+// CHECK-NEXT: InitListExpr {{.*}} 'FourFloats'
+// CHECK-NEXT: InitListExpr {{.*}} 'TwoFloats'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating>
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
+// CHECK-NEXT: MemberExpr {{.*}} 'float' xvalue .X {{.*}}
+// CHECK-NEXT: OpaqueValueExpr [[OVEArg:0x[0-9A-Fa-f]+]] {{.*}} 'TwoFloats' xvalue
+// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'TwoFloats' xvalue
+// CHECK-NEXT: CallExpr {{.*}} 'TwoFloats'
+
+// I don't care about the call here, just skip ahead to the next argument, and
+// verify that we match the same OpaqueValueExpr.
+
+// CHECK: MemberExpr {{.*}} 'float' xvalue .Y {{.*}}
+// CHECK-NEXT: OpaqueValueExpr [[OVEArg]] {{.*}} 'TwoFloats' xvalue
+// CHECK-NEXT: MaterializeTemporaryExpr {{.*}} 'TwoFloats' xvalue
+// CHECK-NEXT: CallExpr {{.*}} 'TwoFloats'
+FourFloats case16() {
+ float X = 0;
+ FourFloats FF = {0, makeTwo(X), 3};
+ return FF;
+}
diff --git a/clang/test/SemaHLSL/Language/InitLists.hlsl b/clang/test/SemaHLSL/Language/InitLists.hlsl
new file mode 100644
index 0000000000000..3607dfd8aedbc
--- /dev/null
+++ b/clang/test/SemaHLSL/Language/InitLists.hlsl
@@ -0,0 +1,126 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -finclude-default-header -verify -Wdouble-promotion -Wconversion %s
+
+struct TwoFloats {
+ float X, Y;
+};
+
+struct TwoInts {
+ int Z, W;
+};
+
+struct Doggo {
+ int4 LegState;
+ int TailState;
+ float HairCount;
+ float4 EarDirection[2];
+};
+
+struct AnimalBits {
+ int Legs[4];
+ uint State;
+ int64_t Counter;
+ float4 LeftDir;
+ float4 RightDir;
+};
+
+struct Kitteh {
+ int4 Legs;
+ int TailState;
+ float HairCount;
+ float4 Claws[2];
+};
+
+struct Zoo {
+ Doggo Dogs[2];
+ Kitteh Cats[4];
+};
+
+struct FourFloats : TwoFloats {
+ float Z, W;
+};
+
+struct SlicyBits {
+ int Z : 8;
+ int W : 8;
+};
+
+struct ContainsResource { // #ContainsResource
+ int X;
+ RWBuffer<float4> B;
+};
+
+struct ContainsResourceInverted {
+ RWBuffer<float4> B;
+ int X;
+};
+
+void fn() {
+ TwoFloats TF1 = {{{1.0, 2}}};
+ TwoFloats TF2 = {1,2};
+ int Val = 1;
+ TwoFloats TF3 = {Val, 2}; // expected-warning{{implicit conversion from 'int' to 'float' may lose precision}}
+ int2 TwoVals = 1.xx;
+ int2 Something = 1.xxx; // expected-warning{{implicit conversion truncates vector: 'vector<int, 3>' (vector of 3 'int' values) to 'vector<int, 2>' (vector of 2 'int' values)}}
+ TwoFloats TF4 = {TwoVals}; // expected-warning{{implicit conversion from 'int' to 'float' may lose precision}} expected-warning{{implicit conversion from 'int' to 'float' may lose precision}}
+
+ TwoInts TI1 = {TwoVals};
+ TwoInts TI2 = {TF4}; // expected-warning{{implicit conversion turns floating-point number into integer: 'float' to 'int'}} expected-warning{{implicit conversion turns floating-point number into integer: 'float' to 'int'}}
+
+ Doggo D1 = {TI1, TI2, {Val, Val}, {{TF1, TF2}, {TF3, TF4}}}; // expected-warning{{implicit conversion from 'int' to 'float' may lose precision}}
+ AnimalBits A1 = {D1}; // expected-warning{{implicit conversion turns floating-point number into integer: 'float' to 'long'}} expected-warning{{implicit conversion changes signedness: 'int' to 'unsigned int'}}
+
+ Zoo Z1 = {D1, A1, D1, A1, D1, A1}; // #insanity
+
+ // expected-warning@#insanity{{implicit conversion from 'int64_t' (aka 'long') to 'float' may lose precision}}
+ // expected-warning@#insanity{{implicit conversion changes signedness: 'uint' (aka 'unsigned int') to 'int'}}
+ // expected-warning@#insanity{{implicit conversion from 'int64_t' (aka 'long') to 'float' may lose precision}}
+ // expected-warning@#insanity{{implicit conversion changes signedness: 'uint' (aka 'unsigned int') to 'int'}}
+ // expected-warning@#insanity{{implicit conversion from 'int64_t' (aka 'long') to 'float' may lose precision}}
+ // expected-warning@#insanity{{implicit conversion changes signedness: 'uint' (aka 'unsigned int') to 'int'}}
+}
+
+void fn2() {
+ TwoFloats TF2 = {1,2};
+ FourFloats FF1 = {TF2, TF2};
+ FourFloats FF2 = {1,2,3,4};
+ FourFloats FF3 = {1.xxx, 2};
+
+ SlicyBits SB1 = {1,2};
+ TwoInts TI1 = {SB1};
+ SlicyBits SB2 = {TI1};
+}
+
+void Errs() {
+ TwoFloats F1 = {}; // expected-error{{too few initializers in list for type 'TwoFloats' (expected 2 but found 0)}}
+ TwoFloats F2 = {1}; // expected-error{{too few initializers in list for type 'TwoFloats' (expected 2 but found 1)}}
+ TwoFloats F3 = {1,2,3}; // expected-error{{too many initializers in list for type 'TwoFloats' (expected 2 but found 3)}}
+
+ int2 Something = {1.xxx}; // expected-error{{too many initializers in list for type 'int2' (aka 'vector<int, 2>') (expected 2 but found 3)}}
+}
+
+struct R {
+ int A;
+ union { // #anon
+ float F;
+ int4 G;
+ };
+};
+
+// expected-note@#anon{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to}}
+// expected-note@#anon{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to}}
+
+void Err2(RWBuffer<float4> B) {
+ ContainsResource RS1 = {1, B};
+ ContainsResource RS2 = (1.xx); // expected-error{{no viable conversion from 'vector<int, 2>' (vector of 2 'int' values) to 'ContainsResource'}}
+ ContainsResource RS3 = {B, 1}; // expected-error{{no viable conversion from 'RWBuffer<float4>' (aka 'RWBuffer<vector<float, 4>>') to 'int'}}
+ ContainsResourceInverted IR = {RS1}; // expected-error{{no viable conversion from 'int' to 'hlsl::RWBuffer<vector<float, 4>>'}}
+
+ R r = {1,2}; // expected-error{{no viable conversion from 'int' to 'R::(anonymous union at}}
+}
+
+// expected-note@#ContainsResource{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'vector<int, 2>' (vector of 2 'int' values) to 'const ContainsResource &' for 1st argument}}
+// expected-note@#ContainsResource{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'vector<int, 2>' (vector of 2 'int' values) to 'ContainsResource &&' for 1st argument}}
+
+// These notes refer to the RWBuffer constructors that do not have source locations
+// expected-note@*{{candidate constructor (the implicit copy constructor) not viable}}
+// expected-note@*{{candidate constructor (the implicit move constructor) not viable}}
More information about the cfe-commits
mailing list