summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp32
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp62
-rw-r--r--clang/lib/Sema/SemaStmt.cpp14
-rw-r--r--clang/lib/Sema/SemaType.cpp43
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;
}
OpenPOWER on IntegriCloud