Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td	(revision 158272)
+++ include/clang/Basic/Attr.td	(working copy)
@@ -135,7 +135,7 @@
 def Aligned : InheritableAttr {
   let Spellings = ["aligned", "align"];
   let Subjects = [NonBitField, NormalVar, Tag];
-  let Args = [AlignedArgument<"Alignment">];
+  let Args = [AlignedArgument<"Alignment">, BoolArgument<"IsMSDeclSpec">];
   let Namespaces = ["", "std"];
 }
 
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td	(revision 158272)
+++ include/clang/Basic/DiagnosticParseKinds.td	(working copy)
@@ -481,6 +481,9 @@
   "introducing an attribute">;
 def err_alignas_pack_exp_unsupported : Error<
   "pack expansions in alignment specifiers are not supported yet">;
+def err_unknown_ms_declspec : Error<"unrecognized __declspec attribute %0">;
+def err_ms_declspec_type : Error<
+  "__declspec attributes must be an identifier or string literal">;
 
 /// C++ Templates
 def err_expected_template : Error<"expected template">;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 158272)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -1619,11 +1619,16 @@
 
 def err_attribute_aligned_not_power_of_two : Error<
   "requested alignment is not a power of 2">;
+def err_attribute_aligned_greater_than_8192 : Error<
+  "requested alignment must be 8192 bytes or smaller">;
 def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
   "'%0' redeclared without %1 attribute: previous %1 ignored">;
 def warn_attribute_ignored : Warning<"%0 attribute ignored">;
 def warn_unknown_attribute_ignored : Warning<
   "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
+def warn_unhandled_ms_attribute_ignored : Warning<
+  "__declspec %0 is a valid Microsoft attribute, but is ignored">, 
+  InGroup<IgnoredAttributes>;
 def warn_attribute_invalid_on_stmt : Warning<
   "attribute %0 cannot be specified on a statement">,
   InGroup<IgnoredAttributes>;
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 158272)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -1790,7 +1790,14 @@
   }
   void ParseMicrosoftAttributes(ParsedAttributes &attrs,
                                 SourceLocation *endLoc = 0);
-  void ParseMicrosoftDeclSpec(ParsedAttributes &attrs);
+  void ParseMicrosoftDeclSpec(ParsedAttributes &Attrs);
+  bool IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident);
+  bool ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, 
+                                      SourceLocation Loc,
+                                      ParsedAttributes &Attrs);
+  void ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName, 
+                                            SourceLocation AttrNameLoc, 
+                                            ParsedAttributes &Attrs);
   void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
   void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
   void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
Index: include/clang/Sema/AttributeList.h
===================================================================
--- include/clang/Sema/AttributeList.h	(revision 158272)
+++ include/clang/Sema/AttributeList.h	(working copy)
@@ -80,6 +80,9 @@
   /// availability attribute.
   unsigned IsAvailability : 1;
 
+  /// True if this attribute is actually a type attribute
+  unsigned IsTypeAttribute : 1;
+
   unsigned AttrKind : 8;
 
   /// \brief The location of the 'unavailable' keyword in an
@@ -123,13 +126,13 @@
                 IdentifierInfo *scopeName, SourceLocation scopeLoc,
                 IdentifierInfo *parmName, SourceLocation parmLoc,
                 Expr **args, unsigned numArgs,
-                bool declspec, bool cxx0x)
+                bool declspec, bool cxx0x, bool isTypeAttr)
     : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
       NumArgs(numArgs),
       DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false),
       UsedAsTypeAttr(false), IsAvailability(false), 
-      NextInPosition(0), NextInPool(0) {
+      IsTypeAttribute(isTypeAttr), NextInPosition(0), NextInPool(0) {
     if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
     AttrKind = getKind(getName(), getScopeName());
   }
@@ -142,13 +145,13 @@
                 const AvailabilityChange &obsoleted,
                 SourceLocation unavailable, 
                 const Expr *messageExpr,
-                bool declspec, bool cxx0x)
+                bool declspec, bool cxx0x, bool isTypeAttr)
     : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
       NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x),
       Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
       UnavailableLoc(unavailable), MessageExpr(messageExpr),
-      NextInPosition(0), NextInPool(0) {
+      IsTypeAttribute(isTypeAttr), NextInPosition(0), NextInPool(0) {
     new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
     new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
     new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
@@ -184,6 +187,8 @@
   bool isInvalid() const { return Invalid; }
   void setInvalid(bool b = true) const { Invalid = b; }
 
+  bool isTypeAttribute() const { return IsTypeAttribute; }
+
   bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
   void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
 
@@ -371,15 +376,15 @@
   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
                         IdentifierInfo *parmName, SourceLocation parmLoc,
-                        Expr **args, unsigned numArgs,
-                        bool declspec = false, bool cxx0x = false) {
+                        Expr **args, unsigned numArgs, bool declspec = false, 
+                        bool cxx0x = false, bool isTypeAttribute = false) {
     void *memory = allocate(sizeof(AttributeList)
                             + numArgs * sizeof(Expr*));
     return add(new (memory) AttributeList(attrName, attrRange,
                                           scopeName, scopeLoc,
                                           parmName, parmLoc,
                                           args, numArgs,
-                                          declspec, cxx0x));
+                                          declspec, cxx0x, isTypeAttribute));
   }
 
   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
@@ -389,15 +394,15 @@
                         const AvailabilityChange &deprecated,
                         const AvailabilityChange &obsoleted,
                         SourceLocation unavailable,
-                        const Expr *MessageExpr,
-                        bool declspec = false, bool cxx0x = false) {
+                        const Expr *MessageExpr, bool declspec = false, 
+                        bool cxx0x = false, bool isTypeAttribute = false) {
     void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
     return add(new (memory) AttributeList(attrName, attrRange,
                                           scopeName, scopeLoc,
                                           parmName, parmLoc,
                                           introduced, deprecated, obsoleted,
                                           unavailable, MessageExpr,
-                                          declspec, cxx0x));
+                                          declspec, cxx0x, isTypeAttribute));
   }
 
   AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
@@ -498,11 +503,11 @@
   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
                         IdentifierInfo *parmName, SourceLocation parmLoc,
-                        Expr **args, unsigned numArgs,
-                        bool declspec = false, bool cxx0x = false) {
+                        Expr **args, unsigned numArgs, bool declspec = false, 
+                        bool cxx0x = false, bool isTypeAttribute = false) {
     AttributeList *attr =
       pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
-                  args, numArgs, declspec, cxx0x);
+                  args, numArgs, declspec, cxx0x, isTypeAttribute);
     add(attr);
     return attr;
   }
@@ -514,13 +519,12 @@
                         const AvailabilityChange &deprecated,
                         const AvailabilityChange &obsoleted,
                         SourceLocation unavailable,
-                        const Expr *MessageExpr,
-                        bool declspec = false, bool cxx0x = false) {
+                        const Expr *MessageExpr, bool declspec = false, 
+                        bool cxx0x = false, bool isTypeAttribute = false) {
     AttributeList *attr =
       pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
                   introduced, deprecated, obsoleted, unavailable,
-                  MessageExpr,
-                  declspec, cxx0x);
+                  MessageExpr, declspec, cxx0x, isTypeAttribute);
     add(attr);
     return attr;
   }
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 158272)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -6329,8 +6329,10 @@
   void AddCFAuditedAttribute(Decl *D);
 
   /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
-  void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E);
-  void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T);
+  void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, 
+                      bool isDeclSpec);
+  void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T, 
+                      bool isDeclSpec);
 
   /// \brief The kind of conversion being performed.
   enum CheckedConversionKind {
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 158272)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -281,61 +281,164 @@
   }
 }
 
+///
+/// ParseMicrosoftDeclSpecWithSingleArg
+///
+/// \brief Parses a single argument for a declspec, including the 
+// surrounding parens
+void Parser::ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName, 
+                                                  SourceLocation AttrNameLoc,
+                                                  ParsedAttributes &Attrs)
+{
+  BalancedDelimiterTracker T(*this, tok::l_paren);
+  if (T.expectAndConsume(diag::err_expected_lparen_after, 
+                          AttrName->getNameStart(), tok::r_paren)) {
+    return;
+  }
 
-/// ParseMicrosoftDeclSpec - Parse an __declspec construct
+  ExprResult ArgExpr(ParseConstantExpression());
+  if (!ArgExpr.isInvalid()) {
+    Expr *ExprList = ArgExpr.take();
+    Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), 
+                  &ExprList, 1, true);
+  } else {
+    T.skipToEnd();
+  }
+
+  T.consumeClose();
+}
+
+/// 
+/// IsSimpleMicrosoftDeclSpec
 ///
+/// \brief Determines whether a declspec is a "simple" one requiring no 
+/// arguments.
+bool Parser::IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident) {
+  return llvm::StringSwitch<bool>(Ident->getName())
+    .Case("dllimport", true)
+    .Case("dllexport", true)
+    .Case("noreturn", true)
+    .Case("nothrow", true)
+    .Case("noinline", true)
+    .Case("naked", true)
+    .Case("appdomain", true)
+    .Case("process", true)
+    .Case("jitintrinsic", true)
+    .Case("noalias", true)
+    .Case("restrict", true)
+    .Case("novtable", true)
+    .Case("selectany", true)
+    .Case("thread", true)
+    .Default(false);
+}
+
+/// 
+/// ParseComplexMicrosoftDeclSpec
+///
+/// \brief Attempts to parse a declspec which is not simple (one that takes 
+/// parameters).  Will return false if we properly handled the declspec, or
+/// true if it is an unknown declspec.
+bool Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, 
+                                            SourceLocation Loc,
+                                            ParsedAttributes &Attrs) {
+  // Try to handle the easy case first -- these declspecs all take a single
+  // parameter as their argument
+  if (llvm::StringSwitch<bool>(Ident->getName())
+      .Case("uuid", true)
+      .Case("align", true)
+      .Case("allocate", true)
+      .Default(false)) {
+    ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs);
+  } else if (Ident->getName() == "deprecated") {
+    // The deprecated declspec has an optional single argument, so we will 
+    // check for a l-paren to decide whether we should parse an argument or 
+    // not.
+    if (Tok.getKind() == tok::l_paren)
+      ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs);
+    else
+      Attrs.addNew(Ident, Loc, 0, Loc, 0, SourceLocation(), 0, 0, true );
+  } else if (Ident->getName() == "property") {
+    // The property declspec is more complex in that it can take one or two
+    // assignment expressions as a parameter, but the lhs of the assignment 
+    // must be named get or put.
+    //
+    // For right now, we will just skip to the closing right paren of the 
+    // property expression
+    //
+    // FIXME: we should deal with __declspec(property) at some point because it
+    // is used in the platform SDK headers for the Parallel Patterns Library
+    // and ATL.
+    return true;
+  } else {
+    // We don't recognize this as a valid declspec, so let the caller know
+    Diag(Loc, diag::err_unknown_ms_declspec) << Ident;   
+    return true;
+  }
+  return false;
+}
+
 /// [MS] decl-specifier:
 ///             __declspec ( extended-decl-modifier-seq )
 ///
 /// [MS] extended-decl-modifier-seq:
 ///             extended-decl-modifier[opt]
 ///             extended-decl-modifier extended-decl-modifier-seq
-
-void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &attrs) {
+void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) {
   assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
 
   ConsumeToken();
-  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
-                       "declspec")) {
-    SkipUntil(tok::r_paren, true); // skip until ) or ;
+  BalancedDelimiterTracker T(*this, tok::l_paren);
+  if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec", 
+                          tok::r_paren)) {
     return;
   }
 
-  while (Tok.getIdentifierInfo()) {
-    IdentifierInfo *AttrName = Tok.getIdentifierInfo();
-    SourceLocation AttrNameLoc = ConsumeToken();
-    
-    // FIXME: Remove this when we have proper __declspec(property()) support.
-    // Just skip everything inside property().
-    if (AttrName->getName() == "property") {
-      ConsumeParen();
-      SkipUntil(tok::r_paren);
+  // We expect either a well-known identifier or a generic string.  Anything
+  // else is a malformed declspec.
+  bool IsString = Tok.getKind() == tok::string_literal ? true : false;
+  if (!IsString && Tok.getKind() != tok::identifier && 
+      Tok.getKind() != tok::kw_restrict) {
+    Diag(Tok, diag::err_ms_declspec_type);
+    T.skipToEnd();
+    return;
+  }
+
+  IdentifierInfo *AttrName;
+  SourceLocation AttrNameLoc;
+  if (IsString) {
+    SmallString<8> StrBuffer;
+    bool Invalid = false;
+    StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid);
+    if (Invalid) {
+      T.skipToEnd();
+      return;
     }
-    if (Tok.is(tok::l_paren)) {
-      ConsumeParen();
-      // FIXME: This doesn't parse __declspec(property(get=get_func_name))
-      // correctly.
-      ExprResult ArgExpr(ParseAssignmentExpression());
-      if (!ArgExpr.isInvalid()) {
-        Expr *ExprList = ArgExpr.take();
-        attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
-                     SourceLocation(), &ExprList, 1, true);
-      }
-      if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
-        SkipUntil(tok::r_paren, false);
-    } else {
-      attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc,
-                   0, SourceLocation(), 0, 0, true);
-    }
+    AttrName = PP.getIdentifierInfo( Str );
+    AttrNameLoc = ConsumeStringToken();
+  } else {
+    AttrName = Tok.getIdentifierInfo();
+    AttrNameLoc = ConsumeToken();
   }
-  if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
-    SkipUntil(tok::r_paren, false);
-  return;
+  
+  if (IsString || IsSimpleMicrosoftDeclSpec(AttrName)) {
+    // If we have a generic string, we will allow it because there is no 
+    // documented list of allowable string declspecs, but we know they exist 
+    // (for instance, SAL declspecs in older versions of MSVC).
+    //
+    // Alternatively, if the identifier is a simple one, then it requires no 
+    // arguments and can be turned into an attribute directly.
+    Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), 
+                  0, 0, true );
+  } else if(ParseComplexMicrosoftDeclSpec(AttrName, AttrNameLoc, Attrs)) {
+    T.skipToEnd();
+    return;
+  }
+
+  T.consumeClose();
 }
 
 void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
   // Treat these like attributes
-  // FIXME: Allow Sema to distinguish between these and real attributes!
   while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
          Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl)   ||
          Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) ||
@@ -344,7 +447,7 @@
     IdentifierInfo *AttrName = Tok.getIdentifierInfo();
     SourceLocation AttrNameLoc = ConsumeToken();
     attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
-                 SourceLocation(), 0, 0, true);
+                 SourceLocation(), 0, 0, true, false, true);
   }
 }
 
@@ -354,7 +457,7 @@
     IdentifierInfo *AttrName = Tok.getIdentifierInfo();
     SourceLocation AttrNameLoc = ConsumeToken();
     attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
-                 SourceLocation(), 0, 0, true);
+                 SourceLocation(), 0, 0, true, false, true);
   }
 }
 
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp	(revision 158272)
+++ lib/Sema/SemaDeclAttr.cpp	(working copy)
@@ -2900,30 +2900,34 @@
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     return;
   }
-  
+
   //FIXME: The C++0x version of this attribute has more limited applicabilty
   //       than GNU's, and should error out when it is used to specify a
   //       weaker alignment, rather than being silently ignored.
 
   if (Attr.getNumArgs() == 0) {
-    D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, true, 0));
+    D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, 
+                true, 0, Attr.isDeclspecAttribute()));
     return;
   }
 
-  S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0));
+  S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0), 
+                    Attr.isDeclspecAttribute());
 }
 
-void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E) {
+void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, 
+                          bool isDeclSpec) {
   // FIXME: Handle pack-expansions here.
   if (DiagnoseUnexpandedParameterPack(E))
     return;
 
   if (E->isTypeDependent() || E->isValueDependent()) {
     // Save dependent expressions in the AST to be instantiated.
-    D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E));
+    D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E, 
+                                            isDeclSpec));
     return;
   }
-
+  
   SourceLocation AttrLoc = AttrRange.getBegin();
   // FIXME: Cache the number on the Attr object?
   llvm::APSInt Alignment(32);
@@ -2938,14 +2942,26 @@
       << E->getSourceRange();
     return;
   }
+  if (isDeclSpec) {
+    // We've already verified it's a power of 2, now let's make sure it's
+    // 8192 or less
+    if (Alignment.getZExtValue() > 8192) {
+      Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) 
+        << E->getSourceRange();
+      return;
+    }
+  }
 
-  D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take()));
+  D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take(), 
+                                          isDeclSpec));
 }
 
-void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS) {
+void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, 
+                          bool isDeclSpec) {
   // FIXME: Cache the number on the Attr object if non-dependent?
   // FIXME: Perform checking of type validity
-  D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, false, TS));
+  D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, false, TS, 
+                                          isDeclSpec));
   return;
 }
 
@@ -3782,22 +3798,6 @@
                  ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context));
 }
 
-static bool isKnownDeclSpecAttr(const AttributeList &Attr) {
-  switch (Attr.getKind()) {
-  default:
-    return false;
-  case AttributeList::AT_dllimport:
-  case AttributeList::AT_dllexport:
-  case AttributeList::AT_uuid:
-  case AttributeList::AT_deprecated:
-  case AttributeList::AT_noreturn:
-  case AttributeList::AT_nothrow:
-  case AttributeList::AT_naked:
-  case AttributeList::AT_noinline:
-    return true;
-  }
-}
-
 //===----------------------------------------------------------------------===//
 // Microsoft specific attribute handlers.
 //===----------------------------------------------------------------------===//
@@ -3906,10 +3906,10 @@
 static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
                                        const AttributeList &Attr) {
   switch (Attr.getKind()) {
-    case AttributeList::AT_ibaction:            handleIBAction(S, D, Attr); break;
-    case AttributeList::AT_iboutlet:          handleIBOutlet(S, D, Attr); break;
-    case AttributeList::AT_iboutletcollection:
-      handleIBOutletCollection(S, D, Attr); break;
+  case AttributeList::AT_ibaction:          handleIBAction(S, D, Attr); break;
+  case AttributeList::AT_iboutlet:          handleIBOutlet(S, D, Attr); break;
+  case AttributeList::AT_iboutletcollection:
+    handleIBOutletCollection(S, D, Attr); break;
   case AttributeList::AT_address_space:
   case AttributeList::AT_opencl_image_access:
   case AttributeList::AT_objc_gc:
@@ -4146,7 +4146,9 @@
     // Ask target about the attribute.
     const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
     if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
-      S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored)
+      S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ? 
+              diag::warn_unhandled_ms_attribute_ignored : 
+              diag::warn_unknown_attribute_ignored)
         << Attr.getName();
     break;
   }
@@ -4162,8 +4164,11 @@
   if (Attr.isInvalid())
     return;
 
-  if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr))
-    // FIXME: Try to deal with other __declspec attributes!
+  // Type attributes are still treated as declaration attributes by 
+  // ParseMicrosoftTypeAttributes and ParseBorlandTypeAttributes.  We don't 
+  // want to process them, however, because we will simply warn about ignoring 
+  // them.  So instead, we will bail out early.
+  if (Attr.isTypeAttribute())
     return;
 
   if (NonInheritable)
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp	(revision 158272)
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp	(working copy)
@@ -79,14 +79,16 @@
           ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
                                         TemplateArgs);
           if (!Result.isInvalid())
-            AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>());
+            AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(), 
+                            Aligned->getIsMSDeclSpec());
         } else {
           TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
                                              TemplateArgs,
                                              Aligned->getLocation(),
                                              DeclarationName());
           if (Result)
-            AddAlignedAttr(Aligned->getLocation(), New, Result);
+            AddAlignedAttr(Aligned->getLocation(), New, Result, 
+                            Aligned->getIsMSDeclSpec());
         }
         continue;
       }
Index: test/CodeGen/ms-declspecs.c
===================================================================
--- test/CodeGen/ms-declspecs.c	(revision 158272)
+++ test/CodeGen/ms-declspecs.c	(working copy)
@@ -1,5 +1,13 @@
 // RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -fms-compatibility -o - | FileCheck %s
 
+struct __declspec(align(16)) S {
+  char x;
+};
+union { struct S s; } u;
+
+// CHECK: @u = {{.*}}zeroinitializer, align 16
+
+
 // CHECK: define void @t3() nounwind noinline naked {
 __declspec(naked) void t3() {}
 
Index: test/Parser/MicrosoftExtensions.c
===================================================================
--- test/Parser/MicrosoftExtensions.c	(revision 158272)
+++ test/Parser/MicrosoftExtensions.c	(working copy)
@@ -3,10 +3,10 @@
 int __stdcall func();
 typedef int (__cdecl *tptr)();
 void (*__fastcall fastpfunc)();
-struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) __declspec(novtable) IUnknown {};
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) __declspec(novtable) IUnknown {}; /* expected-warning{{__declspec 'novtable' is a valid Microsoft attribute, but is ignored}} */
 extern __declspec(dllimport) void __stdcall VarR4FromDec();
 __declspec(deprecated) __declspec(deprecated) char * __cdecl ltoa( long _Val, char * _DstBuf, int _Radix);
-__declspec(noalias) __declspec(restrict) void * __cdecl xxx( void * _Memory );
+__declspec(noalias) __declspec(restrict) void * __cdecl xxx( void * _Memory ); /* expected-warning{{__declspec 'noalias' is a valid Microsoft attribute, but is ignored}} expected-warning{{__declspec 'restrict' is a valid Microsoft attribute, but is ignored}} */
 typedef __w64 unsigned long ULONG_PTR, *PULONG_PTR;
 
 void * __ptr64 PtrToPtr64(const void *p)
@@ -69,7 +69,7 @@
 [repeatable][source_annotation_attribute( Parameter|ReturnValue )]
 struct SA_Post{ SA_Post(); int attr; };
 
-[returnvalue:SA_Post( attr=1)] 
+[returnvalue:SA_Post( attr=1)]
 int foo1([SA_Post(attr=1)] void *param);
 
 
@@ -80,3 +80,9 @@
   __assume(a);
   __debugbreak();
 }
+
+struct __declspec(frobble) S1 {};	// expected-error {{unrecognized __declspec attribute 'frobble'}}
+struct __declspec(12) S2 {};	// expected-error {{__declspec attributes must be an identifier or string literal}}
+
+// We don't expect any diagnostics for a string declspec
+struct __declspec("testing") S3 {}; /* expected-warning{{__declspec '"testing"' is a valid Microsoft attribute, but is ignored}} */
Index: test/Sema/MicrosoftCompatibility.c
===================================================================
--- test/Sema/MicrosoftCompatibility.c	(revision 158272)
+++ test/Sema/MicrosoftCompatibility.c	(working copy)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-compatibility
 
-enum ENUM1; // expected-warning {{forward references to 'enum' types are a Microsoft extension}}    
+enum ENUM1; // expected-warning {{forward references to 'enum' types are a Microsoft extension}}
 enum ENUM1 var1 = 3;
 enum ENUM1* var2 = 0;
 
@@ -14,3 +14,8 @@
 __declspec(noreturn) void f6( void ) {
 	return;  // expected-warning {{function 'f6' declared 'noreturn' should not return}}
 }
+
+__declspec(align(32768)) struct S1 { int a; } s;	/* expected-error{{requested alignment must be 8192 bytes or smaller}} */
+__declspec(aligned)	struct S2 {}; /* expected-error{{unrecognized __declspec attribute 'aligned'}} */
+
+struct __declspec(appdomain) S3 {}; /* expected-warning {{__declspec 'appdomain' is a valid Microsoft attribute, but is ignored}} */
\ No newline at end of file
Index: test/Sema/MicrosoftExtensions.c
===================================================================
--- test/Sema/MicrosoftExtensions.c	(revision 158272)
+++ test/Sema/MicrosoftExtensions.c	(working copy)
@@ -93,6 +93,8 @@
 #define MY_TEXT		"This is also deprecated"
 __declspec(deprecated(MY_TEXT)) void Dfunc1( void ) {} // expected-note {{'Dfunc1' declared here}}
 
+struct __declspec(deprecated(123)) DS2 {};	// expected-error {{argument to deprecated attribute was not a string literal}}
+
 void test( void ) {
 	e1 = one;	// expected-warning {{'e1' is deprecated: This is deprecated}}
 	struct DS1 s = { 0 };	// expected-warning {{'DS1' is deprecated}}
