r215347 - Sema: Handle declspecs without declarators in records properly in C mode
David Majnemer
david.majnemer at gmail.com
Mon Aug 11 00:29:54 PDT 2014
Author: majnemer
Date: Mon Aug 11 02:29:54 2014
New Revision: 215347
URL: http://llvm.org/viewvc/llvm-project?rev=215347&view=rev
Log:
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;
};
};
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/Parser/declarators.c
cfe/trunk/test/Sema/MicrosoftExtensions.c
cfe/trunk/test/Sema/anonymous-struct-union.c
cfe/trunk/test/SemaObjC/ivar-lookup.m
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=215347&r1=215346&r2=215347&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Aug 11 02:29:54 2014
@@ -6149,8 +6149,9 @@ def err_anonymous_record_bad_member : Er
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>;
+def ext_ms_anonymous_record : ExtWarn<
+ "anonymous %select{structs|unions}0 are a Microsoft extension">,
+ InGroup<Microsoft>;
// C++ local classes
def err_reference_to_local_var_in_enclosing_function : Error<
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=215347&r1=215346&r2=215347&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug 11 02:29:54 2014
@@ -3444,21 +3444,36 @@ Decl *Sema::ParsedFreeStandingDeclSpec(S
}
}
- // 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(
///
/// 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);
Modified: cfe/trunk/test/Parser/declarators.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/declarators.c?rev=215347&r1=215346&r2=215347&view=diff
==============================================================================
--- cfe/trunk/test/Parser/declarators.c (original)
+++ cfe/trunk/test/Parser/declarators.c Mon Aug 11 02:29:54 2014
@@ -113,6 +113,7 @@ enum E1 { e1 }: // expected-error {{expe
struct EnumBitfield { // expected-warning {{struct without named members is a GNU extension}}
enum E2 { e2 } : 4; // ok
struct S { int n; }: // expected-error {{expected ';'}}
+ // expected-warning at -1 {{declaration does not declare anything}}
};
Modified: cfe/trunk/test/Sema/MicrosoftExtensions.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/MicrosoftExtensions.c?rev=215347&r1=215346&r2=215347&view=diff
==============================================================================
--- cfe/trunk/test/Sema/MicrosoftExtensions.c (original)
+++ cfe/trunk/test/Sema/MicrosoftExtensions.c Mon Aug 11 02:29:54 2014
@@ -39,9 +39,24 @@ struct nested2 {
NESTED1; // expected-warning {{anonymous structs are a Microsoft extension}}
};
+struct nested3 {
+ long d;
+ struct nested4 { // expected-warning {{anonymous structs are a Microsoft extension}}
+ long e;
+ };
+ union nested5 { // expected-warning {{anonymous unions are a Microsoft extension}}
+ long f;
+ };
+};
+
+typedef union nested6 {
+ long f;
+} NESTED6;
+
struct test {
int c;
struct nested2; // expected-warning {{anonymous structs are a Microsoft extension}}
+ NESTED6; // expected-warning {{anonymous unions are a Microsoft extension}}
};
void foo()
Modified: cfe/trunk/test/Sema/anonymous-struct-union.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/anonymous-struct-union.c?rev=215347&r1=215346&r2=215347&view=diff
==============================================================================
--- cfe/trunk/test/Sema/anonymous-struct-union.c (original)
+++ cfe/trunk/test/Sema/anonymous-struct-union.c Mon Aug 11 02:29:54 2014
@@ -37,7 +37,7 @@ void test_unqual_references(struct X x,
struct Redecl {
int x; // expected-note{{previous declaration is here}}
- struct y { };
+ struct y { }; // expected-warning{{declaration does not declare anything}}
union {
int x; // expected-error{{member of anonymous union redeclares 'x'}}
Modified: cfe/trunk/test/SemaObjC/ivar-lookup.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/ivar-lookup.m?rev=215347&r1=215346&r2=215347&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/ivar-lookup.m (original)
+++ cfe/trunk/test/SemaObjC/ivar-lookup.m Mon Aug 11 02:29:54 2014
@@ -99,9 +99,9 @@ extern struct foo x;
};
struct S {
__typeof(myStatus) __in; // fails.
- struct S1 {
+ struct S1 { // expected-warning {{declaration does not declare anything}}
__typeof(myStatus) __in; // fails.
- struct S {
+ struct S { // expected-warning {{declaration does not declare anything}}
__typeof(myStatus) __in; // fails.
};
};
More information about the cfe-commits
mailing list