diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/AnalysisBasedWarnings.cpp | 33 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 137 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprMember.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Sema/SemaPseudoObject.cpp | 3 |
6 files changed, 161 insertions, 73 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 86e9dc2d648..bc25c0a5548 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -957,19 +957,42 @@ static void diagnoseRepeatedUseOfWeak(Sema &S, const WeakObjectProfileTy &Key = I->second->first; const WeakUseVector &Uses = I->second->second; - // For complicated expressions like self.foo.bar, it's hard to keep track - // of whether 'self.foo' is the same between two cases. We can only be - // 100% sure of a repeated use if the "base" part of the key is a variable, - // rather than, say, another property. + // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy + // may not contain enough information to determine that these are different + // properties. We can only be 100% sure of a repeated use in certain cases, + // and we adjust the diagnostic kind accordingly so that the less certain + // case can be turned off if it is too noisy. unsigned DiagKind; if (Key.isExactProfile()) DiagKind = diag::warn_arc_repeated_use_of_weak; else DiagKind = diag::warn_arc_possible_repeated_use_of_weak; + // Classify the weak object being accessed for better warning text. + // This enum should stay in sync with the cases in + // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. + enum { + Variable, + Property, + ImplicitProperty, + Ivar + } ObjectKind; + + const NamedDecl *D = Key.getProperty(); + if (isa<VarDecl>(D)) + ObjectKind = Variable; + else if (isa<ObjCPropertyDecl>(D)) + ObjectKind = Property; + else if (isa<ObjCMethodDecl>(D)) + ObjectKind = ImplicitProperty; + else if (isa<ObjCIvarDecl>(D)) + ObjectKind = Ivar; + else + llvm_unreachable("Unexpected weak object kind!"); + // Show the first time the object was read. S.Diag(FirstRead->getLocStart(), DiagKind) - << FunctionKind + << ObjectKind << D << FunctionKind << FirstRead->getSourceRange(); // Print all the other accesses as notes. diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 84cdb2b6f04..8555562d0dc 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -82,65 +82,77 @@ static bool isSelfExpr(const Expr *E) { return M->getSelfDecl() == Param; } +FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy +FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) { + E = E->IgnoreParenCasts(); + + const NamedDecl *D = 0; + bool IsExact = false; + + switch (E->getStmtClass()) { + case Stmt::DeclRefExprClass: + D = cast<DeclRefExpr>(E)->getDecl(); + IsExact = isa<VarDecl>(D); + break; + case Stmt::MemberExprClass: { + const MemberExpr *ME = cast<MemberExpr>(E); + D = ME->getMemberDecl(); + IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()); + break; + } + case Stmt::ObjCIvarRefExprClass: { + const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E); + D = IE->getDecl(); + IsExact = isSelfExpr(IE->getBase()); + break; + } + case Stmt::PseudoObjectExprClass: { + const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E); + const ObjCPropertyRefExpr *BaseProp = + dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm()); + if (BaseProp) { + D = getBestPropertyDecl(BaseProp); + + const Expr *DoubleBase = BaseProp->getBase(); + if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase)) + DoubleBase = OVE->getSourceExpr(); + + IsExact = isSelfExpr(DoubleBase); + } + break; + } + default: + break; + } + + return BaseInfoTy(D, IsExact); +} + + FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( const ObjCPropertyRefExpr *PropE) - : Base(0, false), Property(getBestPropertyDecl(PropE)) { + : Base(0, true), Property(getBestPropertyDecl(PropE)) { if (PropE->isObjectReceiver()) { const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase()); - const Expr *E = OVE->getSourceExpr()->IgnoreParenCasts(); - - switch (E->getStmtClass()) { - case Stmt::DeclRefExprClass: - Base.setPointer(cast<DeclRefExpr>(E)->getDecl()); - Base.setInt(isa<VarDecl>(Base.getPointer())); - break; - case Stmt::MemberExprClass: { - const MemberExpr *ME = cast<MemberExpr>(E); - Base.setPointer(ME->getMemberDecl()); - Base.setInt(isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())); - break; - } - case Stmt::ObjCIvarRefExprClass: { - const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E); - Base.setPointer(IE->getDecl()); - if (isSelfExpr(IE->getBase())) - Base.setInt(true); - break; - } - case Stmt::PseudoObjectExprClass: { - const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E); - const ObjCPropertyRefExpr *BaseProp = - dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm()); - if (BaseProp) { - Base.setPointer(getBestPropertyDecl(BaseProp)); - - const Expr *DoubleBase = BaseProp->getBase(); - if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase)) - DoubleBase = OVE->getSourceExpr(); - - if (isSelfExpr(DoubleBase)) - Base.setInt(true); - } - break; - } - default: - break; - } + const Expr *E = OVE->getSourceExpr(); + Base = getBaseInfo(E); } else if (PropE->isClassReceiver()) { Base.setPointer(PropE->getClassReceiver()); - Base.setInt(true); } else { assert(PropE->isSuperReceiver()); - Base.setInt(true); } } -void FunctionScopeInfo::recordUseOfWeak(const ObjCPropertyRefExpr *RefExpr) { - assert(RefExpr); - WeakUseVector &Uses = - WeakObjectUses[FunctionScopeInfo::WeakObjectProfileTy(RefExpr)]; - Uses.push_back(WeakUseTy(RefExpr, RefExpr->isMessagingGetter())); +FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( + const DeclRefExpr *DRE) + : Base(0, true), Property(DRE->getDecl()) { + assert(isa<VarDecl>(Property)); +} + +FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( + const ObjCIvarRefExpr *IvarE) + : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) { } void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { @@ -164,22 +176,27 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { return; } - if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) { - // Has this property been seen as a weak property? - FunctionScopeInfo::WeakObjectUseMap::iterator Uses = - WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(RefExpr)); - if (Uses == WeakObjectUses.end()) - return; + // Has this weak object been seen before? + FunctionScopeInfo::WeakObjectUseMap::iterator Uses; + if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) + Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(RefExpr)); + else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E)) + Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(IvarE)); + else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(DRE)); + else + return; - // Has there been a read from the property using this Expr? - FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse = - std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true)); - if (ThisUse == Uses->second.rend()) - return; + if (Uses == WeakObjectUses.end()) + return; - ThisUse->markSafe(); + // Has there been a read from the object using this Expr? + FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse = + std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true)); + if (ThisUse == Uses->second.rend()) return; - } + + ThisUse->markSafe(); } BlockScopeInfo::~BlockScopeInfo() { } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 7951a71e4ed..ebb6cd10652 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5639,9 +5639,19 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc, if (LHSType.isNull()) LHSType = LHS->getType(); + + Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime(); + + if (LT == Qualifiers::OCL_Weak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->markSafeWeakUse(LHS); + } + if (checkUnsafeAssigns(Loc, LHSType, RHS)) return; - Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime(); + // FIXME. Check for other life times. if (LT != Qualifiers::OCL_None) return; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 597e4d6f77c..0570dd38c79 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1425,6 +1425,15 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, MarkDeclRefReferenced(E); + if (getLangOpts().ObjCARCWeak && isa<VarDecl>(D) && + Ty.getObjCLifetime() == Qualifiers::OCL_Weak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + E->getLocStart()); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->recordUseOfWeak(E); + } + // Just in case we're building an illegal pointer-to-member. FieldDecl *FD = dyn_cast<FieldDecl>(D); if (FD && FD->isBitField()) @@ -1986,9 +1995,22 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, ObjCMethodFamily MF = CurMethod->getMethodFamily(); if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize) Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName(); - return Owned(new (Context) - ObjCIvarRefExpr(IV, IV->getType(), Loc, - SelfExpr.take(), true, true)); + + ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(), + Loc, + SelfExpr.take(), + true, true); + + if (getLangOpts().ObjCAutoRefCount) { + if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->recordUseOfWeak(Result); + } + } + + return Owned(Result); } } else if (CurMethod->isInstanceMethod()) { // We should warn if a local variable hides an ivar. diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index ec787d67a3f..ff580697e6d 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -1272,9 +1273,23 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (warn) Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName(); } - return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), - MemberLoc, BaseExpr.take(), - IsArrow)); + + ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(), + MemberLoc, + BaseExpr.take(), + IsArrow); + + if (getLangOpts().ObjCAutoRefCount) { + if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + MemberLoc); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->recordUseOfWeak(Result); + } + } + + return Owned(Result); } // Objective-C property access. diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index b07a59b81c2..501fa113ce8 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -845,7 +845,8 @@ ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, SyntacticForm->getLocStart()); if (Level != DiagnosticsEngine::Ignored) - S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr); + S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr, + SyntacticRefExpr->isMessagingGetter()); } return PseudoOpBuilder::complete(SyntacticForm); |