Index: cfe/trunk/test/CodeGenCXX/optnone-and-attributes.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/optnone-and-attributes.cpp +++ cfe/trunk/test/CodeGenCXX/optnone-and-attributes.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 < %s -triple i386-mingw32 -fms-extensions -emit-llvm -x c++ | FileCheck %s + +// optnone wins over inlinehint. +// Test that both func1 and func2 are marked optnone and noinline. + +// Definition with both optnone and inlinehint. +__attribute__((optnone)) +inline int func1(int a) { + return a + a + a + a; +} +// CHECK: @_Z5func1i({{.*}}) [[OPTNONE:#[0-9]+]] + +// optnone declaration, inlinehint definition. +__attribute__((optnone)) +int func2(int a); + +inline int func2(int a) { + return a + a + a + a; +} +// CHECK: @_Z5func2i({{.*}}) [[OPTNONE]] + +// Keep alive the definitions of func1 and func2. +int foo() { + int val = func1(1); + return val + func2(2); +} + +// optnone wins over minsize. +__attribute__((optnone)) +int func3(int a); + +__attribute__((minsize)) +int func3(int a) { + return a + a + a + a; +} +// Same attribute set as everything else, therefore no 'minsize'. +// CHECK: @_Z5func3i({{.*}}) [[OPTNONE]] + + +// Verify that noreturn is compatible with optnone. +__attribute__((noreturn)) +extern void exit_from_function(); + +__attribute__((noreturn)) __attribute((optnone)) +extern void noreturn_function(int a) { exit_from_function(); } +// CHECK: @_Z17noreturn_functioni({{.*}}) [[NORETURN:#[0-9]+]] + + +// Verify that __declspec(noinline) is compatible with optnone. +__declspec(noinline) __attribute__((optnone)) +void func4() { return; } +// CHECK: @_Z5func4v() [[OPTNONE]] + +__declspec(noinline) +extern void func5(); + +__attribute__((optnone)) +void func5() { return; } +// CHECK: @_Z5func5v() [[OPTNONE]] + + +// Verify also that optnone can be used on dllexport functions. +// Adding attribute optnone on a dllimport function has no effect. + +__attribute__((dllimport)) +__attribute__((optnone)) +int imported_optnone_func(int a); + +__attribute__((dllexport)) +__attribute__((optnone)) +int exported_optnone_func(int a) { + return imported_optnone_func(a); // use of imported func +} +// CHECK: @_Z21exported_optnone_funci({{.*}}) [[OPTNONE]] +// CHECK: declare dllimport {{.*}} @_Z21imported_optnone_funci({{.*}}) [[DLLIMPORT:#[0-9]+]] + + +// CHECK: attributes [[OPTNONE]] = { noinline {{.*}} optnone +// CHECK: attributes [[NORETURN]] = { noinline noreturn {{.*}} optnone + +// CHECK: attributes [[DLLIMPORT]] = +// CHECK-SAME-NOT: optnone Index: cfe/trunk/test/CodeGenCXX/optnone-class-members.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/optnone-class-members.cpp +++ cfe/trunk/test/CodeGenCXX/optnone-class-members.cpp @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -x c++ | FileCheck %s + +// Test attribute 'optnone' on methods: +// -- member functions; +// -- static member functions. + +// Verify that all methods of struct A are associated to the same attribute set. +// The attribute set shall contain attributes 'noinline' and 'optnone'. + +struct A { + // Definition of an optnone static method. + __attribute__((optnone)) + static int static_optnone_method(int a) { + return a + a; + } + // CHECK: @_ZN1A21static_optnone_methodEi({{.*}}) [[OPTNONE:#[0-9]+]] + + // Definition of an optnone normal method. + __attribute__((optnone)) + int optnone_method(int a) { + return a + a + a + a; + } + // CHECK: @_ZN1A14optnone_methodEi({{.*}}) [[OPTNONE]] + + // Declaration of an optnone method with out-of-line definition + // that doesn't say optnone. + __attribute__((optnone)) + int optnone_decl_method(int a); + + // Methods declared without attribute optnone; the definitions will + // have attribute optnone, and we verify optnone wins. + __forceinline static int static_forceinline_method(int a); + __attribute__((always_inline)) int alwaysinline_method(int a); + __attribute__((noinline)) int noinline_method(int a); + __attribute__((minsize)) int minsize_method(int a); +}; + +void foo() { + A a; + A::static_optnone_method(4); + a.optnone_method(14); + a.optnone_decl_method(12); + A::static_forceinline_method(5); + a.alwaysinline_method(5); + a.noinline_method(6); + a.minsize_method(7); +} + +// No attribute here, should still be on the definition. +int A::optnone_decl_method(int a) { + return a; +} +// CHECK: @_ZN1A19optnone_decl_methodEi({{.*}}) [[OPTNONE]] + +// optnone implies noinline; therefore attribute noinline is added to +// the set of function attributes. +// forceinline is instead translated as 'always_inline'. +// However 'noinline' wins over 'always_inline' and therefore +// the resulting attributes for this method are: noinline + optnone +__attribute__((optnone)) +int A::static_forceinline_method(int a) { + return a + a + a + a; +} +// CHECK: @_ZN1A25static_forceinline_methodEi({{.*}}) [[OPTNONE]] + +__attribute__((optnone)) +int A::alwaysinline_method(int a) { + return a + a + a + a; +} +// CHECK: @_ZN1A19alwaysinline_methodEi({{.*}}) [[OPTNONE]] + +// 'noinline' + 'noinline and optnone' = 'noinline and optnone' +__attribute__((optnone)) +int A::noinline_method(int a) { + return a + a + a + a; +} +// CHECK: @_ZN1A15noinline_methodEi({{.*}}) [[OPTNONE]] + +// 'optnone' wins over 'minsize' +__attribute__((optnone)) +int A::minsize_method(int a) { + return a + a + a + a; +} +// CHECK: @_ZN1A14minsize_methodEi({{.*}}) [[OPTNONE]] + + +// Test attribute 'optnone' on methods: +// -- pure virtual functions +// -- base virtual and derived virtual +// -- base virtual but not derived virtual +// -- optnone methods redefined in override + +// A method defined in override doesn't inherit the function attributes of the +// superclass method. + +struct B { + virtual int pure_virtual(int a) = 0; + __attribute__((optnone)) + virtual int pure_virtual_with_optnone(int a) = 0; + + virtual int base(int a) { + return a + a + a + a; + } + + __attribute__((optnone)) + virtual int optnone_base(int a) { + return a + a + a + a; + } + + __attribute__((optnone)) + virtual int only_base_virtual(int a) { + return a + a; + } +}; + +struct C : public B { + __attribute__((optnone)) + virtual int pure_virtual(int a) { + return a + a + a + a; + } + + virtual int pure_virtual_with_optnone(int a) { + return a + a + a + a; + } + + __attribute__((optnone)) + virtual int base(int a) { + return a + a; + } + + virtual int optnone_base(int a) { + return a + a; + } + + int only_base_virtual(int a) { + return a + a + a + a; + } +}; + +int bar() { + C c; + int result; + result = c.pure_virtual(3); + result += c.pure_virtual_with_optnone(2); + result += c.base(5); + result += c.optnone_base(7); + result += c.only_base_virtual(9); + return result; +} + +// CHECK: @_ZN1C12pure_virtualEi({{.*}}) {{.*}} [[OPTNONE]] +// CHECK: @_ZN1C25pure_virtual_with_optnoneEi({{.*}}) {{.*}} [[NORMAL:#[0-9]+]] +// CHECK: @_ZN1C4baseEi({{.*}}) {{.*}} [[OPTNONE]] +// CHECK: @_ZN1C12optnone_baseEi({{.*}}) {{.*}} [[NORMAL]] +// CHECK: @_ZN1C17only_base_virtualEi({{.*}}) {{.*}} [[NORMAL]] +// CHECK: @_ZN1B4baseEi({{.*}}) {{.*}} [[NORMAL]] +// CHECK: @_ZN1B12optnone_baseEi({{.*}}) {{.*}} [[OPTNONE]] +// CHECK: @_ZN1B17only_base_virtualEi({{.*}}) {{.*}} [[OPTNONE]] + + +// CHECK: attributes [[NORMAL]] = +// CHECK-SAME-NOT: noinline +// CHECK-SAME-NOT: optnone +// CHECK: attributes [[OPTNONE]] = {{.*}} noinline {{.*}} optnone Index: cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp +++ cfe/trunk/test/CodeGenCXX/optnone-def-decl.cpp @@ -90,5 +90,6 @@ // CHECK: @_Z28forceinline_optnone_functionii({{.*}}) [[OPTNONE]] // CHECK: attributes [[OPTNONE]] = { noinline nounwind optnone {{.*}} } -// CHECK: attributes [[NORMAL]] = { nounwind {{.*}} } - +// CHECK: attributes [[NORMAL]] = +// CHECK-SAME-NOT: noinline +// CHECK-SAME-NOT: optnone Index: cfe/trunk/test/CodeGenCXX/optnone-templates.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/optnone-templates.cpp +++ cfe/trunk/test/CodeGenCXX/optnone-templates.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - | FileCheck %s + +// Test optnone on template instantiations. + +//-- Effect of optnone on generic add template function. + +template T template_normal(T a) +{ + return a + a; +} + +template __attribute__((optnone)) T template_optnone(T a) +{ + return a + a + a; +} + +// This function should cause instantiations of each template, one marked +// with the 'optnone' attribute. +int container(int i) +{ + return template_normal(i) + template_optnone(i); +} + +// CHECK: @_Z15template_normalIiET_S0_({{.*}}) [[NORMAL:#[0-9]+]] +// CHECK: @_Z16template_optnoneIiET_S0_({{.*}}) [[OPTNONE:#[0-9]+]] + + +//-- Effect of optnone on a partial specialization. +// FIRST TEST: a method becomes marked with optnone in the specialization. + +template class template_normal_base { +public: + T method(T t, U u) + { + return t + static_cast(u); + } +}; + +template class template_normal_base +{ +public: + __attribute__((optnone)) int method (int t, U u) + { + return t - static_cast(u); + } +}; + +// This function should cause an instantiation of the full template (whose +// method is not marked optnone) and an instantiation of the partially +// specialized template (whose method is marked optnone). +void container2() +{ + int y = 2; + float z = 3.0; + template_normal_base class_normal; + template_normal_base class_optnone; + float r1 = class_normal.method(z, y); + float r2 = class_optnone.method(y, z); +} + +// CHECK: @_ZN20template_normal_baseIfiE6methodEfi({{.*}}) [[NORMAL]] +// CHECK: @_ZN20template_normal_baseIifE6methodEif({{.*}}) [[OPTNONE]] + + +//-- Effect of optnone on a partial specialization. +// SECOND TEST: a method loses optnone in the specialization. + +template class template_optnone_base { +public: + __attribute__((optnone)) T method(T t, U u) + { + return t + static_cast(u); + } +}; + +template class template_optnone_base +{ +public: + int method (int t, U u) + { + return t - static_cast(u); + } +}; + +// This function should cause an instantiation of the full template (whose +// method is marked optnone) and an instantiation of the partially +// specialized template (whose method is not marked optnone). +void container3() +{ + int y = 2; + float z = 3.0; + template_optnone_base class_optnone; + template_optnone_base class_normal; + float r1 = class_optnone.method(z, y); + float r2 = class_normal.method(y, z); +} + +// CHECK: @_ZN21template_optnone_baseIfiE6methodEfi({{.*}}) [[OPTNONE]] +// CHECK: @_ZN21template_optnone_baseIifE6methodEif({{.*}}) [[NORMAL]] + + +// CHECK: attributes [[NORMAL]] = +// CHECK-SAME-NOT: optnone +// CHECK: attributes [[OPTNONE]] = {{.*}} optnone