From 60478662327f9eef3d02a1d3619f666451958c60 Mon Sep 17 00:00:00 2001 From: Nico Rieck Date: Sat, 22 Feb 2014 19:47:30 +0000 Subject: [PATCH] Reorganize and improve semantic tests for dllexport/import llvm-svn: 201947 --- clang/lib/Sema/SemaDeclAttr.cpp | 4 +- clang/test/Rewriter/dllimport-typedef.c | 2 +- clang/test/Sema/dllexport.c | 113 ++++++++++++++ clang/test/Sema/dllimport-dllexport.c | 48 ------ clang/test/Sema/dllimport.c | 68 +++++++++ clang/test/SemaCXX/dllexport.cpp | 189 ++++++++++++++++++++++++ clang/test/SemaCXX/dllimport.cpp | 127 ++++++++++++++++ 7 files changed, 500 insertions(+), 51 deletions(-) create mode 100644 clang/test/Sema/dllexport.c delete mode 100644 clang/test/Sema/dllimport-dllexport.c create mode 100644 clang/test/Sema/dllimport.c create mode 100644 clang/test/SemaCXX/dllexport.cpp create mode 100644 clang/test/SemaCXX/dllimport.cpp diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 1de06af775d5..7679fdb78973 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3786,7 +3786,7 @@ static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D, DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex) { if (D->hasAttr()) { - Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport"; + Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'dllimport'"; return NULL; } @@ -3834,7 +3834,7 @@ static void handleDLLImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex) { if (DLLImportAttr *Import = D->getAttr()) { - Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport"; + Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import; D->dropAttr(); } diff --git a/clang/test/Rewriter/dllimport-typedef.c b/clang/test/Rewriter/dllimport-typedef.c index 97610ddb28e1..b587f16f3e41 100644 --- a/clang/test/Rewriter/dllimport-typedef.c +++ b/clang/test/Rewriter/dllimport-typedef.c @@ -10,7 +10,7 @@ typedef __declspec(dllimport) int CB(void); void bar() { return 1; } // CHECK-NEG: error: void function 'bar' should not return a value -// CHECK-NEG: 1 error generated +// CHECK-NEG: {{^}}1 error generated // CHECK-POS: warning: 'dllimport' attribute only applies to variables and functions // CHECK-POS: error: void function 'bar' should not return a value // CHECK-POS: 1 warning and 1 error generated diff --git a/clang/test/Sema/dllexport.c b/clang/test/Sema/dllexport.c new file mode 100644 index 000000000000..fb209e1aa63e --- /dev/null +++ b/clang/test/Sema/dllexport.c @@ -0,0 +1,113 @@ +// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c99 %s +// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c11 %s +// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c11 %s +// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c99 %s + +// Invalid usage. +__declspec(dllexport) typedef int typedef1; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +typedef __declspec(dllexport) int typedef2; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +typedef int __declspec(dllexport) typedef3; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +typedef __declspec(dllexport) void (*FunTy)(); // expected-warning{{'dllexport' attribute only applies to variables and functions}} +enum __declspec(dllexport) Enum { EnumVal }; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +struct __declspec(dllexport) Record {}; // expected-warning{{'dllexport' attribute only applies to variables and functions}} + + + +//===----------------------------------------------------------------------===// +// Globals +//===----------------------------------------------------------------------===// + +// Export declaration. +__declspec(dllexport) extern int ExternGlobalDecl; + +// dllexport implies a definition. +__declspec(dllexport) int GlobalDef; + +// Export definition. +__declspec(dllexport) int GlobalInit1 = 1; +int __declspec(dllexport) GlobalInit2 = 1; + +// Declare, then export definition. +__declspec(dllexport) extern int GlobalDeclInit; +int GlobalDeclInit = 1; + +// Export in local scope. +void functionScope() { + __declspec(dllexport) extern int ExternLocalVarDecl; +} + + + +//===----------------------------------------------------------------------===// +// Functions +//===----------------------------------------------------------------------===// + +// Export function declaration. Check different placements. +__attribute__((dllexport)) void decl1A(); // Sanity check with __attribute__ +__declspec(dllexport) void decl1B(); + +void __attribute__((dllexport)) decl2A(); +void __declspec(dllexport) decl2B(); + +// Export function definition. +__declspec(dllexport) void def() {} + +// Export inline function. +__declspec(dllexport) inline void inlineFunc1() {} // expected-warning{{'dllexport' attribute ignored}} +extern void inlineFunc1(); + +inline void __attribute__((dllexport)) inlineFunc2() {} // expected-warning{{'dllexport' attribute ignored}} +extern void inlineFunc2(); + +// Redeclarations +__declspec(dllexport) void redecl1(); +__declspec(dllexport) void redecl1(); + +__declspec(dllexport) void redecl2(); + void redecl2(); + +__declspec(dllexport) void redecl3(); + void redecl3() {} + + + +//===----------------------------------------------------------------------===// +// Precedence +//===----------------------------------------------------------------------===// + +// dllexport takes precedence over dllimport if both are specified. +__attribute__((dllimport, dllexport)) extern int PrecedenceExternGlobal1A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllimport) __declspec(dllexport) extern int PrecedenceExternGlobal1B; // expected-warning{{'dllimport' attribute ignored}} + +__attribute__((dllexport, dllimport)) extern int PrecedenceExternGlobal2A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) __declspec(dllimport) extern int PrecedenceExternGlobal2B; // expected-warning{{'dllimport' attribute ignored}} + +__attribute__((dllimport, dllexport)) int PrecedenceGlobal1A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B; // expected-warning{{'dllimport' attribute ignored}} + +__attribute__((dllexport, dllimport)) int PrecedenceGlobal2A; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} +__declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +__declspec(dllexport) extern int PrecedenceExternGlobalRedecl1; +__declspec(dllimport) extern int PrecedenceExternGlobalRedecl1; // expected-warning{{'dllimport' attribute ignored}} + +__declspec(dllimport) extern int PrecedenceExternGlobalRedecl2; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) extern int PrecedenceExternGlobalRedecl2; + +__declspec(dllexport) extern int PrecedenceGlobalRedecl1; +__declspec(dllimport) int PrecedenceGlobalRedecl1; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +__declspec(dllimport) extern int PrecedenceGlobalRedecl2; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) int PrecedenceGlobalRedecl2; + +void __attribute__((dllimport, dllexport)) precedence1A() {} // expected-warning{{'dllimport' attribute ignored}} +void __declspec(dllimport) __declspec(dllexport) precedence1B() {} // expected-warning{{'dllimport' attribute ignored}} + +void __attribute__((dllexport, dllimport)) precedence2A() {} // expected-warning{{'dllimport' attribute ignored}} +void __declspec(dllexport) __declspec(dllimport) precedence2B() {} // expected-warning{{'dllimport' attribute ignored}} + +void __declspec(dllimport) precedenceRedecl1(); // expected-warning{{'dllimport' attribute ignored}} +void __declspec(dllexport) precedenceRedecl1() {} + +void __declspec(dllexport) precedenceRedecl2(); +void __declspec(dllimport) precedenceRedecl2() {} // expected-warning{{'dllimport' attribute ignored}} diff --git a/clang/test/Sema/dllimport-dllexport.c b/clang/test/Sema/dllimport-dllexport.c deleted file mode 100644 index e93507846e60..000000000000 --- a/clang/test/Sema/dllimport-dllexport.c +++ /dev/null @@ -1,48 +0,0 @@ -// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify %s - -inline void __attribute__((dllexport)) foo1(){} // expected-warning{{'dllexport' attribute ignored}} -inline void __attribute__((dllimport)) foo2(){} // expected-warning{{'dllimport' attribute ignored}} - -void __attribute__((dllimport)) foo3(){} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}} - -void __attribute__((dllimport, dllexport)) foo4(); // expected-warning{{dllimport attribute ignored}} - -void __attribute__((dllexport)) foo5(); -void __attribute__((dllimport)) foo5(); // expected-warning{{dllimport attribute ignored}} - -typedef int __attribute__((dllexport)) type6; // expected-warning{{'dllexport' attribute only applies to variables and functions}} - -typedef int __attribute__((dllimport)) type7; // expected-warning{{'dllimport' attribute only applies to variables and functions}} - -void __attribute__((dllimport)) foo6(); -void foo6(){} // expected-warning {{'foo6' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} - -// PR6269 -inline void __declspec(dllexport) foo7(){} // expected-warning{{'dllexport' attribute ignored}} -inline void __declspec(dllimport) foo8(){} // expected-warning{{'dllimport' attribute ignored}} - -void __declspec(dllimport) foo9(){} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}} - -void __declspec(dllimport) __declspec(dllexport) foo10(); // expected-warning{{dllimport attribute ignored}} - -void __declspec(dllexport) foo11(); -void __declspec(dllimport) foo11(); // expected-warning{{dllimport attribute ignored}} - -typedef int __declspec(dllexport) type1; // expected-warning{{'dllexport' attribute only applies to variables and functions}} - -typedef int __declspec(dllimport) type2; // expected-warning{{'dllimport' attribute only applies to variables and functions}} - -void __declspec(dllimport) foo12(); -void foo12(){} // expected-warning {{'foo12' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} - -void __attribute__((dllimport)) foo13(); // expected-warning{{dllimport attribute ignored}} -void __attribute__((dllexport)) foo13(); - -extern int foo14 __attribute__((dllexport)); -extern int foo14 __attribute__((dllimport)); // expected-warning{{dllimport attribute ignored}} - -__declspec(dllimport) int foo15 = 54; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} - -extern __declspec(dllimport) int foo17; -int foo17 = 54; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} diff --git a/clang/test/Sema/dllimport.c b/clang/test/Sema/dllimport.c new file mode 100644 index 000000000000..ee1ad882b6a9 --- /dev/null +++ b/clang/test/Sema/dllimport.c @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c99 %s +// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c11 %s +// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c11 %s +// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c99 %s + +// Invalid usage. +__declspec(dllimport) typedef int typedef1; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +typedef __declspec(dllimport) int typedef2; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +typedef int __declspec(dllimport) typedef3; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +typedef __declspec(dllimport) void (*FunTy)(); // expected-warning{{'dllimport' attribute only applies to variables and functions}} +enum __declspec(dllimport) Enum { EnumVal }; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +struct __declspec(dllimport) Record {}; // expected-warning{{'dllimport' attribute only applies to variables and functions}} + + + +//===----------------------------------------------------------------------===// +// Globals +//===----------------------------------------------------------------------===// + +// Import declaration. +__declspec(dllimport) extern int ExternGlobalDecl; + +// dllimport implies a declaration. FIXME: This should not warn. +__declspec(dllimport) int GlobalDecl; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +// Not allowed on definitions. +__declspec(dllimport) int GlobalInit1 = 1; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} +int __declspec(dllimport) GlobalInit2 = 1; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +// Declare, then reject definition. +__declspec(dllimport) extern int ExternGlobalDeclInit; +int ExternGlobalDeclInit = 1; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +// Redeclarations +__declspec(dllimport) extern int GlobalRedecl1; +__declspec(dllimport) extern int GlobalRedecl1; + +// Import in local scope. +void functionScope() { + __declspec(dllimport) extern int ExternLocalVarDecl; +} + + + +//===----------------------------------------------------------------------===// +// Functions +//===----------------------------------------------------------------------===// + +// Import function declaration. Check different placements. +__attribute__((dllimport)) void decl1A(); // Sanity check with __attribute__ +__declspec(dllimport) void decl1B(); + +void __attribute__((dllimport)) decl2A(); +void __declspec(dllimport) decl2B(); + +// Not allowed on function definitions. +__declspec(dllimport) void def() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}} + +// Import inline function. +__declspec(dllimport) inline void inlineFunc1() {} // expected-warning{{'dllimport' attribute ignored}} +inline void __attribute__((dllimport)) inlineFunc2() {} // expected-warning{{'dllimport' attribute ignored}} + +// Redeclarations +__declspec(dllimport) void redecl1(); +__declspec(dllimport) void redecl1(); + +__declspec(dllimport) void redecl3(); + void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} diff --git a/clang/test/SemaCXX/dllexport.cpp b/clang/test/SemaCXX/dllexport.cpp new file mode 100644 index 000000000000..114ebd02bbf9 --- /dev/null +++ b/clang/test/SemaCXX/dllexport.cpp @@ -0,0 +1,189 @@ +// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c++1y %s +// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c++1y %s +// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c++11 %s + +// Helper structs to make templates more expressive. +struct ImplicitInst_Exported {}; +struct ExplicitDecl_Exported {}; +struct ExplicitInst_Exported {}; +struct ExplicitSpec_Exported {}; +struct ExplicitSpec_Def_Exported {}; +struct ExplicitSpec_InlineDef_Exported {}; +struct ExplicitSpec_NotExported {}; + + +// Invalid usage. +__declspec(dllexport) typedef int typedef1; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +typedef __declspec(dllexport) int typedef2; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +typedef int __declspec(dllexport) typedef3; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +typedef __declspec(dllexport) void (*FunTy)(); // expected-warning{{'dllexport' attribute only applies to variables and functions}} +enum __declspec(dllexport) Enum {}; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +#if __has_feature(cxx_strong_enums) + enum class __declspec(dllexport) EnumClass {}; // expected-warning{{'dllexport' attribute only applies to variables and functions}} +#endif + + + +//===----------------------------------------------------------------------===// +// Globals +//===----------------------------------------------------------------------===// + +// Export declaration. +__declspec(dllexport) extern int ExternGlobalDecl; + +// dllexport implies a definition. +__declspec(dllexport) int GlobalDef; + +// Export definition. +__declspec(dllexport) int GlobalInit1 = 1; +int __declspec(dllexport) GlobalInit2 = 1; + +// Declare, then export definition. +__declspec(dllexport) extern int GlobalDeclInit; +int GlobalDeclInit = 1; + +// Export in local scope. +void functionScope() { + __declspec(dllexport) extern int ExternLocalVarDecl; +} + + + +//===----------------------------------------------------------------------===// +// Functions +//===----------------------------------------------------------------------===// + +// Export function declaration. Check different placements. +__attribute__((dllexport)) void decl1A(); // Sanity check with __attribute__ +__declspec(dllexport) void decl1B(); + +void __attribute__((dllexport)) decl2A(); +void __declspec(dllexport) decl2B(); + +// Export function definition. +__declspec(dllexport) void def() {} + +// extern "C" +extern "C" __declspec(dllexport) void externC() {} + +// Export inline function. +__declspec(dllexport) inline void inlineFunc1() {} // expected-warning{{'dllexport' attribute ignored}} +inline void __attribute__((dllexport)) inlineFunc2() {} // expected-warning{{'dllexport' attribute ignored}} + +__declspec(dllexport) inline void inlineDecl(); // expected-warning{{'dllexport' attribute ignored}} + void inlineDecl() {} + +__declspec(dllexport) void inlineDef(); + inline void inlineDef() {} + +// Redeclarations +__declspec(dllexport) void redecl1(); +__declspec(dllexport) void redecl1() {} + +__declspec(dllexport) void redecl2(); + void redecl2() {} + + + +//===----------------------------------------------------------------------===// +// Function templates +//===----------------------------------------------------------------------===// + +// Export function template declaration. Check different placements. +template __declspec(dllexport) void funcTmplDecl1(); +template void __declspec(dllexport) funcTmplDecl2(); + +// Export function template definition. +template __declspec(dllexport) void funcTmplDef() {} + +// Redeclarations +template __declspec(dllexport) void funcTmplRedecl1(); +template __declspec(dllexport) void funcTmplRedecl1() {} + +template __declspec(dllexport) void funcTmplRedecl2(); +template void funcTmplRedecl2() {} + +template __declspec(dllexport) void funcTmplRedecl3(); +template void funcTmplRedecl3() {} + + +template void funcTmpl() {} +template __declspec(dllexport) void exportedFuncTmplDecl(); +template __declspec(dllexport) void exportedFuncTmpl() {} + +// Export implicit instantiation of an exported function template. +void useFunTmplDecl() { exportedFuncTmplDecl(); } +void useFunTmplDef() { exportedFuncTmpl(); } + +// Export explicit instantiation declaration of an exported function template. +extern template void exportedFuncTmpl(); + template void exportedFuncTmpl(); + +// Export explicit instantiation definition of an exported function template. +template void exportedFuncTmpl(); + +// Export specialization of an exported function template. +template<> __declspec(dllexport) void exportedFuncTmpl(); +template<> __declspec(dllexport) void exportedFuncTmpl() {} +template<> __declspec(dllexport) inline void exportedFuncTmpl() {} // expected-warning{{'dllexport' attribute ignored}} + +// Not exporting specialization of an exported function template without +// explicit dllexport. +template<> void exportedFuncTmpl() {} + + +// Export explicit instantiation declaration of a non-exported function template. +extern template __declspec(dllexport) void funcTmpl(); + template __declspec(dllexport) void funcTmpl(); + +// Export explicit instantiation definition of a non-exported function template. +template __declspec(dllexport) void funcTmpl(); + +// Export specialization of a non-exported function template. +template<> __declspec(dllexport) void funcTmpl(); +template<> __declspec(dllexport) void funcTmpl() {} +template<> __declspec(dllexport) inline void funcTmpl() {} // expected-warning{{'dllexport' attribute ignored}} + + + +//===----------------------------------------------------------------------===// +// Precedence +//===----------------------------------------------------------------------===// + +// dllexport takes precedence over dllimport if both are specified. +__attribute__((dllimport, dllexport)) extern int PrecedenceExternGlobal1A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllimport) __declspec(dllexport) extern int PrecedenceExternGlobal1B; // expected-warning{{'dllimport' attribute ignored}} + +__attribute__((dllexport, dllimport)) extern int PrecedenceExternGlobal2A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) __declspec(dllimport) extern int PrecedenceExternGlobal2B; // expected-warning{{'dllimport' attribute ignored}} + +__attribute__((dllimport, dllexport)) int PrecedenceGlobal1A; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllimport) __declspec(dllexport) int PrecedenceGlobal1B; // expected-warning{{'dllimport' attribute ignored}} + +__attribute__((dllexport, dllimport)) int PrecedenceGlobal2A; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} +__declspec(dllexport) __declspec(dllimport) int PrecedenceGlobal2B; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +__declspec(dllexport) extern int PrecedenceExternGlobalRedecl1; +__declspec(dllimport) extern int PrecedenceExternGlobalRedecl1; // expected-warning{{'dllimport' attribute ignored}} + +__declspec(dllimport) extern int PrecedenceExternGlobalRedecl2; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) extern int PrecedenceExternGlobalRedecl2; + +__declspec(dllexport) extern int PrecedenceGlobalRedecl1; +__declspec(dllimport) int PrecedenceGlobalRedecl1; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +__declspec(dllimport) extern int PrecedenceGlobalRedecl2; // expected-warning{{'dllimport' attribute ignored}} +__declspec(dllexport) int PrecedenceGlobalRedecl2; + +void __attribute__((dllimport, dllexport)) precedence1A() {} // expected-warning{{'dllimport' attribute ignored}} +void __declspec(dllimport) __declspec(dllexport) precedence1B() {} // expected-warning{{'dllimport' attribute ignored}} + +void __attribute__((dllexport, dllimport)) precedence2A() {} // expected-warning{{'dllimport' attribute ignored}} +void __declspec(dllexport) __declspec(dllimport) precedence2B() {} // expected-warning{{'dllimport' attribute ignored}} + +void __declspec(dllimport) precedenceRedecl1(); // expected-warning{{'dllimport' attribute ignored}} +void __declspec(dllexport) precedenceRedecl1() {} + +void __declspec(dllexport) precedenceRedecl2(); +void __declspec(dllimport) precedenceRedecl2() {} // expected-warning{{'dllimport' attribute ignored}} diff --git a/clang/test/SemaCXX/dllimport.cpp b/clang/test/SemaCXX/dllimport.cpp new file mode 100644 index 000000000000..d04a4b990aaf --- /dev/null +++ b/clang/test/SemaCXX/dllimport.cpp @@ -0,0 +1,127 @@ +// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -verify -std=c++1y %s +// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -verify -std=c++1y %s +// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -verify -std=c++11 %s + +// Helper structs to make templates more expressive. +struct ImplicitInst_Imported {}; +struct ExplicitDecl_Imported {}; +struct ExplicitInst_Imported {}; +struct ExplicitSpec_Imported {}; +struct ExplicitSpec_Def_Imported {}; +struct ExplicitSpec_InlineDef_Imported {}; +struct ExplicitSpec_NotImported {}; + + +// Invalid usage. +__declspec(dllimport) typedef int typedef1; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +typedef __declspec(dllimport) int typedef2; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +typedef int __declspec(dllimport) typedef3; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +typedef __declspec(dllimport) void (*FunTy)(); // expected-warning{{'dllimport' attribute only applies to variables and functions}} +enum __declspec(dllimport) Enum {}; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +#if __has_feature(cxx_strong_enums) + enum class __declspec(dllimport) EnumClass {}; // expected-warning{{'dllimport' attribute only applies to variables and functions}} +#endif + + + +//===----------------------------------------------------------------------===// +// Globals +//===----------------------------------------------------------------------===// + +// Import declaration. +__declspec(dllimport) extern int ExternGlobalDecl; + +// dllimport implies a declaration. FIXME: This should not warn. +__declspec(dllimport) int GlobalDecl; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +// Not allowed on definitions. +__declspec(dllimport) int GlobalInit1 = 1; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} +int __declspec(dllimport) GlobalInit2 = 1; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +// Declare, then reject definition. +__declspec(dllimport) extern int ExternGlobalDeclInit; +int ExternGlobalDeclInit = 1; // expected-warning{{'dllimport' attribute cannot be specified on a definition}} + +// Redeclarations +__declspec(dllimport) extern int GlobalRedecl1; +__declspec(dllimport) extern int GlobalRedecl1; + +// Import in local scope. +void functionScope() { + __declspec(dllimport) extern int ExternLocalVarDecl; +} + + + +//===----------------------------------------------------------------------===// +// Functions +//===----------------------------------------------------------------------===// + +// Import function declaration. Check different placements. +__attribute__((dllimport)) void decl1A(); // Sanity check with __attribute__ +__declspec(dllimport) void decl1B(); + +void __attribute__((dllimport)) decl2A(); +void __declspec(dllimport) decl2B(); + +// Not allowed on function definitions. +__declspec(dllimport) void def() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}} + +// extern "C" +extern "C" __declspec(dllexport) void externC(); + +// Import inline function. +__declspec(dllimport) inline void inlineFunc1() {} // expected-warning{{'dllimport' attribute ignored}} +inline void __attribute__((dllimport)) inlineFunc2() {} // expected-warning{{'dllimport' attribute ignored}} + +// Redeclarations +__declspec(dllimport) void redecl1(); +__declspec(dllimport) void redecl1(); + +__declspec(dllimport) void redecl3(); + void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + + + +//===----------------------------------------------------------------------===// +// Function templates +//===----------------------------------------------------------------------===// + +// Import function template declaration. Check different placements. +template __declspec(dllimport) void funcTmplDecl1(); +template void __declspec(dllimport) funcTmplDecl2(); + +// Redeclarations +template __declspec(dllimport) void funcTmplRedecl1(); +template __declspec(dllimport) void funcTmplRedecl1(); + +template __declspec(dllimport) void funcTmplRedecl2(); +template void funcTmplRedecl2(); + +template __declspec(dllimport) void funcTmplRedecl3(); +template void funcTmplRedecl3() {} // expected-warning{{'funcTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} + + +template void funcTmpl() {} +template __declspec(dllimport) void importedFuncTmpl(); + +// Import specialization of an imported function template. A definition must be +// declared inline. +template<> __declspec(dllimport) void importedFuncTmpl(); +template<> __declspec(dllimport) void importedFuncTmpl() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}} +template<> __declspec(dllimport) inline void importedFuncTmpl() {} // expected-warning{{'dllimport' attribute ignored}} + +// Not importing specialization of an imported function template without +// explicit dllimport. +template<> void importedFuncTmpl() {} + + +// Import explicit instantiation declaration of a non-imported function template. +extern template __declspec(dllimport) void funcTmpl(); + +// Import specialization of a non-imported function template. A definition must +// be declared inline. +template<> __declspec(dllimport) void funcTmpl(); +template<> __declspec(dllimport) void funcTmpl() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}} +template<> __declspec(dllimport) inline void funcTmpl() {} // expected-warning{{'dllimport' attribute ignored}}