Add full dllimport / dllexport support: both sema checks and codegen.
Patch by Ilya Okonsky

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61437 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 81283a8..759ef09 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -685,6 +685,41 @@
     return;
   }
 
+  // Attribute can be applied only to functions or variables.
+  if (isa<VarDecl>(d)) {
+    d->addAttr(new DLLImportAttr());
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(d);
+  if (!FD) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << "dllimport" << "function or variable";
+    return;
+  }
+
+  // Currently, the dllimport attribute is ignored for inlined functions.
+  // Warning is emitted.
+  if (FD->isInline()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+    return;
+  }
+
+  // The attribute is also overridden by a subsequent declaration as dllexport.
+  // Warning is emitted.
+  for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
+       nextAttr = nextAttr->getNext()) {
+    if (nextAttr->getKind() == AttributeList::AT_dllexport) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+      return;
+    }
+  }
+
+  if (d->getAttr<DLLExportAttr>()) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+    return;
+  }
+
   d->addAttr(new DLLImportAttr());
 }
 
@@ -695,6 +730,27 @@
     return;
   }
 
+  // Attribute can be applied only to functions or variables.
+  if (isa<VarDecl>(d)) {
+    d->addAttr(new DLLExportAttr());
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(d);
+  if (!FD) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << "dllexport" << "function or variable";
+    return;
+  }
+
+  // Currently, the dllexport attribute is ignored for inlined functions,
+  // unless the -fkeep-inline-functions flag has been used. Warning is emitted;
+  if (FD->isInline()) {
+    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
+    return;
+  }
+
   d->addAttr(new DLLExportAttr());
 }