]> granicus.if.org Git - clang/commitdiff
Sema: Diagnose undefined structs used as Microsoft anonymous structs
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 18 Sep 2014 00:42:05 +0000 (00:42 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 18 Sep 2014 00:42:05 +0000 (00:42 +0000)
Previously, we would not mark structs containing anonymous structs as
invalid.  Later, horrific things would occur when trying to determine
the size of the parent record.

Instead, require the struct to be a complete type when used as an
anonymous struct.  Mark both the anonymous field for the struct and the
parent context as invalid (this is similar to what we do when a struct
contains a field with an incomplete type.)

This fixes PR11847.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218006 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/Sema/MicrosoftExtensions.c

index 1f2cf7bc9f18d0f500f0020b5f7ac86b5acd0410..0aaa60c90fe6d5a002c5302ddb7a0422c9ab12a5 100644 (file)
@@ -4066,13 +4066,16 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
   TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
   assert(TInfo && "couldn't build declarator info for anonymous struct");
 
+  auto *ParentDecl = cast<RecordDecl>(CurContext);
+  QualType RecTy = Context.getTypeDeclType(Record);
+
   // Create a declaration for this anonymous struct.
   NamedDecl *Anon = FieldDecl::Create(Context,
-                             cast<RecordDecl>(CurContext),
+                             ParentDecl,
                              DS.getLocStart(),
                              DS.getLocStart(),
                              /*IdentifierInfo=*/nullptr,
-                             Context.getTypeDeclType(Record),
+                             RecTy,
                              TInfo,
                              /*BitWidth=*/nullptr, /*Mutable=*/false,
                              /*InitStyle=*/ICIS_NoInit);
@@ -4088,10 +4091,13 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
   Chain.push_back(Anon);
 
   RecordDecl *RecordDef = Record->getDefinition();
-  if (!RecordDef || InjectAnonymousStructOrUnionMembers(*this, S, CurContext,
-                                                        RecordDef, AS_none,
-                                                        Chain, true))
+  if (RequireCompleteType(Anon->getLocation(), RecTy,
+                          diag::err_field_incomplete) ||
+      InjectAnonymousStructOrUnionMembers(*this, S, CurContext, RecordDef,
+                                          AS_none, Chain, true)) {
     Anon->setInvalidDecl();
+    ParentDecl->setInvalidDecl();
+  }
 
   return Anon;
 }
index 908ec04876e2332c99da34591b079e5259ee3623..e7032305fc07f517c76689a48f3ea0f81fd8086c 100644 (file)
@@ -104,6 +104,14 @@ typedef struct {
   AA; // expected-warning {{anonymous structs are a Microsoft extension}}
 } BB;
 
+struct anon_fault {
+  struct undefined; // expected-warning {{anonymous structs are a Microsoft extension}}
+                    // expected-error@-1 {{field has incomplete type 'struct undefined'}}
+                    // expected-note@-2 {{forward declaration of 'struct undefined'}}
+};
+
+const int anon_falt_size = sizeof(struct anon_fault);
+
 __declspec(deprecated("This is deprecated")) enum DE1 { one, two } e1; // expected-note {{'e1' has been explicitly marked deprecated here}}
 struct __declspec(deprecated) DS1 { int i; float f; }; // expected-note {{'DS1' has been explicitly marked deprecated here}}