aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2013-03-28 23:39:11 +0000
committerFariborz Jahanian <fjahanian@apple.com>2013-03-28 23:39:11 +0000
commit99a72d2d875321b4d91e6aef4e20b289f3d05db4 (patch)
treecd9a388a4f2207bbcfb2b43eac4257c02a23c7ff /lib/Sema/SemaExpr.cpp
parent123243cfd80f790a27edd1b829cd190a85f6c006 (diff)
Objective-C: Produce precise diagnostic when
'isa' ivar is accessed provided it is the first ivar. Fixit hint will follow in another patch. This is continuation of // rdar://13503456 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178313 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp38
1 files changed, 36 insertions, 2 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 238d833c38..c6882908c2 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -450,6 +450,34 @@ static void CheckForNullPointerDereference(Sema &S, Expr *E) {
}
}
+static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
+ bool IsAssign) {
+ const ObjCIvarDecl *IV = OIRE->getDecl();
+ if (!IV)
+ return;
+
+ DeclarationName MemberName = IV->getDeclName();
+ IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+ if (!Member || !Member->isStr("isa"))
+ return;
+
+ const Expr *Base = OIRE->getBase();
+ QualType BaseType = Base->getType();
+ if (OIRE->isArrow())
+ BaseType = BaseType->getPointeeType();
+ if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>())
+ if (ObjCInterfaceDecl *IDecl = OTy->getInterface()) {
+ ObjCInterfaceDecl *ClassDeclared = 0;
+ ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
+ if (!ClassDeclared->getSuperClass()
+ && (*ClassDeclared->ivar_begin()) == IV) {
+ S.Diag(OIRE->getLocation(), IsAssign ? diag::warn_objc_isa_assign
+ : diag::warn_objc_isa_use);
+ S.Diag(IV->getLocation(), diag::note_ivar_decl);
+ }
+ }
+}
+
ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// Handle any placeholder expressions which made it here.
if (E->getType()->isPlaceholderType()) {
@@ -503,7 +531,10 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
else
Diag(E->getExprLoc(), diag::warn_objc_isa_use);
}
-
+ else if (const ObjCIvarRefExpr *OIRE =
+ dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts()))
+ DiagnoseDirectIsaAccess(*this, OIRE, false);
+
// C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the prvalue is the
// cv-unqualified version of T. Otherwise, the type of the
@@ -8561,7 +8592,10 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
else
Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign);
}
-
+ else if (const ObjCIvarRefExpr *OIRE =
+ dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts()))
+ DiagnoseDirectIsaAccess(*this, OIRE, true);
+
if (CompResultTy.isNull())
return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc,
ResultTy, VK, OK, OpLoc,