From 8f0ed914902f2d108ca2bd0b64b32c876bf24e5c Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Mon, 11 Aug 2014 07:29:54 +0000 Subject: Sema: Handle declspecs without declarators in records properly in C mode We had two bugs: - We wouldn't properly warn when a struct/union/enum was mentioned inside of a record definition if no declarator was provided. We should have mentioned that this declaration declares nothing. - We didn't properly support Microsoft's extension where certain declspecs without declarators would act as anonymous structs/unions. * We completely ignored the case where such a declspec could be a union. * We didn't properly handle the case where a record was defined inside another record: struct X { int a; struct Y { int b; }; }; llvm-svn: 215347 --- clang/lib/Sema/SemaDecl.cpp | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'clang/lib/Sema/SemaDecl.cpp') 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(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(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); -- cgit v1.2.3