[cfe-commits] r62112 - in /cfe/trunk: Driver/clang.cpp include/clang/Basic/DiagnosticKinds.def lib/Parse/DeclSpec.cpp lib/Parse/ParseDecl.cpp lib/Sema/SemaDecl.cpp test/Parser/cxx-class.cpp test/Sema/anonymous-struct-union.c test/SemaCXX/anonymous-union.cpp test/SemaObjC/property-9.m
Douglas Gregor
dgregor at apple.com
Mon Jan 12 14:49:07 PST 2009
Author: dgregor
Date: Mon Jan 12 16:49:06 2009
New Revision: 62112
URL: http://llvm.org/viewvc/llvm-project?rev=62112&view=rev
Log:
Implement support for anonymous structs and unions in C. Both C and
C++ handle anonymous structs/unions in the same way. Addresses several
bugs:
<rdar://problem/6259534>
<rdar://problem/6481130>
<rdar://problem/6483159>
The test case in PR clang/1750 now passes with -fsyntax-only, but
CodeGen for inline assembler still fails.
Added:
cfe/trunk/test/Sema/anonymous-struct-union.c
Modified:
cfe/trunk/Driver/clang.cpp
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/Parse/DeclSpec.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/Parser/cxx-class.cpp
cfe/trunk/test/SemaCXX/anonymous-union.cpp
cfe/trunk/test/SemaObjC/property-9.m
Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=62112&r1=62111&r2=62112&view=diff
==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Mon Jan 12 16:49:06 2009
@@ -714,9 +714,6 @@
Diags.setDiagnosticMapping(diag::warn_implicit_function_decl,
diag::MAP_IGNORE);
- if (MSExtensions) // MS allows unnamed struct/union fields.
- Diags.setDiagnosticMapping(diag::w_no_declarators, diag::MAP_IGNORE);
-
// If -pedantic-errors is set, turn extensions that warn by default into
// errors.
if (ErrorOnExtensions) {
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=62112&r1=62111&r2=62112&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Jan 12 16:49:06 2009
@@ -270,8 +270,6 @@
// Parser Diagnostics
//===----------------------------------------------------------------------===//
-DIAG(w_no_declarators, WARNING,
- "declaration does not declare anything")
DIAG(w_asm_qualifier_ignored, WARNING,
"ignored %0 qualifier on asm")
@@ -1496,7 +1494,9 @@
DIAG(err_anonymous_union_with_storage_spec, ERROR,
"anonymous union at class scope must not have a storage specifier")
DIAG(err_anonymous_struct_not_member, ERROR,
- "anonymous structs and classes must be class members")
+ "anonymous %select{structs|structs and classes}0 must be %select{struct or union|class}0 members")
+DIAG(err_anonymous_union_not_member, ERROR,
+ "anonymous unions must be struct or union members")
DIAG(err_anonymous_union_member_redecl, ERROR,
"member of anonymous union redeclares %0")
DIAG(err_anonymous_struct_member_redecl, ERROR,
Modified: cfe/trunk/lib/Parse/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/DeclSpec.cpp?rev=62112&r1=62111&r2=62112&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Parse/DeclSpec.cpp Mon Jan 12 16:49:06 2009
@@ -319,5 +319,5 @@
|| tst == TST_struct
|| tst == TST_class
|| tst == TST_enum
- ) && getTypeRep() != 0;
+ ) && getTypeRep() != 0 && StorageClassSpec != DeclSpec::SCS_typedef;
}
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=62112&r1=62111&r2=62112&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jan 12 16:49:06 2009
@@ -888,9 +888,10 @@
SourceLocation DSStart = Tok.getLocation();
ParseSpecifierQualifierList(DS);
- // If there are no declarators, issue a warning.
+ // If there are no declarators, this is a free-standing declaration
+ // specifier. Let the actions module cope with it.
if (Tok.is(tok::semi)) {
- Diag(DSStart, diag::w_no_declarators);
+ Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
return;
}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=62112&r1=62111&r2=62112&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Jan 12 16:49:06 2009
@@ -861,7 +861,20 @@
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed.
Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
- // FIXME: Isn't that more of a parser diagnostic than a sema diagnostic?
+ TagDecl *Tag
+ = dyn_cast_or_null<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
+ if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
+ if (!Record->getDeclName() && Record->isDefinition() &&
+ DS.getStorageClassSpec() != DeclSpec::SCS_typedef)
+ return BuildAnonymousStructOrUnion(S, DS, Record);
+
+ // Microsoft allows unnamed struct/union fields. Don't complain
+ // about them.
+ // FIXME: Should we support Microsoft's extensions in this area?
+ if (Record->getDeclName() && getLangOptions().Microsoft)
+ return Tag;
+ }
+
if (!DS.isMissingDeclaratorOk()) {
// FIXME: This diagnostic is emitted even when various previous
// errors occurred (see e.g. test/Sema/decl-invalid.c). However,
@@ -872,14 +885,6 @@
return 0;
}
- TagDecl *Tag
- = dyn_cast_or_null<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
- if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
- if (!Record->getDeclName() && Record->isDefinition() &&
- !Record->isInvalidDecl())
- return BuildAnonymousStructOrUnion(S, DS, Record);
- }
-
return Tag;
}
@@ -1031,10 +1036,16 @@
}
} else {
// FIXME: Check GNU C semantics
+ if (Record->isUnion() && !Owner->isRecord()) {
+ Diag(Record->getLocation(), diag::err_anonymous_union_not_member)
+ << (int)getLangOptions().CPlusPlus;
+ Invalid = true;
+ }
}
if (!Record->isUnion() && !Owner->isRecord()) {
- Diag(Record->getLocation(), diag::err_anonymous_struct_not_member);
+ Diag(Record->getLocation(), diag::err_anonymous_struct_not_member)
+ << (int)getLangOptions().CPlusPlus;
Invalid = true;
}
@@ -1084,7 +1095,8 @@
// Inject the members of the anonymous struct/union into the owning
// context and into the identifier resolver chain for name lookup
// purposes.
- Invalid = Invalid || InjectAnonymousStructOrUnionMembers(S, Owner, Record);
+ if (InjectAnonymousStructOrUnionMembers(S, Owner, Record))
+ Invalid = true;
// Mark this as an anonymous struct/union type. Note that we do not
// do this until after we have already checked and injected the
@@ -2890,6 +2902,7 @@
case DeclSpec::TST_enum: Kind = TagDecl::TK_enum; break;
}
+ DeclContext *SearchDC = CurContext;
DeclContext *DC = CurContext;
DeclContext *LexicalContext = CurContext;
ScopedDecl *PrevDecl = 0;
@@ -2924,8 +2937,8 @@
// with C structs, unions, and enums when looking for a matching
// tag declaration or definition. See the similar lookup tweak
// in Sema::LookupDecl; is there a better way to deal with this?
- while (isa<RecordDecl>(DC) || isa<EnumDecl>(DC))
- DC = DC->getParent();
+ while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
+ SearchDC = SearchDC->getParent();
}
}
@@ -2943,7 +2956,7 @@
// If this is a use of a previous tag, or if the tag is already declared
// in the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
- if (TK == TK_Reference || isDeclInScope(PrevDecl, DC, S)) {
+ if (TK == TK_Reference || isDeclInScope(PrevDecl, SearchDC, S)) {
// Make sure that this wasn't declared as an enum and now used as a
// struct or something similar.
if (PrevTagDecl->getTagKind() != Kind) {
@@ -2991,7 +3004,7 @@
// PrevDecl. If it's NULL, we have a new definition.
} else {
// PrevDecl is a namespace.
- if (isDeclInScope(PrevDecl, DC, S)) {
+ if (isDeclInScope(PrevDecl, SearchDC, S)) {
// The tag name clashes with a namespace name, issue an error and
// recover by making this tag be anonymous.
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
@@ -3024,6 +3037,8 @@
// C structs and unions.
// Find the context where we'll be declaring the tag.
+ // FIXME: We would like to maintain the current DeclContext as the
+ // lexical context,
while (DC->isRecord())
DC = DC->getParent();
LexicalContext = DC;
@@ -3110,11 +3125,7 @@
CurContext = OldContext;
} else
PushOnScopeChains(New, S);
- } else if (getLangOptions().CPlusPlus) {
- // FIXME: We also want to do this for C, but if this tag is
- // defined within a structure CurContext will point to the context
- // enclosing the structure, and we would end up inserting the tag
- // type into the wrong place.
+ } else {
LexicalContext->addDecl(Context, New);
}
Modified: cfe/trunk/test/Parser/cxx-class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-class.cpp?rev=62112&r1=62111&r2=62112&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-class.cpp (original)
+++ cfe/trunk/test/Parser/cxx-class.cpp Mon Jan 12 16:49:06 2009
@@ -8,7 +8,7 @@
struct S {};
enum {};
- int; // expected-error {{error: declaration does not declare anything}}
+ int; // expected-error {{declaration does not declare anything}}
int : 1, : 2;
public:
Added: cfe/trunk/test/Sema/anonymous-struct-union.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/anonymous-struct-union.c?rev=62112&view=auto
==============================================================================
--- cfe/trunk/test/Sema/anonymous-struct-union.c (added)
+++ cfe/trunk/test/Sema/anonymous-struct-union.c Mon Jan 12 16:49:06 2009
@@ -0,0 +1,82 @@
+// RUN: clang -fsyntax-only -verify %s
+struct X {
+ union {
+ float f3;
+ double d2;
+ } named;
+
+ union {
+ int i;
+ float f;
+
+ union {
+ float f2;
+ double d;
+ };
+ };
+
+ struct {
+ int a;
+ float b;
+ };
+};
+
+void test_unqual_references(struct X x, const struct X xc) {
+ x.i = 0;
+ x.f = 0.0;
+ x.f2 = x.f;
+ x.d = x.f;
+ x.f3 = 0; // expected-error{{no member named 'f3'}}
+ x.a = 0;
+
+ xc.d = 0.0; // expected-error{{read-only variable is not assignable}}
+ xc.f = 0; // expected-error{{read-only variable is not assignable}}
+ xc.a = 0; // expected-error{{read-only variable is not assignable}}
+}
+
+
+struct Redecl {
+ int x; // expected-note{{previous declaration is here}}
+ struct y { };
+
+ union {
+ int x; // expected-error{{member of anonymous union redeclares 'x'}}
+ float y;
+ double z; // expected-note{{previous declaration is here}}
+ double zz; // expected-note{{previous declaration is here}}
+ };
+
+ int z; // expected-error{{duplicate member 'z'}}
+ void zz(); // expected-error{{duplicate member 'zz'}} \
+ // expected-error{{field 'zz' declared as a function}}
+};
+
+union { // expected-error{{anonymous unions must be struct or union members}}
+ int int_val;
+ float float_val;
+};
+
+static union { // expected-error{{anonymous unions must be struct or union members}}
+ int int_val2;
+ float float_val2;
+};
+
+void f() {
+ int_val2 = 0; // expected-error{{use of undeclared identifier}}
+ float_val2 = 0.0; // expected-error{{use of undeclared identifier}}
+}
+
+void g() {
+ union { // expected-error{{anonymous unions must be struct or union members}}
+ int i;
+ float f2;
+ };
+ i = 0; // expected-error{{use of undeclared identifier}}
+ f2 = 0.0; // expected-error{{use of undeclared identifier}}
+}
+
+// <rdar://problem/6483159>
+struct s0 { union { int f0; }; };
+
+// <rdar://problem/6481130>
+typedef struct { }; // expected-error{{declaration does not declare anything}}
Modified: cfe/trunk/test/SemaCXX/anonymous-union.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/anonymous-union.cpp?rev=62112&r1=62111&r2=62112&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/anonymous-union.cpp (original)
+++ cfe/trunk/test/SemaCXX/anonymous-union.cpp Mon Jan 12 16:49:06 2009
@@ -108,3 +108,6 @@
protected: float x2; // expected-error{{anonymous union cannot contain a protected data member}}
};
};
+
+// <rdar://problem/6481130>
+typedef union { }; // expected-error{{declaration does not declare anything}}
Modified: cfe/trunk/test/SemaObjC/property-9.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-9.m?rev=62112&r1=62111&r2=62112&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-9.m (original)
+++ cfe/trunk/test/SemaObjC/property-9.m Mon Jan 12 16:49:06 2009
@@ -43,9 +43,9 @@
int _awesome;
}
- at property (readonly) int; // expected-warning {{declaration does not declare anything}}
+ at property (readonly) int; // expected-error {{declaration does not declare anything}}
@property (readonly) ; // expected-error {{type name requires a specifier or qualifier}} \
- expected-warning {{declaration does not declare anything}}
+ expected-error {{declaration does not declare anything}}
@property (readonly) int : 4; // expected-error {{property requires fields to be named}}
More information about the cfe-commits
mailing list