From 04c4455dd443c67584d59c5d993aaada92233073 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 24 Jan 2012 00:40:15 +0000 Subject: [PATCH] objective-c: Ignore with warning forward class declaration whose name matches a typedef declaring an object type. // rdar://10733000 llvm-svn: 148760 --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ clang/lib/Sema/SemaDeclObjC.cpp | 15 ++++++---- clang/test/SemaObjC/forward-class-1.m | 4 +-- clang/test/SemaObjC/forward-class-redeclare.m | 29 +++++++++++++++++++ clang/test/SemaObjC/typedef-class.m | 4 +-- 5 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 clang/test/SemaObjC/forward-class-redeclare.m diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index dfe49108acb9..73f3cda545b6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2809,6 +2809,9 @@ def err_redefinition_different_type : Error< "redefinition of %0 with a different type">; def err_redefinition_different_kind : Error< "redefinition of %0 as different kind of symbol">; +def warn_forward_class_redefinition : Warning< + "redefinition of forward class %0 of a typedef name of an object type is ignored">, + InGroup>; def err_redefinition_different_typedef : Error< "%select{typedef|type alias|type alias template}0 redefinition with different types (%1 vs %2)">; def err_tag_reference_non_tag : Error< diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index ff92453ca7fb..4264b7105a7f 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -1776,17 +1776,22 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, // typedef NSObject < XCElementTogglerP > XCElementToggler; // @class XCElementToggler; // - // FIXME: Make an extension? + // Here we have chosen to ignore the forward class declaration + // with a warning. Since this is the implied behavior. TypedefNameDecl *TDD = dyn_cast(PrevDecl); if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; Diag(PrevDecl->getLocation(), diag::note_previous_definition); } else { // a forward class declaration matching a typedef name of a class refers - // to the underlying class. - if (const ObjCObjectType *OI = - TDD->getUnderlyingType()->getAs()) - PrevDecl = OI->getInterface(); + // to the underlying class. Just ignore the forward class with a warning + // as this will force the intended behavior which is to lookup the typedef + // name. + if (isa(TDD->getUnderlyingType())) { + Diag(AtClassLoc, diag::warn_forward_class_redefinition) << IdentList[i]; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + continue; + } } } diff --git a/clang/test/SemaObjC/forward-class-1.m b/clang/test/SemaObjC/forward-class-1.m index e8c36957a31d..30a06358c5ef 100644 --- a/clang/test/SemaObjC/forward-class-1.m +++ b/clang/test/SemaObjC/forward-class-1.m @@ -31,14 +31,14 @@ @protocol XCElementP @end -typedef NSObject XCElement; +typedef NSObject XCElement; // expected-note {{previous definition is here}} @interface XCElementMainImp { XCElement * _editingElement; } @end -@class XCElement; +@class XCElement; // expected-warning {{redefinition of forward class 'XCElement' of a typedef name of an object type is ignored}} @implementation XCElementMainImp - (XCElement *)editingElement { return _editingElement; } diff --git a/clang/test/SemaObjC/forward-class-redeclare.m b/clang/test/SemaObjC/forward-class-redeclare.m new file mode 100644 index 000000000000..80dc33536280 --- /dev/null +++ b/clang/test/SemaObjC/forward-class-redeclare.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar://10733000 + +@interface NSObject @end + +@protocol PLAssetContainer +@property (readonly, nonatomic, retain) id assets; +@end + + +typedef NSObject PLAlbum; // expected-note {{previous definition is here}} + +@class PLAlbum; // expected-warning {{redefinition of forward class 'PLAlbum' of a typedef name of an object type is ignore}} + +@interface PLPhotoBrowserController +{ + PLAlbum *_album; +} +@end + +@interface WPhotoViewController:PLPhotoBrowserController +@end + +@implementation WPhotoViewController +- (void)_prepareForContracting +{ + (void)_album.assets; +} +@end diff --git a/clang/test/SemaObjC/typedef-class.m b/clang/test/SemaObjC/typedef-class.m index c983195b243e..bd68397fd969 100644 --- a/clang/test/SemaObjC/typedef-class.m +++ b/clang/test/SemaObjC/typedef-class.m @@ -48,13 +48,13 @@ typedef NSObject < XCElementSpacerP > XCElementSpacer; @protocol XCElementTogglerP < XCElementP > -(void) setDisplayed:(BOOL) displayed; @end -typedef NSObject < XCElementTogglerP > XCElementToggler; +typedef NSObject < XCElementTogglerP > XCElementToggler; // expected-note {{previous definition is here}} @interface XCElementRootFace:NSObject {} @end @interface XCElementFace:XCElementRootFace {} @end -@class XCElementToggler; +@class XCElementToggler; // expected-warning {{redefinition of forward class 'XCElementToggler' of a typedef name of an object type is ignored}} @interface XCRASlice:XCElementFace {} @end