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,6 +1619,8 @@
 
 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">;
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: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 158272)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -281,56 +281,138 @@
   }
 }
 
+///
+/// ParseMicrosoftDeclSpecWithSingleArg
+///
+/// Parses a single argument for a declspec, including the surround parens
+void Parser::ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName, 
+                                                  SourceLocation AttrNameLoc,
+                                                  ParsedAttributes &Attrs)
+{
+  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+                        AttrName->getNameStart())) {
+    SkipUntil(tok::r_paren, true); // skip until ) or ;
+    return;
+  }
 
-/// ParseMicrosoftDeclSpec - Parse an __declspec construct
+  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);
+}
+
+/// 
+/// IsSimpleMicrosoftDeclSpec
 ///
+/// 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
+///
+/// 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
+    SkipUntil(tok::r_paren, false);
+  } else {
+    // We don't recognize this as a valid declspec, so let the caller know
+    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")) {
+                       "__declspec")) {
     SkipUntil(tok::r_paren, true); // skip until ) or ;
     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);
-    }
-    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);
-    }
+  // 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);
+    SkipUntil(tok::r_paren, false);
+    return;
   }
+
+  IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+  SourceLocation AttrNameLoc = ConsumeToken();
+  
+  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)) {
+    Diag(AttrNameLoc, diag::err_unknown_ms_declspec) << AttrName;
+  }
+
   if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
     SkipUntil(tok::r_paren, false);
-  return;
 }
 
 void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp	(revision 158272)
+++ lib/Sema/SemaDeclAttr.cpp	(working copy)
@@ -2901,12 +2901,21 @@
     return;
   }
   
+  if (Attr.isDeclspecAttribute()) {
+    // Microsoft's align attribute must must be named "align" and not "aligned"
+    // The parser should catch this and never create the attribute in the first
+    // place.
+    assert(Attr.getName()->getName() == "align" &&
+            "Parser did not catch align attribute spelling");
+  }
+
   //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));
     return;
   }
 
@@ -2923,7 +2932,7 @@
     D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E));
     return;
   }
-
+  
   SourceLocation AttrLoc = AttrRange.getBegin();
   // FIXME: Cache the number on the Attr object?
   llvm::APSInt Alignment(32);
@@ -2938,6 +2947,15 @@
       << E->getSourceRange();
     return;
   }
+  if (Context.getLangOpts().MicrosoftMode) {
+    // 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()));
 }
@@ -3794,6 +3812,7 @@
   case AttributeList::AT_nothrow:
   case AttributeList::AT_naked:
   case AttributeList::AT_noinline:
+  case AttributeList::AT_aligned:
     return true;
   }
 }
@@ -4163,7 +4182,6 @@
     return;
 
   if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr))
-    // FIXME: Try to deal with other __declspec attributes!
     return;
 
   if (NonInheritable)
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)
@@ -80,3 +80,6 @@
   __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}}
\ No newline at end of file
Index: test/Sema/MicrosoftCompatibility.c
===================================================================
--- test/Sema/MicrosoftCompatibility.c	(revision 158272)
+++ test/Sema/MicrosoftCompatibility.c	(working copy)
@@ -14,3 +14,7 @@
 __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'}} */
+
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}}
