From e20931b2ccd10de2fd25d9a6fbe9c166e7430f23 Mon Sep 17 00:00:00 2001 From: serge-sans-paille Date: Wed, 19 Apr 2023 16:15:17 +0200 Subject: [PATCH] [clang] Restrict Inline Builtin to non-static, non-odr linkage Inline builtins have a very special behavior compared to other functions, it's better if we keep them restricted to a minimal set of functions. Add a linkage check which prevents considering ODR definitions as inline builtins. Fix #62958 Differential Revision: https://reviews.llvm.org/D148723 --- clang/lib/AST/Decl.cpp | 19 +++++++++++++++++-- clang/test/CodeGen/inline-builtin-comdat.c | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGen/inline-builtin-comdat.c diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 5317b9d..e441c33 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3314,8 +3314,23 @@ bool FunctionDecl::isInlineBuiltinDeclaration() const { return false; const FunctionDecl *Definition; - return hasBody(Definition) && Definition->isInlineSpecified() && - Definition->hasAttr(); + if (!hasBody(Definition)) + return false; + + if (!Definition->isInlineSpecified() || + !Definition->hasAttr()) + return false; + + ASTContext &Context = getASTContext(); + switch (Context.GetGVALinkageForFunction(this)) { + case GVA_Internal: + case GVA_DiscardableODR: + case GVA_StrongODR: + return false; + case GVA_AvailableExternally: + case GVA_StrongExternal: + return true; + } } bool FunctionDecl::isDestroyingOperatorDelete() const { diff --git a/clang/test/CodeGen/inline-builtin-comdat.c b/clang/test/CodeGen/inline-builtin-comdat.c new file mode 100644 index 0000000..1b00711 --- /dev/null +++ b/clang/test/CodeGen/inline-builtin-comdat.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-windows -S -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s +// Inline builtin are not supported for odr linkage +// CHECK-NOT: .inline + +double __cdecl frexp( double _X, int* _Y); +inline __attribute__((always_inline)) long double __cdecl frexpl( long double __x, int *__exp ) { + return (long double) frexp((double)__x, __exp ); +} + +long double pain(void) +{ + long double f = 123.45; + int i; + long double f2 = frexpl(f, &i); + return f2; +} -- 2.7.4