From cf632c9ffd8c80344aac9876748db66ddd9b516d Mon Sep 17 00:00:00 2001 From: Devin Coughlin Date: Tue, 30 Aug 2016 23:07:14 +0000 Subject: [PATCH] [analyzer] Use lazily created buffer in EmptyLocalizationContextChecker Fix a crash when relexing the underlying memory buffer to find incorrect arguments to NSLocalizedString(). With precompiled headers, the raw buffer may be NULL. Instead, use the source manager to get the buffer, which will lazily create the buffer for precompiled headers. rdar://problem/27429091 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@280174 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp | 9 ++++++++- test/Analysis/Inputs/localization-pch.h | 5 +++++ test/Analysis/localization-aggressive.m | 8 +++++++- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 test/Analysis/Inputs/localization-pch.h diff --git a/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp index 1386f97cda..d1dab6d27d 100644 --- a/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp @@ -1016,6 +1016,8 @@ void EmptyLocalizationContextChecker::checkASTDecl( void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr( const ObjCMessageExpr *ME) { + // FIXME: We may be able to use PPCallbacks to check for empy context + // comments as part of preprocessing and avoid this re-lexing hack. const ObjCInterfaceDecl *OD = ME->getReceiverInterface(); if (!OD) return; @@ -1050,7 +1052,12 @@ void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr( SE = Mgr.getSourceManager().getSLocEntry(SLInfo.first); } - llvm::MemoryBuffer *BF = SE.getFile().getContentCache()->getRawBuffer(); + bool Invalid = false; + llvm::MemoryBuffer *BF = + Mgr.getSourceManager().getBuffer(SLInfo.first, SL, &Invalid); + if (Invalid) + return; + Lexer TheLexer(SL, LangOptions(), BF->getBufferStart(), BF->getBufferStart() + SLInfo.second, BF->getBufferEnd()); diff --git a/test/Analysis/Inputs/localization-pch.h b/test/Analysis/Inputs/localization-pch.h new file mode 100644 index 0000000000..973270e24e --- /dev/null +++ b/test/Analysis/Inputs/localization-pch.h @@ -0,0 +1,5 @@ +// Used to test missing checker for missing localization context comments +// in precompiled headers. + +#define MyLocalizedStringInPCH(key) NSLocalizedString((key), @"") + diff --git a/test/Analysis/localization-aggressive.m b/test/Analysis/localization-aggressive.m index 79c9c13312..89950d4eed 100644 --- a/test/Analysis/localization-aggressive.m +++ b/test/Analysis/localization-aggressive.m @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -analyze -fblocks -analyzer-store=region -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=optin.osx.cocoa.localizability.EmptyLocalizationContextChecker -verify -analyzer-config AggressiveReport=true %s +// RUN: %clang_cc1 -fblocks -x objective-c-header -emit-pch -o %t.pch %S/Inputs/localization-pch.h + +// RUN: %clang_cc1 -analyze -fblocks -analyzer-store=region -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=optin.osx.cocoa.localizability.EmptyLocalizationContextChecker -include-pch %t.pch -verify -analyzer-config AggressiveReport=true %s // These declarations were reduced using Delta-Debugging from Foundation.h // on Mac OS X. @@ -249,6 +251,10 @@ NSString *ForceLocalized(NSString *str) { return str; } NSString *string3 = NSLocalizedString((0 ? @"Critical" : @"Current"),nil); // expected-warning {{Localized string macro should include a non-empty comment for translators}} } +- (void)testMacroExpansionDefinedInPCH { + NSString *string = MyLocalizedStringInPCH(@"Hello"); // expected-warning {{Localized string macro should include a non-empty comment for translators}} +} + #define KCLocalizedString(x,comment) NSLocalizedString(x, comment) #define POSSIBLE_FALSE_POSITIVE(s,other) KCLocalizedString(s,@"Comment") -- 2.40.0