| 1 | // RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -disable-O0-optnone -emit-llvm -o - | FileCheck %s |
| 2 | |
| 3 | // Test optnone on template instantiations. |
| 4 | |
| 5 | //-- Effect of optnone on generic add template function. |
| 6 | |
| 7 | template <typename T> T template_normal(T a) |
| 8 | { |
| 9 | return a + a; |
| 10 | } |
| 11 | |
| 12 | template <typename T> __attribute__((optnone)) T template_optnone(T a) |
| 13 | { |
| 14 | return a + a + a; |
| 15 | } |
| 16 | |
| 17 | // This function should cause instantiations of each template, one marked |
| 18 | // with the 'optnone' attribute. |
| 19 | int container(int i) |
| 20 | { |
| 21 | return template_normal<int>(i) + template_optnone<int>(i); |
| 22 | } |
| 23 | |
| 24 | // CHECK: @_Z15template_normalIiET_S0_({{.*}}) [[NORMAL:#[0-9]+]] |
| 25 | // CHECK: @_Z16template_optnoneIiET_S0_({{.*}}) [[OPTNONE:#[0-9]+]] |
| 26 | |
| 27 | |
| 28 | //-- Effect of optnone on a partial specialization. |
| 29 | // FIRST TEST: a method becomes marked with optnone in the specialization. |
| 30 | |
| 31 | template <typename T, typename U> class template_normal_base { |
| 32 | public: |
| 33 | T method(T t, U u) |
| 34 | { |
| 35 | return t + static_cast<T>(u); |
| 36 | } |
| 37 | }; |
| 38 | |
| 39 | template <typename U> class template_normal_base<int, U> |
| 40 | { |
| 41 | public: |
| 42 | __attribute__((optnone)) int method (int t, U u) |
| 43 | { |
| 44 | return t - static_cast<int>(u); |
| 45 | } |
| 46 | }; |
| 47 | |
| 48 | // This function should cause an instantiation of the full template (whose |
| 49 | // method is not marked optnone) and an instantiation of the partially |
| 50 | // specialized template (whose method is marked optnone). |
| 51 | void container2() |
| 52 | { |
| 53 | int y = 2; |
| 54 | float z = 3.0; |
| 55 | template_normal_base<float, int> class_normal; |
| 56 | template_normal_base<int, float> class_optnone; |
| 57 | float r1 = class_normal.method(z, y); |
| 58 | float r2 = class_optnone.method(y, z); |
| 59 | } |
| 60 | |
| 61 | // CHECK: @_ZN20template_normal_baseIfiE6methodEfi({{.*}}) [[NORMAL]] |
| 62 | // CHECK: @_ZN20template_normal_baseIifE6methodEif({{.*}}) [[OPTNONE]] |
| 63 | |
| 64 | |
| 65 | //-- Effect of optnone on a partial specialization. |
| 66 | // SECOND TEST: a method loses optnone in the specialization. |
| 67 | |
| 68 | template <typename T, typename U> class template_optnone_base { |
| 69 | public: |
| 70 | __attribute__((optnone)) T method(T t, U u) |
| 71 | { |
| 72 | return t + static_cast<T>(u); |
| 73 | } |
| 74 | }; |
| 75 | |
| 76 | template <typename U> class template_optnone_base<int, U> |
| 77 | { |
| 78 | public: |
| 79 | int method (int t, U u) |
| 80 | { |
| 81 | return t - static_cast<int>(u); |
| 82 | } |
| 83 | }; |
| 84 | |
| 85 | // This function should cause an instantiation of the full template (whose |
| 86 | // method is marked optnone) and an instantiation of the partially |
| 87 | // specialized template (whose method is not marked optnone). |
| 88 | void container3() |
| 89 | { |
| 90 | int y = 2; |
| 91 | float z = 3.0; |
| 92 | template_optnone_base<float, int> class_optnone; |
| 93 | template_optnone_base<int, float> class_normal; |
| 94 | float r1 = class_optnone.method(z, y); |
| 95 | float r2 = class_normal.method(y, z); |
| 96 | } |
| 97 | |
| 98 | // CHECK: @_ZN21template_optnone_baseIfiE6methodEfi({{.*}}) [[OPTNONE]] |
| 99 | // CHECK: @_ZN21template_optnone_baseIifE6methodEif({{.*}}) [[NORMAL]] |
| 100 | |
| 101 | |
| 102 | // CHECK: attributes [[NORMAL]] = |
| 103 | // CHECK-NOT: optnone |
| 104 | // CHECK: attributes [[OPTNONE]] = {{.*}} optnone |
| 105 | |