microsoft / DirectXShaderCompiler

This repo hosts the source for the DirectX Shader Compiler which is based on LLVM/Clang.
Other
3.09k stars 690 forks source link

[Valgrind] Conditional branches on uninitialized SourceLocation::ID #6003

Open ChristianReinbold opened 1 year ago

ChristianReinbold commented 1 year ago

Description

When compiling a simple spir-v raygen shader sampling a texture with a linux build of DXC, Valgrind's memcheck identifies several conditional branches on uninitialized memory. In recent times, we regularly faced sporadic dxc crashes on Windows after applying seemingly harmless modifications to our production codebase (e.g. repeat a redundant assignment operation), which cannot be reproduced reliably on different dev machines. We suspect some corrupt memory to be the culprit, which is why we started investigating with memcheck. The memcheck issues found in our production codebase match those in the minimal working example described below.

Steps to Reproduce

Assuming you have a valid dxc & valgrind in your path, run

valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes dxc -T lib_6_4 -spirv -fspv-target-env=vulkan1.2 -enable-16bit-types -HV 2021 -O0 -Zi shader.hlsl -Fo shader.spv

where shader.hlsl is placed in the current working directory and contains

[[vk::binding(0)]] Texture2D texture_;
[[vk::binding(0)]] SamplerState sampler_;

[shader("raygeneration")]
void main() {
    texture_.SampleLevel(sampler_, float2(0.3f, 0.4f), 0);
}

Actual Behavior

Valgrind outputs

 Memcheck, a memory error detector
 Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
 Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info

 Conditional jump or move depends on uninitialised value(s)
    at 0x65F836E: clang::TypeLoc::getBeginLoc() const (TypeLoc.cpp:195)
    by 0x61E9DCC: clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformType(clang::TypeSourceInfo*) (TreeTransform.h:3779)
    by 0x61E12F1: clang::Sema::SubstType(clang::TypeSourceInfo*, clang::MultiLevelTemplateArgumentList const&, clang::SourceLocation, clang::DeclarationName) (SemaTemplateInstantiate.cpp:1473)
    by 0x6225134: clang::TemplateDeclInstantiator::VisitFieldDecl(clang::FieldDecl*) (SemaTemplateInstantiateDecl.cpp:582)
    by 0x621729B: clang::declvisitor::Base<clang::declvisitor::make_ptr, clang::TemplateDeclInstantiator, clang::Decl*>::Visit(clang::Decl*) (DeclNodes.inc:343)
    by 0x61E3A56: clang::Sema::InstantiateClass(clang::SourceLocation, clang::CXXRecordDecl*, clang::CXXRecordDecl*, clang::MultiLevelTemplateArgumentList const&, clang::TemplateSpecializationKind, bool) (SemaTemplateInstantiate.cpp:2102)
    by 0x61E5051: clang::Sema::InstantiateClassTemplateSpecialization(clang::SourceLocation, clang::ClassTemplateSpecializationDecl*, clang::TemplateSpecializationKind, bool) (SemaTemplateInstantiate.cpp:2504)
    by 0x629F61D: clang::Sema::RequireCompleteTypeImpl(clang::SourceLocation, clang::QualType, clang::Sema::TypeDiagnoser&) (SemaType.cpp:6759)
    by 0x629EC9C: clang::Sema::RequireCompleteType(clang::SourceLocation, clang::QualType, clang::Sema::TypeDiagnoser&) (SemaType.cpp:6568)
    by 0x629FA62: clang::Sema::RequireCompleteType(clang::SourceLocation, clang::QualType, unsigned int) (SemaType.cpp:6813)
    by 0x5C96E1D: clang::Sema::ActOnUninitializedDecl(clang::Decl*, bool) (SemaDecl.cpp:9627)
    by 0x6A8DDBC: clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::ForRangeInit*) (ParseDecl.cpp:2799)
  Uninitialised value was created by a heap allocation
    at 0x4C38833: operator new(unsigned long) (vg_replace_malloc.c:417)
    by 0x50A5C69: llvm::MallocAllocator::Allocate(unsigned long, unsigned long) (Allocator.h:96)
    by 0x516B899: llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul>::StartNewSlab() (Allocator.h:314)
    by 0x516A7E6: llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul>::Allocate(unsigned long, unsigned long) (Allocator.h:243)
    by 0x5841E8F: clang::ASTContext::Allocate(unsigned long, unsigned int) const (ASTContext.h:502)
    by 0x637DCBF: clang::ASTContext::getTemplateSpecializationType(clang::TemplateName, clang::TemplateArgument const*, unsigned int, clang::QualType) const (ASTContext.cpp:3444)
    by 0x637DA1A: clang::ASTContext::getTemplateSpecializationType(clang::TemplateName, clang::TemplateArgumentListInfo const&, clang::QualType) const (ASTContext.cpp:3399)
    by 0x5F97BA3: GetOrCreateTemplateSpecialization(clang::ASTContext&, clang::Sema&, clang::ClassTemplateDecl*, llvm::ArrayRef<clang::TemplateArgument>) (SemaHLSL.cpp:799)
    by 0x5F9817F: GetOrCreateVectorSpecialization(clang::ASTContext&, clang::Sema*, clang::ClassTemplateDecl*, clang::QualType, unsigned long) (SemaHLSL.cpp:855)
    by 0x5FC2C6A: HLSLExternalSource::LookupVectorType(hlsl::HLSLScalarType, unsigned int) (SemaHLSL.cpp:3979)
    by 0x5FC4DE7: HLSLExternalSource::NewSimpleAggregateType(ArTypeObjectKind, ArBasicKind, unsigned long, unsigned int, unsigned int) (SemaHLSL.cpp:4611)
    by 0x5FBFF27: HLSLExternalSource::AddObjectSubscripts(ArBasicKind, clang::ClassTemplateDecl*, clang::CXXRecordDecl*, SubscriptOperatorRecord) (SemaHLSL.cpp:3416)

 Conditional jump or move depends on uninitialised value(s)
    at 0x61FB3CA: clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TemporaryBase::TemporaryBase(clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>&, clang::SourceLocation, clang::DeclarationName) (TreeTransform.h:186)
    by 0x61E9DE4: clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformType(clang::TypeSourceInfo*) (TreeTransform.h:3779)
    by 0x61E12F1: clang::Sema::SubstType(clang::TypeSourceInfo*, clang::MultiLevelTemplateArgumentList const&, clang::SourceLocation, clang::DeclarationName) (SemaTemplateInstantiate.cpp:1473)
    by 0x6225134: clang::TemplateDeclInstantiator::VisitFieldDecl(clang::FieldDecl*) (SemaTemplateInstantiateDecl.cpp:582)
    by 0x621729B: clang::declvisitor::Base<clang::declvisitor::make_ptr, clang::TemplateDeclInstantiator, clang::Decl*>::Visit(clang::Decl*) (DeclNodes.inc:343)
    by 0x61E3A56: clang::Sema::InstantiateClass(clang::SourceLocation, clang::CXXRecordDecl*, clang::CXXRecordDecl*, clang::MultiLevelTemplateArgumentList const&, clang::TemplateSpecializationKind, bool) (SemaTemplateInstantiate.cpp:2102)
    by 0x61E5051: clang::Sema::InstantiateClassTemplateSpecialization(clang::SourceLocation, clang::ClassTemplateSpecializationDecl*, clang::TemplateSpecializationKind, bool) (SemaTemplateInstantiate.cpp:2504)
    by 0x629F61D: clang::Sema::RequireCompleteTypeImpl(clang::SourceLocation, clang::QualType, clang::Sema::TypeDiagnoser&) (SemaType.cpp:6759)
    by 0x629EC9C: clang::Sema::RequireCompleteType(clang::SourceLocation, clang::QualType, clang::Sema::TypeDiagnoser&) (SemaType.cpp:6568)
    by 0x629FA62: clang::Sema::RequireCompleteType(clang::SourceLocation, clang::QualType, unsigned int) (SemaType.cpp:6813)
    by 0x5C96E1D: clang::Sema::ActOnUninitializedDecl(clang::Decl*, bool) (SemaDecl.cpp:9627)
    by 0x6A8DDBC: clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::ForRangeInit*) (ParseDecl.cpp:2799)
  Uninitialised value was created by a heap allocation
    at 0x4C38833: operator new(unsigned long) (vg_replace_malloc.c:417)
    by 0x50A5C69: llvm::MallocAllocator::Allocate(unsigned long, unsigned long) (Allocator.h:96)
    by 0x516B899: llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul>::StartNewSlab() (Allocator.h:314)
    by 0x516A7E6: llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul>::Allocate(unsigned long, unsigned long) (Allocator.h:243)
    by 0x5841E8F: clang::ASTContext::Allocate(unsigned long, unsigned int) const (ASTContext.h:502)
    by 0x637DCBF: clang::ASTContext::getTemplateSpecializationType(clang::TemplateName, clang::TemplateArgument const*, unsigned int, clang::QualType) const (ASTContext.cpp:3444)
    by 0x637DA1A: clang::ASTContext::getTemplateSpecializationType(clang::TemplateName, clang::TemplateArgumentListInfo const&, clang::QualType) const (ASTContext.cpp:3399)
    by 0x5F97BA3: GetOrCreateTemplateSpecialization(clang::ASTContext&, clang::Sema&, clang::ClassTemplateDecl*, llvm::ArrayRef<clang::TemplateArgument>) (SemaHLSL.cpp:799)
    by 0x5F9817F: GetOrCreateVectorSpecialization(clang::ASTContext&, clang::Sema*, clang::ClassTemplateDecl*, clang::QualType, unsigned long) (SemaHLSL.cpp:855)
    by 0x5FC2C6A: HLSLExternalSource::LookupVectorType(hlsl::HLSLScalarType, unsigned int) (SemaHLSL.cpp:3979)
    by 0x5FC4DE7: HLSLExternalSource::NewSimpleAggregateType(ArTypeObjectKind, ArBasicKind, unsigned long, unsigned int, unsigned int) (SemaHLSL.cpp:4611)
    by 0x5FBFF27: HLSLExternalSource::AddObjectSubscripts(ArBasicKind, clang::ClassTemplateDecl*, clang::CXXRecordDecl*, SubscriptOperatorRecord) (SemaHLSL.cpp:3416)

 Conditional jump or move depends on uninitialised value(s)
    at 0x5F9DE84: HLSLExternalSource::MatchArguments(IntrinsicDefIter const&, clang::QualType, clang::QualType, llvm::ArrayRef<clang::Expr*>, std::vector<clang::QualType, std::allocator<clang::QualType> >*, unsigned long&) (SemaHLSL.cpp:6465)
    by 0x5FA8366: HLSLExternalSource::DeduceTemplateArgumentsForHLSL(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&) (SemaHLSL.cpp:10005)
    by 0x5FA9BEC: hlsl::DeduceTemplateArgumentsForHLSL(clang::Sema*, clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&) (SemaHLSL.cpp:10426)
    by 0x61A4EFF: clang::Sema::DeduceTemplateArguments(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&, bool) (SemaTemplateDeduction.cpp:3348)
    by 0x6071E48: clang::Sema::AddMethodTemplateCandidate(clang::FunctionTemplateDecl*, clang::DeclAccessPair, clang::CXXRecordDecl*, clang::TemplateArgumentListInfo*, clang::QualType, clang::Expr::Classification, llvm::ArrayRef<clang::Expr*>, clang::OverloadCandidateSet&, bool, bool) (SemaOverload.cpp:6284)
    by 0x6087AAC: clang::Sema::BuildCallToMemberFunction(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation) (SemaOverload.cpp:11885)
    by 0x5E31CDE: clang::Sema::ActOnCallExpr(clang::Scope*, clang::Expr*, clang::SourceLocation, llvm::MutableArrayRef<clang::Expr*>, clang::SourceLocation, clang::Expr*, bool) (SemaExpr.cpp:5002)
    by 0x6AC589D: clang::Parser::ParsePostfixExpressionSuffix(clang::ActionResult<clang::Expr*, true>) (ParseExpr.cpp:1669)
    by 0x6AC4825: clang::Parser::ParseCastExpression(bool, bool, bool&, clang::Parser::TypeCastState) (ParseExpr.cpp:1473)
    by 0x6AC093A: clang::Parser::ParseCastExpression(bool, bool, clang::Parser::TypeCastState) (ParseExpr.cpp:482)
    by 0x6ABF5A3: clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState) (ParseExpr.cpp:175)
    by 0x6ABF341: clang::Parser::ParseExpression(clang::Parser::TypeCastState) (ParseExpr.cpp:121)
  Uninitialised value was created by a stack allocation
    at 0x5FA7CB3: HLSLExternalSource::DeduceTemplateArgumentsForHLSL(clang::FunctionTemplateDecl*, clang::TemplateArgumentListInfo*, llvm::ArrayRef<clang::Expr*>, clang::FunctionDecl*&, clang::sema::TemplateDeductionInfo&) (SemaHLSL.cpp:9920)

HEAP SUMMARY:
    in use at exit: 451 bytes in 11 blocks
  total heap usage: 3,452 allocs, 3,441 frees, 1,707,881 bytes allocated

16 bytes in 1 blocks are still reachable in loss record 1 of 9
   at 0x4C38833: operator new(unsigned long) (vg_replace_malloc.c:417)
   by 0x51AD5F5: DxcCoGetMalloc(unsigned int, IMalloc**) (WinIncludes.cpp:42)
   by 0x519669A: DxcInitThreadMalloc() (dxcmem.cpp:34)
   by 0x4FE8A55: InitMaybeFail() (DXCompiler.cpp:58)
   by 0x4FE8B48: DllMain() (DXCompiler.cpp:90)
   by 0x4008F19: call_init.part.0 (dl-init.c:72)
   by 0x4009019: call_init (dl-init.c:118)
   by 0x4009019: _dl_init (dl-init.c:119)
   by 0x401DC89: ??? (in /usr/lib64/ld-2.28.so)
   by 0x10: ???
   by 0x1FFEFFF88A: ???
   by 0x1FFEFFF88E: ???
   by 0x1FFEFFF8BA: ???

16 bytes in 1 blocks are still reachable in loss record 2 of 9
   at 0x4C38833: operator new(unsigned long) (vg_replace_malloc.c:417)
   by 0x500FC9F: DxilLibInitialize() (dxillib.cpp:27)
   by 0x4FE8ABA: InitMaybeFail() (DXCompiler.cpp:68)
   by 0x4FE8B48: DllMain() (DXCompiler.cpp:90)
   by 0x4008F19: call_init.part.0 (dl-init.c:72)
   by 0x4009019: call_init (dl-init.c:118)
   by 0x4009019: _dl_init (dl-init.c:119)
   by 0x401DC89: ??? (in /usr/lib64/ld-2.28.so)
   by 0x10: ???
   by 0x1FFEFFF88A: ???
   by 0x1FFEFFF88E: ???
   by 0x1FFEFFF8BA: ???
   by 0x1FFEFFF8E2: ???

16 bytes in 1 blocks are still reachable in loss record 3 of 9
   at 0x4C380A5: malloc (vg_replace_malloc.c:380)
   by 0x400BF83: UnknownInlinedFun (rtld-malloc.h:56)
   by 0x400BF83: decompose_rpath.isra.7 (dl-load.c:626)
   by 0x400CCD1: cache_rpath (dl-load.c:2064)
   by 0x400CCD1: _dl_map_object (dl-load.c:2071)
   by 0x4010DA8: dl_open_worker_begin (dl-open.c:532)
   by 0x9F27903: _dl_catch_exception (in /usr/lib64/libc-2.28.so)
   by 0x4010706: dl_open_worker (dl-open.c:768)
   by 0x9F27903: _dl_catch_exception (in /usr/lib64/libc-2.28.so)
   by 0x4010950: _dl_open (dl-open.c:876)
   by 0x8C4CF89: dlopen_doit (in /usr/lib64/libdl-2.28.so)
   by 0x9F27903: _dl_catch_exception (in /usr/lib64/libc-2.28.so)
   by 0x9F279C2: _dl_catch_error (in /usr/lib64/libc-2.28.so)
   by 0x8C4D52D: _dlerror_run (in /usr/lib64/libdl-2.28.so)

16 bytes in 1 blocks are still reachable in loss record 4 of 9
   at 0x4C38833: operator new(unsigned long) (vg_replace_malloc.c:417)
   by 0x601515: DxcCoGetMalloc(unsigned int, IMalloc**) (WinIncludes.cpp:42)
   by 0x5E6426: DxcInitThreadMalloc() (dxcmem.cpp:34)
   by 0x423C95: dxc::main(int, char const**) (dxc.cpp:1351)
   by 0x41B485: main (dxcmain.cpp:20)

16 bytes in 1 blocks are still reachable in loss record 5 of 9
   at 0x4C380A5: malloc (vg_replace_malloc.c:380)
   by 0x601651: DxcCoMalloc::Alloc(unsigned long) (WinIncludes.cpp:28)
   by 0x5E64B3: DxcInitThreadMalloc() (dxcmem.cpp:39)
   by 0x423C95: dxc::main(int, char const**) (dxc.cpp:1351)
   by 0x41B485: main (dxcmain.cpp:20)

31 bytes in 3 blocks are still reachable in loss record 6 of 9
   at 0x4C38833: operator new(unsigned long) (vg_replace_malloc.c:417)
   by 0x58E17D: llvm::MallocAllocator::Allocate(unsigned long, unsigned long) (Allocator.h:96)
   by 0x58F566: llvm::StringMapEntry<char>* llvm::StringMapEntry<char>::Create<llvm::MallocAllocator, char>(llvm::StringRef, llvm::MallocAllocator&, char&&) (StringMap.h:154)
   by 0x58EDA5: llvm::StringMap<char, llvm::MallocAllocator>::insert(std::pair<llvm::StringRef, char>) (StringMap.h:328)
   by 0x58E64B: llvm::StringSet<llvm::MallocAllocator>::insert(llvm::StringRef) (StringSet.h:29)
   by 0x58C7D3: llvm::opt::OptTable::OptTable(llvm::opt::OptTable::Info const*, unsigned int, bool) (OptTable.cpp:136)
   by 0x5EE580: (anonymous namespace)::HlslOptTable::HlslOptTable() (HLSLOptions.cpp:48)
   by 0x5EE610: hlsl::options::initHlslOptTable() (HLSLOptions.cpp:57)
   by 0x423CBB: dxc::main(int, char const**) (dxc.cpp:1355)
   by 0x41B485: main (dxcmain.cpp:20)

40 bytes in 1 blocks are still reachable in loss record 7 of 9
   at 0x4C380A5: malloc (vg_replace_malloc.c:380)
   by 0x5759319: llvm::sys::MutexImpl::MutexImpl(bool) (Mutex.cpp:49)
   by 0x5010222: llvm::sys::SmartMutex<false>::SmartMutex(bool) (Mutex.h:101)
   by 0x500FCAF: DxilLibInitialize() (dxillib.cpp:27)
   by 0x4FE8ABA: InitMaybeFail() (DXCompiler.cpp:68)
   by 0x4FE8B48: DllMain() (DXCompiler.cpp:90)
   by 0x4008F19: call_init.part.0 (dl-init.c:72)
   by 0x4009019: call_init (dl-init.c:118)
   by 0x4009019: _dl_init (dl-init.c:119)
   by 0x401DC89: ??? (in /usr/lib64/ld-2.28.so)
   by 0x10: ???
   by 0x1FFEFFF88A: ???
   by 0x1FFEFFF88E: ???

96 bytes in 1 blocks are still reachable in loss record 8 of 9
   at 0x4C390B5: operator new(unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:497)
   by 0x5EE600: hlsl::options::initHlslOptTable() (HLSLOptions.cpp:57)
   by 0x423CBB: dxc::main(int, char const**) (dxc.cpp:1355)
   by 0x41B485: main (dxcmain.cpp:20)

204 bytes in 1 blocks are still reachable in loss record 9 of 9
   at 0x4C38833: operator new(unsigned long) (vg_replace_malloc.c:417)
   by 0x61E2B2: llvm::StringMapImpl::init(unsigned int) (StringMap.cpp:47)
   by 0x61E340: llvm::StringMapImpl::LookupBucketFor(llvm::StringRef) (StringMap.cpp:66)
   by 0x58ECCD: llvm::StringMap<char, llvm::MallocAllocator>::insert(std::pair<llvm::StringRef, char>) (StringMap.h:319)
   by 0x58E64B: llvm::StringSet<llvm::MallocAllocator>::insert(llvm::StringRef) (StringSet.h:29)
   by 0x58C7D3: llvm::opt::OptTable::OptTable(llvm::opt::OptTable::Info const*, unsigned int, bool) (OptTable.cpp:136)
   by 0x5EE580: (anonymous namespace)::HlslOptTable::HlslOptTable() (HLSLOptions.cpp:48)
   by 0x5EE610: hlsl::options::initHlslOptTable() (HLSLOptions.cpp:57)
   by 0x423CBB: dxc::main(int, char const**) (dxc.cpp:1355)
   by 0x41B485: main (dxcmain.cpp:20)

LEAK SUMMARY:
   definitely lost: 0 bytes in 0 blocks
   indirectly lost: 0 bytes in 0 blocks
     possibly lost: 0 bytes in 0 blocks
   still reachable: 451 bytes in 11 blocks
        suppressed: 0 bytes in 0 blocks

For lists of detected and suppressed errors, rerun with: -s
ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 2 from 2)

My own investigation boils down to two issues:

  1. an uninitialized ID in the source location accessed by TypeLoc::getLocalSourceRange()::getBegin(). Unfortunately, the ID seems to come out of some opaque data blocked accessed via a void pointer. It looks strange to me that - when debugging - the Class of the TypeLoc is clang::TypeLoc::Record, but the memory block in which the uninitialized ID resides in is allocated when constructing a VarDecl. However, I am not aware how clang's custom memory management works, so maybe this mismatch can be explained. If I have to guess, some casting or pointer arithmetics is going wrong. At least I was not able to find any obviously missing initializations of members when constructing a VarDecl. I kind of feel blocked now in continuing to resolve this. It would be great if someone with more experience of the dxc & clang codebase could take over. Note that I have not looked into the memory leaks reported by Valgrind. They seem to be related to one-time setup & teardown of global state, and thus will not impact the stability of dxc.

  2. When processing arguments of the SampleLevel intrinsic an out-of-bounds access is happening in SemaHLSL.cpp:6465 if (Template[pIntrinsic->pArgs[0].uTemplateId] == AR_TOBJ_OBJECT) Turns out this has been already fixed on the main branch. Would be great if we see this change in the next release.

Environment DXC debug build with v1.7.2308 sources on RedHat 8.6 (reproduces both issues) DXC debug build with main (hash ceff9b804) sources on RedHat 8.6 (only reproduces first issue, not second)

sudonatalie commented 11 months ago

The Conditional jump or move depends on uninitialised value(s) at 0x69931D0: clang::TypeLoc::getBeginLoc() const (TypeLoc.cpp:195) is also present when compiling to dxil, so this isn't specific to the SPIR-V backend. Not yet sure how to debug it but I'll move it to general triage for now.