Skip to content

Commit d437fba

Browse files
author
serge-sans-paille
committed
Reapply Allow system header to provide their own implementation of some builtin
This reverts commit 3d210ed. See https://reviews.llvm.org/D71082 for the patch and discussion that make it possible to reapply this patch.
1 parent 6b84083 commit d437fba

File tree

6 files changed

+58
-1
lines changed

6 files changed

+58
-1
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2309,6 +2309,9 @@ class FunctionDecl : public DeclaratorDecl,
23092309
/// true through IsAligned.
23102310
bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;
23112311

2312+
/// Determine if this function provides an inline implementation of a builtin.
2313+
bool isInlineBuiltinDeclaration() const;
2314+
23122315
/// Determine whether this is a destroying operator delete.
23132316
bool isDestroyingOperatorDelete() const;
23142317

clang/lib/AST/Decl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3046,6 +3046,14 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction(bool *IsAligned) const
30463046
return Params == FPT->getNumParams();
30473047
}
30483048

3049+
bool FunctionDecl::isInlineBuiltinDeclaration() const {
3050+
if (!getBuiltinID())
3051+
return false;
3052+
3053+
const FunctionDecl *Definition;
3054+
return hasBody(Definition) && Definition->isInlineSpecified();
3055+
}
3056+
30493057
bool FunctionDecl::isDestroyingOperatorDelete() const {
30503058
// C++ P0722:
30513059
// Within a class C, a single object deallocation function with signature

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4621,8 +4621,15 @@ RValue CodeGenFunction::EmitSimpleCallExpr(const CallExpr *E,
46214621
}
46224622

46234623
static CGCallee EmitDirectCallee(CodeGenFunction &CGF, const FunctionDecl *FD) {
4624+
46244625
if (auto builtinID = FD->getBuiltinID()) {
4625-
return CGCallee::forBuiltin(builtinID, FD);
4626+
// Replaceable builtin provide their own implementation of a builtin. Unless
4627+
// we are in the builtin implementation itself, don't call the actual
4628+
// builtin. If we are in the builtin implementation, avoid trivial infinite
4629+
// recursion.
4630+
if (!FD->isInlineBuiltinDeclaration() ||
4631+
CGF.CurFn->getName() == FD->getName())
4632+
return CGCallee::forBuiltin(builtinID, FD);
46264633
}
46274634

46284635
llvm::Constant *calleePtr = EmitFunctionDeclPointer(CGF.CGM, FD);

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,6 +1840,11 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
18401840
else if (const auto *SA = FD->getAttr<SectionAttr>())
18411841
F->setSection(SA->getName());
18421842

1843+
if (FD->isInlineBuiltinDeclaration()) {
1844+
F->addAttribute(llvm::AttributeList::FunctionIndex,
1845+
llvm::Attribute::NoBuiltin);
1846+
}
1847+
18431848
if (FD->isReplaceableGlobalAllocationFunction()) {
18441849
// A replaceable global allocation function does not act like a builtin by
18451850
// default, only if it is invoked by a new-expression or delete-expression.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang_cc1 -verify -S -emit-llvm -o- %s -isystem %S -DWITH_DECL | FileCheck --check-prefix=CHECK-WITH-DECL %s
2+
// RUN: %clang_cc1 -verify -S -emit-llvm -o- %s -isystem %S -UWITH_DECL | FileCheck --check-prefix=CHECK-NO-DECL %s
3+
// RUN: %clang_cc1 -verify -S -emit-llvm -o- %s -isystem %S -DWITH_SELF_REFERENCE_DECL | FileCheck --check-prefix=CHECK-SELF-REF-DECL %s
4+
//
5+
// CHECK-WITH-DECL-NOT: @llvm.memcpy
6+
// CHECK-NO-DECL: @llvm.memcpy
7+
// CHECK-SELF-REF-DECL: @llvm.memcpy
8+
//
9+
#include <memcpy-nobuiltin.inc>
10+
void test(void *dest, void const *from, size_t n) {
11+
memcpy(dest, from, n);
12+
13+
static char buffer[1];
14+
memcpy(buffer, from, 2); // expected-warning {{'memcpy' will always overflow; destination buffer has size 1, but size argument is 2}}
15+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <stddef.h>
2+
extern void *memcpy(void *dest, void const *from, size_t n);
3+
4+
#ifdef WITH_DECL
5+
inline void *memcpy(void *dest, void const *from, size_t n) {
6+
char const *ifrom = from;
7+
char *idest = dest;
8+
while (n--)
9+
*idest++ = *ifrom++;
10+
return dest;
11+
}
12+
#endif
13+
#ifdef WITH_SELF_REFERENCE_DECL
14+
inline void *memcpy(void *dest, void const *from, size_t n) {
15+
if (n != 0)
16+
memcpy(dest, from, n);
17+
return dest;
18+
}
19+
#endif

0 commit comments

Comments
 (0)