1*7e8283aeSChandler Carruth // RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-passes -emit-llvm -x c++ | FileCheck %s 29d6940baSPaul Robinson 39d6940baSPaul Robinson // Test attribute 'optnone' on methods: 49d6940baSPaul Robinson // -- member functions; 59d6940baSPaul Robinson // -- static member functions. 69d6940baSPaul Robinson 79d6940baSPaul Robinson // Verify that all methods of struct A are associated to the same attribute set. 89d6940baSPaul Robinson // The attribute set shall contain attributes 'noinline' and 'optnone'. 99d6940baSPaul Robinson 109d6940baSPaul Robinson struct A { 119d6940baSPaul Robinson // Definition of an optnone static method. 129d6940baSPaul Robinson __attribute__((optnone)) static_optnone_methodA139d6940baSPaul Robinson static int static_optnone_method(int a) { 149d6940baSPaul Robinson return a + a; 159d6940baSPaul Robinson } 169d6940baSPaul Robinson // CHECK: @_ZN1A21static_optnone_methodEi({{.*}}) [[OPTNONE:#[0-9]+]] 179d6940baSPaul Robinson 189d6940baSPaul Robinson // Definition of an optnone normal method. 199d6940baSPaul Robinson __attribute__((optnone)) optnone_methodA209d6940baSPaul Robinson int optnone_method(int a) { 219d6940baSPaul Robinson return a + a + a + a; 229d6940baSPaul Robinson } 239d6940baSPaul Robinson // CHECK: @_ZN1A14optnone_methodEi({{.*}}) [[OPTNONE]] 249d6940baSPaul Robinson 259d6940baSPaul Robinson // Declaration of an optnone method with out-of-line definition 269d6940baSPaul Robinson // that doesn't say optnone. 279d6940baSPaul Robinson __attribute__((optnone)) 289d6940baSPaul Robinson int optnone_decl_method(int a); 299d6940baSPaul Robinson 309d6940baSPaul Robinson // Methods declared without attribute optnone; the definitions will 319d6940baSPaul Robinson // have attribute optnone, and we verify optnone wins. 329d6940baSPaul Robinson __forceinline static int static_forceinline_method(int a); 339d6940baSPaul Robinson __attribute__((always_inline)) int alwaysinline_method(int a); 349d6940baSPaul Robinson __attribute__((noinline)) int noinline_method(int a); 359d6940baSPaul Robinson __attribute__((minsize)) int minsize_method(int a); 369d6940baSPaul Robinson }; 379d6940baSPaul Robinson foo()389d6940baSPaul Robinsonvoid foo() { 399d6940baSPaul Robinson A a; 409d6940baSPaul Robinson A::static_optnone_method(4); 419d6940baSPaul Robinson a.optnone_method(14); 429d6940baSPaul Robinson a.optnone_decl_method(12); 439d6940baSPaul Robinson A::static_forceinline_method(5); 449d6940baSPaul Robinson a.alwaysinline_method(5); 459d6940baSPaul Robinson a.noinline_method(6); 469d6940baSPaul Robinson a.minsize_method(7); 479d6940baSPaul Robinson } 489d6940baSPaul Robinson 499d6940baSPaul Robinson // No attribute here, should still be on the definition. optnone_decl_method(int a)509d6940baSPaul Robinsonint A::optnone_decl_method(int a) { 519d6940baSPaul Robinson return a; 529d6940baSPaul Robinson } 539d6940baSPaul Robinson // CHECK: @_ZN1A19optnone_decl_methodEi({{.*}}) [[OPTNONE]] 549d6940baSPaul Robinson 559d6940baSPaul Robinson // optnone implies noinline; therefore attribute noinline is added to 569d6940baSPaul Robinson // the set of function attributes. 579d6940baSPaul Robinson // forceinline is instead translated as 'always_inline'. 589d6940baSPaul Robinson // However 'noinline' wins over 'always_inline' and therefore 599d6940baSPaul Robinson // the resulting attributes for this method are: noinline + optnone 609d6940baSPaul Robinson __attribute__((optnone)) static_forceinline_method(int a)619d6940baSPaul Robinsonint A::static_forceinline_method(int a) { 629d6940baSPaul Robinson return a + a + a + a; 639d6940baSPaul Robinson } 649d6940baSPaul Robinson // CHECK: @_ZN1A25static_forceinline_methodEi({{.*}}) [[OPTNONE]] 659d6940baSPaul Robinson 669d6940baSPaul Robinson __attribute__((optnone)) alwaysinline_method(int a)679d6940baSPaul Robinsonint A::alwaysinline_method(int a) { 689d6940baSPaul Robinson return a + a + a + a; 699d6940baSPaul Robinson } 709d6940baSPaul Robinson // CHECK: @_ZN1A19alwaysinline_methodEi({{.*}}) [[OPTNONE]] 719d6940baSPaul Robinson 729d6940baSPaul Robinson // 'noinline' + 'noinline and optnone' = 'noinline and optnone' 739d6940baSPaul Robinson __attribute__((optnone)) noinline_method(int a)749d6940baSPaul Robinsonint A::noinline_method(int a) { 759d6940baSPaul Robinson return a + a + a + a; 769d6940baSPaul Robinson } 779d6940baSPaul Robinson // CHECK: @_ZN1A15noinline_methodEi({{.*}}) [[OPTNONE]] 789d6940baSPaul Robinson 799d6940baSPaul Robinson // 'optnone' wins over 'minsize' 809d6940baSPaul Robinson __attribute__((optnone)) minsize_method(int a)819d6940baSPaul Robinsonint A::minsize_method(int a) { 829d6940baSPaul Robinson return a + a + a + a; 839d6940baSPaul Robinson } 849d6940baSPaul Robinson // CHECK: @_ZN1A14minsize_methodEi({{.*}}) [[OPTNONE]] 859d6940baSPaul Robinson 869d6940baSPaul Robinson 879d6940baSPaul Robinson // Test attribute 'optnone' on methods: 889d6940baSPaul Robinson // -- pure virtual functions 899d6940baSPaul Robinson // -- base virtual and derived virtual 909d6940baSPaul Robinson // -- base virtual but not derived virtual 919d6940baSPaul Robinson // -- optnone methods redefined in override 929d6940baSPaul Robinson 939d6940baSPaul Robinson // A method defined in override doesn't inherit the function attributes of the 949d6940baSPaul Robinson // superclass method. 959d6940baSPaul Robinson 969d6940baSPaul Robinson struct B { 979d6940baSPaul Robinson virtual int pure_virtual(int a) = 0; 989d6940baSPaul Robinson __attribute__((optnone)) 999d6940baSPaul Robinson virtual int pure_virtual_with_optnone(int a) = 0; 1009d6940baSPaul Robinson baseB1019d6940baSPaul Robinson virtual int base(int a) { 1029d6940baSPaul Robinson return a + a + a + a; 1039d6940baSPaul Robinson } 1049d6940baSPaul Robinson 1059d6940baSPaul Robinson __attribute__((optnone)) optnone_baseB1069d6940baSPaul Robinson virtual int optnone_base(int a) { 1079d6940baSPaul Robinson return a + a + a + a; 1089d6940baSPaul Robinson } 1099d6940baSPaul Robinson 1109d6940baSPaul Robinson __attribute__((optnone)) only_base_virtualB1119d6940baSPaul Robinson virtual int only_base_virtual(int a) { 1129d6940baSPaul Robinson return a + a; 1139d6940baSPaul Robinson } 1149d6940baSPaul Robinson }; 1159d6940baSPaul Robinson 1169d6940baSPaul Robinson struct C : public B { 1179d6940baSPaul Robinson __attribute__((optnone)) pure_virtualC1189d6940baSPaul Robinson virtual int pure_virtual(int a) { 1199d6940baSPaul Robinson return a + a + a + a; 1209d6940baSPaul Robinson } 1219d6940baSPaul Robinson pure_virtual_with_optnoneC1229d6940baSPaul Robinson virtual int pure_virtual_with_optnone(int a) { 1239d6940baSPaul Robinson return a + a + a + a; 1249d6940baSPaul Robinson } 1259d6940baSPaul Robinson 1269d6940baSPaul Robinson __attribute__((optnone)) baseC1279d6940baSPaul Robinson virtual int base(int a) { 1289d6940baSPaul Robinson return a + a; 1299d6940baSPaul Robinson } 1309d6940baSPaul Robinson optnone_baseC1319d6940baSPaul Robinson virtual int optnone_base(int a) { 1329d6940baSPaul Robinson return a + a; 1339d6940baSPaul Robinson } 1349d6940baSPaul Robinson only_base_virtualC1359d6940baSPaul Robinson int only_base_virtual(int a) { 1369d6940baSPaul Robinson return a + a + a + a; 1379d6940baSPaul Robinson } 1389d6940baSPaul Robinson }; 1399d6940baSPaul Robinson bar()1409d6940baSPaul Robinsonint bar() { 1419d6940baSPaul Robinson C c; 1429d6940baSPaul Robinson int result; 1439d6940baSPaul Robinson result = c.pure_virtual(3); 1449d6940baSPaul Robinson result += c.pure_virtual_with_optnone(2); 1459d6940baSPaul Robinson result += c.base(5); 1469d6940baSPaul Robinson result += c.optnone_base(7); 1479d6940baSPaul Robinson result += c.only_base_virtual(9); 1489d6940baSPaul Robinson return result; 1499d6940baSPaul Robinson } 1509d6940baSPaul Robinson 1519d6940baSPaul Robinson // CHECK: @_ZN1C12pure_virtualEi({{.*}}) {{.*}} [[OPTNONE]] 1529d6940baSPaul Robinson // CHECK: @_ZN1C25pure_virtual_with_optnoneEi({{.*}}) {{.*}} [[NORMAL:#[0-9]+]] 1539d6940baSPaul Robinson // CHECK: @_ZN1C4baseEi({{.*}}) {{.*}} [[OPTNONE]] 1549d6940baSPaul Robinson // CHECK: @_ZN1C12optnone_baseEi({{.*}}) {{.*}} [[NORMAL]] 1559d6940baSPaul Robinson // CHECK: @_ZN1C17only_base_virtualEi({{.*}}) {{.*}} [[NORMAL]] 1569d6940baSPaul Robinson // CHECK: @_ZN1B4baseEi({{.*}}) {{.*}} [[NORMAL]] 1579d6940baSPaul Robinson // CHECK: @_ZN1B12optnone_baseEi({{.*}}) {{.*}} [[OPTNONE]] 1589d6940baSPaul Robinson // CHECK: @_ZN1B17only_base_virtualEi({{.*}}) {{.*}} [[OPTNONE]] 1599d6940baSPaul Robinson 1609d6940baSPaul Robinson 1619d6940baSPaul Robinson // CHECK: attributes [[NORMAL]] = 162ae06ca0cSJustin Lebar // CHECK-NOT: noinline 163ae06ca0cSJustin Lebar // CHECK-NOT: optnone 1649d6940baSPaul Robinson // CHECK: attributes [[OPTNONE]] = {{.*}} noinline {{.*}} optnone 165