From 97dc0c8c29f857fcffffc2b1ebaad459e91dc150 Mon Sep 17 00:00:00 2001 From: Devin Coughlin Date: Thu, 28 Apr 2016 19:44:40 +0000 Subject: [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 --- .../Checkers/LocalizationChecker.cpp | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp') 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 { + + 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 &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(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 Point = Succ->getLocation().getAs(); + if (!Point.hasValue()) + return nullptr; + + auto *LiteralExpr = dyn_cast(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> { -- cgit v1.2.3