diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 32 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 62 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 43 |
4 files changed, 90 insertions, 61 deletions
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index fe9a7841cfd..f4e2fb32053 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -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. diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 28a5a430557..c4f01c093a7 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -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; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index a424a8a1b0e..e8a61044b5d 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -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()) { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c0d910b4286..6ea3f4827a1 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -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; } |