Allow dllimport/dllexport on inline functions and adjust the linkage.

This is a step towards handling these attributes on classes (PR11170).

Differential Revision: http://reviews.llvm.org/D3772

llvm-svn: 208925
diff --git a/clang/test/CodeGen/dllexport.c b/clang/test/CodeGen/dllexport.c
new file mode 100644
index 0000000..ce5636c
--- /dev/null
+++ b/clang/test/CodeGen/dllexport.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple i686-pc-win32 -std=c99 -O2 -disable-llvm-optzns -emit-llvm < %s | FileCheck %s
+
+#define DLLEXPORT __declspec(dllexport)
+
+inline void DLLEXPORT f() {}
+extern void DLLEXPORT f();
+
+// CHECK: define weak_odr dllexport void @f()
diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp
new file mode 100644
index 0000000..fe98068
--- /dev/null
+++ b/clang/test/CodeGenCXX/dllexport.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple i686-pc-win32 -x c++ -O2 -disable-llvm-optzns -emit-llvm < %s | FileCheck %s
+
+#define DLLEXPORT __declspec(dllexport)
+
+void DLLEXPORT a();
+// CHECK-DAG: declare dllexport void @"\01?a@@YAXXZ"()
+
+inline void DLLEXPORT b() {}
+// CHECK-DAG: define weak_odr dllexport void @"\01?b@@YAXXZ"()
+
+template <typename T> void c() {}
+template void DLLEXPORT c<int>();
+// CHECK-DAG: define weak_odr dllexport void @"\01??$c@H@@YAXXZ"()
+
+struct S {
+  void DLLEXPORT a() {}
+  // CHECK-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@S@@QAEXXZ"
+};
+
+void user() {
+  // FIXME: dllexported functions must be emitted even if they're not referenced in this TU.
+  a();
+  b();
+  &S::a;
+}
diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp
new file mode 100644
index 0000000..d8e58f7
--- /dev/null
+++ b/clang/test/CodeGenCXX/dllimport.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple i686-pc-win32 -x c++ -O2 -disable-llvm-optzns -emit-llvm < %s | FileCheck %s
+
+#define DLLIMPORT __declspec(dllimport)
+
+void DLLIMPORT a();
+// CHECK-DAG: declare dllimport void @"\01?a@@YAXXZ"()
+
+inline void DLLIMPORT b() {}
+// CHECK-DAG: define available_externally dllimport void @"\01?b@@YAXXZ"()
+
+template <typename T> inline void c() {} // FIXME: MSVC accepts this without 'inline' too.
+template void DLLIMPORT c<int>();
+// CHECK-DAG: define available_externally dllimport void @"\01??$c@H@@YAXXZ"()
+
+struct S {
+  void DLLIMPORT a() {}
+  // CHECK-DAG: define available_externally dllimport x86_thiscallcc void @"\01?a@S@@QAEXXZ"
+};
+
+void user(S* s) {
+  a();
+  b();
+  c<int>();
+  s->a();
+}
diff --git a/clang/test/Sema/dllexport.c b/clang/test/Sema/dllexport.c
index 8a71e5d..3a80b0b 100644
--- a/clang/test/Sema/dllexport.c
+++ b/clang/test/Sema/dllexport.c
@@ -69,10 +69,10 @@
 __declspec(dllexport) void def() {}
 
 // Export inline function.
-__declspec(dllexport) inline void inlineFunc1() {} // expected-warning{{'dllexport' attribute ignored}}
+__declspec(dllexport) inline void inlineFunc1() {}
 extern void inlineFunc1();
 
-inline void __attribute__((dllexport)) inlineFunc2() {} // expected-warning{{'dllexport' attribute ignored}}
+inline void __attribute__((dllexport)) inlineFunc2() {}
 extern void inlineFunc2();
 
 // Redeclarations
diff --git a/clang/test/Sema/dllimport.c b/clang/test/Sema/dllimport.c
index a498294..fa3e2b3 100644
--- a/clang/test/Sema/dllimport.c
+++ b/clang/test/Sema/dllimport.c
@@ -97,11 +97,11 @@
 void __declspec(dllimport)      decl2B();
 
 // Not allowed on function definitions.
-__declspec(dllimport) void def() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
+__declspec(dllimport) void def() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
 
 // Import inline function.
-__declspec(dllimport) inline void inlineFunc1() {} // expected-warning{{'dllimport' attribute ignored}}
-inline void __attribute__((dllimport)) inlineFunc2() {} // expected-warning{{'dllimport' attribute ignored}}
+__declspec(dllimport) inline void inlineFunc1() {}
+inline void __attribute__((dllimport)) inlineFunc2() {}
 
 // Redeclarations
 __declspec(dllimport) void redecl1();
diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp
index 0f6ebbb..3420d20 100644
--- a/clang/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp
@@ -122,7 +122,7 @@
 void f2(void); // expected-note{{previous declaration is here}}
 };
 
-__declspec(dllimport) void AAA::f2(void) { // expected-error{{'dllimport' attribute can be applied only to symbol}}
+__declspec(dllimport) void AAA::f2(void) { // expected-error{{dllimport cannot be applied to non-inline function definition}}
                                            // expected-error@-1{{redeclaration of 'AAA::f2' cannot add 'dllimport' attribute}}
 
 }
diff --git a/clang/test/SemaCXX/dllexport.cpp b/clang/test/SemaCXX/dllexport.cpp
index 3558eef..6d67ec2 100644
--- a/clang/test/SemaCXX/dllexport.cpp
+++ b/clang/test/SemaCXX/dllexport.cpp
@@ -92,10 +92,10 @@
 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 inlineFunc1() {}
+inline void __attribute__((dllexport)) inlineFunc2() {}
 
-__declspec(dllexport) inline void inlineDecl(); // expected-warning{{'dllexport' attribute ignored}}
+__declspec(dllexport) inline void inlineDecl();
                              void inlineDecl() {}
 
 __declspec(dllexport) void inlineDef();
@@ -188,7 +188,7 @@
 // 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}}
+template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {}
 
 // Not exporting specialization of an exported function template without
 // explicit dllexport.
@@ -205,7 +205,7 @@
 // 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}}
+template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {}
 
 
 
diff --git a/clang/test/SemaCXX/dllimport.cpp b/clang/test/SemaCXX/dllimport.cpp
index 95e9e7d..def18fa 100644
--- a/clang/test/SemaCXX/dllimport.cpp
+++ b/clang/test/SemaCXX/dllimport.cpp
@@ -116,14 +116,14 @@
 void __declspec(dllimport)      decl2B();
 
 // Not allowed on function definitions.
-__declspec(dllimport) void def() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
+__declspec(dllimport) void def() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
 
 // 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}}
+__declspec(dllimport) inline void inlineFunc1() {}
+inline void __attribute__((dllimport)) inlineFunc2() {}
 
 // Redeclarations
 __declspec(dllimport) void redecl1();
@@ -209,8 +209,8 @@
 // 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}}
+template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
+template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {}
 
 // Not importing specialization of an imported function template without
 // explicit dllimport.
@@ -223,5 +223,5 @@
 // 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}}
+template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{dllimport cannot be applied to non-inline function definition}}
+template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {}