!CodeGenOpts.DisableO0ImplyOptNone && CodeGenOpts.OptimizationLevel == 0;
// We can't add optnone in the following cases, it won't pass the verifier.
ShouldAddOptNone &= !D->hasAttr<MinSizeAttr>();
- ShouldAddOptNone &= !F->hasFnAttribute(llvm::Attribute::AlwaysInline);
ShouldAddOptNone &= !D->hasAttr<AlwaysInlineAttr>();
- if (ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) {
+ // Add optnone, but do so only if the function isn't always_inline.
+ if ((ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) &&
+ !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
B.addAttribute(llvm::Attribute::OptimizeNone);
// OptimizeNone implies noinline; we should not be inlining such functions.
B.addAttribute(llvm::Attribute::NoInline);
- assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
- "OptimizeNone and AlwaysInline on same function!");
// We still need to handle naked functions even though optnone subsumes
// much of their semantics.
B.addAttribute(llvm::Attribute::NoInline);
} else if (D->hasAttr<NoDuplicateAttr>()) {
B.addAttribute(llvm::Attribute::NoDuplicate);
- } else if (D->hasAttr<NoInlineAttr>()) {
+ } else if (D->hasAttr<NoInlineAttr>() && !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
+ // Add noinline if the function isn't always_inline.
B.addAttribute(llvm::Attribute::NoInline);
} else if (D->hasAttr<AlwaysInlineAttr>() &&
!F->hasFnAttribute(llvm::Attribute::NoInline)) {
// CHECK: @llvm.global_ctors = appending global {{.*}} { i32 65535, void ()* [[CTOR0:@.*]], i8* null }
// CHECK: @llvm.global_dtors = appending global {{.*}} { i32 65535, void ()* [[DTOR0:@.*]], i8* null }
+// Check that the base destructor is marked as always_inline when generating
+// code for kext.
+
+namespace testBaseDestructor {
+#pragma clang optimize off
+struct D {
+ virtual ~D();
+};
+
+D::~D() {}
+#pragma clang optimize on
+}
+
+// CHECK: define void @_ZN18testBaseDestructor1DD2Ev({{.*}}) unnamed_addr #[[ATTR0:.*]] align 2 {
+
+// CHECK: define void @_ZN18testBaseDestructor1DD1Ev({{.*}}) unnamed_addr #[[ATTR1:.*]] align 2 {
+
+// CHECK: define void @_ZN18testBaseDestructor1DD0Ev({{.*}}) unnamed_addr #[[ATTR1]] align 2 {
+
// rdar://11241230
namespace test0 {
struct A { A(); ~A(); };
// CHECK: define internal void [[DTOR0]]()
// CHECK: call void @_ZN5test01AD1Ev([[A]]* @_ZN5test01aE)
// CHECK-NEXT: ret void
+
+// CHECK: attributes #[[ATTR0]] = { alwaysinline nounwind {{.*}} }
+// CHECK: attributes #[[ATTR1]] = { noinline nounwind {{.*}} }