Index: test/Sema/dllimport-dllexport.c
===================================================================
--- test/Sema/dllimport-dllexport.c	(revision 96294)
+++ test/Sema/dllimport-dllexport.c	(working copy)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple i386-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}}
@@ -16,3 +16,21 @@
 
 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 variable and function types}}
+
+typedef int __declspec(dllimport) type2; // expected-warning{{'dllimport' attribute only applies to variable and function}}
+
+void __declspec(dllimport) foo12();
+void foo12(){} // expected-warning {{'foo12' redeclared without dllimport attribute: previous dllimport ignored}}
Index: test/Parser/MicrosoftExtensions.c
===================================================================
--- test/Parser/MicrosoftExtensions.c	(revision 96294)
+++ test/Parser/MicrosoftExtensions.c	(working copy)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -x objective-c++ %s
+// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify -fms-extensions -x objective-c++ %s
 __stdcall int func0();
 int __stdcall func();
 typedef int (__cdecl *tptr)();
Index: test/CodeGen/dllimport-dllexport.c
===================================================================
--- test/CodeGen/dllimport-dllexport.c	(revision 96294)
+++ test/CodeGen/dllimport-dllexport.c	(working copy)
@@ -1,7 +1,12 @@
-// RUN: %clang_cc1 -emit-llvm < %s -o %t
-// RUN: grep 'dllexport' %t | count 1
-// RUN: not grep 'dllimport' %t
+// RUN: %clang_cc1 -triple i386-mingw32 -emit-llvm < %s | FileCheck %s
 
 void __attribute__((dllimport)) foo1();
 void __attribute__((dllexport)) foo1(){}
+// CHECK: define dllexport void @foo1
 void __attribute__((dllexport)) foo2();
+
+// PR6269
+__declspec(dllimport) void foo3();
+__declspec(dllexport) void foo3(){}
+// CHECK: define dllexport void @foo3
+__declspec(dllexport) void foo4();
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp	(revision 96294)
+++ lib/Sema/SemaDeclAttr.cpp	(working copy)
@@ -813,82 +813,6 @@
   D->addAttr(::new (S.Context) WeakImportAttr());
 }
 
-static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
-  // check the attribute arguments.
-  if (Attr.getNumArgs() != 0) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
-    return;
-  }
-
-  // Attribute can be applied only to functions or variables.
-  if (isa<VarDecl>(D)) {
-    D->addAttr(::new (S.Context) DLLImportAttr());
-    return;
-  }
-
-  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
-  if (!FD) {
-    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
-      << Attr.getName() << 2 /*variable and function*/;
-    return;
-  }
-
-  // Currently, the dllimport attribute is ignored for inlined functions.
-  // Warning is emitted.
-  if (FD->isInlineSpecified()) {
-    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 (S.Context) DLLImportAttr());
-}
-
-static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
-  // check the attribute arguments.
-  if (Attr.getNumArgs() != 0) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
-    return;
-  }
-
-  // Attribute can be applied only to functions or variables.
-  if (isa<VarDecl>(D)) {
-    D->addAttr(::new (S.Context) DLLExportAttr());
-    return;
-  }
-
-  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
-  if (!FD) {
-    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
-      << Attr.getName() << 2 /*variable and function*/;
-    return;
-  }
-
-  // Currently, the dllexport attribute is ignored for inlined functions, unless
-  // the -fkeep-inline-functions flag has been used. Warning is emitted;
-  if (FD->isInlineSpecified()) {
-    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
-    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
-    return;
-  }
-
-  D->addAttr(::new (S.Context) DLLExportAttr());
-}
-
 static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
                                     Sema &S) {
   // Attribute has 3 arguments.
@@ -1786,6 +1710,11 @@
   };
 }
 
+static bool isKnownDeclSpecAttr(const AttributeList &Attr) {
+  return Attr.getKind() == AttributeList::AT_dllimport ||
+         Attr.getKind() == AttributeList::AT_dllexport;
+}
+
 //===----------------------------------------------------------------------===//
 // Top Level Sema Entry Points
 //===----------------------------------------------------------------------===//
@@ -1796,8 +1725,8 @@
 /// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
 static void ProcessDeclAttribute(Scope *scope, Decl *D,
                                  const AttributeList &Attr, Sema &S) {
-  if (Attr.isDeclspecAttribute())
-    // FIXME: Try to deal with __declspec attributes!
+  if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr))
+   // FIXME: Try to deal with other __declspec attributes!
     return;
   switch (Attr.getKind()) {
   case AttributeList::AT_IBOutlet:    HandleIBOutletAttr  (D, Attr, S); break;
@@ -1820,8 +1749,6 @@
   case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
   case AttributeList::AT_deprecated:  HandleDeprecatedAttr  (D, Attr, S); break;
   case AttributeList::AT_destructor:  HandleDestructorAttr  (D, Attr, S); break;
-  case AttributeList::AT_dllexport:   HandleDLLExportAttr   (D, Attr, S); break;
-  case AttributeList::AT_dllimport:   HandleDLLImportAttr   (D, Attr, S); break;
   case AttributeList::AT_ext_vector_type:
     HandleExtVectorTypeAttr(scope, D, Attr, S);
     break;
@@ -1883,8 +1810,11 @@
   default:
     // Ask target about the attribute.
     const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
-    if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
-      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+    if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) {
+      const TargetAttributesSema &OSTargetAttrs = S.getOSTargetAttributesSema();
+      if (!OSTargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
+        S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+    }
     break;
   }
 }
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h	(revision 96294)
+++ lib/Sema/Sema.h	(working copy)
@@ -182,6 +182,7 @@
   Sema(const Sema&);           // DO NOT IMPLEMENT
   void operator=(const Sema&); // DO NOT IMPLEMENT
   mutable const TargetAttributesSema* TheTargetAttributesSema;
+  mutable const TargetAttributesSema* TheOSTargetAttributesSema;
 public:
   const LangOptions &LangOpts;
   Preprocessor &PP;
@@ -544,6 +545,7 @@
   Diagnostic &getDiagnostics() const { return Diags; }
   SourceManager &getSourceManager() const { return SourceMgr; }
   const TargetAttributesSema &getTargetAttributesSema() const;
+  const TargetAttributesSema &getOSTargetAttributesSema() const;
 
   /// \brief Helper class that creates diagnostics with optional
   /// template instantiation stacks.
Index: lib/Sema/TargetAttributesSema.cpp
===================================================================
--- lib/Sema/TargetAttributesSema.cpp	(revision 96294)
+++ lib/Sema/TargetAttributesSema.cpp	(working copy)
@@ -112,6 +112,100 @@
   };
 }
 
+static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // Attribute can be applied only to functions or variables.
+  if (isa<VarDecl>(D)) {
+    D->addAttr(::new (S.Context) DLLImportAttr());
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+  if (!FD) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  // Currently, the dllimport attribute is ignored for inlined functions.
+  // Warning is emitted.
+  if (FD->isInlineSpecified()) {
+    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 (S.Context) DLLImportAttr());
+}
+
+static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+
+  // Attribute can be applied only to functions or variables.
+  if (isa<VarDecl>(D)) {
+    D->addAttr(::new (S.Context) DLLExportAttr());
+    return;
+  }
+
+  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+  if (!FD) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << 2 /*variable and function*/;
+    return;
+  }
+
+  // Currently, the dllexport attribute is ignored for inlined functions, unless
+  // the -fkeep-inline-functions flag has been used. Warning is emitted;
+  if (FD->isInlineSpecified()) {
+    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
+    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
+    return;
+  }
+
+  D->addAttr(::new (S.Context) DLLExportAttr());
+}
+
+namespace {
+  class Win32AttributesSema : public TargetAttributesSema {
+  public:
+    Win32AttributesSema() { }
+    bool ProcessDeclAttribute(Scope *scope, Decl *D,
+                              const AttributeList &Attr, Sema &S) const {
+      switch (Attr.getKind()) {
+      case AttributeList::AT_dllimport: HandleDLLImportAttr(D, Attr, S);
+                                        return true;
+      case AttributeList::AT_dllexport: HandleDLLExportAttr(D, Attr, S);
+                                        return true;
+      default:                          break;
+      }
+      return false;
+    }
+  };
+}
+
 const TargetAttributesSema &Sema::getTargetAttributesSema() const {
   if (TheTargetAttributesSema)
     return *TheTargetAttributesSema;
@@ -128,3 +222,18 @@
   }
 }
 
+const TargetAttributesSema &Sema::getOSTargetAttributesSema() const {
+  if (TheOSTargetAttributesSema)
+    return *TheOSTargetAttributesSema;
+
+  const llvm::Triple &Triple(Context.Target.getTriple());
+  switch (Triple.getOS()) {
+  default:
+    return *(TheOSTargetAttributesSema = new TargetAttributesSema);
+
+  case llvm::Triple::MinGW32:
+  case llvm::Triple::Win32:
+    return *(TheOSTargetAttributesSema = new Win32AttributesSema);
+  }
+}
+
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp	(revision 96294)
+++ lib/Sema/Sema.cpp	(working copy)
@@ -112,7 +112,7 @@
 Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
            bool CompleteTranslationUnit,
            CodeCompleteConsumer *CodeCompleter)
-  : TheTargetAttributesSema(0),
+  : TheTargetAttributesSema(0), TheOSTargetAttributesSema(0),
     LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
     Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
     ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), 
