Skip to content

Commit 0fbe860

Browse files
serge-sans-pailletstellar
authored andcommitted
[Clang][Fortify] drop inline decls when redeclared
When an inline builtin declaration is shadowed by an actual declaration, we must reference the actual declaration, even if it's not the last, following GCC behavior. This fixes #54715 Differential Revision: https://reviews.llvm.org/D123308 (cherry picked from commit 301e0d9)
1 parent 571c7d8 commit 0fbe860

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4895,15 +4895,25 @@ RValue CodeGenFunction::EmitSimpleCallExpr(const CallExpr *E,
48954895
return EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue);
48964896
}
48974897

4898+
// Detect the unusual situation where an inline version is shadowed by a
4899+
// non-inline version. In that case we should pick the external one
4900+
// everywhere. That's GCC behavior too.
4901+
static bool OnlyHasInlineBuiltinDeclaration(const FunctionDecl *FD) {
4902+
for (const FunctionDecl *PD = FD; PD; PD = PD->getPreviousDecl())
4903+
if (!PD->isInlineBuiltinDeclaration())
4904+
return false;
4905+
return true;
4906+
}
4907+
48984908
static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) {
48994909
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
49004910

49014911
if (auto builtinID = FD->getBuiltinID()) {
49024912
std::string FDInlineName = (FD->getName() + ".inline").str();
49034913
// When directing calling an inline builtin, call it through it's mangled
49044914
// name to make it clear it's not the actual builtin.
4905-
if (FD->isInlineBuiltinDeclaration() &&
4906-
CGF.CurFn->getName() != FDInlineName) {
4915+
if (CGF.CurFn->getName() != FDInlineName &&
4916+
OnlyHasInlineBuiltinDeclaration(FD)) {
49074917
llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD);
49084918
llvm::Function *Fn = llvm::cast<llvm::Function>(CalleePtr);
49094919
llvm::Module *M = Fn->getParent();
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 -triple x86_64 -S -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
2+
//
3+
// Verifies that clang-generated *.inline are removed when shadowed by an
4+
// external definition, even when that definition appears at the end of the
5+
// file.
6+
7+
// CHECK-NOT: strlen.inline
8+
9+
extern unsigned long strlen(char const *s);
10+
11+
extern __inline __attribute__((__always_inline__)) __attribute__((__gnu_inline__)) unsigned long strlen(char const *s) {
12+
return 1;
13+
}
14+
15+
static unsigned long chesterfield(char const *s) {
16+
return strlen(s);
17+
}
18+
static unsigned long (*_strlen)(char const *ptr);
19+
20+
unsigned long blutch(char const *s) {
21+
return chesterfield(s);
22+
}
23+
24+
unsigned long strlen(char const *s) {
25+
return _strlen(s);
26+
}

0 commit comments

Comments
 (0)