objective-c: Ignore with warning forward class declaration whose name

matches a typedef declaring an object type. // rdar://10733000

llvm-svn: 148760
This commit is contained in:
Fariborz Jahanian 2012-01-24 00:40:15 +00:00
parent ed975232bc
commit 04c4455dd4
5 changed files with 46 additions and 9 deletions

View File

@ -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<DiagGroup<"objc-forward-class-redefinition">>;
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<

View File

@ -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<TypedefNameDecl>(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<ObjCObjectType>())
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<ObjCObjectType>(TDD->getUnderlyingType())) {
Diag(AtClassLoc, diag::warn_forward_class_redefinition) << IdentList[i];
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
continue;
}
}
}

View File

@ -31,14 +31,14 @@
@protocol XCElementP @end
typedef NSObject <XCElementP> XCElement;
typedef NSObject <XCElementP> 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; }

View File

@ -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 <PLAssetContainer> 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

View File

@ -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