This patch reorganizes and improves the tests for the current support of
dllimport and dllexport. It provides the basis for further patches
implementing full semantic checking for these attributes.

These tests don't include class members and templates yet to reduce the
test churn for the first commits. I also only test using __declspec
(there are one or two tests using __attribute__) as it seems overkill to
duplicate everything. If it's absolutely required to check both
spellings, I would do so by duplicating all runlines and using macros.

-Nico
>From e511d8c41becd5e465753e295be3142da726f420 Mon Sep 17 00:00:00 2001
From: Nico Rieck <[email protected]>
Date: Thu, 13 Feb 2014 01:04:11 +0100
Subject: [PATCH] Reorganize and improve semantic tests for dllexport/import

---
 lib/Sema/SemaDeclAttr.cpp         |   4 +-
 test/Rewriter/dllimport-typedef.c |   2 +-
 test/Sema/dllexport.c             | 113 +++++++++++++++++++++++
 test/Sema/dllimport-dllexport.c   |  48 ----------
 test/Sema/dllimport.c             |  68 ++++++++++++++
 test/SemaCXX/dllexport.cpp        | 189 ++++++++++++++++++++++++++++++++++++++
 test/SemaCXX/dllimport.cpp        | 127 +++++++++++++++++++++++++
 7 files changed, 500 insertions(+), 51 deletions(-)
 create mode 100644 test/Sema/dllexport.c
 delete mode 100644 test/Sema/dllimport-dllexport.c
 create mode 100644 test/Sema/dllimport.c
 create mode 100644 test/SemaCXX/dllexport.cpp
 create mode 100644 test/SemaCXX/dllimport.cpp

diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 1bc34aa..9b7c3a9 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -3822,7 +3822,7 @@ static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
 DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range,
                                         unsigned AttrSpellingListIndex) {
   if (D->hasAttr<DLLExportAttr>()) {
-    Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
+    Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'dllimport'";
     return NULL;
   }
 
@@ -3870,7 +3870,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<DLLImportAttr>()) {
-    Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
+    Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import;
     D->dropAttr<DLLImportAttr>();
   }
 
diff --git a/test/Rewriter/dllimport-typedef.c b/test/Rewriter/dllimport-typedef.c
index 97610dd..b587f16 100644
--- a/test/Rewriter/dllimport-typedef.c
+++ b/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/test/Sema/dllexport.c b/test/Sema/dllexport.c
new file mode 100644
index 0000000..fb209e1
--- /dev/null
+++ b/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/test/Sema/dllimport-dllexport.c b/test/Sema/dllimport-dllexport.c
deleted file mode 100644
index e935078..0000000
--- a/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/test/Sema/dllimport.c b/test/Sema/dllimport.c
new file mode 100644
index 0000000..ee1ad88
--- /dev/null
+++ b/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/test/SemaCXX/dllexport.cpp b/test/SemaCXX/dllexport.cpp
new file mode 100644
index 0000000..114ebd0
--- /dev/null
+++ b/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<typename T> __declspec(dllexport) void funcTmplDecl1();
+template<typename T> void __declspec(dllexport) funcTmplDecl2();
+
+// Export function template definition.
+template<typename T> __declspec(dllexport) void funcTmplDef() {}
+
+// Redeclarations
+template<typename T> __declspec(dllexport) void funcTmplRedecl1();
+template<typename T> __declspec(dllexport) void funcTmplRedecl1() {}
+
+template<typename T> __declspec(dllexport) void funcTmplRedecl2();
+template<typename T>                       void funcTmplRedecl2() {}
+
+template<typename T> __declspec(dllexport) void funcTmplRedecl3();
+template<typename T>                       void funcTmplRedecl3() {}
+
+
+template<typename T> void funcTmpl() {}
+template<typename T> __declspec(dllexport) void exportedFuncTmplDecl();
+template<typename T> __declspec(dllexport) void exportedFuncTmpl() {}
+
+// Export implicit instantiation of an exported function template.
+void useFunTmplDecl() { exportedFuncTmplDecl<ImplicitInst_Exported>(); }
+void useFunTmplDef() { exportedFuncTmpl<ImplicitInst_Exported>(); }
+
+// Export explicit instantiation declaration of an exported function template.
+extern template void exportedFuncTmpl<ExplicitDecl_Exported>();
+       template void exportedFuncTmpl<ExplicitDecl_Exported>();
+
+// Export explicit instantiation definition of an exported function template.
+template void exportedFuncTmpl<ExplicitInst_Exported>();
+
+// Export specialization of an exported function template.
+template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Exported>();
+template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Def_Exported>() {}
+template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {} // expected-warning{{'dllexport' attribute ignored}}
+
+// Not exporting specialization of an exported function template without
+// explicit dllexport.
+template<> void exportedFuncTmpl<ExplicitSpec_NotExported>() {}
+
+
+// Export explicit instantiation declaration of a non-exported function template.
+extern template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>();
+       template __declspec(dllexport) void funcTmpl<ExplicitDecl_Exported>();
+
+// Export explicit instantiation definition of a non-exported function template.
+template __declspec(dllexport) void funcTmpl<ExplicitInst_Exported>();
+
+// Export specialization of a non-exported function template.
+template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Exported>();
+template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Def_Exported>() {}
+template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {} // 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/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp
new file mode 100644
index 0000000..d04a4b9
--- /dev/null
+++ b/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<typename T> __declspec(dllimport) void funcTmplDecl1();
+template<typename T> void __declspec(dllimport) funcTmplDecl2();
+
+// Redeclarations
+template<typename T> __declspec(dllimport) void funcTmplRedecl1();
+template<typename T> __declspec(dllimport) void funcTmplRedecl1();
+
+template<typename T> __declspec(dllimport) void funcTmplRedecl2();
+template<typename T>                       void funcTmplRedecl2();
+
+template<typename T> __declspec(dllimport) void funcTmplRedecl3();
+template<typename T>                       void funcTmplRedecl3() {} // expected-warning{{'funcTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+
+template<typename T> void funcTmpl() {}
+template<typename T> __declspec(dllimport) void importedFuncTmpl();
+
+// Import specialization of an imported function template. A definition must be
+// declared inline.
+template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Imported>();
+template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
+template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {} // expected-warning{{'dllimport' attribute ignored}}
+
+// Not importing specialization of an imported function template without
+// explicit dllimport.
+template<> void importedFuncTmpl<ExplicitSpec_NotImported>() {}
+
+
+// Import explicit instantiation declaration of a non-imported function template.
+extern template __declspec(dllimport) void funcTmpl<ExplicitDecl_Imported>();
+
+// Import specialization of a non-imported function template. A definition must
+// be declared inline.
+template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Imported>();
+template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
+template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {} // expected-warning{{'dllimport' attribute ignored}}
-- 
1.8.1.msysgit.1

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to