Skip to content

Commit 4516dc1

Browse files
committed
Don't add optnone or noinline if the function is already marked as
always_inline. The assertion in SetLLVMFunctionAttributesForDefinition used to fail when there was attribute OptimizeNone on the AST function and attribute always_inline on the IR function. This happens because base destructors are annotated with always_inline when the code is compiled with -fapple-kext (see r124757). rdar://problem/57169694
1 parent a578adc commit 4516dc1

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -1515,16 +1515,15 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
15151515
!CodeGenOpts.DisableO0ImplyOptNone && CodeGenOpts.OptimizationLevel == 0;
15161516
// We can't add optnone in the following cases, it won't pass the verifier.
15171517
ShouldAddOptNone &= !D->hasAttr<MinSizeAttr>();
1518-
ShouldAddOptNone &= !F->hasFnAttribute(llvm::Attribute::AlwaysInline);
15191518
ShouldAddOptNone &= !D->hasAttr<AlwaysInlineAttr>();
15201519

1521-
if (ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) {
1520+
// Add optnone, but do so only if the function isn't always_inline.
1521+
if ((ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) &&
1522+
!F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
15221523
B.addAttribute(llvm::Attribute::OptimizeNone);
15231524

15241525
// OptimizeNone implies noinline; we should not be inlining such functions.
15251526
B.addAttribute(llvm::Attribute::NoInline);
1526-
assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
1527-
"OptimizeNone and AlwaysInline on same function!");
15281527

15291528
// We still need to handle naked functions even though optnone subsumes
15301529
// much of their semantics.
@@ -1540,7 +1539,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
15401539
B.addAttribute(llvm::Attribute::NoInline);
15411540
} else if (D->hasAttr<NoDuplicateAttr>()) {
15421541
B.addAttribute(llvm::Attribute::NoDuplicate);
1543-
} else if (D->hasAttr<NoInlineAttr>()) {
1542+
} else if (D->hasAttr<NoInlineAttr>() && !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
1543+
// Add noinline if the function isn't always_inline.
15441544
B.addAttribute(llvm::Attribute::NoInline);
15451545
} else if (D->hasAttr<AlwaysInlineAttr>() &&
15461546
!F->hasFnAttribute(llvm::Attribute::NoInline)) {

clang/test/CodeGenCXX/apple-kext.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@
44
// CHECK: @llvm.global_ctors = appending global {{.*}} { i32 65535, void ()* [[CTOR0:@.*]], i8* null }
55
// CHECK: @llvm.global_dtors = appending global {{.*}} { i32 65535, void ()* [[DTOR0:@.*]], i8* null }
66

7+
// Check that the base destructor is marked as always_inline when generating
8+
// code for kext.
9+
10+
namespace testBaseDestructor {
11+
#pragma clang optimize off
12+
struct D {
13+
virtual ~D();
14+
};
15+
16+
D::~D() {}
17+
#pragma clang optimize on
18+
}
19+
20+
// CHECK: define void @_ZN18testBaseDestructor1DD2Ev({{.*}}) unnamed_addr #[[ATTR0:.*]] align 2 {
21+
22+
// CHECK: define void @_ZN18testBaseDestructor1DD1Ev({{.*}}) unnamed_addr #[[ATTR1:.*]] align 2 {
23+
24+
// CHECK: define void @_ZN18testBaseDestructor1DD0Ev({{.*}}) unnamed_addr #[[ATTR1]] align 2 {
25+
726
// rdar://11241230
827
namespace test0 {
928
struct A { A(); ~A(); };
@@ -20,3 +39,6 @@ namespace test0 {
2039
// CHECK: define internal void [[DTOR0]]()
2140
// CHECK: call void @_ZN5test01AD1Ev([[A]]* @_ZN5test01aE)
2241
// CHECK-NEXT: ret void
42+
43+
// CHECK: attributes #[[ATTR0]] = { alwaysinline nounwind {{.*}} }
44+
// CHECK: attributes #[[ATTR1]] = { noinline nounwind {{.*}} }

0 commit comments

Comments
 (0)