diff options
author | Devin Coughlin <dcoughlin@apple.com> | 2016-04-28 19:44:40 +0000 |
---|---|---|
committer | Devin Coughlin <dcoughlin@apple.com> | 2016-04-28 19:44:40 +0000 |
commit | 97dc0c8c29f857fcffffc2b1ebaad459e91dc150 (patch) | |
tree | 8d57cf4dc491102ca8bab1b1ff42c0869ebdd459 /clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp | |
parent | e8c6840c71db30f07e7eaa6796d6d2c189330e58 (diff) | |
download | bcm5719-llvm-97dc0c8c29f857fcffffc2b1ebaad459e91dc150.tar.gz bcm5719-llvm-97dc0c8c29f857fcffffc2b1ebaad459e91dc150.zip |
[analyzer] Add path note for localizability checker.
Add a path note indicating the location of the non-localized string
literal in NonLocalizedStringChecker.
rdar://problem/25981525
llvm-svn: 267924
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp index a25f3e01c91..7be2f574f0e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp @@ -111,6 +111,30 @@ NonLocalizedStringChecker::NonLocalizedStringChecker() { "Localizability Issue (Apple)")); } +namespace { +class NonLocalizedStringBRVisitor final + : public BugReporterVisitorImpl<NonLocalizedStringBRVisitor> { + + const MemRegion *NonLocalizedString; + bool Satisfied; + +public: + NonLocalizedStringBRVisitor(const MemRegion *NonLocalizedString) + : NonLocalizedString(NonLocalizedString), Satisfied(false) { + assert(NonLocalizedString); + } + + PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, + const ExplodedNode *Pred, + BugReporterContext &BRC, + BugReport &BR) override; + + void Profile(llvm::FoldingSetNodeID &ID) const override { + ID.Add(NonLocalizedString); + } +}; +} // End anonymous namespace. + #define NEW_RECEIVER(receiver) \ llvm::DenseMap<Selector, uint8_t> &receiver##M = \ UIMethods.insert({&Ctx.Idents.get(#receiver), \ @@ -676,6 +700,11 @@ void NonLocalizedStringChecker::reportLocalizationError( R->addRange(M.getSourceRange()); } R->markInteresting(S); + + const MemRegion *StringRegion = S.getAsRegion(); + if (StringRegion) + R->addVisitor(llvm::make_unique<NonLocalizedStringBRVisitor>(StringRegion)); + C.emitReport(std::move(R)); } @@ -866,6 +895,41 @@ void NonLocalizedStringChecker::checkPostStmt(const ObjCStringLiteral *SL, setNonLocalizedState(sv, C); } +PathDiagnosticPiece * +NonLocalizedStringBRVisitor::VisitNode(const ExplodedNode *Succ, + const ExplodedNode *Pred, + BugReporterContext &BRC, BugReport &BR) { + if (Satisfied) + return nullptr; + + Optional<StmtPoint> Point = Succ->getLocation().getAs<StmtPoint>(); + if (!Point.hasValue()) + return nullptr; + + auto *LiteralExpr = dyn_cast<ObjCStringLiteral>(Point->getStmt()); + if (!LiteralExpr) + return nullptr; + + ProgramStateRef State = Succ->getState(); + SVal LiteralSVal = State->getSVal(LiteralExpr, Succ->getLocationContext()); + if (LiteralSVal.getAsRegion() != NonLocalizedString) + return nullptr; + + Satisfied = true; + + PathDiagnosticLocation L = + PathDiagnosticLocation::create(*Point, BRC.getSourceManager()); + + if (!L.isValid() || !L.asLocation().isValid()) + return nullptr; + + auto *Piece = new PathDiagnosticEventPiece(L, + "Non-localized string literal here"); + Piece->addRange(LiteralExpr->getSourceRange()); + + return Piece; +} + namespace { class EmptyLocalizationContextChecker : public Checker<check::ASTDecl<ObjCImplementationDecl>> { |