1// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -x c++ | FileCheck %s 2 3// Test attribute 'optnone' on methods: 4// -- member functions; 5// -- static member functions. 6 7// Verify that all methods of struct A are associated to the same attribute set. 8// The attribute set shall contain attributes 'noinline' and 'optnone'. 9 10struct A { 11 // Definition of an optnone static method. 12 __attribute__((optnone)) 13 static int static_optnone_method(int a) { 14 return a + a; 15 } 16 // CHECK: @_ZN1A21static_optnone_methodEi({{.*}}) [[OPTNONE:#[0-9]+]] 17 18 // Definition of an optnone normal method. 19 __attribute__((optnone)) 20 int optnone_method(int a) { 21 return a + a + a + a; 22 } 23 // CHECK: @_ZN1A14optnone_methodEi({{.*}}) [[OPTNONE]] 24 25 // Declaration of an optnone method with out-of-line definition 26 // that doesn't say optnone. 27 __attribute__((optnone)) 28 int optnone_decl_method(int a); 29 30 // Methods declared without attribute optnone; the definitions will 31 // have attribute optnone, and we verify optnone wins. 32 __forceinline static int static_forceinline_method(int a); 33 __attribute__((always_inline)) int alwaysinline_method(int a); 34 __attribute__((noinline)) int noinline_method(int a); 35 __attribute__((minsize)) int minsize_method(int a); 36}; 37 38void foo() { 39 A a; 40 A::static_optnone_method(4); 41 a.optnone_method(14); 42 a.optnone_decl_method(12); 43 A::static_forceinline_method(5); 44 a.alwaysinline_method(5); 45 a.noinline_method(6); 46 a.minsize_method(7); 47} 48 49// No attribute here, should still be on the definition. 50int A::optnone_decl_method(int a) { 51 return a; 52} 53// CHECK: @_ZN1A19optnone_decl_methodEi({{.*}}) [[OPTNONE]] 54 55// optnone implies noinline; therefore attribute noinline is added to 56// the set of function attributes. 57// forceinline is instead translated as 'always_inline'. 58// However 'noinline' wins over 'always_inline' and therefore 59// the resulting attributes for this method are: noinline + optnone 60__attribute__((optnone)) 61int A::static_forceinline_method(int a) { 62 return a + a + a + a; 63} 64// CHECK: @_ZN1A25static_forceinline_methodEi({{.*}}) [[OPTNONE]] 65 66__attribute__((optnone)) 67int A::alwaysinline_method(int a) { 68 return a + a + a + a; 69} 70// CHECK: @_ZN1A19alwaysinline_methodEi({{.*}}) [[OPTNONE]] 71 72// 'noinline' + 'noinline and optnone' = 'noinline and optnone' 73__attribute__((optnone)) 74int A::noinline_method(int a) { 75 return a + a + a + a; 76} 77// CHECK: @_ZN1A15noinline_methodEi({{.*}}) [[OPTNONE]] 78 79// 'optnone' wins over 'minsize' 80__attribute__((optnone)) 81int A::minsize_method(int a) { 82 return a + a + a + a; 83} 84// CHECK: @_ZN1A14minsize_methodEi({{.*}}) [[OPTNONE]] 85 86 87// Test attribute 'optnone' on methods: 88// -- pure virtual functions 89// -- base virtual and derived virtual 90// -- base virtual but not derived virtual 91// -- optnone methods redefined in override 92 93// A method defined in override doesn't inherit the function attributes of the 94// superclass method. 95 96struct B { 97 virtual int pure_virtual(int a) = 0; 98 __attribute__((optnone)) 99 virtual int pure_virtual_with_optnone(int a) = 0; 100 101 virtual int base(int a) { 102 return a + a + a + a; 103 } 104 105 __attribute__((optnone)) 106 virtual int optnone_base(int a) { 107 return a + a + a + a; 108 } 109 110 __attribute__((optnone)) 111 virtual int only_base_virtual(int a) { 112 return a + a; 113 } 114}; 115 116struct C : public B { 117 __attribute__((optnone)) 118 virtual int pure_virtual(int a) { 119 return a + a + a + a; 120 } 121 122 virtual int pure_virtual_with_optnone(int a) { 123 return a + a + a + a; 124 } 125 126 __attribute__((optnone)) 127 virtual int base(int a) { 128 return a + a; 129 } 130 131 virtual int optnone_base(int a) { 132 return a + a; 133 } 134 135 int only_base_virtual(int a) { 136 return a + a + a + a; 137 } 138}; 139 140int bar() { 141 C c; 142 int result; 143 result = c.pure_virtual(3); 144 result += c.pure_virtual_with_optnone(2); 145 result += c.base(5); 146 result += c.optnone_base(7); 147 result += c.only_base_virtual(9); 148 return result; 149} 150 151// CHECK: @_ZN1C12pure_virtualEi({{.*}}) {{.*}} [[OPTNONE]] 152// CHECK: @_ZN1C25pure_virtual_with_optnoneEi({{.*}}) {{.*}} [[NORMAL:#[0-9]+]] 153// CHECK: @_ZN1C4baseEi({{.*}}) {{.*}} [[OPTNONE]] 154// CHECK: @_ZN1C12optnone_baseEi({{.*}}) {{.*}} [[NORMAL]] 155// CHECK: @_ZN1C17only_base_virtualEi({{.*}}) {{.*}} [[NORMAL]] 156// CHECK: @_ZN1B4baseEi({{.*}}) {{.*}} [[NORMAL]] 157// CHECK: @_ZN1B12optnone_baseEi({{.*}}) {{.*}} [[OPTNONE]] 158// CHECK: @_ZN1B17only_base_virtualEi({{.*}}) {{.*}} [[OPTNONE]] 159 160 161// CHECK: attributes [[NORMAL]] = 162// CHECK-NOT: noinline 163// CHECK-NOT: optnone 164// CHECK: attributes [[OPTNONE]] = {{.*}} noinline {{.*}} optnone 165