return Result;
}
+static AllocFnKind getAllocFnKind(const Value *V) {
+ if (const auto *CB = dyn_cast<CallBase>(V)) {
+ Attribute Attr = CB->getFnAttr(Attribute::AllocKind);
+ if (Attr.isValid())
+ return AllocFnKind(Attr.getValueAsInt());
+ }
+ return AllocFnKind::Unknown;
+}
+
+static AllocFnKind getAllocFnKind(const Function *F) {
+ Attribute Attr = F->getFnAttribute(Attribute::AllocKind);
+ if (Attr.isValid())
+ return AllocFnKind(Attr.getValueAsInt());
+ return AllocFnKind::Unknown;
+}
+
+static bool checkFnAllocKind(const Value *V, AllocFnKind Wanted) {
+ return (getAllocFnKind(V) & Wanted) != AllocFnKind::Unknown;
+}
+
+static bool checkFnAllocKind(const Function *F, AllocFnKind Wanted) {
+ return (getAllocFnKind(F) & Wanted) != AllocFnKind::Unknown;
+}
+
/// Tests if a value is a call or invoke to a library function that
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
/// like).
bool llvm::isAllocationFn(const Value *V, const TargetLibraryInfo *TLI) {
- return getAllocationData(V, AnyAlloc, TLI).has_value();
+ return getAllocationData(V, AnyAlloc, TLI).has_value() ||
+ checkFnAllocKind(V, AllocFnKind::Alloc | AllocFnKind::Realloc);
}
bool llvm::isAllocationFn(
- const Value *V, function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
- return getAllocationData(V, AnyAlloc, GetTLI).has_value();
+ const Value *V,
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
+ return getAllocationData(V, AnyAlloc, GetTLI).has_value() ||
+ checkFnAllocKind(V, AllocFnKind::Alloc | AllocFnKind::Realloc);
}
/// Tests if a value is a call or invoke to a library function that
/// Tests if a value is a call or invoke to a library function that
/// allocates memory (either malloc, calloc, or strdup like).
bool llvm::isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI) {
- return getAllocationData(V, AllocLike, TLI).has_value();
+ return getAllocationData(V, AllocLike, TLI).has_value() ||
+ checkFnAllocKind(V, AllocFnKind::Alloc);
}
/// Tests if a functions is a call or invoke to a library function that
/// reallocates memory (e.g., realloc).
bool llvm::isReallocLikeFn(const Function *F, const TargetLibraryInfo *TLI) {
- return getAllocationDataForFunction(F, ReallocLike, TLI).has_value();
+ return getAllocationDataForFunction(F, ReallocLike, TLI).has_value() ||
+ checkFnAllocKind(F, AllocFnKind::Realloc);
}
Value *llvm::getReallocatedOperand(const CallBase *CB,
// All currently supported realloc functions reallocate the first argument.
return CB->getArgOperand(0);
}
+ if (checkFnAllocKind(CB, AllocFnKind::Realloc))
+ return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
return nullptr;
}
if (isCallocLikeFn(Alloc, TLI))
return Constant::getNullValue(Ty);
+ AllocFnKind AK = getAllocFnKind(Alloc);
+ if ((AK & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
+ return UndefValue::get(Ty);
+ if ((AK & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
+ return Constant::getNullValue(Ty);
+
return nullptr;
}
const auto FreeData = getFreeFunctionDataForFunction(Callee, TLIFn);
if (FreeData)
return mangledNameForMallocFamily(FreeData.value().Family);
+ if (checkFnAllocKind(I, AllocFnKind::Free | AllocFnKind::Alloc |
+ AllocFnKind::Realloc)) {
+ Attribute Attr = cast<CallBase>(I)->getFnAttr("alloc-family");
+ if (Attr.isValid())
+ return Attr.getValueAsString();
+ }
return None;
}
bool llvm::isLibFreeFunction(const Function *F, const LibFunc TLIFn) {
Optional<FreeFnsTy> FnData = getFreeFunctionDataForFunction(F, TLIFn);
if (!FnData)
- return false;
+ return checkFnAllocKind(F, AllocFnKind::Free);
// Check free prototype.
// FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
return CB->getArgOperand(0);
}
+ if (checkFnAllocKind(CB, AllocFnKind::Free))
+ return CB->getArgOperandWithAttribute(Attribute::AllocatedPointer);
+
return nullptr;
}