From a338d577bb4fbf9013cf0c22c211d25bf3c41a26 Mon Sep 17 00:00:00 2001 From: Jeroen Dobbelaere Date: Thu, 18 Feb 2021 17:29:46 +0100 Subject: [PATCH] [clang] functions with the 'const' or 'pure' attribute must always return. As described in * https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute * https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute An `__attribute__((pure))` function must always return, as well as an `__attribute__((const))` function. Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D96960 (cherry picked from commit 46757ccb49ab88da54ca8ddd43665d5255ee80f7) --- clang/lib/CodeGen/CGCall.cpp | 5 +++++ clang/test/CodeGen/complex-builtins.c | 3 ++- clang/test/CodeGen/complex-libcalls.c | 3 ++- clang/test/CodeGen/function-attributes.c | 2 +- clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp | 8 ++++---- clang/test/Sema/libbuiltins-ctype-powerpc64.c | 2 +- clang/test/Sema/libbuiltins-ctype-x86_64.c | 2 +- 7 files changed, 16 insertions(+), 9 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 42801372189..bc7582c6798 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1995,9 +1995,14 @@ void CodeGenModule::ConstructAttributeList( if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ReadNone); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + // gcc specifies that 'const' functions have greater restrictions than + // 'pure' functions, so they also cannot have infinite loops. + FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ReadOnly); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + // gcc specifies that 'pure' functions cannot have infinite loops. + FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ArgMemOnly); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); diff --git a/clang/test/CodeGen/complex-builtins.c b/clang/test/CodeGen/complex-builtins.c index 96c0e711701..6fea8a9f028 100644 --- a/clang/test/CodeGen/complex-builtins.c +++ b/clang/test/CodeGen/complex-builtins.c @@ -133,7 +133,7 @@ void foo(float f) { // NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] // HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] -// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[WILLRETURN_NOT_READNONE:#[0-9]+]] __builtin_cpow(f,f); __builtin_cpowf(f,f); __builtin_cpowl(f,f); @@ -202,3 +202,4 @@ void foo(float f) { // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } diff --git a/clang/test/CodeGen/complex-libcalls.c b/clang/test/CodeGen/complex-libcalls.c index 9bd419a8382..44d6849c0a7 100644 --- a/clang/test/CodeGen/complex-libcalls.c +++ b/clang/test/CodeGen/complex-libcalls.c @@ -133,7 +133,7 @@ void foo(float f) { // NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] // HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] -// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[WILLRETURN_NOT_READNONE:#[0-9]+]] cpow(f,f); cpowf(f,f); cpowl(f,f); @@ -202,3 +202,4 @@ void foo(float f) { // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } diff --git a/clang/test/CodeGen/function-attributes.c b/clang/test/CodeGen/function-attributes.c index ffb86a6cd27..f14f2480100 100644 --- a/clang/test/CodeGen/function-attributes.c +++ b/clang/test/CodeGen/function-attributes.c @@ -115,5 +115,5 @@ void f20(void) { // CHECK: attributes [[SR]] = { nounwind optsize{{.*}} "stackrealign"{{.*}} } // CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} } // CHECK: attributes [[NR]] = { noreturn optsize } -// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone } +// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone willreturn } // CHECK: attributes [[RT_CALL]] = { optsize returns_twice } diff --git a/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp b/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp index 25400a552e5..e1d539608fc 100644 --- a/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp +++ b/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp @@ -15,8 +15,8 @@ int f(void) { // CHECK: declare i32 @_Z1tv() [[TF2:#[0-9]+]] // CHECK: attributes [[TF]] = { {{.*}} } -// CHECK: attributes [[NUW_RN]] = { nounwind readnone{{.*}} } -// CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } +// CHECK: attributes [[NUW_RN]] = { nounwind readnone willreturn{{.*}} } +// CHECK: attributes [[NUW_RO]] = { nounwind readonly willreturn{{.*}} } // CHECK: attributes [[TF2]] = { {{.*}} } -// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone willreturn } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } diff --git a/clang/test/Sema/libbuiltins-ctype-powerpc64.c b/clang/test/Sema/libbuiltins-ctype-powerpc64.c index bfd79acb0ab..ba0efb20594 100644 --- a/clang/test/Sema/libbuiltins-ctype-powerpc64.c +++ b/clang/test/Sema/libbuiltins-ctype-powerpc64.c @@ -62,4 +62,4 @@ void test(int x) { // CHECK: declare signext i32 @toupper(i32 signext) [[NUW_RO:#[0-9]+]] // CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } diff --git a/clang/test/Sema/libbuiltins-ctype-x86_64.c b/clang/test/Sema/libbuiltins-ctype-x86_64.c index 4934e6f1675..b8a2c7e8158 100644 --- a/clang/test/Sema/libbuiltins-ctype-x86_64.c +++ b/clang/test/Sema/libbuiltins-ctype-x86_64.c @@ -62,4 +62,4 @@ void test(int x) { // CHECK: declare i32 @toupper(i32) [[NUW_RO:#[0-9]+]] // CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } -- 2.11.0