llvm/unittests/IR/VerifierTest.cpp
Peter Collingbourne 5420de3f15 DebugInfo: New metadata representation for global variables.
This patch reverses the edge from DIGlobalVariable to GlobalVariable.
This will allow us to more easily preserve debug info metadata when
manipulating global variables.

Fixes PR30362. A program for upgrading test cases is attached to that
bug.

Differential Revision: http://reviews.llvm.org/D20147

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281284 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-13 01:12:59 +00:00

200 lines
6.6 KiB
C++

//===- llvm/unittest/IR/VerifierTest.cpp - Verifier unit tests --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "gtest/gtest.h"
namespace llvm {
namespace {
TEST(VerifierTest, Branch_i1) {
LLVMContext C;
Module M("M", C);
FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
Function *F = cast<Function>(M.getOrInsertFunction("foo", FTy));
BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
BasicBlock *Exit = BasicBlock::Create(C, "exit", F);
ReturnInst::Create(C, Exit);
// To avoid triggering an assertion in BranchInst::Create, we first create
// a branch with an 'i1' condition ...
Constant *False = ConstantInt::getFalse(C);
BranchInst *BI = BranchInst::Create(Exit, Exit, False, Entry);
// ... then use setOperand to redirect it to a value of different type.
Constant *Zero32 = ConstantInt::get(IntegerType::get(C, 32), 0);
BI->setOperand(0, Zero32);
EXPECT_TRUE(verifyFunction(*F));
}
TEST(VerifierTest, InvalidRetAttribute) {
LLVMContext C;
Module M("M", C);
FunctionType *FTy = FunctionType::get(Type::getInt32Ty(C), /*isVarArg=*/false);
Function *F = cast<Function>(M.getOrInsertFunction("foo", FTy));
AttributeSet AS = F->getAttributes();
F->setAttributes(AS.addAttribute(C, AttributeSet::ReturnIndex,
Attribute::UWTable));
std::string Error;
raw_string_ostream ErrorOS(Error);
EXPECT_TRUE(verifyModule(M, &ErrorOS));
EXPECT_TRUE(StringRef(ErrorOS.str()).startswith(
"Attribute 'uwtable' only applies to functions!"));
}
TEST(VerifierTest, CrossModuleRef) {
LLVMContext C;
Module M1("M1", C);
Module M2("M2", C);
Module M3("M3", C);
FunctionType *FTy = FunctionType::get(Type::getInt32Ty(C), /*isVarArg=*/false);
Function *F1 = cast<Function>(M1.getOrInsertFunction("foo1", FTy));
Function *F2 = cast<Function>(M2.getOrInsertFunction("foo2", FTy));
Function *F3 = cast<Function>(M3.getOrInsertFunction("foo3", FTy));
BasicBlock *Entry1 = BasicBlock::Create(C, "entry", F1);
BasicBlock *Entry3 = BasicBlock::Create(C, "entry", F3);
// BAD: Referencing function in another module
CallInst::Create(F2,"call",Entry1);
// BAD: Referencing personality routine in another module
F3->setPersonalityFn(F2);
// Fill in the body
Constant *ConstZero = ConstantInt::get(Type::getInt32Ty(C), 0);
ReturnInst::Create(C, ConstZero, Entry1);
ReturnInst::Create(C, ConstZero, Entry3);
std::string Error;
raw_string_ostream ErrorOS(Error);
EXPECT_TRUE(verifyModule(M2, &ErrorOS));
EXPECT_TRUE(StringRef(ErrorOS.str())
.equals("Global is used by function in a different module\n"
"i32 ()* @foo2\n"
"; ModuleID = 'M2'\n"
"i32 ()* @foo3\n"
"; ModuleID = 'M3'\n"
"Global is referenced in a different module!\n"
"i32 ()* @foo2\n"
"; ModuleID = 'M2'\n"
" %call = call i32 @foo2()\n"
"i32 ()* @foo1\n"
"; ModuleID = 'M1'\n"));
Error.clear();
EXPECT_TRUE(verifyModule(M1, &ErrorOS));
EXPECT_TRUE(StringRef(ErrorOS.str()).equals(
"Referencing function in another module!\n"
" %call = call i32 @foo2()\n"
"; ModuleID = 'M1'\n"
"i32 ()* @foo2\n"
"; ModuleID = 'M2'\n"));
Error.clear();
EXPECT_TRUE(verifyModule(M3, &ErrorOS));
EXPECT_TRUE(StringRef(ErrorOS.str()).startswith(
"Referencing personality function in another module!"));
// Erase bad methods to avoid triggering an assertion failure on destruction
F1->eraseFromParent();
F3->eraseFromParent();
}
TEST(VerifierTest, InvalidVariableLinkage) {
LLVMContext C;
Module M("M", C);
new GlobalVariable(M, Type::getInt8Ty(C), false,
GlobalValue::LinkOnceODRLinkage, nullptr, "Some Global");
std::string Error;
raw_string_ostream ErrorOS(Error);
EXPECT_TRUE(verifyModule(M, &ErrorOS));
EXPECT_TRUE(
StringRef(ErrorOS.str()).startswith("Global is external, but doesn't "
"have external or weak linkage!"));
}
TEST(VerifierTest, InvalidFunctionLinkage) {
LLVMContext C;
Module M("M", C);
FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
Function::Create(FTy, GlobalValue::LinkOnceODRLinkage, "foo", &M);
std::string Error;
raw_string_ostream ErrorOS(Error);
EXPECT_TRUE(verifyModule(M, &ErrorOS));
EXPECT_TRUE(
StringRef(ErrorOS.str()).startswith("Global is external, but doesn't "
"have external or weak linkage!"));
}
#ifndef _MSC_VER
// FIXME: This test causes an ICE in MSVC 2013.
TEST(VerifierTest, StripInvalidDebugInfo) {
LLVMContext C;
Module M("M", C);
DIBuilder DIB(M);
DIB.createCompileUnit(dwarf::DW_LANG_C89, "broken.c", "/",
"unittest", false, "", 0);
DIB.finalize();
EXPECT_FALSE(verifyModule(M));
// Now break it.
auto *File = DIB.createFile("not-a-CU.f", ".");
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu");
NMD->addOperand(File);
EXPECT_TRUE(verifyModule(M));
ModulePassManager MPM(true);
MPM.addPass(VerifierPass(false));
ModuleAnalysisManager MAM(true);
MAM.registerPass([&] { return VerifierAnalysis(); });
MPM.run(M, MAM);
EXPECT_FALSE(verifyModule(M));
}
#endif
TEST(VerifierTest, StripInvalidDebugInfoLegacy) {
LLVMContext C;
Module M("M", C);
DIBuilder DIB(M);
DIB.createCompileUnit(dwarf::DW_LANG_C89, "broken.c", "/",
"unittest", false, "", 0);
DIB.finalize();
EXPECT_FALSE(verifyModule(M));
// Now break it.
auto *File = DIB.createFile("not-a-CU.f", ".");
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu");
NMD->addOperand(File);
EXPECT_TRUE(verifyModule(M));
legacy::PassManager Passes;
Passes.add(createVerifierPass(false));
Passes.run(M);
EXPECT_FALSE(verifyModule(M));
}
} // end anonymous namespace
} // end namespace llvm