summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-08-11 07:29:54 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-08-11 07:29:54 +0000
commit8f0ed914902f2d108ca2bd0b64b32c876bf24e5c (patch)
treeddd509dc55c077e6d546b74efd9aa59b59d38fa1
parent69f3528c6abc83efd48977ba9c67150b93f15580 (diff)
downloadbcm5719-llvm-8f0ed914902f2d108ca2bd0b64b32c876bf24e5c.tar.gz
bcm5719-llvm-8f0ed914902f2d108ca2bd0b64b32c876bf24e5c.zip
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
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td5
-rw-r--r--clang/lib/Sema/SemaDecl.cpp44
-rw-r--r--clang/test/Parser/declarators.c1
-rw-r--r--clang/test/Sema/MicrosoftExtensions.c15
-rw-r--r--clang/test/Sema/anonymous-struct-union.c2
-rw-r--r--clang/test/SemaObjC/ivar-lookup.m4
6 files changed, 50 insertions, 21 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 624555c8076..ca37b076fe5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6149,8 +6149,9 @@ def err_anonymous_record_bad_member : Error<
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<
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);
diff --git a/clang/test/Parser/declarators.c b/clang/test/Parser/declarators.c
index c424d697353..e3024206e4f 100644
--- a/clang/test/Parser/declarators.c
+++ b/clang/test/Parser/declarators.c
@@ -113,6 +113,7 @@ enum E1 { e1 }: // expected-error {{expected ';'}}
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@-1 {{declaration does not declare anything}}
};
diff --git a/clang/test/Sema/MicrosoftExtensions.c b/clang/test/Sema/MicrosoftExtensions.c
index 429dd943a74..f64012098b2 100644
--- a/clang/test/Sema/MicrosoftExtensions.c
+++ b/clang/test/Sema/MicrosoftExtensions.c
@@ -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()
diff --git a/clang/test/Sema/anonymous-struct-union.c b/clang/test/Sema/anonymous-struct-union.c
index 35d31754162..26dbeb87f5f 100644
--- a/clang/test/Sema/anonymous-struct-union.c
+++ b/clang/test/Sema/anonymous-struct-union.c
@@ -37,7 +37,7 @@ void test_unqual_references(struct X x, const struct X xc) {
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'}}
diff --git a/clang/test/SemaObjC/ivar-lookup.m b/clang/test/SemaObjC/ivar-lookup.m
index 938c8eb189a..57f432c717a 100644
--- a/clang/test/SemaObjC/ivar-lookup.m
+++ b/clang/test/SemaObjC/ivar-lookup.m
@@ -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.
};
};
OpenPOWER on IntegriCloud