diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -166,6 +166,14 @@ return Changed; } +static bool setArgNoUndef(Function &F, unsigned ArgNo) { + if (F.hasParamAttribute(ArgNo, Attribute::NoUndef)) + return false; + F.addParamAttr(ArgNo, Attribute::NoUndef); + ++NumNoUndef; + return true; +} + static bool setRetAndArgsNoUndef(Function &F) { return setRetNoUndef(F) | setArgsNoUndef(F); } @@ -323,8 +331,10 @@ Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); return Changed; - case LibFunc_strdup: case LibFunc_strndup: + Changed |= setArgNoUndef(F, 1); + LLVM_FALLTHROUGH; + case LibFunc_strdup: Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); @@ -383,7 +393,7 @@ case LibFunc_malloc: case LibFunc_vec_malloc: Changed |= setOnlyAccessesInaccessibleMemory(F); - Changed |= setRetNoUndef(F); + Changed |= setRetAndArgsNoUndef(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); Changed |= setWillReturn(F); @@ -471,10 +481,12 @@ Changed |= setRetDoesNotAlias(F); Changed |= setWillReturn(F); Changed |= setDoesNotCapture(F, 0); + Changed |= setArgNoUndef(F, 1); return Changed; case LibFunc_reallocf: Changed |= setRetNoUndef(F); Changed |= setWillReturn(F); + Changed |= setArgNoUndef(F, 1); return Changed; case LibFunc_read: // May throw; "read" is a valid pthread cancellation point. @@ -517,7 +529,7 @@ return Changed; case LibFunc_aligned_alloc: Changed |= setOnlyAccessesInaccessibleMemory(F); - Changed |= setRetNoUndef(F); + Changed |= setRetAndArgsNoUndef(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); Changed |= setWillReturn(F); @@ -549,7 +561,7 @@ case LibFunc_calloc: case LibFunc_vec_calloc: Changed |= setOnlyAccessesInaccessibleMemory(F); - Changed |= setRetNoUndef(F); + Changed |= setRetAndArgsNoUndef(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); Changed |= setWillReturn(F); @@ -833,7 +845,7 @@ return Changed; case LibFunc_valloc: Changed |= setOnlyAccessesInaccessibleMemory(F); - Changed |= setRetNoUndef(F); + Changed |= setRetAndArgsNoUndef(F); Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); Changed |= setWillReturn(F); @@ -908,8 +920,10 @@ Changed |= setRetAndArgsNoUndef(F); Changed |= setDoesNotCapture(F, 3); return Changed; - case LibFunc_dunder_strdup: case LibFunc_dunder_strndup: + Changed |= setArgNoUndef(F, 1); + LLVM_FALLTHROUGH; + case LibFunc_dunder_strdup: Changed |= setDoesNotThrow(F); Changed |= setRetDoesNotAlias(F); Changed |= setWillReturn(F); diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll --- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll +++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll @@ -178,7 +178,7 @@ ; CHECK: declare x86_fp80 @acosl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN]] declare x86_fp80 @acosl(x86_fp80) -; CHECK: declare noalias noundef i8* @aligned_alloc(i64, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND:#[0-9]+]] +; CHECK: declare noalias noundef i8* @aligned_alloc(i64 noundef, i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND:#[0-9]+]] declare i8* @aligned_alloc(i64, i64) ; CHECK: declare double @asin(double) [[NOFREE_NOUNWIND_WILLRETURN]] @@ -250,7 +250,7 @@ ; CHECK: declare void @bzero(i8* nocapture writeonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]] declare void @bzero(i8*, i64) -; CHECK: declare noalias noundef i8* @calloc(i64, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +; CHECK: declare noalias noundef i8* @calloc(i64 noundef, i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare i8* @calloc(i64, i64) ; CHECK: declare double @cbrt(double) [[NOFREE_NOUNWIND_WILLRETURN]] @@ -610,7 +610,7 @@ ; CHECK-LINUX: declare noundef i32 @lstat64(i8* nocapture noundef readonly, %opaque* nocapture noundef) [[NOFREE_NOUNWIND]] declare i32 @lstat64(i8*, %opaque*) -; CHECK: declare noalias noundef i8* @malloc(i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] +; CHECK: declare noalias noundef i8* @malloc(i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] declare i8* @malloc(i64) ; CHECK-LINUX: declare noalias noundef i8* @memalign(i64, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] @@ -727,10 +727,10 @@ ; CHECK: declare noundef i64 @readlink(i8* nocapture noundef readonly, i8* nocapture noundef, i64 noundef) [[NOFREE_NOUNWIND]] declare i64 @readlink(i8*, i8*, i64) -; CHECK: declare noalias noundef i8* @realloc(i8* nocapture, i64) [[NOUNWIND]] +; CHECK: declare noalias noundef i8* @realloc(i8* nocapture, i64 noundef) [[NOUNWIND]] declare i8* @realloc(i8*, i64) -; CHECK: declare noundef i8* @reallocf(i8*, i64) +; CHECK: declare noundef i8* @reallocf(i8*, i64 noundef) declare i8* @reallocf(i8*, i64) ; CHECK: declare noundef i8* @realpath(i8* nocapture noundef readonly, i8* noundef) [[NOFREE_NOUNWIND]] @@ -871,7 +871,7 @@ ; CHECK: declare i8* @strncpy(i8* noalias returned writeonly, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]] declare i8* @strncpy(i8*, i8*, i64) -; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64) [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN]] +; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64 noundef) [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN]] declare i8* @strndup(i8*, i64) ; CHECK: declare i64 @strnlen(i8*, i64) [[NOFREE_NOUNWIND_WILLRETURN]] @@ -979,7 +979,7 @@ ; CHECK: declare noundef i32 @utimes(i8* nocapture noundef readonly, %opaque* nocapture noundef readonly) [[NOFREE_NOUNWIND]] declare i32 @utimes(i8*, %opaque*) -; CHECK: declare noalias noundef i8* @valloc(i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] +; CHECK: declare noalias noundef i8* @valloc(i64 noundef) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] declare i8* @valloc(i64) ; CHECK: declare noundef i32 @vfprintf(%opaque* nocapture noundef, i8* nocapture noundef readonly, %opaque* noundef) [[NOFREE_NOUNWIND]]