From aefb23092ca0be00a2bde958518039102d7939fe Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 14 Sep 2007 16:27:55 +0000 Subject: [PATCH] Semantic analysis for objective-c ivars. llvm-svn: 41954 --- clang/Parse/ParseObjc.cpp | 2 ++ clang/Sema/SemaDecl.cpp | 33 ++++++++++++++++++++++-------- clang/test/Sema/ivar-sem-check-1.m | 15 ++++++++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 clang/test/Sema/ivar-sem-check-1.m diff --git a/clang/Parse/ParseObjc.cpp b/clang/Parse/ParseObjc.cpp index d3b8d8dccc2a..22b3985ef003 100644 --- a/clang/Parse/ParseObjc.cpp +++ b/clang/Parse/ParseObjc.cpp @@ -661,6 +661,8 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl) { if (AllIvarDecls.size()) { // Check for {} - no ivars in braces Actions.ObjcAddInstanceVariable(interfaceDecl, &AllIvarDecls[0], AllIvarDecls.size(), &AllVisibilities[0]); + Actions.ParseRecordBody(LBraceLoc, interfaceDecl, + &AllIvarDecls[0], AllIvarDecls.size()); } MatchRHSPunctuation(tok::r_brace, LBraceLoc); return; diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp index 9300b9cd813f..05ec2040ff65 100644 --- a/clang/Sema/SemaDecl.cpp +++ b/clang/Sema/SemaDecl.cpp @@ -1092,10 +1092,13 @@ Sema::DeclTy *Sema::ParseField(Scope *S, DeclTy *TagDecl, return NewFD; } +// FIXME: Change ParseRecordBody name to something more generic as +// it also used for ivar semantics check. void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl, DeclTy **Fields, unsigned NumFields) { - RecordDecl *Record = cast(static_cast(RecDecl)); - if (Record->isDefinition()) { + RecordDecl *Record = + dyn_cast_or_null(static_cast(RecDecl)); + if (Record && Record->isDefinition()) { // Diagnose code like: // struct S { struct S {} X; }; // We discover this when we complete the outer S. Reject and ignore the @@ -1110,9 +1113,13 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl, unsigned NumNamedMembers = 0; llvm::SmallVector RecFields; llvm::SmallSet FieldIDs; - for (unsigned i = 0; i != NumFields; ++i) { - FieldDecl *FD = cast_or_null(static_cast(Fields[i])); + + FieldDecl *FD; + if (Record) + FD = cast_or_null(static_cast(Fields[i])); + else + FD = cast_or_null(static_cast(Fields[i])); if (!FD) continue; // Already issued a diagnostic. // Get the type for the field. @@ -1128,6 +1135,11 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl, // C99 6.7.2.1p2 - A field may not be an incomplete type except... if (FDTy->isIncompleteType()) { + if (!Record) { // Incomplete ivar type is always an error. + Diag(FD->getLocation(), diag::err_field_incomplete, FD->getName()); + delete FD; + continue; + } if (i != NumFields-1 || // ... that the last member ... Record->getKind() != Decl::Struct || // ... of a structure ... !FDTy->isArrayType()) { //... may have incomplete array type. @@ -1135,7 +1147,7 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl, delete FD; continue; } - if (NumNamedMembers < 1) { //... must have more than named member ... + if (NumNamedMembers < 1) { //... must have more than named member ... Diag(FD->getLocation(), diag::err_flexible_array_empty_struct, FD->getName()); delete FD; @@ -1143,7 +1155,8 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl, } // Okay, we have a legal flexible array member at the end of the struct. - Record->setHasFlexibleArrayMember(true); + if (Record) + Record->setHasFlexibleArrayMember(true); } @@ -1152,7 +1165,7 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl, if (const RecordType *FDTTy = FDTy->getAsRecordType()) { if (FDTTy->getDecl()->hasFlexibleArrayMember()) { // If this is a member of a union, then entire union becomes "flexible". - if (Record->getKind() == Decl::Union) { + if (Record && Record->getKind() == Decl::Union) { Record->setHasFlexibleArrayMember(true); } else { // If this is a struct/class and this is not the last element, reject @@ -1169,7 +1182,8 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl, // as an extension. Diag(FD->getLocation(), diag::ext_flexible_array_in_struct, FD->getName()); - Record->setHasFlexibleArrayMember(true); + if (Record) + Record->setHasFlexibleArrayMember(true); } } } @@ -1201,7 +1215,8 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl, // Okay, we successfully defined 'Record'. - Record->defineBody(&RecFields[0], RecFields.size()); + if (Record) + Record->defineBody(&RecFields[0], RecFields.size()); } void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl, diff --git a/clang/test/Sema/ivar-sem-check-1.m b/clang/test/Sema/ivar-sem-check-1.m new file mode 100644 index 000000000000..fd7a0ff62c48 --- /dev/null +++ b/clang/test/Sema/ivar-sem-check-1.m @@ -0,0 +1,15 @@ +struct S; +typedef int FOO(); + +@interface INTF +{ + struct F {} JJ; + int arr[]; // expected-error {{field 'arr' has incomplete type}} + struct S IC; // expected-error {{field 'IC' has incomplete type}} + struct T { struct T {} X; }YYY; // expected-error {{nested redefinition of 'struct'}} + FOO BADFUNC; // expected-error {{field 'BADFUNC' declared as a function}} + int kaka; + int kaka; // expected-error {{duplicate member 'kaka'}} + char ch[]; // expected-error {{field 'ch' has incomplete type}} +} +@end