diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index fa18c3cd0f404..c60f9c4808420 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1158,6 +1158,7 @@ void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { static bool isType(const Metadata *MD) { return !MD || isa(MD); } static bool isScope(const Metadata *MD) { return !MD || isa(MD); } static bool isDINode(const Metadata *MD) { return !MD || isa(MD); } +static bool isMDTuple(const Metadata *MD) { return !MD || isa(MD); } void Verifier::visitDILocation(const DILocation &N) { CheckDI(N.getRawScope() && isa(N.getRawScope()), @@ -1320,6 +1321,29 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) { if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) { CheckDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N, N.getRawExtraData()); + } else if (N.getTag() == dwarf::DW_TAG_template_alias) { + CheckDI(isMDTuple(N.getRawExtraData()), "invalid template parameters", &N, + N.getRawExtraData()); + } else if (auto *ExtraData = N.getRawExtraData()) { + auto IsValidExtraData = [&]() { + if (isa(ExtraData) || isa(ExtraData) || + isa(ExtraData)) + return true; + if (auto *Tuple = dyn_cast(ExtraData)) { + if (N.getTag() != dwarf::DW_TAG_inheritance && + N.getTag() != dwarf::DW_TAG_member && + N.getTag() != dwarf::DW_TAG_variable) + return false; + if (Tuple->getNumOperands() != 1) + return false; + return isa_and_nonnull(Tuple->getOperand(0).get()); + } + return false; + }; + CheckDI(IsValidExtraData(), + "extraData must be ConstantAsMetadata, MDString, DIObjCProperty, " + "or MDTuple with single ConstantAsMetadata operand", + &N, ExtraData); } if (N.getTag() == dwarf::DW_TAG_set_type) { diff --git a/llvm/test/Verifier/diderivedtype-extradata-tuple.ll b/llvm/test/Verifier/diderivedtype-extradata-tuple.ll new file mode 100644 index 0000000000000..e3f7a46bf905b --- /dev/null +++ b/llvm/test/Verifier/diderivedtype-extradata-tuple.ll @@ -0,0 +1,66 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +;; Test that extraData with MDTuple is only allowed for specific DWARF tags: +;; DW_TAG_inheritance, DW_TAG_member, and DW_TAG_variable + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} + +!1 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + +; Keep all metadata nodes alive so verifier can check them +!named = !{!1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19} +!2 = !{i32 0} + +; Valid: DW_TAG_inheritance with tuple extraData should be accepted +!3 = !DIDerivedType(tag: DW_TAG_inheritance, baseType: !1, size: 32, extraData: !2) + +; Valid: DW_TAG_member with tuple extraData should be accepted +!4 = !DIDerivedType(tag: DW_TAG_member, name: "field", baseType: !1, size: 32, extraData: !2) + +; Valid: DW_TAG_variable (static member) with tuple extraData should be accepted +!5 = !DIDerivedType(tag: DW_TAG_variable, name: "var", baseType: !1, extraData: !2, flags: DIFlagStaticMember) + +; Invalid: DW_TAG_typedef with tuple extraData should be rejected +; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand +; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_typedef +!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy", baseType: !1, extraData: !2) + +; Invalid: Empty tuple should be rejected +!7 = !{} +; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand +; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member +!8 = !DIDerivedType(tag: DW_TAG_member, name: "field2", baseType: !1, extraData: !7) + +; Invalid: Tuple with multiple operands should be rejected +!9 = !{i32 0, i32 1} +; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand +; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member +!10 = !DIDerivedType(tag: DW_TAG_member, name: "field3", baseType: !1, extraData: !9) + +; Invalid: Tuple with non-ConstantAsMetadata operand should be rejected +!11 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!12 = !{!11} +; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand +; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member +!13 = !DIDerivedType(tag: DW_TAG_member, name: "field4", baseType: !1, extraData: !12) + +; Valid: ConstantAsMetadata as extraData should still work for any tag +!14 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy2", baseType: !1, extraData: i32 42) + +; Valid: MDString as extraData should still work for any tag +!15 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy3", baseType: !1, extraData: !"some string") + +; Valid: DW_TAG_template_alias with proper template parameters tuple +; Template aliases are handled specially and accept any MDTuple for template parameters +!16 = !DITemplateTypeParameter(name: "T", type: !1) +!17 = !{!16} +!18 = !DIDerivedType(tag: DW_TAG_template_alias, name: "MyAlias", baseType: !1, extraData: !17) + +; Invalid: DW_TAG_template_alias with non-tuple extraData should fail +; CHECK: invalid template parameters +; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_template_alias +!19 = !DIDerivedType(tag: DW_TAG_template_alias, name: "FailingAlias", baseType: !1, extraData: i32 42) + +; CHECK: warning: ignoring invalid debug info +