[llvm-branch-commits] [clang] b283265 - Revert 9007f06af0e "Revert "Allow system header to provide their own implementation of some builtin""
Hans Wennborg via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Jan 17 03:55:45 PST 2020
Author: Hans Wennborg
Date: 2020-01-17T12:51:06+01:00
New Revision: b28326516ca3ad9d51688532e944f491ce8b7908
URL: https://github.com/llvm/llvm-project/commit/b28326516ca3ad9d51688532e944f491ce8b7908
DIFF: https://github.com/llvm/llvm-project/commit/b28326516ca3ad9d51688532e944f491ce8b7908.diff
LOG: Revert 9007f06af0e "Revert "Allow system header to provide their own implementation of some builtin""
This should no longer be necessary after
cd4c65f91d5 "Add __warn_memset_zero_len builtin as a workaround for glibc issue"
Added:
clang/test/CodeGen/memcpy-nobuiltin.c
clang/test/CodeGen/memcpy-nobuiltin.inc
Modified:
clang/include/clang/AST/Decl.h
clang/lib/AST/Decl.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CodeGenModule.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 620ab4b089db..43c6c7b85db4 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -2309,6 +2309,9 @@ class FunctionDecl : public DeclaratorDecl,
/// true through IsAligned.
bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;
+ /// Determine if this function provides an inline implementation of a builtin.
+ bool isInlineBuiltinDeclaration() const;
+
/// Determine whether this is a destroying operator delete.
bool isDestroyingOperatorDelete() const;
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index be59d88b73f1..0d30f64b992e 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3046,6 +3046,14 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const
return Params == FPT->getNumParams();
}
+bool FunctionDecl::isInlineBuiltinDeclaration() const {
+ if (!getBuiltinID())
+ return false;
+
+ const FunctionDecl *Definition;
+ return hasBody(Definition) && Definition->isInlineSpecified();
+}
+
bool FunctionDecl::isDestroyingOperatorDelete() const {
// C++ P0722:
// Within a class C, a single object deallocation function with signature
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index b23d9df5f4ba..8e0604181fb1 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4621,8 +4621,15 @@ RValue CodeGenFunction::EmitSimpleCallExpr(const CallExpr *E,
}
static CGCallee EmitDirectCallee(CodeGenFunction &CGF, const FunctionDecl *FD) {
+
if (auto builtinID = FD->getBuiltinID()) {
- return CGCallee::forBuiltin(builtinID, FD);
+ // Replaceable builtin provide their own implementation of a builtin. Unless
+ // we are in the builtin implementation itself, don't call the actual
+ // builtin. If we are in the builtin implementation, avoid trivial infinite
+ // recursion.
+ if (!FD->isInlineBuiltinDeclaration() ||
+ CGF.CurFn->getName() == FD->getName())
+ return CGCallee::forBuiltin(builtinID, FD);
}
llvm::Constant *calleePtr = EmitFunctionDeclPointer(CGF.CGM, FD);
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 038078bbe88d..57beda26677c 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1840,6 +1840,11 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
else if (const auto *SA = FD->getAttr<SectionAttr>())
F->setSection(SA->getName());
+ if (FD->isInlineBuiltinDeclaration()) {
+ F->addAttribute(llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoBuiltin);
+ }
+
if (FD->isReplaceableGlobalAllocationFunction()) {
// A replaceable global allocation function does not act like a builtin by
// default, only if it is invoked by a new-expression or delete-expression.
diff --git a/clang/test/CodeGen/memcpy-nobuiltin.c b/clang/test/CodeGen/memcpy-nobuiltin.c
new file mode 100644
index 000000000000..fb51d87413a1
--- /dev/null
+++ b/clang/test/CodeGen/memcpy-nobuiltin.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -verify -S -emit-llvm -o- %s -isystem %S -DWITH_DECL | FileCheck --check-prefix=CHECK-WITH-DECL %s
+// RUN: %clang_cc1 -verify -S -emit-llvm -o- %s -isystem %S -UWITH_DECL | FileCheck --check-prefix=CHECK-NO-DECL %s
+// RUN: %clang_cc1 -verify -S -emit-llvm -o- %s -isystem %S -DWITH_SELF_REFERENCE_DECL | FileCheck --check-prefix=CHECK-SELF-REF-DECL %s
+//
+// CHECK-WITH-DECL-NOT: @llvm.memcpy
+// CHECK-NO-DECL: @llvm.memcpy
+// CHECK-SELF-REF-DECL: @llvm.memcpy
+//
+#include <memcpy-nobuiltin.inc>
+void test(void *dest, void const *from, size_t n) {
+ memcpy(dest, from, n);
+
+ static char buffer[1];
+ memcpy(buffer, from, 2); // expected-warning {{'memcpy' will always overflow; destination buffer has size 1, but size argument is 2}}
+}
diff --git a/clang/test/CodeGen/memcpy-nobuiltin.inc b/clang/test/CodeGen/memcpy-nobuiltin.inc
new file mode 100644
index 000000000000..25eab0a9ffd0
--- /dev/null
+++ b/clang/test/CodeGen/memcpy-nobuiltin.inc
@@ -0,0 +1,19 @@
+#include <stddef.h>
+extern void *memcpy(void *dest, void const *from, size_t n);
+
+#ifdef WITH_DECL
+inline void *memcpy(void *dest, void const *from, size_t n) {
+ char const *ifrom = from;
+ char *idest = dest;
+ while (n--)
+ *idest++ = *ifrom++;
+ return dest;
+}
+#endif
+#ifdef WITH_SELF_REFERENCE_DECL
+inline void *memcpy(void *dest, void const *from, size_t n) {
+ if (n != 0)
+ memcpy(dest, from, n);
+ return dest;
+}
+#endif
More information about the llvm-branch-commits
mailing list