Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 119948)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -3030,6 +3030,8 @@
 def err_anonymous_record_nonpublic_member : Error<
   "anonymous %select{struct|union}0 cannot contain a "
   "%select{private|protected}1 data member">;
+def ext_ms_anonymous_struct : ExtWarn<
+  "anonymous structs are a Microsoft extension">, InGroup<Microsoft>;
 
 // C++ local classes
 def err_reference_to_local_var_in_enclosing_function : Error<
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 119948)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -787,6 +787,9 @@
                                     AccessSpecifier AS,
                                     RecordDecl *Record);
 
+  Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, 
+                                       RecordDecl *Record);
+
   bool isAcceptableTagRedeclaration(const TagDecl *Previous,
                                     TagTypeKind NewTag,
                                     SourceLocation NewTagLoc,
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 119948)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -1646,12 +1646,24 @@
       Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators)
         << DS.getSourceRange();
     }
+  }
 
-    // Microsoft allows unnamed struct/union fields. Don't complain
-    // about them.
-    // FIXME: Should we support Microsoft's extensions in this area?
-    if (Record->getDeclName() && getLangOptions().Microsoft)
-      return Tag;
+  // Check for Microsoft C extension: anonymous struct.
+  if (getLangOptions().Microsoft && !getLangOptions().CPlusPlus &&
+      CurContext->isRecord() &&
+      DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) {
+    // Handle 2 kinds of anonymous struct:
+    //   struct STRUCT;
+    // and
+    //   STRUCT_TYPE;  <- where STRUCT_TYPE is a typedef struct.
+    RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag);
+    if ((Record && Record->getDeclName() && !Record->isDefinition()) ||
+        (DS.getTypeSpecType() == DeclSpec::TST_typename &&
+         DS.getRepAsType().get()->isStructureType())) {
+      Diag(DS.getSourceRange().getBegin(), diag::ext_ms_anonymous_struct)
+        << DS.getSourceRange();
+      return BuildMicrosoftCAnonymousStruct(S, DS, Record);
+    }
   }
   
   if (getLangOptions().CPlusPlus && 
@@ -1749,7 +1761,8 @@
                                                 DeclContext *Owner,
                                                 RecordDecl *AnonRecord,
                                                 AccessSpecifier AS,
-                              llvm::SmallVector<NamedDecl*, 2> &Chaining) {
+                              llvm::SmallVector<NamedDecl*, 2> &Chaining,
+                                                      bool MSAnonStruct) {
   unsigned diagKind
     = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
                             : diag::err_anonymous_struct_member_redecl;
@@ -1796,12 +1809,29 @@
     } else if (const RecordType *InnerRecordType
                  = (*F)->getType()->getAs<RecordType>()) {
       RecordDecl *InnerRecord = InnerRecordType->getDecl();
+      Chaining.push_back(*F);
 
-      Chaining.push_back(*F);
+      // Normal anonymous struct/union.
       if (InnerRecord->isAnonymousStructOrUnion())
         Invalid = Invalid ||
           InjectAnonymousStructOrUnionMembers(SemaRef, S, Owner,
-                                              InnerRecord, AS, Chaining);
+                                              InnerRecord, AS, Chaining,
+                                              MSAnonStruct);
+
+      // Microsoft anonymous struct.
+      if (MSAnonStruct && InnerRecord->isStruct()) {
+        // MS struct anon must not be definition.
+        bool IsDefinition = false;
+        if (TagDecl *Tag = dyn_cast<TagDecl>((*F)->getUnderlyingDecl()))
+           IsDefinition = Tag->isDefinition();
+
+        if (!IsDefinition)
+          Invalid = Invalid ||
+            InjectAnonymousStructOrUnionMembers(SemaRef, S, Owner,
+                                              InnerRecord, AS, Chaining,
+                                              MSAnonStruct);
+      }
+
       Chaining.pop_back();
     }
   }
@@ -1847,7 +1877,7 @@
   llvm_unreachable("unknown storage class specifier");
 }
 
-/// ActOnAnonymousStructOrUnion - Handle the declaration of an
+/// BuildAnonymousStructOrUnion - Handle the declaration of an
 /// anonymous structure or union. Anonymous unions are a C++ feature
 /// (C++ [class.union]) and a GNU C extension; anonymous structures
 /// are a GNU C and GNU C++ extension.
@@ -2020,7 +2050,8 @@
   llvm::SmallVector<NamedDecl*, 2> Chain;
   Chain.push_back(Anon);
 
-  if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS, Chain))
+  if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS,
+                                          Chain, false))
     Invalid = true;
 
   // Mark this as an anonymous struct/union type. Note that we do not
@@ -2037,7 +2068,58 @@
   return Anon;
 }
 
+/// BuildMicrosoftCAnonymousStruct - Handle the declaration of an
+/// Microsoft C anonymous structure.
+/// Ref: http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx
+/// Example:
+///
+/// struct A { int a; };
+/// struct B { struct A; int b; };
+///
+/// void foo() {
+///   B var;
+///   var.a = 3; 
+/// }
+///
+Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
+                                           RecordDecl *Record) {
+  
+  // If there is no Record, get the record via the typedef.
+  if (!Record)
+    Record = DS.getRepAsType().get()->getAsStructureType()->getDecl();
 
+  // Mock up a declarator.
+  Declarator Dc(DS, Declarator::TypeNameContext);
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
+  assert(TInfo && "couldn't build declarator info for anonymous struct");
+
+  // Create a declaration for this anonymous struct.
+  NamedDecl* Anon = FieldDecl::Create(Context,
+                             dyn_cast<RecordDecl>(CurContext),
+                             DS.getSourceRange().getBegin(),
+                             /*IdentifierInfo=*/0,
+                             Context.getTypeDeclType(Record),
+                             TInfo,
+                             /*BitWidth=*/0, /*Mutable=*/false);
+  Anon->setImplicit();
+
+  // Add the anonymous struct object to the current context.
+  CurContext->addDecl(Anon);
+
+  // Inject the members of the anonymous struct into the current
+  // context and into the identifier resolver chain for name lookup
+  // purposes.
+  llvm::SmallVector<NamedDecl*, 2> Chain;
+  Chain.push_back(Anon);
+
+  if (InjectAnonymousStructOrUnionMembers(*this, S, CurContext,
+                                          Record->getDefinition(),
+                                          AS_none, Chain, true))
+    Anon->setInvalidDecl();
+
+  return Anon;
+}
+
 /// GetNameForDeclarator - Determine the full declaration name for the
 /// given Declarator.
 DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) {
Index: test/CodeGen/ms-anonymous-struct.c
===================================================================
--- test/CodeGen/ms-anonymous-struct.c	(revision 0)
+++ test/CodeGen/ms-anonymous-struct.c	(revision 0)
@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -fms-extensions -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: %struct.nested1 = type { i32, i32 }
+typedef struct nested1 {
+    long a1;
+    long b1;
+} NESTED1;
+
+// CHECK: %struct.nested2 = type { i32, %struct.nested1, i32 }
+struct nested2 {
+    long a;
+    NESTED1; 
+    long b;
+};
+
+// CHECK: %struct.test = type { i32, %struct.nested2, i32 }
+struct test {
+    int    x;
+    struct nested2; 
+    int    y;
+};
+
+
+void foo()
+{
+  // CHECK: %var = alloca %struct.test, align 4
+  struct test var;
+
+  // CHECK: getelementptr inbounds %struct.test* %var, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested2* %{{.*}}, i32 0, i32 0
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var.a;
+
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %var, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested2* %{{.*}}, i32 0, i32 2
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var.b;
+
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %var, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested2* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested1* %{{.*}}, i32 0, i32 0
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var.a1;
+
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %{{.*}}var, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested2* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested1* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var.b1;
+
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %var, i32 0, i32 0
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var.x;
+
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %var, i32 0, i32 2
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var.y;
+}
+
+void foo2(struct test* var)
+{
+  // CHECK: alloca %struct.test*, align 4
+  // CHECK-NEXT: store %struct.test* %var, %struct.test** %{{.*}}, align 4
+  // CHECK-NEXT: load %struct.test** %{{.*}}, align 4
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested2* %{{.*}}, i32 0, i32 0
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var->a;
+
+  // CHECK-NEXT: load %struct.test** %{{.*}}, align 4
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested2* %{{.*}}, i32 0, i32 2
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var->b;
+
+  // CHECK-NEXT: load %struct.test** %{{.*}}, align 4
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested2* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested1* %{{.*}}, i32 0, i32 0
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var->a1;
+
+  // CHECK-NEXT: load %struct.test** %{{.*}}, align 4
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested2* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: getelementptr inbounds %struct.nested1* %{{.*}}, i32 0, i32 1
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var->b1;
+
+  // CHECK-NEXT: load %struct.test** %{{.*}}, align 4
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %{{.*}}, i32 0, i32 0
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var->x;
+
+  // CHECK-NEXT: load %struct.test** %{{.*}}, align 4
+  // CHECK-NEXT: getelementptr inbounds %struct.test* %{{.*}}, i32 0, i32 2
+  // CHECK-NEXT: load i32* %{{.*}}, align 4
+  var->y;
+}
Index: test/Sema/MicrosoftExtensions.c
===================================================================
--- test/Sema/MicrosoftExtensions.c	(revision 119948)
+++ test/Sema/MicrosoftExtensions.c	(working copy)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
+// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
 
 
 struct A
@@ -31,3 +31,36 @@
 	ENUM2_b = 0x9FFFFFFF, // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
 	ENUM2_c = 0x100000000 // expected-warning {{enumerator value is not representable in the underlying type 'int'}}
 };
+
+
+typedef struct notnested {
+    long bad1;
+	long bad2;
+} NOTNESTED;
+
+
+typedef struct nested1 {
+    long a;
+	struct notnested var1;
+	NOTNESTED var2;
+} NESTED1;
+
+struct nested2 {
+    long b;
+    NESTED1;  // expected-warning {{anonymous structs are a Microsoft extension}}
+};
+
+struct test {
+    int    c;
+    struct nested2;   // expected-warning {{anonymous structs are a Microsoft extension}}
+};
+
+void foo()
+{
+  struct test var;
+  var.a;
+  var.b;
+  var.c;
+  var.bad1;   // expected-error {{no member named 'bad1' in 'struct test'}}
+  var.bad2;   // expected-error {{no member named 'bad2' in 'struct test'}}
+}
