--- /dev/null
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -fms-extensions -verify -o - %s | FileCheck %s
+// expected-no-diagnostics
+
+// Simple case
+
+int __declspec(code_seg("foo_one")) bar_one() { return 1; }
+//CHECK: define {{.*}}bar_one{{.*}} section "foo_one"
+
+// Simple case - explicit attribute used over pragma
+#pragma code_seg("foo_two")
+int __declspec(code_seg("foo_three")) bar2() { return 2; }
+//CHECK: define {{.*}}bar2{{.*}} section "foo_three"
+
+// Check that attribute on one function doesn't affect another
+int another1() { return 1001; }
+//CHECK: define {{.*}}another1{{.*}} section "foo_two"
+
+// Member functions
+
+struct __declspec(code_seg("foo_four")) Foo {
+ int bar3() {return 0;}
+ int bar4();
+ int __declspec(code_seg("foo_six")) bar6() { return 6; }
+ int bar7() { return 7; }
+ struct Inner {
+ int bar5() { return 5; }
+ } z;
+ virtual int baz1() { return 1; }
+};
+
+struct __declspec(code_seg("foo_four")) FooTwo : Foo {
+ int baz1() { return 20; }
+};
+
+int caller1() {
+ Foo f; return f.bar3();
+}
+
+//CHECK: define {{.*}}bar3@Foo{{.*}} section "foo_four"
+int Foo::bar4() { return 4; }
+//CHECK: define {{.*}}bar4@Foo{{.*}} section "foo_four"
+
+#pragma code_seg("someother")
+
+int caller2() {
+ Foo f;
+ Foo *fp = new FooTwo;
+ return f.z.bar5() + f.bar6() + f.bar7() + fp->baz1();
+}
+// TBD: MS Compiler and Docs do not match for nested routines
+// Doc says: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_four"
+// Compiler says: define {{.*}}bar5@Inner@Foo{{.*}} section "foo_two"
+//CHECK: define {{.*}}bar6@Foo{{.*}} section "foo_six"
+//CHECK: define {{.*}}bar7@Foo{{.*}} section "foo_four"
+// Check that code_seg active at class declaration is not used on member
+// declared outside class when it is not active.
+
+#pragma code_seg(push,"AnotherSeg")
+
+struct FooThree {
+ int bar8();
+ int bar9() { return 9; }
+};
+
+#pragma code_seg(pop)
+
+
+int FooThree::bar8() {return 0;}
+
+int caller3()
+{
+ FooThree f;
+ return f.bar8() + f.bar9();
+}
+
+//CHECK: define {{.*}}bar8@FooThree{{.*}} section "someother"
+//CHECK: define {{.*}}bar9@FooThree{{.*}} section "AnotherSeg"
+
+struct NonTrivialCopy {
+ NonTrivialCopy();
+ NonTrivialCopy(const NonTrivialCopy&);
+ ~NonTrivialCopy();
+};
+
+// check the section for compiler-generated function with declspec.
+
+struct __declspec(code_seg("foo_seven")) FooFour {
+ FooFour() {}
+ int __declspec(code_seg("foo_eight")) bar10(int t) { return t; }
+ NonTrivialCopy f;
+};
+
+//CHECK: define {{.*}}0FooFour@@QAE@ABU0@@Z{{.*}} section "foo_seven"
+// check the section for compiler-generated function with no declspec.
+
+struct FooFive {
+ FooFive() {}
+ int __declspec(code_seg("foo_nine")) bar11(int t) { return t; }
+ NonTrivialCopy f;
+};
+
+//CHECK: define {{.*}}0FooFive@@QAE@ABU0@@Z{{.*}} section "someother"
+
+#pragma code_seg("YetAnother")
+int caller4()
+{
+ FooFour z1;
+ FooFour z2 = z1;
+ FooFive y1;
+ FooFive y2 = y1;
+ return z2.bar10(0) + y2.bar11(1);
+}
+
+//CHECK: define {{.*}}bar10@FooFour{{.*}} section "foo_eight"
+//CHECK: define {{.*}}bar11@FooFive{{.*}} section "foo_nine"
+
+struct FooSix {
+ #pragma code_seg("foo_ten")
+ int bar12() { return 12; }
+ #pragma code_seg("foo_eleven")
+ int bar13() { return 13; }
+};
+
+int bar14() { return 14; }
+//CHECK: define {{.*}}bar14{{.*}} section "foo_eleven"
+
+int caller5()
+{
+ FooSix fsix;
+ return fsix.bar12() + fsix.bar13();
+}
+
+//CHECK: define {{.*}}bar12@FooSix{{.*}} section "foo_ten"
+//CHECK: define {{.*}}bar13@FooSix{{.*}} section "foo_eleven"
+//CHECK: define {{.*}}baz1@FooTwo{{.*}} section "foo_four"
--- /dev/null
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -std=c++11 -fms-extensions -verify -o - %s | FileCheck %s
+// expected-no-diagnostics
+
+// Class member templates
+
+#pragma code_seg(push, "something")
+
+template <typename T>
+struct __declspec(code_seg("foo_one")) ClassOne {
+ int bar1(T t) { return int(t); }
+ int bar2(T t);
+ int bar3(T t);
+};
+
+template <typename T>
+int ClassOne<T>::bar2(T t) {
+ return int(t);
+}
+
+int caller1() {
+ ClassOne<int> coi;
+ return coi.bar1(6) + coi.bar2(3);
+}
+
+//CHECK: define {{.*}}bar1@?$ClassOne{{.*}} section "foo_one"
+//CHECK: define {{.*}}bar2@?$ClassOne{{.*}} section "foo_one"
+
+
+template <typename T>
+struct ClassTwo {
+ int bar11(T t) { return int(t); }
+ int bar22(T t);
+ int bar33(T t);
+};
+
+#pragma code_seg("newone")
+
+template <typename T>
+int ClassTwo<T>::bar22(T t) {
+ return int(t);
+}
+
+#pragma code_seg("someother")
+
+template <typename T>
+int ClassTwo<T>::bar33(T t) {
+ return int(t);
+}
+
+#pragma code_seg("yetanother")
+
+int caller2() {
+ ClassTwo<int> coi;
+ return coi.bar11(6) + coi.bar22(3) + coi.bar33(44);
+}
+
+//CHECK: define {{.*}}bar11@?$ClassTwo{{.*}} section "something"
+//CHECK: define {{.*}}bar22@?$ClassTwo{{.*}} section "newone"
+//CHECK: define {{.*}}bar33@?$ClassTwo{{.*}} section "someother"
+
+template<>
+struct ClassOne<double>
+{
+ int bar44(double d) { return 1; }
+};
+template<>
+struct __declspec(code_seg("foo_three")) ClassOne<long>
+{
+ int bar55(long d) { return 1; }
+};
+
+#pragma code_seg("onemore")
+int caller3() {
+ ClassOne<double> d;
+ ClassOne<long> l;
+ return d.bar44(1.0)+l.bar55(1);
+}
+
+//CHECK: define {{.*}}bar44{{.*}} section "yetanother"
+//CHECK: define {{.*}}bar55{{.*}} section "foo_three"
+
+
+// Function templates
+template <typename T>
+int __declspec(code_seg("foo_four")) bar66(T t) { return int(t); }
+
+// specializations do not take the segment from primary
+template<>
+int bar66(int i) { return 0; }
+
+#pragma code_seg(pop)
+
+template<>
+int bar66(char c) { return 0; }
+
+struct A1 {int i;};
+template<>
+int __declspec(code_seg("foo_five")) bar66(A1 a) { return a.i; }
+
+int caller4()
+{
+// but instantiations do use the section from the primary
+return bar66(0) + bar66(1.0) + bar66('c');
+}
+//CHECK: define {{.*}}bar66@H{{.*}} section "onemore"
+//CHECK-NOT: define {{.*}}bar66@D{{.*}} section
+//CHECK: define {{.*}}bar66@UA1{{.*}} section "foo_five"
+//CHECK: define {{.*}}bar66@N{{.*}} section "foo_four"
+
+
+#pragma code_seg("another")
+// Member functions
+struct __declspec(code_seg("foo_four")) Foo {
+ int bar3() {return 0;}
+ __declspec(code_seg("foo_lala")) int bar4() {return 0;} }; int caller() {Foo f; return f.bar3() + f.bar4(); }
+
+//CHECK: define {{.*}}bar3@Foo{{.*}} section "foo_four"
+//CHECK: define {{.*}}bar4@Foo{{.*}} section "foo_lala"
+
+// Lambdas
+#pragma code_seg("something")
+
+int __declspec(code_seg("foo")) bar1()
+{
+ int lala = 4;
+ auto l = [=](int i) { return i+4; };
+ return l(-4);
+}
+
+//CHECK: define {{.*}}bar1{{.*}} section "foo"
+//CHECK: define {{.*}}lambda{{.*}}bar1{{.*}} section "something"
+
+double __declspec(code_seg("foo")) bar2()
+{
+ double lala = 4.0;
+ auto l = [=](double d) __declspec(code_seg("another")) { return d+4.0; };
+ return l(4.0);
+}
+
+//CHECK: define {{.*}}bar2{{.*}} section "foo"
+//CHECK: define {{.*}}lambda{{.*}}bar2{{.*}} section "another"
--- /dev/null
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -fms-extensions -verify -o - %s | FileCheck %s
+// expected-no-diagnostics
+// The Microsoft document says: "When this attribute is applied to a class,
+// all member functions of the class and nested classes - this includes
+// compiler-generated special member functions - are put in the specified segment."
+// But the MS compiler does not always follow that. A bug has been reported:
+// see https://reviews.llvm.org/D22931, the Microsoft feedback page is no
+// longer available.
+// The MS compiler will apply a declspec from the parent class if there is no
+// #pragma code_seg active at the class definition. If there is an active
+// code_seg that is used instead.
+
+// No active code_seg
+
+struct __declspec(code_seg("foo_outer")) Foo1 {
+ struct Inner {
+ void bar1();
+ static void bar2();
+ };
+};
+void Foo1::Inner::bar1() {}
+void Foo1::Inner::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo1{{.*}} section "foo_outer"
+//CHECK: define {{.*}}bar2@Inner@Foo1{{.*}} section "foo_outer"
+
+struct __declspec(code_seg("foo_outer")) Foo2 {
+ struct __declspec(code_seg("foo_inner")) Inner {
+ void bar1();
+ static void bar2();
+ };
+};
+void Foo2::Inner::bar1() {}
+void Foo2::Inner::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo2{{.*}} section "foo_inner"
+//CHECK: define {{.*}}bar2@Inner@Foo2{{.*}} section "foo_inner"
+
+#pragma code_seg(push, "otherseg")
+struct __declspec(code_seg("foo_outer")) Foo3 {
+ struct Inner {
+ void bar1();
+ static void bar2();
+ };
+};
+void Foo3::Inner::bar1() {}
+void Foo3::Inner::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo3{{.*}} section "otherseg"
+//CHECK: define {{.*}}bar2@Inner@Foo3{{.*}} section "otherseg"
+
+struct __declspec(code_seg("foo_outer")) Foo4 {
+ struct __declspec(code_seg("foo_inner")) Inner {
+ void bar1();
+ static void bar2();
+ };
+};
+void Foo4::Inner::bar1() {}
+void Foo4::Inner::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo4{{.*}} section "foo_inner"
+//CHECK: define {{.*}}bar2@Inner@Foo4{{.*}} section "foo_inner"
+
+#pragma code_seg(pop)
+// Back to no active pragma
+struct __declspec(code_seg("foo_outer")) Foo5 {
+ struct Inner {
+ void bar1();
+ static void bar2();
+ struct __declspec(code_seg("inner1_seg")) Inner1 {
+ struct Inner2 {
+ void bar1();
+ static void bar2();
+ };
+ };
+ };
+};
+void Foo5::Inner::bar1() {}
+void Foo5::Inner::bar2() {}
+void Foo5::Inner::Inner1::Inner2::bar1() {}
+void Foo5::Inner::Inner1::Inner2::bar2() {}
+
+//CHECK: define {{.*}}bar1@Inner@Foo5{{.*}} section "foo_outer"
+//CHECK: define {{.*}}bar2@Inner@Foo5{{.*}} section "foo_outer"
+//CHECK: define {{.*}}bar1@Inner2@Inner1@Inner@Foo5{{.*}} section "inner1_seg"
+//CHECK: define {{.*}}bar2@Inner2@Inner1@Inner@Foo5{{.*}} section "inner1_seg"
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32
+// expected-no-diagnostics
+
+// Non-Member Function Overloading is involved
+
+int __declspec(code_seg("foo_one")) bar_one(int) { return 1; }
+//CHECK: define {{.*}}bar_one{{.*}} section "foo_one"
+int __declspec(code_seg("foo_two")) bar_one(int,float) { return 11; }
+//CHECK: define {{.*}}bar_one{{.*}} section "foo_two"
+int __declspec(code_seg("foo_three")) bar_one(float) { return 12; }
+//CHECK: define {{.*}}bar_one{{.*}} section "foo_three"
+
+// virtual function overloading is involved
+
+struct __declspec(code_seg("my_one")) Base3 {
+ virtual int barA(int) { return 1; }
+ virtual int barA(int,float) { return 2; }
+ virtual int barA(float) { return 3; }
+
+ virtual void __declspec(code_seg("my_two")) barB(int) { }
+ virtual void __declspec(code_seg("my_three")) barB(float) { }
+ virtual void __declspec(code_seg("my_four")) barB(int, float) { }
+
+};
+
+//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one"
+//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one"
+//CHECK: define {{.*}}barA@Base3{{.*}} section "my_one"
+//CHECK: define {{.*}}barB@Base3{{.*}} section "my_two"
+//CHECK: define {{.*}}barB@Base3{{.*}} section "my_three"
+//CHECK: define {{.*}}barB@Base3{{.*}} section "my_four"
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32
+
+struct __declspec(code_seg("my_one")) FooOne {
+ int barC();
+};
+
+struct FooTwo {
+ int __declspec(code_seg("my_three")) barD();
+ int barE();
+};
+int __declspec(code_seg("my_four")) FooOne::barC() { return 10; }
+// expected-warning@-1 {{section does not match previous declaration}}
+// expected-note@3{{previous attribute is here}}
+int __declspec(code_seg("my_five")) FooTwo::barD() { return 20; }
+// expected-warning@-1 {{section does not match previous declaration}}
+// expected-note@8 {{previous attribute is here}}
+int __declspec(code_seg("my_six")) FooTwo::barE() { return 30; }
+// expected-warning@-1 {{section does not match previous declaration}}
+// expected-note@9 {{previous declaration is here}}
+
+// Microsoft docs say:
+// If a base-class has a code_seg attribute, derived classes must have the
+// same attribute.
+struct __declspec(code_seg("my_base")) Base1 {};
+struct Base2 {};
+
+struct D1 : Base1 {};
+//expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-note@24 {{base class 'Base1' specified here}}
+struct __declspec(code_seg("my_derived")) D2 : Base1 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-note@24 {{base class 'Base1' specified here}}
+struct __declspec(code_seg("my_derived")) D3 : Base2 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-note@25 {{base class 'Base2' specified here}}
+
+template <typename T> struct __declspec(code_seg("my_base")) MB : T { };
+template <typename T> struct __declspec(code_seg("my_derived")) MD : T { };
+MB<Base1> mb1; // ok
+MB<Base2> mb2;
+// expected-error@37 {{derived class must specify the same code segment as its base classes}}
+// expected-note@-2 {{in instantiation of template class}}
+// expected-note@25 {{base class 'Base2' specified here}}
+MD<Base1> md1;
+// expected-error@38 {{derived class must specify the same code segment as its base classes}}
+// expected-note@-2 {{in instantiation of template class}}
+// expected-note@24 {{base class 'Base1' specified here}}
+MD<Base2> md2;
+// expected-error@38 {{derived class must specify the same code segment as its base classes}}
+// expected-note@-2 {{in instantiation of template class}}
+// expected-note@25 {{base class 'Base2' specified here}}
+
+// Virtual overrides must have the same code_seg.
+struct __declspec(code_seg("my_one")) Base3 {
+ virtual int barA() { return 1; }
+ virtual int __declspec(code_seg("my_two")) barB() { return 2; }
+};
+struct __declspec(code_seg("my_one")) Derived3 : Base3 {
+ int barA() { return 4; } // ok
+ int barB() { return 6; }
+ // expected-error@-1 {{overriding virtual function must specify the same code segment as its overridden function}}
+ // expected-note@56 {{previous declaration is here}}
+};
+
+struct Base4 {
+ virtual int __declspec(code_seg("my_one")) barA() {return 1;}
+ virtual int barB() { return 2;}
+};
+struct Derived4 : Base4 {
+ virtual int barA() {return 1;}
+ // expected-error@-1 {{overriding virtual function must specify the same code segment as its overridden function}}
+ // expected-note@66 {{previous declaration is here}}
+ virtual int __declspec(code_seg("my_two")) barB() {return 1;}
+ // expected-error@-1 {{overriding virtual function must specify the same code segment as its overridden function}}
+ // expected-note@67 {{previous declaration is here}}
+};
+
+// MS gives an error when different code segments are used but a warning when a duplicate is used
+
+// Function
+int __declspec(code_seg("foo")) __declspec(code_seg("foo")) bar1() { return 1; }
+// expected-warning@-1 {{duplicate code segment specifiers}}
+int __declspec(code_seg("foo")) __declspec(code_seg("bar")) bar2() { return 1; }
+// expected-error@-1 {{conflicting code segment specifiers}}
+
+// Class
+struct __declspec(code_seg("foo")) __declspec(code_seg("foo")) Foo {
+ // expected-warning@-1 {{duplicate code segment specifiers}}
+ int bar3() {return 0;}
+};
+struct __declspec(code_seg("foo")) __declspec(code_seg("bar")) FooSix {
+ // expected-error@-1 {{conflicting code segment specifiers}}
+ int bar3() {return 0;}
+};
+
+//Class Members
+struct FooThree {
+ int __declspec(code_seg("foo")) __declspec(code_seg("foo")) bar1() { return 1; }
+ // expected-warning@-1 {{duplicate code segment specifiers}}
+ int __declspec(code_seg("foo")) __declspec(code_seg("bar")) bar2() { return 1; }
+ // expected-error@-1 {{conflicting code segment specifiers}}
+ int bar8();
+ int bar9() { return 9; }
+};
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32
+
+// Multiple inheritance is involved (code segmments all disagree between the bases and derived class)
+struct __declspec(code_seg("my_base")) Base1 {};
+struct Base2 {};
+
+struct D1 : Base1, Base2 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-note@4 {{base class 'Base1' specified here}}
+
+struct __declspec(code_seg("my_derived")) D2 : Base2, Base1 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@5 {{base class 'Base2' specified here}}
+// expected-note@4 {{base class 'Base1' specified here}}
+
+// Multiple inheritance (code segments partially agree between the bases and the derived class)
+struct __declspec(code_seg("base_class")) BaseClass1 {};
+struct __declspec(code_seg("base_class")) BaseClass2 {};
+
+struct Derived1 : BaseClass1, BaseClass2 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@18 {{base class 'BaseClass1' specified here}}
+// expected-note@19 {{base class 'BaseClass2' specified here}}
+
+struct __declspec(code_seg("derived_class")) Derived2 : BaseClass2, BaseClass1 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@19 {{base class 'BaseClass2' specified here}}
+// expected-note@18 {{base class 'BaseClass1' specified here}}
+
+struct __declspec(code_seg("base_class")) Derived3 : BaseClass2, BaseClass1 {}; //OK
+struct __declspec(code_seg("base_class")) Derived4 : BaseClass1, BaseClass2 {}; //OK
+
+// Multiple inheritance is involved (code segmments all agree between the bases and derived class)
+struct __declspec(code_seg("foo_base")) B1 {};
+struct __declspec(code_seg("foo_base")) B2 {};
+struct __declspec(code_seg("foo_base")) Derived : B1, B2 {};
+
+// virtual Inheritance is involved (code segmments all disagree between the bases and derived class)
+struct __declspec(code_seg("my_one")) Base {
+ virtual int barA() { return 1; } ;
+};
+
+struct __declspec(code_seg("my_two")) Derived5 : virtual Base {
+ virtual int barB() { return 2; };
+};
+// expected-error@-3 {{derived class must specify the same code segment as its base classes}}
+// expected-note@42 {{base class 'Base' specified here}}
+
+struct __declspec(code_seg("my_three")) Derived6 : virtual Base {
+ virtual int barC() { return 3; };
+};
+// expected-error@-3 {{derived class must specify the same code segment as its base classes}}
+// expected-note@42 {{base class 'Base' specified here}}
+
+struct __declspec(code_seg("my_four")) Derived7 : Derived5, Derived6 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@46 {{base class 'Derived5' specified here}}
+// expected-note@52 {{base class 'Derived6' specified here}}
+
+// virtual Inheritance is involved (code segmments partially agree between the bases and derived class)
+struct __declspec(code_seg("my_class")) BaseClass {
+ virtual int barA() { return 1; } ;
+};
+
+struct __declspec(code_seg("my_class")) DerivedClass1 : virtual BaseClass { //OK
+ virtual int barB() { return 2; };
+};
+
+struct __declspec(code_seg("my_class")) DerivedClass2 : virtual BaseClass { //OK
+ virtual int barC() { return 3; };
+};
+
+struct __declspec(code_seg("my_derived_one")) DerivedClass3 : DerivedClass1, DerivedClass2 {};
+// expected-error@-1 {{derived class must specify the same code segment as its base classes}}
+// expected-error@-2 {{derived class must specify the same code segment as its base classes}}
+// expected-note@69 {{base class 'DerivedClass1' specified here}}
+// expected-note@73 {{base class 'DerivedClass2' specified here}}
+
+// virtual Inheritance is involved (code segmments all agree between the bases and derived class)
+struct __declspec(code_seg("foo_one")) Class {
+ virtual int foo1() { return 10; } ;
+};
+
+struct __declspec(code_seg("foo_one")) Derived_One: virtual Class { //OK
+ virtual int foo2() { return 20; };
+};
+
+struct __declspec(code_seg("foo_one")) Derived_Two : virtual Class { //OK
+ virtual int foo3() { return 30; };
+};
+
+struct __declspec(code_seg("foo_one")) Derived_Three : Derived_One, Derived_Two {}; //OK