diff options
| author | Hans Wennborg <hans@hanshq.net> | 2015-08-15 01:18:16 +0000 |
|---|---|---|
| committer | Hans Wennborg <hans@hanshq.net> | 2015-08-15 01:18:16 +0000 |
| commit | 99000c24c9c08773bb74fede3ed07d6bfd95d538 (patch) | |
| tree | d7d4dbba37c6c7bf562f6416cae8cb8d4f902eac /clang/test/CodeGenCXX | |
| parent | 3a4a60cba5faf2691403206b48b26fca4f666d7c (diff) | |
| download | bcm5719-llvm-99000c24c9c08773bb74fede3ed07d6bfd95d538.tar.gz bcm5719-llvm-99000c24c9c08773bb74fede3ed07d6bfd95d538.zip | |
Delay emitting members of dllexport classes until the class is fully parsed (PR23542)
This enables Clang to correctly handle code such as:
struct __declspec(dllexport) S {
int x = 42;
};
where it would otherwise error due to trying to generate the default
constructor before the in-class initializer for x has been parsed.
Differential Revision: http://reviews.llvm.org/D11850
llvm-svn: 245139
Diffstat (limited to 'clang/test/CodeGenCXX')
| -rw-r--r-- | clang/test/CodeGenCXX/dllexport.cpp | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp index c598880b625..d5d61f32ef9 100644 --- a/clang/test/CodeGenCXX/dllexport.cpp +++ b/clang/test/CodeGenCXX/dllexport.cpp @@ -544,6 +544,7 @@ struct A { struct __declspec(dllexport) B { B(A = 0) {} }; + } // // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@PR23801@@QAEXXZ"({{.*}}) comdat @@ -611,7 +612,6 @@ namespace UseDtorAlias { B::~B() { } // Emit a alias definition of B's constructor. // M32-DAG: @"\01??1B@UseDtorAlias@@QAE@XZ" = dllexport alias {{.*}} @"\01??1A@UseDtorAlias@@QAE@XZ" - } struct __declspec(dllexport) DefaultedCtorsDtors { @@ -729,6 +729,54 @@ extern template struct PR23770DerivedTemplate<int>; template struct __declspec(dllexport) PR23770DerivedTemplate<int>; // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ" +namespace InClassInits { + +struct __declspec(dllexport) S { + int x = 42; +}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::S"* @"\01??0S@InClassInits@@QAE@XZ" + +// dllexport an already instantiated class template. +template <typename T> struct Base { + int x = 42; +}; +Base<int> base; +struct __declspec(dllexport) T : Base<int> { }; +// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::Base"* @"\01??0?$Base@H@InClassInits@@QAE@XZ" + +struct A { A(int); }; +struct __declspec(dllexport) U { + // Class with both default constructor closure and in-class initializer. + U(A = 0) {} + int x = 0; +}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::U"* @"\01??0U@InClassInits@@QAE@UA@1@@Z" + +struct Evil { + template <typename T> struct Base { + int x = 0; + }; + struct S : Base<int> {}; + // The already instantiated Base<int> becomes dllexported below, but the + // in-class initializer for Base<>::x still hasn't been parsed, so emitting + // the default ctor must still be delayed. + struct __declspec(dllexport) T : Base<int> {}; +}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.InClassInits::Evil::Base"* @"\01??0?$Base@H@Evil@InClassInits@@QAE@XZ" + +template <typename T> struct Foo {}; +template <typename T> struct Bar { + Bar<T> &operator=(Foo<T>) {} +}; +struct __declspec(dllexport) Baz { + Bar<int> n; +}; +// After parsing Baz, in ActOnFinishCXXNonNestedClass we would synthesize +// Baz's operator=, causing instantiation of Foo<int> after which +// ActOnFinishCXXNonNestedClass is called, and we would bite our own tail. +// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"\01??4Baz@InClassInits@@QAEAAU01@ABU01@@Z" +} + //===----------------------------------------------------------------------===// // Classes with template base classes |

