forked from OSchip/llvm-project
Use Sema::RequireCompleteType to check for the completeness of
Objective-C classes. This has two purposes: to consistently provide "forward declaration here" notes when we hit an incomplete type, and to give LLDB a chance to complete the type. RequireCompleteType bits from Sean Callanan! llvm-svn: 144573
This commit is contained in:
parent
1fcdaa9c05
commit
4123a86fae
|
@ -373,6 +373,8 @@ def warn_property_attribute : Warning<
|
|||
def warn_property_types_are_incompatible : Warning<
|
||||
"property type %0 is incompatible with type %1 inherited from %2">;
|
||||
def err_undef_interface : Error<"cannot find interface declaration for %0">;
|
||||
def err_category_forward_interface : Error<
|
||||
"cannot define %select{category|class extension}0 for undefined class %1">;
|
||||
def err_class_extension_after_impl : Error<
|
||||
"cannot declare class extension for %0 after class implementation">;
|
||||
def note_implementation_declared : Note<
|
||||
|
@ -3617,7 +3619,7 @@ def err_property_not_as_forward_class : Error<
|
|||
"property %0 refers to an incomplete Objective-C class %1 "
|
||||
"(with no @interface available)">;
|
||||
def note_forward_class : Note<
|
||||
"forward class is declared here">;
|
||||
"forward declaration of class here">;
|
||||
def err_duplicate_property : Error<
|
||||
"property has a previous declaration">;
|
||||
def ext_gnu_void_ptr : Extension<
|
||||
|
|
|
@ -463,11 +463,12 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
if (!SuperClassDecl)
|
||||
Diag(SuperLoc, diag::err_undef_superclass)
|
||||
<< SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
|
||||
else if (SuperClassDecl->isForwardDecl()) {
|
||||
Diag(SuperLoc, diag::err_forward_superclass)
|
||||
<< SuperClassDecl->getDeclName() << ClassName
|
||||
<< SourceRange(AtInterfaceLoc, ClassLoc);
|
||||
Diag(SuperClassDecl->getLocation(), diag::note_forward_class);
|
||||
else if (RequireCompleteType(SuperLoc,
|
||||
Context.getObjCInterfaceType(SuperClassDecl),
|
||||
PDiag(diag::err_forward_superclass)
|
||||
<< SuperClassDecl->getDeclName()
|
||||
<< ClassName
|
||||
<< SourceRange(AtInterfaceLoc, ClassLoc))) {
|
||||
SuperClassDecl = 0;
|
||||
}
|
||||
}
|
||||
|
@ -746,14 +747,20 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
|
|||
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
|
||||
|
||||
/// Check that class of this category is already completely declared.
|
||||
if (!IDecl || IDecl->isForwardDecl()) {
|
||||
|
||||
if (!IDecl
|
||||
|| RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
|
||||
PDiag(diag::err_category_forward_interface)
|
||||
<< (CategoryName == 0))) {
|
||||
// Create an invalid ObjCCategoryDecl to serve as context for
|
||||
// the enclosing method declarations. We mark the decl invalid
|
||||
// to make it clear that this isn't a valid AST.
|
||||
CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
|
||||
ClassLoc, CategoryLoc, CategoryName,IDecl);
|
||||
CDecl->setInvalidDecl();
|
||||
Diag(ClassLoc, diag::err_undef_interface) << ClassName;
|
||||
|
||||
if (!IDecl)
|
||||
Diag(ClassLoc, diag::err_undef_interface) << ClassName;
|
||||
return ActOnObjCContainerStartDefinition(CDecl);
|
||||
}
|
||||
|
||||
|
@ -820,9 +827,12 @@ Decl *Sema::ActOnStartCategoryImplementation(
|
|||
ObjCCategoryImplDecl::Create(Context, CurContext, CatName, IDecl,
|
||||
ClassLoc, AtCatImplLoc);
|
||||
/// Check that class of this category is already completely declared.
|
||||
if (!IDecl || IDecl->isForwardDecl()) {
|
||||
if (!IDecl) {
|
||||
Diag(ClassLoc, diag::err_undef_interface) << ClassName;
|
||||
CDecl->setInvalidDecl();
|
||||
} else if (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
|
||||
diag::err_undef_interface)) {
|
||||
CDecl->setInvalidDecl();
|
||||
}
|
||||
|
||||
// FIXME: PushOnScopeChains?
|
||||
|
@ -867,11 +877,9 @@ Decl *Sema::ActOnStartClassImplementation(
|
|||
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||
} else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
|
||||
// If this is a forward declaration of an interface, warn.
|
||||
if (IDecl->isForwardDecl()) {
|
||||
Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
|
||||
if (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
|
||||
diag::warn_undef_interface))
|
||||
IDecl = 0;
|
||||
}
|
||||
} else {
|
||||
// We did not find anything with the name ClassName; try to correct for
|
||||
// typos in the class name.
|
||||
|
|
|
@ -591,13 +591,13 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
|||
}
|
||||
|
||||
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
|
||||
|
||||
if (IFace->isForwardDecl()) {
|
||||
Diag(MemberLoc, diag::err_property_not_found_forward_class)
|
||||
<< MemberName << QualType(OPT, 0);
|
||||
Diag(IFace->getLocation(), diag::note_forward_class);
|
||||
SourceRange BaseRange = Super? SourceRange(SuperLoc)
|
||||
: BaseExpr->getSourceRange();
|
||||
if (RequireCompleteType(MemberLoc, OPT->getPointeeType(),
|
||||
PDiag(diag::err_property_not_found_forward_class)
|
||||
<< MemberName << BaseRange))
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
// Search for a declared property first.
|
||||
if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
|
||||
// Check whether we can reference this property.
|
||||
|
@ -722,14 +722,10 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
|||
QualType T = Ivar->getType();
|
||||
if (const ObjCObjectPointerType * OBJPT =
|
||||
T->getAsObjCInterfacePointerType()) {
|
||||
const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
|
||||
if (ObjCInterfaceDecl *IFace = IFaceT->getDecl())
|
||||
if (IFace->isForwardDecl()) {
|
||||
Diag(MemberLoc, diag::err_property_not_as_forward_class)
|
||||
<< MemberName << IFace;
|
||||
Diag(IFace->getLocation(), diag::note_forward_class);
|
||||
return ExprError();
|
||||
}
|
||||
if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(),
|
||||
PDiag(diag::err_property_not_as_forward_class)
|
||||
<< MemberName << BaseExpr->getSourceRange()))
|
||||
return ExprError();
|
||||
}
|
||||
Diag(MemberLoc,
|
||||
diag::err_ivar_access_using_property_syntax_suggest)
|
||||
|
@ -1083,13 +1079,14 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
|
|||
(void)DiagnoseUseOfDecl(Class, Loc);
|
||||
// Find the method we are messaging.
|
||||
if (!Method) {
|
||||
if (Class->isForwardDecl()) {
|
||||
if (getLangOptions().ObjCAutoRefCount) {
|
||||
Diag(Loc, diag::err_arc_receiver_forward_class) << ReceiverType;
|
||||
} else {
|
||||
Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName();
|
||||
}
|
||||
|
||||
SourceRange TypeRange
|
||||
= SuperLoc.isValid()? SourceRange(SuperLoc)
|
||||
: ReceiverTypeInfo->getTypeLoc().getSourceRange();
|
||||
if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class),
|
||||
(getLangOptions().ObjCAutoRefCount
|
||||
? PDiag(diag::err_arc_receiver_forward_class)
|
||||
: PDiag(diag::warn_receiver_forward_class))
|
||||
<< TypeRange)) {
|
||||
// A forward class used in messaging is treated as a 'Class'
|
||||
Method = LookupFactoryMethodInGlobalPool(Sel,
|
||||
SourceRange(LBracLoc, RBracLoc));
|
||||
|
@ -1322,13 +1319,21 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
|
|||
// We allow sending a message to a pointer to an interface (an object).
|
||||
ClassDecl = OCIType->getInterfaceDecl();
|
||||
|
||||
if (ClassDecl->isForwardDecl() && getLangOptions().ObjCAutoRefCount) {
|
||||
Diag(Loc, diag::err_arc_receiver_forward_instance)
|
||||
<< OCIType->getPointeeType()
|
||||
<< (Receiver ? Receiver->getSourceRange() : SourceRange(SuperLoc));
|
||||
return ExprError();
|
||||
// Try to complete the type. Under ARC, this is a hard error from which
|
||||
// we don't try to recover.
|
||||
const ObjCInterfaceDecl *forwardClass = 0;
|
||||
if (RequireCompleteType(Loc, OCIType->getPointeeType(),
|
||||
getLangOptions().ObjCAutoRefCount
|
||||
? PDiag(diag::err_arc_receiver_forward_instance)
|
||||
<< (Receiver ? Receiver->getSourceRange()
|
||||
: SourceRange(SuperLoc))
|
||||
: PDiag())) {
|
||||
if (getLangOptions().ObjCAutoRefCount)
|
||||
return ExprError();
|
||||
|
||||
forwardClass = OCIType->getInterfaceDecl();
|
||||
}
|
||||
|
||||
|
||||
// FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
|
||||
// faster than the following method (which can do *many* linear searches).
|
||||
// The idea is to add class info to MethodPool.
|
||||
|
@ -1338,7 +1343,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
|
|||
// Search protocol qualifiers.
|
||||
Method = LookupMethodInQualifiedType(Sel, OCIType, true);
|
||||
|
||||
const ObjCInterfaceDecl *forwardClass = 0;
|
||||
if (!Method) {
|
||||
// If we have implementations in scope, check "private" methods.
|
||||
Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
|
||||
|
@ -1356,8 +1360,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
|
|||
if (OCIType->qual_empty()) {
|
||||
Method = LookupInstanceMethodInGlobalPool(Sel,
|
||||
SourceRange(LBracLoc, RBracLoc));
|
||||
if (OCIType->getInterfaceDecl()->isForwardDecl())
|
||||
forwardClass = OCIType->getInterfaceDecl();
|
||||
if (Method && !forwardClass)
|
||||
Diag(Loc, diag::warn_maynot_respond)
|
||||
<< OCIType->getInterfaceDecl()->getIdentifier() << Sel;
|
||||
|
|
|
@ -1060,13 +1060,13 @@ Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
|
|||
ObjCInterfaceDecl *iface = objectType->getInterface();
|
||||
|
||||
// If we have a forward-declared type, we can't do this check.
|
||||
if (iface && iface->isForwardDecl()) {
|
||||
// This is ill-formed under ARC.
|
||||
if (getLangOptions().ObjCAutoRefCount) {
|
||||
Diag(forLoc, diag::err_arc_collection_forward)
|
||||
<< pointerType->getPointeeType() << collection->getSourceRange();
|
||||
}
|
||||
|
||||
// Under ARC, it is an error not to have a forward-declared class.
|
||||
if (iface &&
|
||||
RequireCompleteType(forLoc, QualType(objectType, 0),
|
||||
getLangOptions().ObjCAutoRefCount
|
||||
? PDiag(diag::err_arc_collection_forward)
|
||||
<< collection->getSourceRange()
|
||||
: PDiag(0))) {
|
||||
// Otherwise, if we have any useful type information, check that
|
||||
// the type declares the appropriate method.
|
||||
} else if (iface || !objectType->qual_empty()) {
|
||||
|
|
|
@ -4098,21 +4098,36 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
|
|||
return true;
|
||||
|
||||
const TagType *Tag = T->getAs<TagType>();
|
||||
const ObjCInterfaceType *IFace = 0;
|
||||
|
||||
if (Tag) {
|
||||
// Avoid diagnosing invalid decls as incomplete.
|
||||
if (Tag->getDecl()->isInvalidDecl())
|
||||
return true;
|
||||
|
||||
// Avoid diagnosing invalid decls as incomplete.
|
||||
if (Tag && Tag->getDecl()->isInvalidDecl())
|
||||
return true;
|
||||
|
||||
// Give the external AST source a chance to complete the type.
|
||||
if (Tag && Tag->getDecl()->hasExternalLexicalStorage()) {
|
||||
Context.getExternalSource()->CompleteType(Tag->getDecl());
|
||||
if (!Tag->isIncompleteType())
|
||||
return false;
|
||||
// Give the external AST source a chance to complete the type.
|
||||
if (Tag->getDecl()->hasExternalLexicalStorage()) {
|
||||
Context.getExternalSource()->CompleteType(Tag->getDecl());
|
||||
if (!Tag->isIncompleteType())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
else if ((IFace = T->getAs<ObjCInterfaceType>())) {
|
||||
// Avoid diagnosing invalid decls as incomplete.
|
||||
if (IFace->getDecl()->isInvalidDecl())
|
||||
return true;
|
||||
|
||||
// Give the external AST source a chance to complete the type.
|
||||
if (IFace->getDecl()->hasExternalLexicalStorage()) {
|
||||
Context.getExternalSource()->CompleteType(IFace->getDecl());
|
||||
if (!IFace->isIncompleteType())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We have an incomplete type. Produce a diagnostic.
|
||||
Diag(Loc, PD) << T;
|
||||
|
||||
|
||||
// If we have a note, produce it.
|
||||
if (!Note.first.isInvalid())
|
||||
Diag(Note.first, Note.second);
|
||||
|
@ -4123,7 +4138,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
|
|||
Diag(Tag->getDecl()->getLocation(),
|
||||
Tag->isBeingDefined() ? diag::note_type_being_defined
|
||||
: diag::note_forward_declaration)
|
||||
<< QualType(Tag, 0);
|
||||
<< QualType(Tag, 0);
|
||||
|
||||
// If the Objective-C class was a forward declaration, produce a note.
|
||||
if (IFace && !IFace->getDecl()->isInvalidDecl())
|
||||
Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ typedef struct _NSZone NSZone;
|
|||
@interface NSObject <NSObject> {} @end
|
||||
extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
|
||||
@class NSArray;
|
||||
@class NSMutableArray, NSIndexSet, NSView, NSPredicate, NSString, NSViewAnimation, NSTimer;
|
||||
@class NSMutableArray, NSIndexSet, NSView, NSPredicate, NSString, NSViewAnimation, NSTimer; // expected-note{{forward declaration of class here}}
|
||||
@interface FooBazController : NSObject {}
|
||||
@end
|
||||
typedef struct {} TazVersion;
|
||||
|
|
|
@ -378,7 +378,7 @@ void test16(void) {
|
|||
[v test16_6: 0];
|
||||
}
|
||||
|
||||
@class Test17;
|
||||
@class Test17; // expected-note 2{{forward declaration of class here}}
|
||||
@protocol Test17p
|
||||
- (void) test17;
|
||||
+ (void) test17;
|
||||
|
@ -651,7 +651,7 @@ void test36(int first, ...) {
|
|||
__builtin_va_end(arglist);
|
||||
}
|
||||
|
||||
@class Test37;
|
||||
@class Test37; // expected-note{{forward declaration of class here}}
|
||||
void test37(Test37 *c) {
|
||||
for (id y in c) { // expected-error {{collection expression type 'Test37' is a forward declaration}}
|
||||
(void) y;
|
||||
|
|
|
@ -31,9 +31,9 @@
|
|||
|
||||
@interface UnknownClass (Category) @end // expected-error {{cannot find interface declaration for 'UnknownClass'}}
|
||||
|
||||
@class MyClass2;
|
||||
@class MyClass2; // expected-note{{forward declaration of class here}}
|
||||
|
||||
@interface MyClass2 (Category) @end // expected-error {{cannot find interface declaration for 'MyClass2'}}
|
||||
@interface MyClass2 (Category) @end // expected-error {{cannot define category for undefined class 'MyClass2'}}
|
||||
|
||||
@interface XCRemoteComputerManager
|
||||
@end
|
||||
|
|
|
@ -31,7 +31,7 @@ typedef int INTF3; // expected-note {{previous definition is here}}
|
|||
|
||||
@implementation INTF4 @end // expected-warning {{cannot find interface declaration for 'INTF4'}}
|
||||
|
||||
@class INTF5;
|
||||
@class INTF5; // expected-note{{forward declaration of class here}}
|
||||
|
||||
@implementation INTF5 { // expected-warning {{cannot find interface declaration for 'INTF5'}}
|
||||
int x;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
@interface E2 <p1,p2,p3> @end // expected-warning {{cannot find protocol definition for 'p3'}}
|
||||
|
||||
@class U1, U2; // expected-note {{forward class is declared here}}
|
||||
@class U1, U2; // expected-note {{forward declaration of class here}}
|
||||
|
||||
@interface E3 : U1 @end // expected-error {{attempting to use the forward class 'U1' as superclass of 'E3'}}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ void test3(Object *o) {
|
|||
__sync_bool_compare_and_swap(&g, 0, o);
|
||||
}
|
||||
|
||||
@class Incomplete_ObjC_class;
|
||||
@class Incomplete_ObjC_class; // expected-note{{forward declaration of class here}}
|
||||
struct Incomplete_struct; // expected-note {{forward declaration}}
|
||||
|
||||
void test_encode() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
@class FOO, BAR; // expected-note {{forward class is declared here}}
|
||||
@class FOO, BAR; // expected-note {{forward declaration of class here}}
|
||||
@class FOO, BAR;
|
||||
|
||||
@interface INTF : FOO // expected-error {{attempting to use the forward class 'FOO' as superclass of 'INTF'}}
|
||||
|
@ -46,7 +46,7 @@ typedef NSObject <XCElementP> XCElement;
|
|||
|
||||
|
||||
// rdar://9653341
|
||||
@class B; // expected-note {{forward class is declared here}}
|
||||
@class B; // expected-note {{forward declaration of class here}}
|
||||
@interface A : B {} // expected-error {{attempting to use the forward class 'B' as superclass of 'A'}}
|
||||
@end
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
@end
|
||||
Class isa;
|
||||
|
||||
@class NotKnown;
|
||||
@class NotKnown; // expected-note{{forward declaration of class here}}
|
||||
|
||||
void foo(NotKnown *n) {
|
||||
[isa new];
|
||||
|
|
|
@ -97,13 +97,13 @@ typedef signed char BOOL;
|
|||
@end
|
||||
|
||||
// rdar://8774513
|
||||
@class MDAInstance; // expected-note {{forward class is declared here}}
|
||||
@class MDAInstance; // expected-note {{forward declaration of class here}}
|
||||
|
||||
@interface MDATestDocument
|
||||
@property(retain) MDAInstance *instance;
|
||||
@end
|
||||
|
||||
id f0(MDATestDocument *d) {
|
||||
return d.instance.path; // expected-error {{property 'path' cannot be found in forward class object 'MDAInstance *'}}
|
||||
return d.instance.path; // expected-error {{property 'path' cannot be found in forward class object 'MDAInstance'}}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ void f3(id o)
|
|||
}
|
||||
|
||||
// rdar://8851803
|
||||
@class SomeOtherClass; // expected-note {{forward class is declared here}}
|
||||
@class SomeOtherClass; // expected-note {{forward declaration of class here}}
|
||||
|
||||
@interface MyClass {
|
||||
SomeOtherClass *someOtherObject;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -verify -fsyntax-only %s
|
||||
|
||||
@class I0;
|
||||
@class I0; // expected-note 3{{forward declaration of class here}}
|
||||
|
||||
// rdar://6811884
|
||||
int g0 = sizeof(I0); // expected-error{{invalid application of 'sizeof' to an incomplete type 'I0'}}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
@end
|
||||
|
||||
|
||||
@class C; // expected-note 5 {{forward class is declared here}}
|
||||
@class C; // expected-note 5 {{forward declaration of class here}}
|
||||
|
||||
void test(C *c) {
|
||||
[c depInA]; // expected-warning {{'depInA' maybe deprecated because receiver type is unknown}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
@class SUPER, Y; // expected-note 2 {{forward class is declared here}}
|
||||
@class SUPER, Y; // expected-note 2 {{forward declaration of class here}}
|
||||
|
||||
@interface INTF :SUPER // expected-error {{attempting to use the forward class 'SUPER' as superclass of 'INTF'}}
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue