From d3ec0ca17ec7891af2c238f1c19a6d1cf6b250fd Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Mon, 30 Mar 2015 16:37:48 +0000 Subject: [PATCH] Verifier: Add operand checks for MDLexicalBlock Add operand checks for `MDLexicalBlock` and `MDLexicalBlockFile`. Like `MDLocalVariable` and `MDLocation`, these nodes always require a scope. There was no test bitrot to fix here (just updated the serialization tests in test/Assembler/mdlexicalblock.ll). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233561 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/DebugInfoMetadata.h | 31 ++++++++++++++++++- lib/AsmParser/LLParser.cpp | 4 +-- lib/IR/AsmWriter.cpp | 8 ++--- lib/IR/DebugInfoMetadata.cpp | 2 ++ lib/IR/LLVMContextImpl.h | 8 ++--- lib/IR/Verifier.cpp | 14 +++++++-- .../invalid-mdlexicalblock-null-scope.ll | 4 +++ .../invalid-mdlexicalblockfile-null-scope.ll | 4 +++ test/Assembler/mdlexicalblock.ll | 12 +++---- unittests/IR/IRBuilderTest.cpp | 4 ++- unittests/IR/MetadataTest.cpp | 19 +++++++----- 11 files changed, 82 insertions(+), 28 deletions(-) create mode 100644 test/Assembler/invalid-mdlexicalblock-null-scope.ll create mode 100644 test/Assembler/invalid-mdlexicalblockfile-null-scope.ll diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index d52c8b89fef..8e7addf234f 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -1129,7 +1129,12 @@ protected: ~MDLexicalBlockBase() {} public: - Metadata *getScope() const { return getOperand(1); } + // FIXME: Remove this once MDScope::getFile() does the same. + MDFile *getFile() const { return cast_or_null(getRawFile()); } + + MDLocalScope *getScope() const { return cast(getRawScope()); } + + Metadata *getRawScope() const { return getOperand(1); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLexicalBlockKind || @@ -1150,6 +1155,15 @@ class MDLexicalBlock : public MDLexicalBlockBase { Column(Column) {} ~MDLexicalBlock() {} + static MDLexicalBlock *getImpl(LLVMContext &Context, MDLocalScope *Scope, + MDFile *File, unsigned Line, unsigned Column, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast(Scope), + static_cast(File), Line, Column, Storage, + ShouldCreate); + } + static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Line, unsigned Column, StorageType Storage, bool ShouldCreate = true); @@ -1160,6 +1174,9 @@ class MDLexicalBlock : public MDLexicalBlockBase { } public: + DEFINE_MDNODE_GET(MDLexicalBlock, (MDLocalScope * Scope, MDFile *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File, unsigned Line, unsigned Column), (Scope, File, Line, Column)) @@ -1186,6 +1203,15 @@ class MDLexicalBlockFile : public MDLexicalBlockBase { Discriminator(Discriminator) {} ~MDLexicalBlockFile() {} + static MDLexicalBlockFile *getImpl(LLVMContext &Context, MDLocalScope *Scope, + MDFile *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast(Scope), + static_cast(File), Discriminator, Storage, + ShouldCreate); + } + static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Discriminator, StorageType Storage, @@ -1197,6 +1223,9 @@ class MDLexicalBlockFile : public MDLexicalBlockBase { } public: + DEFINE_MDNODE_GET(MDLexicalBlockFile, (MDLocalScope * Scope, MDFile *File, + unsigned Discriminator), + (Scope, File, Discriminator)) DEFINE_MDNODE_GET(MDLexicalBlockFile, (Metadata * Scope, Metadata *File, unsigned Discriminator), (Scope, File, Discriminator)) diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 428d80022e2..75ff79094a2 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -3571,7 +3571,7 @@ bool LLParser::ParseMDSubprogram(MDNode *&Result, bool IsDistinct) { /// ::= !MDLexicalBlock(scope: !0, file: !2, line: 7, column: 9) bool LLParser::ParseMDLexicalBlock(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(scope, MDField, ); \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ OPTIONAL(file, MDField, ); \ OPTIONAL(line, LineField, ); \ OPTIONAL(column, ColumnField, ); @@ -3587,7 +3587,7 @@ bool LLParser::ParseMDLexicalBlock(MDNode *&Result, bool IsDistinct) { /// ::= !MDLexicalBlockFile(scope: !0, file: !2, discriminator: 9) bool LLParser::ParseMDLexicalBlockFile(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(scope, MDField, ); \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ OPTIONAL(file, MDField, ); \ REQUIRED(discriminator, MDUnsignedField, (0, UINT32_MAX)); PARSE_MD_FIELDS(); diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index c5782f5937f..e78bc5dcc4b 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1654,8 +1654,8 @@ static void writeMDLexicalBlock(raw_ostream &Out, const MDLexicalBlock *N, const Module *Context) { Out << "!MDLexicalBlock("; MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); - Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); - Printer.printMetadata("file", N->getFile()); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); Printer.printInt("line", N->getLine()); Printer.printInt("column", N->getColumn()); Out << ")"; @@ -1668,8 +1668,8 @@ static void writeMDLexicalBlockFile(raw_ostream &Out, const Module *Context) { Out << "!MDLexicalBlockFile("; MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); - Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); - Printer.printMetadata("file", N->getFile()); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); Printer.printInt("discriminator", N->getDiscriminator(), /* ShouldSkipZero */ false); Out << ")"; diff --git a/lib/IR/DebugInfoMetadata.cpp b/lib/IR/DebugInfoMetadata.cpp index 63a0b59f7d5..754740a34ee 100644 --- a/lib/IR/DebugInfoMetadata.cpp +++ b/lib/IR/DebugInfoMetadata.cpp @@ -272,6 +272,7 @@ MDLexicalBlock *MDLexicalBlock::getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Line, unsigned Column, StorageType Storage, bool ShouldCreate) { + assert(Scope && "Expected scope"); DEFINE_GETIMPL_LOOKUP(MDLexicalBlock, (Scope, File, Line, Column)); Metadata *Ops[] = {File, Scope}; DEFINE_GETIMPL_STORE(MDLexicalBlock, (Line, Column), Ops); @@ -282,6 +283,7 @@ MDLexicalBlockFile *MDLexicalBlockFile::getImpl(LLVMContext &Context, unsigned Discriminator, StorageType Storage, bool ShouldCreate) { + assert(Scope && "Expected scope"); DEFINE_GETIMPL_LOOKUP(MDLexicalBlockFile, (Scope, File, Discriminator)); Metadata *Ops[] = {File, Scope}; DEFINE_GETIMPL_STORE(MDLexicalBlockFile, (Discriminator), Ops); diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index efb741f13fd..70291b5aeaa 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -594,11 +594,11 @@ template <> struct MDNodeKeyImpl { MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Line, unsigned Column) : Scope(Scope), File(File), Line(Line), Column(Column) {} MDNodeKeyImpl(const MDLexicalBlock *N) - : Scope(N->getScope()), File(N->getFile()), Line(N->getLine()), + : Scope(N->getRawScope()), File(N->getRawFile()), Line(N->getLine()), Column(N->getColumn()) {} bool isKeyOf(const MDLexicalBlock *RHS) const { - return Scope == RHS->getScope() && File == RHS->getFile() && + return Scope == RHS->getRawScope() && File == RHS->getRawFile() && Line == RHS->getLine() && Column == RHS->getColumn(); } unsigned getHashValue() const { @@ -614,11 +614,11 @@ template <> struct MDNodeKeyImpl { MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Discriminator) : Scope(Scope), File(File), Discriminator(Discriminator) {} MDNodeKeyImpl(const MDLexicalBlockFile *N) - : Scope(N->getScope()), File(N->getFile()), + : Scope(N->getRawScope()), File(N->getRawFile()), Discriminator(N->getDiscriminator()) {} bool isKeyOf(const MDLexicalBlockFile *RHS) const { - return Scope == RHS->getScope() && File == RHS->getFile() && + return Scope == RHS->getRawScope() && File == RHS->getRawFile() && Discriminator == RHS->getDiscriminator(); } unsigned getHashValue() const { diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index e4aea237bfc..8d7040bad4d 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -302,6 +302,7 @@ private: void visitMDScope(const MDScope &N); void visitMDDerivedTypeBase(const MDDerivedTypeBase &N); void visitMDVariable(const MDVariable &N); + void visitMDLexicalBlockBase(const MDLexicalBlockBase &N); // InstVisitor overrides... using InstVisitor::visit; @@ -871,12 +872,21 @@ void Verifier::visitMDSubprogram(const MDSubprogram &N) { } } -void Verifier::visitMDLexicalBlock(const MDLexicalBlock &N) { +void Verifier::visitMDLexicalBlockBase(const MDLexicalBlockBase &N) { Assert(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N); + Assert(N.getRawScope() && isa(N.getRawScope()), + "invalid local scope", &N, N.getRawScope()); +} + +void Verifier::visitMDLexicalBlock(const MDLexicalBlock &N) { + visitMDLexicalBlockBase(N); + + Assert(N.getLine() || !N.getColumn(), + "cannot have column info without line info", &N); } void Verifier::visitMDLexicalBlockFile(const MDLexicalBlockFile &N) { - Assert(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N); + visitMDLexicalBlockBase(N); } void Verifier::visitMDNamespace(const MDNamespace &N) { diff --git a/test/Assembler/invalid-mdlexicalblock-null-scope.ll b/test/Assembler/invalid-mdlexicalblock-null-scope.ll new file mode 100644 index 00000000000..59a99684797 --- /dev/null +++ b/test/Assembler/invalid-mdlexicalblock-null-scope.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: :[[@LINE+1]]:29: error: 'scope' cannot be null +!0 = !MDLexicalBlock(scope: null) diff --git a/test/Assembler/invalid-mdlexicalblockfile-null-scope.ll b/test/Assembler/invalid-mdlexicalblockfile-null-scope.ll new file mode 100644 index 00000000000..708136c6328 --- /dev/null +++ b/test/Assembler/invalid-mdlexicalblockfile-null-scope.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: :[[@LINE+1]]:33: error: 'scope' cannot be null +!0 = !MDLexicalBlockFile(scope: null) diff --git a/test/Assembler/mdlexicalblock.ll b/test/Assembler/mdlexicalblock.ll index 0a2c3397d35..d88eae747ac 100644 --- a/test/Assembler/mdlexicalblock.ll +++ b/test/Assembler/mdlexicalblock.ll @@ -5,15 +5,15 @@ !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9} !0 = distinct !{} -!1 = distinct !{} +!1 = !MDSubprogram(name: "foo", scope: !2) !2 = !MDFile(filename: "path/to/file", directory: "/path/to/dir") -; CHECK: !3 = !MDLexicalBlock(scope: !0, file: !2, line: 7, column: 35) -!3 = !MDLexicalBlock(scope: !0, file: !2, line: 7, column: 35) +; CHECK: !3 = !MDLexicalBlock(scope: !1, file: !2, line: 7, column: 35) +!3 = !MDLexicalBlock(scope: !1, file: !2, line: 7, column: 35) -; CHECK: !4 = !MDLexicalBlock(scope: !0) -!4 = !MDLexicalBlock(scope: !0) -!5 = !MDLexicalBlock(scope: !0, file: null, line: 0, column: 0) +; CHECK: !4 = !MDLexicalBlock(scope: !1) +!4 = !MDLexicalBlock(scope: !1) +!5 = !MDLexicalBlock(scope: !1, file: null, line: 0, column: 0) ; CHECK: !5 = !MDLexicalBlockFile(scope: !3, file: !2, discriminator: 0) ; CHECK: !6 = !MDLexicalBlockFile(scope: !3, file: !2, discriminator: 1) diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index ca378a37cd5..3901fb85434 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -299,7 +299,9 @@ TEST_F(IRBuilderTest, DIBuilder) { false, true, 1, 0, true, F); EXPECT_TRUE(SP.Verify()); AllocaInst *I = Builder.CreateAlloca(Builder.getInt8Ty()); - auto BadScope = DIB.createLexicalBlockFile(DIDescriptor(), File, 0); + auto BarSP = DIB.createFunction(CU, "bar", "", File, 1, Type, false, true, 1, + 0, true, nullptr); + auto BadScope = DIB.createLexicalBlockFile(BarSP, File, 0); I->setDebugLoc(DebugLoc::get(2, 0, BadScope)); EXPECT_FALSE(SP.Verify()); DIB.finalize(); diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index b722ceac6f9..e9e05fdb753 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -1555,8 +1555,8 @@ TEST_F(MDSubprogramTest, replaceFunction) { typedef MetadataTest MDLexicalBlockTest; TEST_F(MDLexicalBlockTest, get) { - Metadata *Scope = MDTuple::getDistinct(Context, None); - Metadata *File = MDTuple::getDistinct(Context, None); + MDLocalScope *Scope = getSubprogram(); + MDFile *File = getFile(); unsigned Line = 5; unsigned Column = 8; @@ -1569,8 +1569,9 @@ TEST_F(MDLexicalBlockTest, get) { EXPECT_EQ(Column, N->getColumn()); EXPECT_EQ(N, MDLexicalBlock::get(Context, Scope, File, Line, Column)); - EXPECT_NE(N, MDLexicalBlock::get(Context, File, File, Line, Column)); - EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, Scope, Line, Column)); + EXPECT_NE(N, + MDLexicalBlock::get(Context, getSubprogram(), File, Line, Column)); + EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, getFile(), Line, Column)); EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, File, Line + 1, Column)); EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, File, Line, Column + 1)); @@ -1581,8 +1582,8 @@ TEST_F(MDLexicalBlockTest, get) { typedef MetadataTest MDLexicalBlockFileTest; TEST_F(MDLexicalBlockFileTest, get) { - Metadata *Scope = MDTuple::getDistinct(Context, None); - Metadata *File = MDTuple::getDistinct(Context, None); + MDLocalScope *Scope = getSubprogram(); + MDFile *File = getFile(); unsigned Discriminator = 5; auto *N = MDLexicalBlockFile::get(Context, Scope, File, Discriminator); @@ -1593,8 +1594,10 @@ TEST_F(MDLexicalBlockFileTest, get) { EXPECT_EQ(Discriminator, N->getDiscriminator()); EXPECT_EQ(N, MDLexicalBlockFile::get(Context, Scope, File, Discriminator)); - EXPECT_NE(N, MDLexicalBlockFile::get(Context, File, File, Discriminator)); - EXPECT_NE(N, MDLexicalBlockFile::get(Context, Scope, Scope, Discriminator)); + EXPECT_NE(N, MDLexicalBlockFile::get(Context, getSubprogram(), File, + Discriminator)); + EXPECT_NE(N, + MDLexicalBlockFile::get(Context, Scope, getFile(), Discriminator)); EXPECT_NE(N, MDLexicalBlockFile::get(Context, Scope, File, Discriminator + 1)); -- 2.34.1