diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 85c88a3f576..53a647149a8 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3444,21 +3444,36 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } } - // Check for Microsoft C extension: anonymous struct member. - if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus && - CurContext->isRecord() && + // C11 6.7.2.1p2: + // A struct-declaration that does not declare an anonymous structure or + // anonymous union shall contain a struct-declarator-list. + if (!getLangOpts().CPlusPlus && CurContext->isRecord() && DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) { - // Handle 2 kinds of anonymous struct: + // Check for Microsoft C extension: anonymous struct/union member. + // Handle 2 kinds of anonymous struct/union: // struct STRUCT; + // union UNION; // and // STRUCT_TYPE; <- where STRUCT_TYPE is a typedef struct. - RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag); - if ((Record && Record->getDeclName() && !Record->isCompleteDefinition()) || - (DS.getTypeSpecType() == DeclSpec::TST_typename && - DS.getRepAsType().get()->isStructureType())) { - Diag(DS.getLocStart(), diag::ext_ms_anonymous_struct) - << DS.getSourceRange(); - return BuildMicrosoftCAnonymousStruct(S, DS, Record); + // UNION_TYPE; <- where UNION_TYPE is a typedef union. + if ((Tag && Tag->getDeclName()) || + DS.getTypeSpecType() == DeclSpec::TST_typename) { + RecordDecl *Record = nullptr; + if (Tag) + Record = dyn_cast<RecordDecl>(Tag); + else if (const RecordType *RT = + DS.getRepAsType().get()->getAsStructureType()) + Record = RT->getDecl(); + else if (const RecordType *UT = DS.getRepAsType().get()->getAsUnionType()) + Record = UT->getDecl(); + + if (Record && getLangOpts().MicrosoftExt) { + Diag(DS.getLocStart(), diag::ext_ms_anonymous_record) + << Record->isUnion() << DS.getSourceRange(); + return BuildMicrosoftCAnonymousStruct(S, DS, Record); + } + + DeclaresAnything = false; } } @@ -3999,15 +4014,12 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, /// /// void foo() { /// B var; -/// var.a = 3; +/// 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(); + assert(Record && "expected a record!"); // Mock up a declarator. Declarator Dc(DS, Declarator::TypeNameContext); |