diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 9f6cb42e11f..f5d8945ea06 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -28,44 +28,31 @@ namespace llvm { class FunctionPass; class Module; class Function; - -/// \brief An enumeration to specify the action to be taken if errors found. -/// -/// This enumeration is used in the functions below to indicate what should -/// happen if the verifier finds errors. Each of the functions that uses -/// this enumeration as an argument provides a default value for it. The -/// actions are listed below. -enum VerifierFailureAction { - AbortProcessAction, ///< verifyModule will print to stderr and abort() - PrintMessageAction, ///< verifyModule will print to stderr and return true - ReturnStatusAction ///< verifyModule will just return true -}; - -/// \brief Create a verifier pass. -/// -/// Check a module or function for validity. When the pass is used, the -/// action indicated by the \p action argument will be used if errors are -/// found. -FunctionPass * -createVerifierPass(VerifierFailureAction action = AbortProcessAction); +class raw_ostream; /// \brief Check a function for errors, useful for use when debugging a /// pass. /// /// If there are no errors, the function returns false. If an error is found, -/// the action taken depends on the \p action parameter. -bool verifyFunction(const Function &F, - VerifierFailureAction action = AbortProcessAction); +/// a message describing the error is written to OS (if non-null) and false is +/// returned. +bool verifyFunction(const Function &F, raw_ostream *OS = 0); /// \brief Check a module for errors. /// /// If there are no errors, the function returns false. If an error is found, -/// the action taken depends on the \p action parameter. -/// This should only be used for debugging, because it plays games with -/// PassManagers and stuff. -bool verifyModule(const Module &M, - VerifierFailureAction action = AbortProcessAction, - std::string *ErrorInfo = 0); +/// a message describing the error is written to OS (if non-null) and false is +/// returned. +bool verifyModule(const Module &M, raw_ostream *OS = 0); + +/// \brief Create a verifier pass. +/// +/// Check a module or function for validity. This is essentially a pass wrapped +/// around the above verifyFunction and verifyModule routines and +/// functionality. When the pass detects a verification error it is always +/// printed to stderr, and by default they are fatal. You can override that by +/// passing \c false to \p FatalErrors. +FunctionPass *createVerifierPass(bool FatalErrors = true); } // End llvm namespace diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index a88d94945a8..e08e0c4baf2 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -256,7 +256,7 @@ void initializeTypeBasedAliasAnalysisPass(PassRegistry&); void initializeUnifyFunctionExitNodesPass(PassRegistry&); void initializeUnreachableBlockElimPass(PassRegistry&); void initializeUnreachableMachineBlockElimPass(PassRegistry&); -void initializeVerifierPass(PassRegistry&); +void initializeVerifierPassPass(PassRegistry&); void initializeVirtRegMapPass(PassRegistry&); void initializeVirtRegRewriterPass(PassRegistry&); void initializeInstSimplifierPass(PassRegistry&); diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp index ef99e35ffda..c9ce1643c3d 100644 --- a/lib/Analysis/Analysis.cpp +++ b/lib/Analysis/Analysis.cpp @@ -11,6 +11,7 @@ #include "llvm-c/Initialization.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/InitializePasses.h" #include "llvm/PassRegistry.h" #include @@ -72,21 +73,33 @@ void LLVMInitializeAnalysis(LLVMPassRegistryRef R) { LLVMBool LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action, char **OutMessages) { + raw_ostream *DebugOS = Action != LLVMReturnStatusAction ? &errs() : 0; std::string Messages; + raw_string_ostream MsgsOS(Messages); - LLVMBool Result = verifyModule(*unwrap(M), - static_cast(Action), - OutMessages? &Messages : 0); + LLVMBool Result = verifyModule(*unwrap(M), OutMessages ? &MsgsOS : DebugOS); + + // Duplicate the output to stderr. + if (DebugOS && OutMessages) + *DebugOS << MsgsOS.str(); + + if (Action == LLVMAbortProcessAction && Result) + report_fatal_error("Broken module found, compilation aborted!"); if (OutMessages) - *OutMessages = strdup(Messages.c_str()); + *OutMessages = strdup(MsgsOS.str().c_str()); return Result; } LLVMBool LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action) { - return verifyFunction(*unwrap(Fn), - static_cast(Action)); + LLVMBool Result = verifyFunction( + *unwrap(Fn), Action != LLVMReturnStatusAction ? &errs() : 0); + + if (Action == LLVMAbortProcessAction && Result) + report_fatal_error("Broken function found, compilation aborted!"); + + return Result; } void LLVMViewFunctionCFG(LLVMValueRef Fn) { diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 1417e5dc4fd..cd7cb9ed147 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -44,7 +44,7 @@ void llvm::initializeCore(PassRegistry &Registry) { initializePrintModulePassWrapperPass(Registry); initializePrintFunctionPassWrapperPass(Registry); initializePrintBasicBlockPassPass(Registry); - initializeVerifierPass(Registry); + initializeVerifierPassPass(Registry); } void LLVMInitializeCore(LLVMPassRegistryRef R) { diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index a004955e807..feea4850195 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -80,21 +80,15 @@ static cl::opt DisableDebugInfoVerifier("disable-debug-info-verifier", cl::init(true)); namespace { -struct Verifier : public FunctionPass, public InstVisitor { - static char ID; +class Verifier : public InstVisitor { + friend class InstVisitor; - // What to do if verification fails. - VerifierFailureAction Action; - - Module *M; + raw_ostream &OS; + const Module *M; LLVMContext *Context; const DataLayout *DL; DominatorTree DT; - bool Broken; - std::string Messages; - raw_string_ostream MessagesStr; - /// \brief When verifying a basic block, keep track of all of the /// instructions we have seen so far. /// @@ -113,57 +107,45 @@ struct Verifier : public FunctionPass, public InstVisitor { /// \brief Finder keeps track of all debug info MDNodes in a Module. DebugInfoFinder Finder; - Verifier() - : FunctionPass(ID), Action(AbortProcessAction), M(0), Context(0), DL(0), - Broken(false), MessagesStr(Messages), PersonalityFn(0) { - initializeVerifierPass(*PassRegistry::getPassRegistry()); - } - explicit Verifier(VerifierFailureAction Action) - : FunctionPass(ID), Action(Action), M(0), Context(0), DL(0), - Broken(false), MessagesStr(Messages), PersonalityFn(0) { - initializeVerifierPass(*PassRegistry::getPassRegistry()); - } + /// \brief Track the brokenness of the module while recursively visiting. + bool Broken; - bool doInitialization(Module &M) { - this->M = &M; - Context = &M.getContext(); +public: + explicit Verifier(raw_ostream &OS = dbgs()) + : OS(OS), M(0), Context(0), DL(0), PersonalityFn(0), Broken(false) {} - DL = getAnalysisIfAvailable(); - - // We must abort before returning back to the pass manager, or else the - // pass manager may try to run other passes on the broken module. - return abortIfBroken(); - } - - bool runOnFunction(Function &F) { - Broken = false; + bool verify(const Function &F) { + M = F.getParent(); + Context = &M->getContext(); // First ensure the function is well-enough formed to compute dominance // information. - for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { + if (F.empty()) { + OS << "Function '" << F.getName() + << "' does not contain an entry block!\n"; + return false; + } + for (Function::const_iterator I = F.begin(), E = F.end(); I != E; ++I) { if (I->empty() || !I->back().isTerminator()) { - dbgs() << "Basic Block in function '" << F.getName() - << "' does not have terminator!\n"; - I->printAsOperand(dbgs(), true); - dbgs() << "\n"; - Broken = true; + OS << "Basic Block in function '" << F.getName() + << "' does not have terminator!\n"; + I->printAsOperand(OS, true); + OS << "\n"; + return false; } } - if (Broken) - return abortIfBroken(); // Now directly compute a dominance tree. We don't rely on the pass // manager to provide this as it isolates us from a potentially // out-of-date dominator tree and makes it significantly more complex to // run this code outside of a pass manager. - DT.recalculate(F); - - M = F.getParent(); - if (!Context) - Context = &F.getContext(); + // FIXME: It's really gross that we have to cast away constness here. + DT.recalculate(const_cast(F)); Finder.reset(); - visit(F); + Broken = false; + // FIXME: We strip const here because the inst visitor strips const. + visit(const_cast(F)); InstsInThisBlock.clear(); PersonalityFn = 0; @@ -171,14 +153,17 @@ struct Verifier : public FunctionPass, public InstVisitor { // Verify Debug Info. verifyDebugInfo(); - // We must abort before returning back to the pass manager, or else the - // pass manager may try to run other passes on the broken module. - return abortIfBroken(); + return !Broken; } - bool doFinalization(Module &M) { + bool verify(const Module &M) { + this->M = &M; + Context = &M.getContext(); + Finder.reset(); + Broken = false; + // Scan through, checking all of the external function's linkage now... - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { visitGlobalValue(*I); // Check to make sure function prototypes are okay. @@ -186,16 +171,16 @@ struct Verifier : public FunctionPass, public InstVisitor { visitFunction(*I); } - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) visitGlobalVariable(*I); - for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; - ++I) + for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) visitGlobalAlias(*I); - for (Module::named_metadata_iterator I = M.named_metadata_begin(), - E = M.named_metadata_end(); + for (Module::const_named_metadata_iterator I = M.named_metadata_begin(), + E = M.named_metadata_end(); I != E; ++I) visitNamedMDNode(*I); @@ -209,52 +194,26 @@ struct Verifier : public FunctionPass, public InstVisitor { verifyDebugInfo(); } - // If the module is broken, abort at this time. - return abortIfBroken(); - } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - } - - /// abortIfBroken - If the module is broken and we are supposed to abort on - /// this condition, do so. - /// - bool abortIfBroken() { - if (!Broken) - return false; - MessagesStr << "Broken module found, "; - switch (Action) { - case AbortProcessAction: - MessagesStr << "compilation aborted!\n"; - dbgs() << MessagesStr.str(); - // Client should choose different reaction if abort is not desired - abort(); - case PrintMessageAction: - MessagesStr << "verification continues.\n"; - dbgs() << MessagesStr.str(); - return false; - case ReturnStatusAction: - MessagesStr << "compilation terminated.\n"; - return true; - } - llvm_unreachable("Invalid action"); + return !Broken; } +private: // Verification methods... - void visitGlobalValue(GlobalValue &GV); - void visitGlobalVariable(GlobalVariable &GV); - void visitGlobalAlias(GlobalAlias &GA); - void visitNamedMDNode(NamedMDNode &NMD); + void visitGlobalValue(const GlobalValue &GV); + void visitGlobalVariable(const GlobalVariable &GV); + void visitGlobalAlias(const GlobalAlias &GA); + void visitNamedMDNode(const NamedMDNode &NMD); void visitMDNode(MDNode &MD, Function *F); - void visitModuleIdents(Module &M); - void visitModuleFlags(Module &M); - void visitModuleFlag(MDNode *Op, DenseMap &SeenIDs, - SmallVectorImpl &Requirements); - void visitFunction(Function &F); + void visitModuleIdents(const Module &M); + void visitModuleFlags(const Module &M); + void visitModuleFlag(const MDNode *Op, + DenseMap &SeenIDs, + SmallVectorImpl &Requirements); + void visitFunction(const Function &F); void visitBasicBlock(BasicBlock &BB); - using InstVisitor::visit; + // InstVisitor overrides... + using InstVisitor::visit; void visit(Instruction &I); void visitTruncInst(TruncInst &I); @@ -326,17 +285,17 @@ struct Verifier : public FunctionPass, public InstVisitor { if (!V) return; if (isa(V)) { - MessagesStr << *V << '\n'; + OS << *V << '\n'; } else { - V->printAsOperand(MessagesStr, true, M); - MessagesStr << '\n'; + V->printAsOperand(OS, true, M); + OS << '\n'; } } void WriteType(Type *T) { if (!T) return; - MessagesStr << ' ' << *T; + OS << ' ' << *T; } // CheckFailed - A check failed, so print out the condition and the message @@ -345,7 +304,7 @@ struct Verifier : public FunctionPass, public InstVisitor { void CheckFailed(const Twine &Message, const Value *V1 = 0, const Value *V2 = 0, const Value *V3 = 0, const Value *V4 = 0) { - MessagesStr << Message.str() << "\n"; + OS << Message.str() << "\n"; WriteValue(V1); WriteValue(V2); WriteValue(V3); @@ -355,7 +314,7 @@ struct Verifier : public FunctionPass, public InstVisitor { void CheckFailed(const Twine &Message, const Value *V1, Type *T2, const Value *V3 = 0) { - MessagesStr << Message.str() << "\n"; + OS << Message.str() << "\n"; WriteValue(V1); WriteType(T2); WriteValue(V3); @@ -363,7 +322,7 @@ struct Verifier : public FunctionPass, public InstVisitor { } void CheckFailed(const Twine &Message, Type *T1, Type *T2 = 0, Type *T3 = 0) { - MessagesStr << Message.str() << "\n"; + OS << Message.str() << "\n"; WriteType(T1); WriteType(T2); WriteType(T3); @@ -372,9 +331,6 @@ struct Verifier : public FunctionPass, public InstVisitor { }; } // End anonymous namespace -char Verifier::ID = 0; -INITIALIZE_PASS(Verifier, "verify", "Module Verifier", false, false) - // Assert - We know that cond should be true, if not print an error message. #define Assert(C, M) \ do { if (!(C)) { CheckFailed(M); return; } } while (0) @@ -394,7 +350,7 @@ void Verifier::visit(Instruction &I) { } -void Verifier::visitGlobalValue(GlobalValue &GV) { +void Verifier::visitGlobalValue(const GlobalValue &GV) { Assert1(!GV.isDeclaration() || GV.isMaterializable() || GV.hasExternalLinkage() || @@ -408,13 +364,13 @@ void Verifier::visitGlobalValue(GlobalValue &GV) { "Only global variables can have appending linkage!", &GV); if (GV.hasAppendingLinkage()) { - GlobalVariable *GVar = dyn_cast(&GV); + const GlobalVariable *GVar = dyn_cast(&GV); Assert1(GVar && GVar->getType()->getElementType()->isArrayTy(), "Only global arrays can have appending linkage!", GVar); } } -void Verifier::visitGlobalVariable(GlobalVariable &GV) { +void Verifier::visitGlobalVariable(const GlobalVariable &GV) { if (GV.hasInitializer()) { Assert1(GV.getInitializer()->getType() == GV.getType()->getElementType(), "Global variable initializer type does not match global " @@ -459,8 +415,8 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { PointerType *PTy = dyn_cast(ATy->getElementType()); Assert1(PTy, "wrong type for intrinsic global variable", &GV); if (GV.hasInitializer()) { - Constant *Init = GV.getInitializer(); - ConstantArray *InitArray = dyn_cast(Init); + const Constant *Init = GV.getInitializer(); + const ConstantArray *InitArray = dyn_cast(Init); Assert1(InitArray, "wrong initalizer for intrinsic global variable", Init); for (unsigned i = 0, e = InitArray->getNumOperands(); i != e; ++i) { @@ -509,7 +465,7 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { visitGlobalValue(GV); } -void Verifier::visitGlobalAlias(GlobalAlias &GA) { +void Verifier::visitGlobalAlias(const GlobalAlias &GA) { Assert1(!GA.getName().empty(), "Alias name cannot be empty!", &GA); Assert1(GlobalAlias::isValidLinkage(GA.getLinkage()), @@ -520,10 +476,10 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) { "Alias and aliasee types should match!", &GA); Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA); - Constant *Aliasee = GA.getAliasee(); + const Constant *Aliasee = GA.getAliasee(); if (!isa(Aliasee)) { - ConstantExpr *CE = dyn_cast(Aliasee); + const ConstantExpr *CE = dyn_cast(Aliasee); Assert1(CE && (CE->getOpcode() == Instruction::BitCast || CE->getOpcode() == Instruction::AddrSpaceCast || @@ -550,7 +506,7 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) { visitGlobalValue(GA); } -void Verifier::visitNamedMDNode(NamedMDNode &NMD) { +void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) { MDNode *MD = NMD.getOperand(i); if (!MD) @@ -598,7 +554,7 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) { } } -void Verifier::visitModuleIdents(Module &M) { +void Verifier::visitModuleIdents(const Module &M) { const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident"); if (!Idents) return; @@ -616,24 +572,24 @@ void Verifier::visitModuleIdents(Module &M) { } } -void Verifier::visitModuleFlags(Module &M) { +void Verifier::visitModuleFlags(const Module &M) { const NamedMDNode *Flags = M.getModuleFlagsMetadata(); if (!Flags) return; // Scan each flag, and track the flags and requirements. - DenseMap SeenIDs; - SmallVector Requirements; + DenseMap SeenIDs; + SmallVector Requirements; for (unsigned I = 0, E = Flags->getNumOperands(); I != E; ++I) { visitModuleFlag(Flags->getOperand(I), SeenIDs, Requirements); } // Validate that the requirements in the module are valid. for (unsigned I = 0, E = Requirements.size(); I != E; ++I) { - MDNode *Requirement = Requirements[I]; - MDString *Flag = cast(Requirement->getOperand(0)); - Value *ReqValue = Requirement->getOperand(1); + const MDNode *Requirement = Requirements[I]; + const MDString *Flag = cast(Requirement->getOperand(0)); + const Value *ReqValue = Requirement->getOperand(1); - MDNode *Op = SeenIDs.lookup(Flag); + const MDNode *Op = SeenIDs.lookup(Flag); if (!Op) { CheckFailed("invalid requirement on flag, flag is not present in module", Flag); @@ -649,8 +605,10 @@ void Verifier::visitModuleFlags(Module &M) { } } -void Verifier::visitModuleFlag(MDNode *Op, DenseMap&SeenIDs, - SmallVectorImpl &Requirements) { +void +Verifier::visitModuleFlag(const MDNode *Op, + DenseMap &SeenIDs, + SmallVectorImpl &Requirements) { // Each module flag should have three arguments, the merge behavior (a // constant int), the flag ID (an MDString), and the value. Assert1(Op->getNumOperands() == 3, @@ -987,7 +945,7 @@ bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) { // visitFunction - Verify that a function is ok. // -void Verifier::visitFunction(Function &F) { +void Verifier::visitFunction(const Function &F) { // Check function arguments. FunctionType *FT = F.getFunctionType(); unsigned NumArgs = F.arg_size(); @@ -1045,8 +1003,8 @@ void Verifier::visitFunction(Function &F) { // Check that the argument values match the function type for this function... unsigned i = 0; - for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); - I != E; ++I, ++i) { + for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; + ++I, ++i) { Assert2(I->getType() == FT->getParamType(i), "Argument value does not match function argument type!", I, FT->getParamType(i)); @@ -1068,13 +1026,13 @@ void Verifier::visitFunction(Function &F) { Assert1(!isLLVMdotName, "llvm intrinsics cannot be defined!", &F); // Check the entry node - BasicBlock *Entry = &F.getEntryBlock(); + const BasicBlock *Entry = &F.getEntryBlock(); Assert1(pred_begin(Entry) == pred_end(Entry), "Entry block to function must not have predecessors!", Entry); // The address of the entry block cannot be taken, unless it is dead. if (Entry->hasAddressTaken()) { - Assert1(!BlockAddress::get(Entry)->isConstantUsed(), + Assert1(!BlockAddress::lookup(Entry)->isConstantUsed(), "blockaddress may not be used with the entry block!", Entry); } } @@ -2402,30 +2360,71 @@ void Verifier::verifyDebugInfo() { // Implement the public interfaces to this file... //===----------------------------------------------------------------------===// -FunctionPass *llvm::createVerifierPass(VerifierFailureAction action) { - return new Verifier(action); -} - -bool llvm::verifyFunction(const Function &f, VerifierFailureAction action) { +bool llvm::verifyFunction(const Function &f, raw_ostream *OS) { Function &F = const_cast(f); assert(!F.isDeclaration() && "Cannot verify external functions"); - FunctionPassManager FPM(F.getParent()); - Verifier *V = new Verifier(action); - FPM.add(V); - FPM.doInitialization(); - FPM.run(F); - return V->Broken; + raw_null_ostream NullStr; + Verifier V(OS ? *OS : NullStr); + + // Note that this function's return value is inverted from what you would + // expect of a function called "verify". + return !V.verify(F); } -bool llvm::verifyModule(const Module &M, VerifierFailureAction action, - std::string *ErrorInfo) { - PassManager PM; - Verifier *V = new Verifier(action); - PM.add(V); - PM.run(const_cast(M)); +bool llvm::verifyModule(const Module &M, raw_ostream *OS) { + raw_null_ostream NullStr; + Verifier V(OS ? *OS : NullStr); - if (ErrorInfo && V->Broken) - *ErrorInfo = V->MessagesStr.str(); - return V->Broken; + bool Broken = false; + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isDeclaration()) + Broken |= !V.verify(*I); + + // Note that this function's return value is inverted from what you would + // expect of a function called "verify". + return !V.verify(M) || Broken; } + +namespace { +struct VerifierPass : public FunctionPass { + static char ID; + + Verifier V; + bool FatalErrors; + + VerifierPass() : FunctionPass(ID), FatalErrors(true) { + initializeVerifierPassPass(*PassRegistry::getPassRegistry()); + } + explicit VerifierPass(bool FatalErrors) + : FunctionPass(ID), V(dbgs()), FatalErrors(FatalErrors) { + initializeVerifierPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) { + if (!V.verify(F) && FatalErrors) + report_fatal_error("Broken function found, compilation aborted!"); + + return false; + } + + bool doFinalization(Module &M) { + if (!V.verify(M) && FatalErrors) + report_fatal_error("Broken module found, compilation aborted!"); + + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } +}; +} + +char VerifierPass::ID = 0; +INITIALIZE_PASS(VerifierPass, "verify", "Module Verifier", false, false) + +FunctionPass *llvm::createVerifierPass(bool FatalErrors) { + return new VerifierPass(FatalErrors); +} + diff --git a/test/Verifier/2010-08-07-PointerIntrinsic.ll b/test/Verifier/2010-08-07-PointerIntrinsic.ll index a668d04213f..427eb66aa7b 100644 --- a/test/Verifier/2010-08-07-PointerIntrinsic.ll +++ b/test/Verifier/2010-08-07-PointerIntrinsic.ll @@ -1,6 +1,5 @@ -; RUN: not llvm-as < %s 2> %t -; RUN: FileCheck %s --input-file=%t -; CHECK: Broken module +; RUN: not llvm-as < %s 2>&1 | FileCheck %s +; CHECK: assembly parsed, but does not verify as correct ; PR7316 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32" diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp index 97e7d160983..d13caf1955e 100644 --- a/tools/llvm-as/llvm-as.cpp +++ b/tools/llvm-as/llvm-as.cpp @@ -100,11 +100,12 @@ int main(int argc, char **argv) { } if (!DisableVerify) { - std::string Err; - if (verifyModule(*M.get(), ReturnStatusAction, &Err)) { + std::string ErrorStr; + raw_string_ostream OS(ErrorStr); + if (verifyModule(*M.get(), &OS)) { errs() << argv[0] << ": assembly parsed, but does not verify as correct!\n"; - errs() << Err; + errs() << OS.str(); return 1; } } diff --git a/unittests/IR/VerifierTest.cpp b/unittests/IR/VerifierTest.cpp index 8e21fb80fe9..a5ce5fc9d30 100644 --- a/unittests/IR/VerifierTest.cpp +++ b/unittests/IR/VerifierTest.cpp @@ -42,7 +42,7 @@ TEST(VerifierTest, Branch_i1) { Constant *Zero32 = ConstantInt::get(IntegerType::get(C, 32), 0); BI->setOperand(0, Zero32); - EXPECT_TRUE(verifyFunction(*F, ReturnStatusAction)); + EXPECT_TRUE(verifyFunction(*F)); } TEST(VerifierTest, AliasUnnamedAddr) { @@ -58,8 +58,10 @@ TEST(VerifierTest, AliasUnnamedAddr) { "bar", Aliasee, &M); GA->setUnnamedAddr(true); std::string Error; - EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); - EXPECT_TRUE(StringRef(Error).startswith("Alias cannot have unnamed_addr")); + raw_string_ostream ErrorOS(Error); + EXPECT_TRUE(verifyModule(M, &ErrorOS)); + EXPECT_TRUE( + StringRef(ErrorOS.str()).startswith("Alias cannot have unnamed_addr")); } TEST(VerifierTest, InvalidRetAttribute) { @@ -72,9 +74,10 @@ TEST(VerifierTest, InvalidRetAttribute) { Attribute::UWTable)); std::string Error; - EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); - EXPECT_TRUE(StringRef(Error). - startswith("Attribute 'uwtable' only applies to functions!")); + raw_string_ostream ErrorOS(Error); + EXPECT_TRUE(verifyModule(M, &ErrorOS)); + EXPECT_TRUE(StringRef(ErrorOS.str()).startswith( + "Attribute 'uwtable' only applies to functions!")); } }