Home | History | Annotate | Download | only in CodeGenCXX
      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))
     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 
     38 void 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.
     50 int 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))
     61 int A::static_forceinline_method(int a) {
     62   return a + a + a + a;
     63 }
     64 // CHECK: @_ZN1A25static_forceinline_methodEi({{.*}}) [[OPTNONE]]
     65 
     66 __attribute__((optnone))
     67 int 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))
     74 int 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))
     81 int 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 
    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 
    116 struct 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 
    140 int 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