r267924 - [analyzer] Add path note for localizability checker.
Devin Coughlin via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 28 12:44:40 PDT 2016
Author: dcoughlin
Date: Thu Apr 28 14:44:40 2016
New Revision: 267924
URL: http://llvm.org/viewvc/llvm-project?rev=267924&view=rev
Log:
[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
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
cfe/trunk/test/Analysis/localization.m
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp?rev=267924&r1=267923&r2=267924&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp Thu Apr 28 14:44:40 2016
@@ -111,6 +111,30 @@ NonLocalizedStringChecker::NonLocalizedS
"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::reportLo
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::checkPos
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>> {
Modified: cfe/trunk/test/Analysis/localization.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/localization.m?rev=267924&r1=267923&r2=267924&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/localization.m (original)
+++ cfe/trunk/test/Analysis/localization.m Thu Apr 28 14:44:40 2016
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -fblocks -analyzer-store=region -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=alpha.osx.cocoa.localizability.PluralMisuseChecker -verify %s
+// RUN: %clang_cc1 -analyze -fblocks -analyzer-store=region -analyzer-output=text -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=alpha.osx.cocoa.localizability.PluralMisuseChecker -verify %s
// The larger set of tests in located in localization.m. These are tests
// specific for non-aggressive reporting.
@@ -61,11 +61,26 @@ NSString *KHLocalizedString(NSString* ke
UILabel *testLabel = [[UILabel alloc] init];
NSString *bar = NSLocalizedString(@"Hello", @"Comment");
- if (random()) {
- bar = @"Unlocalized string";
+ if (random()) { // expected-note {{Taking true branch}}
+ bar = @"Unlocalized string"; // expected-note {{Non-localized string literal here}}
}
- [testLabel setText:bar]; // expected-warning {{User-facing text should use localized string macro}}
+ [testLabel setText:bar]; // expected-warning {{User-facing text should use localized string macro}} expected-note {{User-facing}}
+}
+
+- (void)testMultipleUnlocalizedStringsInSamePath {
+ UILabel *testLabel = [[UILabel alloc] init];
+ NSString *bar = @"Unlocalized string"; // no-note
+
+ bar = @"Unlocalized string"; // expected-note {{Non-localized string literal here}}
+
+ NSString *other = @"Other unlocalized string."; // no-note
+ (void)other;
+
+ NSString *same = @"Unlocalized string"; // no-note
+ (void)same;
+
+ [testLabel setText:bar]; // expected-warning {{User-facing text should use localized string macro}} expected-note {{User-facing}}
}
- (void)testOneCharacterStringsDoNotGiveAWarning {
@@ -103,14 +118,14 @@ NSString *KHLocalizedString(NSString* ke
- (NSString *)test1:(int)plural {
if (plural) {
- return MCLocalizedString(@"TYPE_PLURAL"); // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
+ return MCLocalizedString(@"TYPE_PLURAL"); // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
return MCLocalizedString(@"TYPE");
}
- (NSString *)test2:(int)numOfReminders {
if (numOfReminders > 0) {
- return [NSString stringWithFormat:@"%@, %@", @"Test", (numOfReminders != 1) ? [NSString stringWithFormat:NSLocalizedString(@"%@ Reminders", @"Plural count of reminders"), numOfReminders] : [NSString stringWithFormat:NSLocalizedString(@"1 reminder", @"One reminder")]]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
+ return [NSString stringWithFormat:@"%@, %@", @"Test", (numOfReminders != 1) ? [NSString stringWithFormat:NSLocalizedString(@"%@ Reminders", @"Plural count of reminders"), numOfReminders] : [NSString stringWithFormat:NSLocalizedString(@"1 reminder", @"One reminder")]]; // expected-warning 2 {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note 2 {{Plural}}
}
return nil;
}
@@ -119,18 +134,18 @@ NSString *KHLocalizedString(NSString* ke
NSString *count;
if (self.unreadArticlesCount > 1)
{
- count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Stories", @"Plural count for new stories")]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
+ count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Stories", @"Plural count for new stories")]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
} else {
- count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Story", @"One new story")]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
+ count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Story", @"One new story")]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
}
- (NSString *)test4:(int)count {
if ( count == 1 )
{
- return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
+ return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
} else {
- return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
+ return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
}
@@ -138,9 +153,9 @@ NSString *KHLocalizedString(NSString* ke
int test = count == 1;
if (test)
{
- return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
+ return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
} else {
- return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
+ return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
}
@@ -154,7 +169,7 @@ NSString *KHLocalizedString(NSString* ke
if (someOtherVariable)
return KHLocalizedString(@"OK",nil); // no-warning
} else {
- return KHLocalizedString(@"value.plural",nil); // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
+ return KHLocalizedString(@"value.plural",nil); // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-note {{Plural}}
}
return nil;
}
@@ -221,6 +236,6 @@ NSString *KHLocalizedString(NSString* ke
@implementation MyDebugView
- (void)setupScreen:(UILabel *)label {
- label.text = @"Unlocalized";
+ label.text = @"Unlocalized"; // no-warning
}
@end
More information about the cfe-commits
mailing list