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 10 struct A { 11 // Definition of an optnone static method. 12 __attribute__((optnone)) static_optnone_methodA13 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)) optnone_methodA20 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 foo()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. optnone_decl_method(int a)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)) static_forceinline_method(int a)61int A::static_forceinline_method(int a) { 62 return a + a + a + a; 63 } 64 // CHECK: @_ZN1A25static_forceinline_methodEi({{.*}}) [[OPTNONE]] 65 66 __attribute__((optnone)) alwaysinline_method(int a)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)) noinline_method(int a)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)) minsize_method(int a)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 96 struct B { 97 virtual int pure_virtual(int a) = 0; 98 __attribute__((optnone)) 99 virtual int pure_virtual_with_optnone(int a) = 0; 100 baseB101 virtual int base(int a) { 102 return a + a + a + a; 103 } 104 105 __attribute__((optnone)) optnone_baseB106 virtual int optnone_base(int a) { 107 return a + a + a + a; 108 } 109 110 __attribute__((optnone)) only_base_virtualB111 virtual int only_base_virtual(int a) { 112 return a + a; 113 } 114 }; 115 116 struct C : public B { 117 __attribute__((optnone)) pure_virtualC118 virtual int pure_virtual(int a) { 119 return a + a + a + a; 120 } 121 pure_virtual_with_optnoneC122 virtual int pure_virtual_with_optnone(int a) { 123 return a + a + a + a; 124 } 125 126 __attribute__((optnone)) baseC127 virtual int base(int a) { 128 return a + a; 129 } 130 optnone_baseC131 virtual int optnone_base(int a) { 132 return a + a; 133 } 134 only_base_virtualC135 int only_base_virtual(int a) { 136 return a + a + a + a; 137 } 138 }; 139 bar()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