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