//
// Another limitation is that it assumes all code will be executed. A store
// through a null pointer in a basic block which is never reached is harmless,
-// but this pass will warn about it anyway.
+// but this pass will warn about it anyway. This is the main reason why most
+// of these checks live here instead of in the Verifier pass.
//
// Optimization passes may make conditions that this pass checks for more or
// less obvious. If an optimization pass appears to be introducing a warning,
raw_string_ostream MessagesStr;
static char ID; // Pass identification, replacement for typeid
- Lint() : FunctionPass(&ID), MessagesStr(Messages) {}
+ Lint() : FunctionPass(ID), MessagesStr(Messages) {}
virtual bool runOnFunction(Function &F);
}
char Lint::ID = 0;
-static RegisterPass<Lint>
-X("lint", "Statically lint-checks LLVM IR", false, true);
+INITIALIZE_PASS(Lint, "lint", "Statically lint-checks LLVM IR", false, true);
// Assert - We know that cond should be true, if not print an error message.
#define Assert(C, M) \
// fairly common mistake to neglect to name a function.
Assert1(F.hasName() || F.hasLocalLinkage(),
"Unusual: Unnamed function with non-local linkage", &F);
+
+ // TODO: Check for irreducible control flow.
}
void Lint::visitCallSite(CallSite CS) {
const FunctionType *FT = F->getFunctionType();
unsigned NumActualArgs = unsigned(CS.arg_end()-CS.arg_begin());
- std::vector<Value *> NoAliasVals;
Assert1(FT->isVarArg() ?
FT->getNumParams() <= NumActualArgs :
"Undefined behavior: Call argument count mismatches callee "
"argument count", &I);
+ Assert1(FT->getReturnType() == I.getType(),
+ "Undefined behavior: Call return type mismatches "
+ "callee return type", &I);
+
// Check argument types (in case the callee was casted) and attributes.
+ // TODO: Verify that caller and callee attributes are compatible.
Function::arg_iterator PI = F->arg_begin(), PE = F->arg_end();
CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
for (; AI != AE; ++AI) {
Assert1(Formal->getType() == Actual->getType(),
"Undefined behavior: Call argument type mismatches "
"callee parameter type", &I);
+
+ // Check that noalias arguments don't alias other arguments. The
+ // AliasAnalysis API isn't expressive enough for what we really want
+ // to do. Known partial overlap is not distinguished from the case
+ // where nothing is known.
if (Formal->hasNoAliasAttr() && Actual->getType()->isPointerTy())
- NoAliasVals.push_back(Actual);
+ for (CallSite::arg_iterator BI = CS.arg_begin(); BI != AE; ++BI) {
+ Assert1(AI == BI || AA->alias(*AI, *BI) != AliasAnalysis::MustAlias,
+ "Unusual: noalias argument aliases another argument", &I);
+ }
+
+ // Check that an sret argument points to valid memory.
if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) {
const Type *Ty =
cast<PointerType>(Formal->getType())->getElementType();
}
}
}
-
- // Check that the noalias arguments don't overlap. The AliasAnalysis API
- // isn't expressive enough for what we really want to do. Known partial
- // overlap is not distinguished from the case where nothing is known.
- for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
- AI != AE; ++AI)
- for (std::vector<Value *>::iterator J = NoAliasVals.begin(),
- E = NoAliasVals.end(); J != E; ++J)
- Assert1(AA->alias(*J, ~0u, *AI, ~0u) != AliasAnalysis::MustAlias,
- "Unusual: noalias argument aliases another argument", &I);
}
if (CS.isCall() && cast<CallInst>(CS.getInstruction())->isTailCall())
}
// TODO: Check that the reference is in bounds.
+// TODO: Check readnone/readonly function attributes.
void Lint::visitMemoryReference(Instruction &I,
Value *Ptr, unsigned Size, unsigned Align,
const Type *Ty, unsigned Flags) {
// This isn't undefined behavior, it's just an obvious pessimization.
Assert1(&I.getParent()->getParent()->getEntryBlock() == I.getParent(),
"Pessimization: Static alloca outside of entry block", &I);
+
+ // TODO: Check for an unusual size (MSB set?)
}
void Lint::visitVAArgInst(VAArgInst &I) {
void Lint::visitIndirectBrInst(IndirectBrInst &I) {
visitMemoryReference(I, I.getAddress(), ~0u, 0, 0, MemRef::Branchee);
+
+ Assert1(I.getNumDestinations() != 0,
+ "Undefined behavior: indirectbr with no destinations", &I);
}
void Lint::visitExtractElementInst(ExtractElementInst &I) {