[Lint][Verifier] NFC: Rename 'Assert*' macros to 'Check*'.

The LLVM IR verifier and analysis linter defines and uses several macros in
code that performs validation of IR expectations. Previously, these macros
were named with an 'Assert' prefix. These names were misleading since the
macro definitions are not conditioned on build kind; they are defined
identically in builds that have asserts enabled and those that do not. This
was confusing since an LLVM developer might expect these macros to be
conditionally enabled as 'assert' is. Further confusion was possible since
the LLVM IR verifier is implicitly disabled (in Clang::ConstructJob()) for
builds without asserts enabled, but only for Clang driver invocations; not
for clang -cc1 invocations. This could make it appear that the macros were
not active for builds without asserts enabled, e.g. when investigating
behavior using the Clang driver, and thus lead to surprises when running
tests that exercise the clang -cc1 interface.

This change renames this set of macros as follows:
  Assert -> Check
  AssertDI -> CheckDI
  AssertTBAA -> CheckTBAA
This commit is contained in:
Tom Honermann 2022-04-01 18:52:29 -07:00 committed by Tom Honermann
parent 019e7b7f6e
commit c54ad13602
2 changed files with 1983 additions and 1982 deletions

View file

@ -166,8 +166,8 @@ public:
}; };
} // end anonymous namespace } // end anonymous namespace
// Assert - We know that cond should be true, if not print an error message. // Check - We know that cond should be true, if not print an error message.
#define Assert(C, ...) \ #define Check(C, ...) \
do { \ do { \
if (!(C)) { \ if (!(C)) { \
CheckFailed(__VA_ARGS__); \ CheckFailed(__VA_ARGS__); \
@ -178,8 +178,8 @@ public:
void Lint::visitFunction(Function &F) { void Lint::visitFunction(Function &F) {
// This isn't undefined behavior, it's just a little unusual, and it's a // This isn't undefined behavior, it's just a little unusual, and it's a
// fairly common mistake to neglect to name a function. // fairly common mistake to neglect to name a function.
Assert(F.hasName() || F.hasLocalLinkage(), Check(F.hasName() || F.hasLocalLinkage(),
"Unusual: Unnamed function with non-local linkage", &F); "Unusual: Unnamed function with non-local linkage", &F);
// TODO: Check for irreducible control flow. // TODO: Check for irreducible control flow.
} }
@ -192,23 +192,23 @@ void Lint::visitCallBase(CallBase &I) {
if (Function *F = dyn_cast<Function>(findValue(Callee, if (Function *F = dyn_cast<Function>(findValue(Callee,
/*OffsetOk=*/false))) { /*OffsetOk=*/false))) {
Assert(I.getCallingConv() == F->getCallingConv(), Check(I.getCallingConv() == F->getCallingConv(),
"Undefined behavior: Caller and callee calling convention differ", "Undefined behavior: Caller and callee calling convention differ",
&I); &I);
FunctionType *FT = F->getFunctionType(); FunctionType *FT = F->getFunctionType();
unsigned NumActualArgs = I.arg_size(); unsigned NumActualArgs = I.arg_size();
Assert(FT->isVarArg() ? FT->getNumParams() <= NumActualArgs Check(FT->isVarArg() ? FT->getNumParams() <= NumActualArgs
: FT->getNumParams() == NumActualArgs, : FT->getNumParams() == NumActualArgs,
"Undefined behavior: Call argument count mismatches callee " "Undefined behavior: Call argument count mismatches callee "
"argument count", "argument count",
&I); &I);
Assert(FT->getReturnType() == I.getType(), Check(FT->getReturnType() == I.getType(),
"Undefined behavior: Call return type mismatches " "Undefined behavior: Call return type mismatches "
"callee return type", "callee return type",
&I); &I);
// Check argument types (in case the callee was casted) and attributes. // Check argument types (in case the callee was casted) and attributes.
// TODO: Verify that caller and callee attributes are compatible. // TODO: Verify that caller and callee attributes are compatible.
@ -218,10 +218,10 @@ void Lint::visitCallBase(CallBase &I) {
Value *Actual = *AI; Value *Actual = *AI;
if (PI != PE) { if (PI != PE) {
Argument *Formal = &*PI++; Argument *Formal = &*PI++;
Assert(Formal->getType() == Actual->getType(), Check(Formal->getType() == Actual->getType(),
"Undefined behavior: Call argument type mismatches " "Undefined behavior: Call argument type mismatches "
"callee parameter type", "callee parameter type",
&I); &I);
// Check that noalias arguments don't alias other arguments. This is // Check that noalias arguments don't alias other arguments. This is
// not fully precise because we don't know the sizes of the dereferenced // not fully precise because we don't know the sizes of the dereferenced
@ -239,9 +239,9 @@ void Lint::visitCallBase(CallBase &I) {
continue; continue;
if (AI != BI && (*BI)->getType()->isPointerTy()) { if (AI != BI && (*BI)->getType()->isPointerTy()) {
AliasResult Result = AA->alias(*AI, *BI); AliasResult Result = AA->alias(*AI, *BI);
Assert(Result != AliasResult::MustAlias && Check(Result != AliasResult::MustAlias &&
Result != AliasResult::PartialAlias, Result != AliasResult::PartialAlias,
"Unusual: noalias argument aliases another argument", &I); "Unusual: noalias argument aliases another argument", &I);
} }
} }
} }
@ -268,10 +268,10 @@ void Lint::visitCallBase(CallBase &I) {
if (PAL.hasParamAttr(ArgNo++, Attribute::ByVal)) if (PAL.hasParamAttr(ArgNo++, Attribute::ByVal))
continue; continue;
Value *Obj = findValue(Arg, /*OffsetOk=*/true); Value *Obj = findValue(Arg, /*OffsetOk=*/true);
Assert(!isa<AllocaInst>(Obj), Check(!isa<AllocaInst>(Obj),
"Undefined behavior: Call with \"tail\" keyword references " "Undefined behavior: Call with \"tail\" keyword references "
"alloca", "alloca",
&I); &I);
} }
} }
} }
@ -299,9 +299,9 @@ void Lint::visitCallBase(CallBase &I) {
/*OffsetOk=*/false))) /*OffsetOk=*/false)))
if (Len->getValue().isIntN(32)) if (Len->getValue().isIntN(32))
Size = LocationSize::precise(Len->getValue().getZExtValue()); Size = LocationSize::precise(Len->getValue().getZExtValue());
Assert(AA->alias(MCI->getSource(), Size, MCI->getDest(), Size) != Check(AA->alias(MCI->getSource(), Size, MCI->getDest(), Size) !=
AliasResult::MustAlias, AliasResult::MustAlias,
"Undefined behavior: memcpy source and destination overlap", &I); "Undefined behavior: memcpy source and destination overlap", &I);
break; break;
} }
case Intrinsic::memcpy_inline: { case Intrinsic::memcpy_inline: {
@ -316,9 +316,9 @@ void Lint::visitCallBase(CallBase &I) {
// isn't expressive enough for what we really want to do. Known partial // isn't expressive enough for what we really want to do. Known partial
// overlap is not distinguished from the case where nothing is known. // overlap is not distinguished from the case where nothing is known.
const LocationSize LS = LocationSize::precise(Size); const LocationSize LS = LocationSize::precise(Size);
Assert(AA->alias(MCII->getSource(), LS, MCII->getDest(), LS) != Check(AA->alias(MCII->getSource(), LS, MCII->getDest(), LS) !=
AliasResult::MustAlias, AliasResult::MustAlias,
"Undefined behavior: memcpy source and destination overlap", &I); "Undefined behavior: memcpy source and destination overlap", &I);
break; break;
} }
case Intrinsic::memmove: { case Intrinsic::memmove: {
@ -337,9 +337,9 @@ void Lint::visitCallBase(CallBase &I) {
} }
case Intrinsic::vastart: case Intrinsic::vastart:
Assert(I.getParent()->getParent()->isVarArg(), Check(I.getParent()->getParent()->isVarArg(),
"Undefined behavior: va_start called in a non-varargs function", "Undefined behavior: va_start called in a non-varargs function",
&I); &I);
visitMemoryReference(I, MemoryLocation::getForArgument(&I, 0, TLI), None, visitMemoryReference(I, MemoryLocation::getForArgument(&I, 0, TLI), None,
nullptr, MemRef::Read | MemRef::Write); nullptr, MemRef::Read | MemRef::Write);
@ -364,20 +364,22 @@ void Lint::visitCallBase(CallBase &I) {
break; break;
case Intrinsic::get_active_lane_mask: case Intrinsic::get_active_lane_mask:
if (auto *TripCount = dyn_cast<ConstantInt>(I.getArgOperand(1))) if (auto *TripCount = dyn_cast<ConstantInt>(I.getArgOperand(1)))
Assert(!TripCount->isZero(), "get_active_lane_mask: operand #2 " Check(!TripCount->isZero(),
"must be greater than 0", &I); "get_active_lane_mask: operand #2 "
"must be greater than 0",
&I);
break; break;
} }
} }
void Lint::visitReturnInst(ReturnInst &I) { void Lint::visitReturnInst(ReturnInst &I) {
Function *F = I.getParent()->getParent(); Function *F = I.getParent()->getParent();
Assert(!F->doesNotReturn(), Check(!F->doesNotReturn(),
"Unusual: Return statement in function with noreturn attribute", &I); "Unusual: Return statement in function with noreturn attribute", &I);
if (Value *V = I.getReturnValue()) { if (Value *V = I.getReturnValue()) {
Value *Obj = findValue(V, /*OffsetOk=*/true); Value *Obj = findValue(V, /*OffsetOk=*/true);
Assert(!isa<AllocaInst>(Obj), "Unusual: Returning alloca value", &I); Check(!isa<AllocaInst>(Obj), "Unusual: Returning alloca value", &I);
} }
} }
@ -392,39 +394,39 @@ void Lint::visitMemoryReference(Instruction &I, const MemoryLocation &Loc,
Value *Ptr = const_cast<Value *>(Loc.Ptr); Value *Ptr = const_cast<Value *>(Loc.Ptr);
Value *UnderlyingObject = findValue(Ptr, /*OffsetOk=*/true); Value *UnderlyingObject = findValue(Ptr, /*OffsetOk=*/true);
Assert(!isa<ConstantPointerNull>(UnderlyingObject), Check(!isa<ConstantPointerNull>(UnderlyingObject),
"Undefined behavior: Null pointer dereference", &I); "Undefined behavior: Null pointer dereference", &I);
Assert(!isa<UndefValue>(UnderlyingObject), Check(!isa<UndefValue>(UnderlyingObject),
"Undefined behavior: Undef pointer dereference", &I); "Undefined behavior: Undef pointer dereference", &I);
Assert(!isa<ConstantInt>(UnderlyingObject) || Check(!isa<ConstantInt>(UnderlyingObject) ||
!cast<ConstantInt>(UnderlyingObject)->isMinusOne(), !cast<ConstantInt>(UnderlyingObject)->isMinusOne(),
"Unusual: All-ones pointer dereference", &I); "Unusual: All-ones pointer dereference", &I);
Assert(!isa<ConstantInt>(UnderlyingObject) || Check(!isa<ConstantInt>(UnderlyingObject) ||
!cast<ConstantInt>(UnderlyingObject)->isOne(), !cast<ConstantInt>(UnderlyingObject)->isOne(),
"Unusual: Address one pointer dereference", &I); "Unusual: Address one pointer dereference", &I);
if (Flags & MemRef::Write) { if (Flags & MemRef::Write) {
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(UnderlyingObject)) if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(UnderlyingObject))
Assert(!GV->isConstant(), "Undefined behavior: Write to read-only memory", Check(!GV->isConstant(), "Undefined behavior: Write to read-only memory",
&I); &I);
Assert(!isa<Function>(UnderlyingObject) && Check(!isa<Function>(UnderlyingObject) &&
!isa<BlockAddress>(UnderlyingObject), !isa<BlockAddress>(UnderlyingObject),
"Undefined behavior: Write to text section", &I); "Undefined behavior: Write to text section", &I);
} }
if (Flags & MemRef::Read) { if (Flags & MemRef::Read) {
Assert(!isa<Function>(UnderlyingObject), "Unusual: Load from function body", Check(!isa<Function>(UnderlyingObject), "Unusual: Load from function body",
&I); &I);
Assert(!isa<BlockAddress>(UnderlyingObject), Check(!isa<BlockAddress>(UnderlyingObject),
"Undefined behavior: Load from block address", &I); "Undefined behavior: Load from block address", &I);
} }
if (Flags & MemRef::Callee) { if (Flags & MemRef::Callee) {
Assert(!isa<BlockAddress>(UnderlyingObject), Check(!isa<BlockAddress>(UnderlyingObject),
"Undefined behavior: Call to block address", &I); "Undefined behavior: Call to block address", &I);
} }
if (Flags & MemRef::Branchee) { if (Flags & MemRef::Branchee) {
Assert(!isa<Constant>(UnderlyingObject) || Check(!isa<Constant>(UnderlyingObject) ||
isa<BlockAddress>(UnderlyingObject), isa<BlockAddress>(UnderlyingObject),
"Undefined behavior: Branch to non-blockaddress", &I); "Undefined behavior: Branch to non-blockaddress", &I);
} }
// Check for buffer overflows and misalignment. // Check for buffer overflows and misalignment.
@ -458,17 +460,17 @@ void Lint::visitMemoryReference(Instruction &I, const MemoryLocation &Loc,
// Accesses from before the start or after the end of the object are not // Accesses from before the start or after the end of the object are not
// defined. // defined.
Assert(!Loc.Size.hasValue() || BaseSize == MemoryLocation::UnknownSize || Check(!Loc.Size.hasValue() || BaseSize == MemoryLocation::UnknownSize ||
(Offset >= 0 && Offset + Loc.Size.getValue() <= BaseSize), (Offset >= 0 && Offset + Loc.Size.getValue() <= BaseSize),
"Undefined behavior: Buffer overflow", &I); "Undefined behavior: Buffer overflow", &I);
// Accesses that say that the memory is more aligned than it is are not // Accesses that say that the memory is more aligned than it is are not
// defined. // defined.
if (!Align && Ty && Ty->isSized()) if (!Align && Ty && Ty->isSized())
Align = DL->getABITypeAlign(Ty); Align = DL->getABITypeAlign(Ty);
if (BaseAlign && Align) if (BaseAlign && Align)
Assert(*Align <= commonAlignment(*BaseAlign, Offset), Check(*Align <= commonAlignment(*BaseAlign, Offset),
"Undefined behavior: Memory reference address is misaligned", &I); "Undefined behavior: Memory reference address is misaligned", &I);
} }
} }
@ -483,34 +485,34 @@ void Lint::visitStoreInst(StoreInst &I) {
} }
void Lint::visitXor(BinaryOperator &I) { void Lint::visitXor(BinaryOperator &I) {
Assert(!isa<UndefValue>(I.getOperand(0)) || !isa<UndefValue>(I.getOperand(1)), Check(!isa<UndefValue>(I.getOperand(0)) || !isa<UndefValue>(I.getOperand(1)),
"Undefined result: xor(undef, undef)", &I); "Undefined result: xor(undef, undef)", &I);
} }
void Lint::visitSub(BinaryOperator &I) { void Lint::visitSub(BinaryOperator &I) {
Assert(!isa<UndefValue>(I.getOperand(0)) || !isa<UndefValue>(I.getOperand(1)), Check(!isa<UndefValue>(I.getOperand(0)) || !isa<UndefValue>(I.getOperand(1)),
"Undefined result: sub(undef, undef)", &I); "Undefined result: sub(undef, undef)", &I);
} }
void Lint::visitLShr(BinaryOperator &I) { void Lint::visitLShr(BinaryOperator &I) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(findValue(I.getOperand(1), if (ConstantInt *CI = dyn_cast<ConstantInt>(findValue(I.getOperand(1),
/*OffsetOk=*/false))) /*OffsetOk=*/false)))
Assert(CI->getValue().ult(cast<IntegerType>(I.getType())->getBitWidth()), Check(CI->getValue().ult(cast<IntegerType>(I.getType())->getBitWidth()),
"Undefined result: Shift count out of range", &I); "Undefined result: Shift count out of range", &I);
} }
void Lint::visitAShr(BinaryOperator &I) { void Lint::visitAShr(BinaryOperator &I) {
if (ConstantInt *CI = if (ConstantInt *CI =
dyn_cast<ConstantInt>(findValue(I.getOperand(1), /*OffsetOk=*/false))) dyn_cast<ConstantInt>(findValue(I.getOperand(1), /*OffsetOk=*/false)))
Assert(CI->getValue().ult(cast<IntegerType>(I.getType())->getBitWidth()), Check(CI->getValue().ult(cast<IntegerType>(I.getType())->getBitWidth()),
"Undefined result: Shift count out of range", &I); "Undefined result: Shift count out of range", &I);
} }
void Lint::visitShl(BinaryOperator &I) { void Lint::visitShl(BinaryOperator &I) {
if (ConstantInt *CI = if (ConstantInt *CI =
dyn_cast<ConstantInt>(findValue(I.getOperand(1), /*OffsetOk=*/false))) dyn_cast<ConstantInt>(findValue(I.getOperand(1), /*OffsetOk=*/false)))
Assert(CI->getValue().ult(cast<IntegerType>(I.getType())->getBitWidth()), Check(CI->getValue().ult(cast<IntegerType>(I.getType())->getBitWidth()),
"Undefined result: Shift count out of range", &I); "Undefined result: Shift count out of range", &I);
} }
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
@ -551,30 +553,30 @@ static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
} }
void Lint::visitSDiv(BinaryOperator &I) { void Lint::visitSDiv(BinaryOperator &I) {
Assert(!isZero(I.getOperand(1), I.getModule()->getDataLayout(), DT, AC), Check(!isZero(I.getOperand(1), I.getModule()->getDataLayout(), DT, AC),
"Undefined behavior: Division by zero", &I); "Undefined behavior: Division by zero", &I);
} }
void Lint::visitUDiv(BinaryOperator &I) { void Lint::visitUDiv(BinaryOperator &I) {
Assert(!isZero(I.getOperand(1), I.getModule()->getDataLayout(), DT, AC), Check(!isZero(I.getOperand(1), I.getModule()->getDataLayout(), DT, AC),
"Undefined behavior: Division by zero", &I); "Undefined behavior: Division by zero", &I);
} }
void Lint::visitSRem(BinaryOperator &I) { void Lint::visitSRem(BinaryOperator &I) {
Assert(!isZero(I.getOperand(1), I.getModule()->getDataLayout(), DT, AC), Check(!isZero(I.getOperand(1), I.getModule()->getDataLayout(), DT, AC),
"Undefined behavior: Division by zero", &I); "Undefined behavior: Division by zero", &I);
} }
void Lint::visitURem(BinaryOperator &I) { void Lint::visitURem(BinaryOperator &I) {
Assert(!isZero(I.getOperand(1), I.getModule()->getDataLayout(), DT, AC), Check(!isZero(I.getOperand(1), I.getModule()->getDataLayout(), DT, AC),
"Undefined behavior: Division by zero", &I); "Undefined behavior: Division by zero", &I);
} }
void Lint::visitAllocaInst(AllocaInst &I) { void Lint::visitAllocaInst(AllocaInst &I) {
if (isa<ConstantInt>(I.getArraySize())) if (isa<ConstantInt>(I.getArraySize()))
// This isn't undefined behavior, it's just an obvious pessimization. // This isn't undefined behavior, it's just an obvious pessimization.
Assert(&I.getParent()->getParent()->getEntryBlock() == I.getParent(), Check(&I.getParent()->getParent()->getEntryBlock() == I.getParent(),
"Pessimization: Static alloca outside of entry block", &I); "Pessimization: Static alloca outside of entry block", &I);
// TODO: Check for an unusual size (MSB set?) // TODO: Check for an unusual size (MSB set?)
} }
@ -588,14 +590,14 @@ void Lint::visitIndirectBrInst(IndirectBrInst &I) {
visitMemoryReference(I, MemoryLocation::getAfter(I.getAddress()), None, visitMemoryReference(I, MemoryLocation::getAfter(I.getAddress()), None,
nullptr, MemRef::Branchee); nullptr, MemRef::Branchee);
Assert(I.getNumDestinations() != 0, Check(I.getNumDestinations() != 0,
"Undefined behavior: indirectbr with no destinations", &I); "Undefined behavior: indirectbr with no destinations", &I);
} }
void Lint::visitExtractElementInst(ExtractElementInst &I) { void Lint::visitExtractElementInst(ExtractElementInst &I) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(findValue(I.getIndexOperand(), if (ConstantInt *CI = dyn_cast<ConstantInt>(findValue(I.getIndexOperand(),
/*OffsetOk=*/false))) /*OffsetOk=*/false)))
Assert( Check(
CI->getValue().ult( CI->getValue().ult(
cast<FixedVectorType>(I.getVectorOperandType())->getNumElements()), cast<FixedVectorType>(I.getVectorOperandType())->getNumElements()),
"Undefined result: extractelement index out of range", &I); "Undefined result: extractelement index out of range", &I);
@ -604,18 +606,18 @@ void Lint::visitExtractElementInst(ExtractElementInst &I) {
void Lint::visitInsertElementInst(InsertElementInst &I) { void Lint::visitInsertElementInst(InsertElementInst &I) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(findValue(I.getOperand(2), if (ConstantInt *CI = dyn_cast<ConstantInt>(findValue(I.getOperand(2),
/*OffsetOk=*/false))) /*OffsetOk=*/false)))
Assert(CI->getValue().ult( Check(CI->getValue().ult(
cast<FixedVectorType>(I.getType())->getNumElements()), cast<FixedVectorType>(I.getType())->getNumElements()),
"Undefined result: insertelement index out of range", &I); "Undefined result: insertelement index out of range", &I);
} }
void Lint::visitUnreachableInst(UnreachableInst &I) { void Lint::visitUnreachableInst(UnreachableInst &I) {
// This isn't undefined behavior, it's merely suspicious. // This isn't undefined behavior, it's merely suspicious.
Assert(&I == &I.getParent()->front() || Check(&I == &I.getParent()->front() ||
std::prev(I.getIterator())->mayHaveSideEffects(), std::prev(I.getIterator())->mayHaveSideEffects(),
"Unusual: unreachable immediately preceded by instruction without " "Unusual: unreachable immediately preceded by instruction without "
"side effects", "side effects",
&I); &I);
} }
/// findValue - Look through bitcasts and simple memory reference patterns /// findValue - Look through bitcasts and simple memory reference patterns

File diff suppressed because it is too large Load diff