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