1 //===- llvm/unittest/IR/VerifierTest.cpp - Verifier unit tests --*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/Verifier.h"
10 #include "llvm/IR/Constants.h"
11 #include "llvm/IR/DIBuilder.h"
12 #include "llvm/IR/DerivedTypes.h"
13 #include "llvm/IR/Function.h"
14 #include "llvm/IR/GlobalAlias.h"
15 #include "llvm/IR/GlobalVariable.h"
16 #include "llvm/IR/IRBuilder.h"
17 #include "llvm/IR/Instructions.h"
18 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/IR/Module.h"
20 #include "gtest/gtest.h"
25 TEST(VerifierTest
, Branch_i1
) {
28 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(C
), /*isVarArg=*/false);
29 Function
*F
= Function::Create(FTy
, Function::ExternalLinkage
, "foo", M
);
30 BasicBlock
*Entry
= BasicBlock::Create(C
, "entry", F
);
31 BasicBlock
*Exit
= BasicBlock::Create(C
, "exit", F
);
32 ReturnInst::Create(C
, Exit
);
34 // To avoid triggering an assertion in BranchInst::Create, we first create
35 // a branch with an 'i1' condition ...
37 Constant
*False
= ConstantInt::getFalse(C
);
38 BranchInst
*BI
= BranchInst::Create(Exit
, Exit
, False
, Entry
);
40 // ... then use setOperand to redirect it to a value of different type.
42 Constant
*Zero32
= ConstantInt::get(IntegerType::get(C
, 32), 0);
43 BI
->setOperand(0, Zero32
);
45 EXPECT_TRUE(verifyFunction(*F
));
48 TEST(VerifierTest
, Freeze
) {
51 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(C
), /*isVarArg=*/false);
52 Function
*F
= Function::Create(FTy
, Function::ExternalLinkage
, "foo", M
);
53 BasicBlock
*Entry
= BasicBlock::Create(C
, "entry", F
);
54 ReturnInst
*RI
= ReturnInst::Create(C
, Entry
);
56 IntegerType
*ITy
= IntegerType::get(C
, 32);
57 ConstantInt
*CI
= ConstantInt::get(ITy
, 0);
59 // Valid type : freeze(<2 x i32>)
60 Constant
*CV
= ConstantVector::getSplat(ElementCount::getFixed(2), CI
);
61 FreezeInst
*FI_vec
= new FreezeInst(CV
);
62 FI_vec
->insertBefore(RI
);
64 EXPECT_FALSE(verifyFunction(*F
));
66 FI_vec
->eraseFromParent();
68 // Valid type : freeze(float)
69 Constant
*CFP
= ConstantFP::get(Type::getDoubleTy(C
), 0.0);
70 FreezeInst
*FI_dbl
= new FreezeInst(CFP
);
71 FI_dbl
->insertBefore(RI
);
73 EXPECT_FALSE(verifyFunction(*F
));
75 FI_dbl
->eraseFromParent();
77 // Valid type : freeze(i32*)
78 PointerType
*PT
= PointerType::get(ITy
, 0);
79 ConstantPointerNull
*CPN
= ConstantPointerNull::get(PT
);
80 FreezeInst
*FI_ptr
= new FreezeInst(CPN
);
81 FI_ptr
->insertBefore(RI
);
83 EXPECT_FALSE(verifyFunction(*F
));
85 FI_ptr
->eraseFromParent();
87 // Valid type : freeze(int)
88 FreezeInst
*FI
= new FreezeInst(CI
);
91 EXPECT_FALSE(verifyFunction(*F
));
93 FI
->eraseFromParent();
96 TEST(VerifierTest
, InvalidRetAttribute
) {
99 FunctionType
*FTy
= FunctionType::get(Type::getInt32Ty(C
), /*isVarArg=*/false);
100 Function
*F
= Function::Create(FTy
, Function::ExternalLinkage
, "foo", M
);
101 AttributeList AS
= F
->getAttributes();
102 F
->setAttributes(AS
.addRetAttribute(
103 C
, Attribute::getWithUWTableKind(C
, UWTableKind::Default
)));
106 raw_string_ostream
ErrorOS(Error
);
107 EXPECT_TRUE(verifyModule(M
, &ErrorOS
));
108 EXPECT_TRUE(StringRef(ErrorOS
.str()).startswith(
109 "Attribute 'uwtable' does not apply to function return values"));
112 /// Test the verifier rejects invalid nofpclass values that the assembler may
113 /// also choose to reject.
114 TEST(VerifierTest
, InvalidNoFPClassAttribute
) {
117 const unsigned InvalidMasks
[] = {0, fcAllFlags
+ 1};
119 for (unsigned InvalidMask
: InvalidMasks
) {
122 FunctionType::get(Type::getFloatTy(C
), /*isVarArg=*/false);
123 Function
*F
= Function::Create(FTy
, Function::ExternalLinkage
, "foo", M
);
124 AttributeList AS
= F
->getAttributes();
126 // Don't use getWithNoFPClass to avoid using out of bounds enum values here.
127 F
->setAttributes(AS
.addRetAttribute(
128 C
, Attribute::get(C
, Attribute::NoFPClass
, InvalidMask
)));
131 raw_string_ostream
ErrorOS(Error
);
132 EXPECT_TRUE(verifyModule(M
, &ErrorOS
));
134 StringRef
ErrMsg(ErrorOS
.str());
136 if (InvalidMask
== 0) {
137 EXPECT_TRUE(ErrMsg
.startswith(
138 "Attribute 'nofpclass' must have at least one test bit set"))
141 EXPECT_TRUE(ErrMsg
.startswith("Invalid value for 'nofpclass' test mask"))
147 TEST(VerifierTest
, CrossModuleRef
) {
152 FunctionType
*FTy
= FunctionType::get(Type::getInt32Ty(C
), /*isVarArg=*/false);
153 Function
*F1
= Function::Create(FTy
, Function::ExternalLinkage
, "foo1", M1
);
154 Function
*F2
= Function::Create(FTy
, Function::ExternalLinkage
, "foo2", M2
);
155 Function
*F3
= Function::Create(FTy
, Function::ExternalLinkage
, "foo3", M3
);
157 BasicBlock
*Entry1
= BasicBlock::Create(C
, "entry", F1
);
158 BasicBlock
*Entry3
= BasicBlock::Create(C
, "entry", F3
);
160 // BAD: Referencing function in another module
161 CallInst::Create(F2
,"call",Entry1
);
163 // BAD: Referencing personality routine in another module
164 F3
->setPersonalityFn(F2
);
167 Constant
*ConstZero
= ConstantInt::get(Type::getInt32Ty(C
), 0);
168 ReturnInst::Create(C
, ConstZero
, Entry1
);
169 ReturnInst::Create(C
, ConstZero
, Entry3
);
172 raw_string_ostream
ErrorOS(Error
);
173 EXPECT_TRUE(verifyModule(M2
, &ErrorOS
));
174 EXPECT_TRUE(StringRef(ErrorOS
.str())
175 .equals("Global is referenced in a different module!\n"
177 "; ModuleID = 'M2'\n"
178 " %call = call i32 @foo2()\n"
180 "; ModuleID = 'M1'\n"
181 "Global is used by function in a different module\n"
183 "; ModuleID = 'M2'\n"
185 "; ModuleID = 'M3'\n"));
188 EXPECT_TRUE(verifyModule(M1
, &ErrorOS
));
189 EXPECT_TRUE(StringRef(ErrorOS
.str()).equals(
190 "Referencing function in another module!\n"
191 " %call = call i32 @foo2()\n"
192 "; ModuleID = 'M1'\n"
194 "; ModuleID = 'M2'\n"));
197 EXPECT_TRUE(verifyModule(M3
, &ErrorOS
));
198 EXPECT_TRUE(StringRef(ErrorOS
.str()).startswith(
199 "Referencing personality function in another module!"));
201 // Erase bad methods to avoid triggering an assertion failure on destruction
202 F1
->eraseFromParent();
203 F3
->eraseFromParent();
206 TEST(VerifierTest
, InvalidVariableLinkage
) {
209 new GlobalVariable(M
, Type::getInt8Ty(C
), false,
210 GlobalValue::LinkOnceODRLinkage
, nullptr, "Some Global");
212 raw_string_ostream
ErrorOS(Error
);
213 EXPECT_TRUE(verifyModule(M
, &ErrorOS
));
215 StringRef(ErrorOS
.str()).startswith("Global is external, but doesn't "
216 "have external or weak linkage!"));
219 TEST(VerifierTest
, InvalidFunctionLinkage
) {
223 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(C
), /*isVarArg=*/false);
224 Function::Create(FTy
, GlobalValue::LinkOnceODRLinkage
, "foo", &M
);
226 raw_string_ostream
ErrorOS(Error
);
227 EXPECT_TRUE(verifyModule(M
, &ErrorOS
));
229 StringRef(ErrorOS
.str()).startswith("Global is external, but doesn't "
230 "have external or weak linkage!"));
233 TEST(VerifierTest
, DetectInvalidDebugInfo
) {
238 DIB
.createCompileUnit(dwarf::DW_LANG_C89
, DIB
.createFile("broken.c", "/"),
239 "unittest", false, "", 0);
241 EXPECT_FALSE(verifyModule(M
));
243 // Now break it by inserting non-CU node to the list of CUs.
244 auto *File
= DIB
.createFile("not-a-CU.f", ".");
245 NamedMDNode
*NMD
= M
.getOrInsertNamedMetadata("llvm.dbg.cu");
246 NMD
->addOperand(File
);
247 EXPECT_TRUE(verifyModule(M
));
253 auto *CU
= DIB
.createCompileUnit(dwarf::DW_LANG_C89
,
254 DIB
.createFile("broken.c", "/"),
255 "unittest", false, "", 0);
256 new GlobalVariable(M
, Type::getInt8Ty(C
), false,
257 GlobalValue::ExternalLinkage
, nullptr, "g");
259 auto *F
= Function::Create(FunctionType::get(Type::getVoidTy(C
), false),
260 Function::ExternalLinkage
, "f", M
);
261 IRBuilder
<> Builder(BasicBlock::Create(C
, "", F
));
262 Builder
.CreateUnreachable();
263 F
->setSubprogram(DIB
.createFunction(
264 CU
, "f", "f", DIB
.createFile("broken.c", "/"), 1, nullptr, 1,
266 DISubprogram::SPFlagLocalToUnit
| DISubprogram::SPFlagDefinition
));
268 EXPECT_FALSE(verifyModule(M
));
270 // Now break it by not listing the CU at all.
271 M
.eraseNamedMetadata(M
.getOrInsertNamedMetadata("llvm.dbg.cu"));
272 EXPECT_TRUE(verifyModule(M
));
276 TEST(VerifierTest
, MDNodeWrongContext
) {
278 auto *Node
= MDNode::get(C1
, std::nullopt
);
281 auto *NamedNode
= M
.getOrInsertNamedMetadata("test");
282 NamedNode
->addOperand(Node
);
285 raw_string_ostream
ErrorOS(Error
);
286 EXPECT_TRUE(verifyModule(M
, &ErrorOS
));
287 EXPECT_TRUE(StringRef(ErrorOS
.str())
288 .startswith("MDNode context does not match Module context!"));
291 TEST(VerifierTest
, AttributesWrongContext
) {
295 FunctionType::get(Type::getVoidTy(C1
), /*isVarArg=*/false);
296 Function
*F1
= Function::Create(FTy1
, Function::ExternalLinkage
, "foo", M1
);
297 F1
->setDoesNotReturn();
301 FunctionType::get(Type::getVoidTy(C2
), /*isVarArg=*/false);
302 Function
*F2
= Function::Create(FTy2
, Function::ExternalLinkage
, "foo", M2
);
303 F2
->copyAttributesFrom(F1
);
305 EXPECT_TRUE(verifyFunction(*F2
));
308 TEST(VerifierTest
, SwitchInst
) {
311 IntegerType
*Int32Ty
= Type::getInt32Ty(C
);
312 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(C
), {Int32Ty
, Int32Ty
},
314 Function
*F
= Function::Create(FTy
, Function::ExternalLinkage
, "foo", M
);
315 BasicBlock
*Entry
= BasicBlock::Create(C
, "entry", F
);
316 BasicBlock
*Default
= BasicBlock::Create(C
, "default", F
);
317 BasicBlock
*OnOne
= BasicBlock::Create(C
, "on_one", F
);
318 BasicBlock
*OnTwo
= BasicBlock::Create(C
, "on_two", F
);
320 BasicBlock
*Exit
= BasicBlock::Create(C
, "exit", F
);
322 BranchInst::Create(Exit
, Default
);
323 BranchInst::Create(Exit
, OnTwo
);
324 BranchInst::Create(Exit
, OnOne
);
325 ReturnInst::Create(C
, Exit
);
327 Value
*Cond
= F
->getArg(0);
328 SwitchInst
*Switch
= SwitchInst::Create(Cond
, Default
, 2, Entry
);
329 Switch
->addCase(ConstantInt::get(Int32Ty
, 1), OnOne
);
330 Switch
->addCase(ConstantInt::get(Int32Ty
, 2), OnTwo
);
332 EXPECT_FALSE(verifyFunction(*F
));
333 // set one case value to function argument.
334 Switch
->setOperand(2, F
->getArg(1));
335 EXPECT_TRUE(verifyFunction(*F
));
338 } // end anonymous namespace
339 } // end namespace llvm