diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index d841e3ca9c6..a59a879b436 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -256,39 +256,7 @@ bool DIType::Verify() const { return isType(); } bool DIBasicType::Verify() const { return isBasicType(); } bool DIDerivedType::Verify() const { return isDerivedType(); } bool DICompositeType::Verify() const { return isCompositeType(); } - -bool DISubprogram::Verify() const { - auto *N = dyn_cast_or_null(DbgNode); - if (!N) - return false; - - // If a DISubprogram has an llvm::Function*, then scope chains from all - // instructions within the function should lead to this DISubprogram. - if (auto *F = getFunction()) { - for (auto &BB : *F) { - for (auto &I : BB) { - MDLocation *DL = I.getDebugLoc(); - if (!DL) - continue; - - // walk the inlined-at scopes - MDScope *Scope = DL->getInlinedAtScope(); - if (!Scope) - return false; - while (!isa(Scope)) { - Scope = cast(Scope)->getScope(); - if (!Scope) - return false; - } - if (!DISubprogram(Scope).describes(F)) - return false; - } - } - } - - return true; -} - +bool DISubprogram::Verify() const { return isSubprogram(); } bool DIGlobalVariable::Verify() const { return isGlobalVariable(); } bool DIVariable::Verify() const { return isVariable(); } diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 171c16bc76b..2bd3f52f5d1 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -921,6 +921,45 @@ void Verifier::visitMDSubprogram(const MDSubprogram &N) { } Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags", &N); + + if (!N.getFunction()) + return; + + // FIXME: Should this be looking through bitcasts? + auto *F = dyn_cast(N.getFunction()->getValue()); + if (!F) + return; + + // Check that all !dbg attachments lead to back to N (or, at least, another + // subprogram that describes the same function). + // + // FIXME: Check this incrementally while visiting !dbg attachments. + // FIXME: Only check when N is the canonical subprogram for F. + SmallPtrSet Seen; + for (auto &BB : *F) + for (auto &I : BB) { + // Be careful about using MDLocation here since we might be dealing with + // broken code (this is the Verifier after all). + MDLocation *DL = + dyn_cast_or_null(I.getDebugLoc().getAsMDNode()); + if (!DL) + continue; + if (!Seen.insert(DL).second) + continue; + + MDLocalScope *Scope = DL->getInlinedAtScope(); + if (Scope && !Seen.insert(Scope).second) + continue; + + MDSubprogram *SP = Scope ? Scope->getSubprogram() : nullptr; + if (SP && !Seen.insert(SP).second) + continue; + + // FIXME: Once N is canonical, check "SP == &N". + Assert(DISubprogram(SP).describes(F), + "!dbg attachment points at wrong subprogram for function", &N, F, + &I, DL, Scope, SP); + } } void Verifier::visitMDLexicalBlockBase(const MDLexicalBlockBase &N) { diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index 3901fb85434..c721ef508bf 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -17,6 +17,7 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" #include "llvm/IR/NoFolder.h" +#include "llvm/IR/Verifier.h" #include "gtest/gtest.h" using namespace llvm; @@ -303,8 +304,8 @@ TEST_F(IRBuilderTest, DIBuilder) { 0, true, nullptr); auto BadScope = DIB.createLexicalBlockFile(BarSP, File, 0); I->setDebugLoc(DebugLoc::get(2, 0, BadScope)); - EXPECT_FALSE(SP.Verify()); DIB.finalize(); + EXPECT_TRUE(verifyModule(*M)); }