1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
  
     | 
    
      // RUN: %clang_cc1 -x c++ -std=c++11 -triple x86_64-unknown-linux -emit-llvm -O2 < %s | FileCheck %s
#pragma clang optimize off
// This is a macro definition and therefore its text is not present after
// preprocessing. The pragma has no effect here.
#define CREATE_FUNC(name)        \
int name (int param) {           \
    return param;                \
}                                \
// This is a declaration and therefore it is not decorated with `optnone`.
extern int foo(int a, int b);
// CHECK-DAG: @_Z3fooii{{.*}} [[ATTRFOO:#[0-9]+]]
// This is a definition and therefore it will be decorated with `optnone`.
int bar(int x, int y) {
    for(int i = 0; i < x; ++i)
        y += x;
    return y + foo(x, y);
}
// CHECK-DAG: @_Z3barii{{.*}} [[ATTRBAR:#[0-9]+]]
// The function "int created (int param)" created by the macro invocation
// is also decorated with the `optnone` attribute because it is within a
// region of code affected by the functionality (not because of the position
// of the macro definition).
CREATE_FUNC (created)
// CHECK-DAG: @_Z7createdi{{.*}} [[ATTRCREATED:#[0-9]+]]
class MyClass {
    public:
        // The declaration of the method is not decorated with `optnone`.
        int method(int blah);
};
// The definition of the method instead is decorated with `optnone`.
int MyClass::method(int blah) {
    return blah + 1;
}
// CHECK-DAG: @_ZN7MyClass6methodEi{{.*}} [[ATTRMETHOD:#[0-9]+]]
// A template declaration will not be decorated with `optnone`.
template <typename T> T twice (T param);
// The template definition will be decorated with the attribute `optnone`.
template <typename T> T thrice (T param) {
    return 3 * param;
}
// This function definition will not be decorated with `optnone` because the
// attribute would conflict with `always_inline`.
int __attribute__((always_inline)) baz(int z) {
    return foo(z, 2);
}
// CHECK-DAG: @_Z3bazi{{.*}} [[ATTRBAZ:#[0-9]+]]
#pragma clang optimize on
// The function "int wombat(int param)" created by the macro is not
// decorated with `optnone`, because the pragma applies its effects only
// after preprocessing. The position of the macro definition is not
// relevant.
CREATE_FUNC (wombat)
// CHECK-DAG: @_Z6wombati{{.*}} [[ATTRWOMBAT:#[0-9]+]]
// This instantiation of the "twice" template function with a "float" type
// will not have an `optnone` attribute because the template declaration was
// not affected by the pragma.
float container (float par) {
    return twice(par);
}
// CHECK-DAG: @_Z9containerf{{.*}} [[ATTRCONTAINER:#[0-9]+]]
// CHECK-DAG: @_Z5twiceIfET_S0_{{.*}} [[ATTRTWICE:#[0-9]+]]
// This instantiation of the "thrice" template function with a "float" type
// will have an `optnone` attribute because the template definition was
// affected by the pragma.
float container2 (float par) {
    return thrice(par);
}
// CHECK-DAG: @_Z10container2f{{.*}} [[ATTRCONTAINER2:#[0-9]+]]
// CHECK-DAG: @_Z6thriceIfET_S0_{{.*}} [[ATTRTHRICEFLOAT:#[0-9]+]]
// A template specialization is a new definition and it will not be
// decorated with an `optnone` attribute because it is now outside of the
// affected region.
template<> int thrice(int par) {
    return (par << 1) + par;
}
int container3 (int par) {
    return thrice(par);
}
// CHECK-DAG: @_Z10container3i{{.*}} [[ATTRCONTAINER3:#[0-9]+]]
// CHECK-DAG: @_Z6thriceIiET_S0_{{.*}} [[ATTRTHRICEINT:#[0-9]+]]
// Check for both noinline and optnone on each function that should have them.
// CHECK-DAG: attributes [[ATTRBAR]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
// CHECK-DAG: attributes [[ATTRCREATED]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
// CHECK-DAG: attributes [[ATTRMETHOD]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
// CHECK-DAG: attributes [[ATTRTHRICEFLOAT]] = { {{.*}}noinline{{.*}}optnone{{.*}} }
// Check that the other functions do NOT have optnone.
// CHECK-DAG-NOT: attributes [[ATTRFOO]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRBAZ]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRWOMBAT]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRCONTAINER]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRTWICE]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRCONTAINER2]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRCONTAINER3]] = { {{.*}}optnone{{.*}} }
// CHECK-DAG-NOT: attributes [[ATTRTHRICEINT]] = { {{.*}}optnone{{.*}} }
 
     |