32 #include "llvm/Support/Unicode.h" 34 using namespace clang;
38 struct LocalizedState {
40 enum Kind { NonLocalized, Localized } K;
41 LocalizedState(
Kind InK) : K(InK) {}
44 bool isLocalized()
const {
return K == Localized; }
45 bool isNonLocalized()
const {
return K == NonLocalized; }
47 static LocalizedState getLocalized() {
return LocalizedState(Localized); }
48 static LocalizedState getNonLocalized() {
49 return LocalizedState(NonLocalized);
53 bool operator==(
const LocalizedState &
X)
const {
return K == X.K; }
56 void Profile(llvm::FoldingSetNodeID &
ID)
const { ID.AddInteger(K); }
59 class NonLocalizedStringChecker
60 :
public Checker<check::PreCall, check::PostCall, check::PreObjCMessage,
61 check::PostObjCMessage,
62 check::PostStmt<ObjCStringLiteral>> {
64 mutable std::unique_ptr<BugType> BT;
68 llvm::DenseMap<Selector, uint8_t>> UIMethods;
70 mutable llvm::SmallSet<std::pair<const IdentifierInfo *, Selector>, 12> LSM;
72 mutable llvm::SmallSet<const IdentifierInfo *, 5> LSF;
75 void initLocStringsMethods(
ASTContext &Ctx)
const;
82 bool isAnnotatedAsReturningLocalized(
const Decl *D)
const;
83 bool isAnnotatedAsTakingLocalized(
const Decl *D)
const;
85 int argumentNumber = 0)
const;
87 int getLocalizedArgumentForSelector(
const IdentifierInfo *Receiver,
91 NonLocalizedStringChecker();
110 NonLocalizedStringChecker::NonLocalizedStringChecker() {
111 BT.reset(
new BugType(
this,
"Unlocalizable string",
112 "Localizability Issue (Apple)"));
122 NonLocalizedStringBRVisitor(
const MemRegion *NonLocalizedString)
123 : NonLocalizedString(NonLocalizedString), Satisfied(
false) {
124 assert(NonLocalizedString);
127 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *Succ,
132 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
133 ID.Add(NonLocalizedString);
138 #define NEW_RECEIVER(receiver) \ 139 llvm::DenseMap<Selector, uint8_t> &receiver##M = \ 140 UIMethods.insert({&Ctx.Idents.get(#receiver), \ 141 llvm::DenseMap<Selector, uint8_t>()}) \ 143 #define ADD_NULLARY_METHOD(receiver, method, argument) \ 144 receiver##M.insert( \ 145 {Ctx.Selectors.getNullarySelector(&Ctx.Idents.get(#method)), argument}); 146 #define ADD_UNARY_METHOD(receiver, method, argument) \ 147 receiver##M.insert( \ 148 {Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(#method)), argument}); 149 #define ADD_METHOD(receiver, method_list, count, argument) \ 150 receiver##M.insert({Ctx.Selectors.getSelector(count, method_list), argument}); 154 void NonLocalizedStringChecker::initUIMethods(
ASTContext &Ctx)
const {
155 if (!UIMethods.empty())
166 ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemTag, 3, 0)
170 ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemImage, 3, 0)
183 ADD_METHOD(UITableViewRowAction, rowActionWithStyleUITableViewRowAction, 3, 1)
195 ADD_METHOD(NSButton, radioButtonWithTitleNSButton, 3, 0)
199 ADD_METHOD(NSButton, buttonWithTitleNSButtonImage, 4, 0)
203 ADD_METHOD(NSButton, checkboxWithTitleNSButton, 3, 0)
207 ADD_METHOD(NSButton, buttonWithTitleNSButtonTarget, 3, 0)
226 ADD_METHOD(NSBrowser, setTitleNSBrowser, 2, 0)
237 ADD_METHOD(UIAlertAction, actionWithTitleUIAlertAction, 3, 0)
243 ADD_METHOD(NSPopUpButton, insertItemWithTitleNSPopUpButton, 2, 0)
252 ADD_METHOD(NSTableViewRowAction, rowActionWithStyleNSTableViewRowAction, 3, 1)
284 ADD_METHOD(NSSegmentedControl, setLabelNSSegmentedControl, 2, 0)
287 ADD_METHOD(NSSegmentedControl, setToolTipNSSegmentedControl, 2, 0)
312 ADD_METHOD(NSMatrix, setToolTipNSMatrix, 2, 0)
328 ADD_METHOD(UIMenuItem, initWithTitleUIMenuItem, 2, 0)
335 ADD_METHOD(UIAlertController, alertControllerWithTitleUIAlertController, 3, 1)
345 initWithTypeUIApplicationShortcutItemIcon, 5, 1)
348 ADD_METHOD(UIApplicationShortcutItem, initWithTypeUIApplicationShortcutItem,
355 &Ctx.
Idents.
get(
"destructiveButtonTitle"),
357 ADD_METHOD(UIActionSheet, initWithTitleUIActionSheet, 5, 0)
366 initWithNameUIAccessibilityCustomAction, 3, 0)
393 ADD_METHOD(NSAttributedString, initWithStringNSAttributedString, 2, 0)
402 ADD_METHOD(UIKeyCommand, keyCommandWithInputUIKeyCommand, 4, 3)
412 &Ctx.
Idents.
get(
"informativeTextWithFormat")};
413 ADD_METHOD(NSAlert, alertWithMessageTextNSAlert, 5, 0)
432 ADD_METHOD(NSWindow, minFrameWidthWithTitleNSWindow, 2, 0)
439 IdentifierInfo *addOptionWithTitleUIDocumentMenuViewController[] = {
443 addOptionWithTitleUIDocumentMenuViewController, 4, 0)
455 ADD_METHOD(UIAlertView, initWithTitleUIAlertView, 5, 0)
485 ADD_METHOD(NSSegmentedCell, setLabelNSSegmentedCell, 2, 0)
488 ADD_METHOD(NSSegmentedCell, setToolTipNSSegmentedCell, 2, 0)
499 ADD_METHOD(NSMenuItem, initWithTitleNSMenuItem, 3, 0)
506 ADD_METHOD(NSPopUpButtonCell, initTextCellNSPopUpButtonCell, 2, 0)
510 ADD_METHOD(NSPopUpButtonCell, insertItemWithTitleNSPopUpButtonCell, 2, 0)
523 ADD_METHOD(NSMenu, insertItemWithTitleNSMenu, 4, 0)
527 ADD_METHOD(NSMenu, addItemWithTitleNSMenu, 3, 0)
543 IdentifierInfo *actionWithIdentifierNSUserNotificationAction[] = {
546 actionWithIdentifierNSUserNotificationAction, 2, 1)
556 ADD_METHOD(UIBarButtonItem, initWithTitleUIBarButtonItem, 4, 0)
565 ADD_METHOD(UISegmentedControl, insertSegmentWithTitleUISegmentedControl, 3, 0)
568 ADD_METHOD(UISegmentedControl, setTitleUISegmentedControl, 2, 0)
572 *initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult[] = {
573 &Ctx.
Idents.
get(
"initWithItemLoadingToken"),
575 ADD_METHOD(NSAccessibilityCustomRotorItemResult,
576 initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult, 2, 1)
583 ADD_METHOD(UIContextualAction, contextualActionWithStyleUIContextualAction, 3,
591 initWithLabelNSAccessibilityCustomRotor, 2, 0)
602 initWithNameNSAccessibilityCustomAction, 2, 0)
603 IdentifierInfo *initWithNameTargetNSAccessibilityCustomAction[] = {
607 initWithNameTargetNSAccessibilityCustomAction, 3, 0)
611 #define LSF_INSERT(function_name) LSF.insert(&Ctx.Idents.get(function_name)); 612 #define LSM_INSERT_NULLARY(receiver, method_name) \ 613 LSM.insert({&Ctx.Idents.get(receiver), Ctx.Selectors.getNullarySelector( \ 614 &Ctx.Idents.get(method_name))}); 615 #define LSM_INSERT_UNARY(receiver, method_name) \ 616 LSM.insert({&Ctx.Idents.get(receiver), \ 617 Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(method_name))}); 618 #define LSM_INSERT_SELECTOR(receiver, method_list, arguments) \ 619 LSM.insert({&Ctx.Idents.get(receiver), \ 620 Ctx.Selectors.getSelector(arguments, method_list)}); 623 void NonLocalizedStringChecker::initLocStringsMethods(
ASTContext &Ctx)
const {
641 LSF_INSERT(
"CFDateFormatterCreateStringWithDate");
642 LSF_INSERT(
"CFDateFormatterCreateStringWithAbsoluteTime");
643 LSF_INSERT(
"CFNumberFormatterCreateStringWithNumber");
648 bool NonLocalizedStringChecker::isAnnotatedAsReturningLocalized(
649 const Decl *D)
const {
655 return Ann->getAnnotation() ==
"returns_localized_nsstring";
661 bool NonLocalizedStringChecker::isAnnotatedAsTakingLocalized(
662 const Decl *D)
const {
668 return Ann->getAnnotation() ==
"takes_localized_nsstring";
673 bool NonLocalizedStringChecker::hasLocalizedState(
SVal S,
677 const LocalizedState *LS = C.
getState()->get<LocalizedMemMap>(mt);
678 if (LS && LS->isLocalized())
686 bool NonLocalizedStringChecker::hasNonLocalizedState(
SVal S,
690 const LocalizedState *LS = C.
getState()->get<LocalizedMemMap>(mt);
691 if (LS && LS->isNonLocalized())
698 void NonLocalizedStringChecker::setLocalizedState(
const SVal S,
703 C.
getState()->set<LocalizedMemMap>(mt, LocalizedState::getLocalized());
709 void NonLocalizedStringChecker::setNonLocalizedState(
const SVal S,
714 mt, LocalizedState::getNonLocalized());
721 return StringRef(name).lower().find(
"debug") != StringRef::npos;
733 if (
auto *ND = dyn_cast<NamedDecl>(D)) {
740 if (
auto *CD = dyn_cast<ObjCContainerDecl>(DC)) {
750 void NonLocalizedStringChecker::reportLocalizationError(
760 "UnlocalizedString");
767 std::unique_ptr<BugReport> R(
new BugReport(
768 *BT,
"User-facing text should use localized string macro", ErrNode));
769 if (argumentNumber) {
774 R->markInteresting(S);
778 R->addVisitor(llvm::make_unique<NonLocalizedStringBRVisitor>(StringRegion));
785 int NonLocalizedStringChecker::getLocalizedArgumentForSelector(
787 auto method = UIMethods.find(Receiver);
789 if (method == UIMethods.end())
792 auto argumentIterator = method->getSecond().find(S);
794 if (argumentIterator == method->getSecond().end())
797 int argumentNumber = argumentIterator->getSecond();
798 return argumentNumber;
802 void NonLocalizedStringChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
814 StringRef SelectorName = SelectorString;
815 assert(!SelectorName.empty());
817 if (odInfo->
isStr(
"NSString")) {
821 if (!(SelectorName.startswith(
"drawAtPoint") ||
822 SelectorName.startswith(
"drawInRect") ||
823 SelectorName.startswith(
"drawWithRect")))
828 bool isNonLocalized = hasNonLocalizedState(svTitle, C);
830 if (isNonLocalized) {
831 reportLocalizationError(svTitle, msg, C);
835 int argumentNumber = getLocalizedArgumentForSelector(odInfo, S);
837 while (argumentNumber < 0 && OD->getSuperClass() !=
nullptr) {
838 for (
const auto *
P : OD->all_referenced_protocols()) {
839 argumentNumber = getLocalizedArgumentForSelector(
P->getIdentifier(), S);
840 if (argumentNumber >= 0)
843 if (argumentNumber < 0) {
844 OD = OD->getSuperClass();
845 argumentNumber = getLocalizedArgumentForSelector(OD->getIdentifier(), S);
849 if (argumentNumber < 0) {
851 if (
const ObjCMethodDecl *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) {
852 auto formals = OMD->parameters();
853 for (
unsigned i = 0, ei = formals.size(); i != ei; ++i) {
854 if (isAnnotatedAsTakingLocalized(formals[i])) {
863 if (argumentNumber < 0)
866 SVal svTitle = msg.getArgSVal(argumentNumber);
869 dyn_cast_or_null<ObjCStringRegion>(svTitle.
getAsRegion())) {
870 StringRef stringValue =
871 SR->getObjCStringLiteral()->getString()->getString();
872 if ((stringValue.trim().size() == 0 && stringValue.size() > 0) ||
875 if (!IsAggressive && llvm::sys::unicode::columnWidthUTF8(stringValue) < 2)
879 bool isNonLocalized = hasNonLocalizedState(svTitle, C);
881 if (isNonLocalized) {
882 reportLocalizationError(svTitle, msg, C, argumentNumber + 1);
886 void NonLocalizedStringChecker::checkPreCall(
const CallEvent &Call,
889 if (D && isa<FunctionDecl>(D)) {
895 if (isAnnotatedAsTakingLocalized(formals[i])) {
897 if (hasNonLocalizedState(actual, C)) {
898 reportLocalizationError(actual, Call, C, i + 1);
918 return ClsName == &Ctx.
Idents.
get(
"NSString") ||
919 ClsName == &Ctx.
Idents.
get(
"NSMutableString");
927 void NonLocalizedStringChecker::checkPostCall(
const CallEvent &Call,
939 for (
unsigned i = 0; i < Call.
getNumArgs(); ++i) {
941 if (hasLocalizedState(argValue, C)) {
943 setLocalizedState(sv, C);
956 if (isAnnotatedAsReturningLocalized(D) || LSF.count(Identifier) != 0) {
957 setLocalizedState(sv, C);
959 !hasLocalizedState(sv, C)) {
961 setNonLocalizedState(sv, C);
964 dyn_cast_or_null<SymbolicRegion>(sv.
getAsRegion());
966 setNonLocalizedState(sv, C);
973 void NonLocalizedStringChecker::checkPostObjCMessage(
const ObjCMethodCall &msg,
988 std::pair<const IdentifierInfo *, Selector> MethodDescription = {odInfo, S};
990 if (LSM.count(MethodDescription) ||
991 isAnnotatedAsReturningLocalized(msg.
getDecl())) {
992 SVal sv = msg.getReturnValue();
993 setLocalizedState(sv, C);
1001 setNonLocalizedState(sv, C);
1004 std::shared_ptr<PathDiagnosticPiece>
1005 NonLocalizedStringBRVisitor::VisitNode(
const ExplodedNode *Succ,
1012 if (!Point.hasValue())
1020 if (LiteralSVal.
getAsRegion() != NonLocalizedString)
1031 auto Piece = std::make_shared<PathDiagnosticEventPiece>(
1032 L,
"Non-localized string literal here");
1033 Piece->addRange(LiteralExpr->getSourceRange());
1035 return std::move(Piece);
1039 class EmptyLocalizationContextChecker
1040 :
public Checker<check::ASTDecl<ObjCImplementationDecl>> {
1054 : MD(InMD), BR(InBR), Mgr(InMgr), Checker(Checker), DCtx(InDCtx) {}
1056 void VisitStmt(
const Stmt *S) { VisitChildren(S); }
1062 void VisitChildren(
const Stmt *S) {
1076 void EmptyLocalizationContextChecker::checkASTDecl(
1083 const Stmt *Body = M->getBody();
1086 MethodCrawler MC(M->getCanonicalDecl(), BR,
this, Mgr, DCtx);
1106 void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr(
1117 if (!(odInfo->
isStr(
"NSBundle") &&
1119 "localizedStringForKey:value:table:")) {
1132 std::pair<FileID, unsigned> SLInfo =
1145 bool Invalid =
false;
1146 llvm::MemoryBuffer *BF =
1152 BF->getBufferStart() + SLInfo.second, BF->getBufferEnd());
1157 while (!TheLexer.LexFromRawLexer(I)) {
1158 if (I.getKind() == tok::l_paren)
1160 if (I.getKind() == tok::r_paren) {
1170 reportEmptyContextError(ME);
1181 if ((Comment.trim().size() == 0 && Comment.size() > 0) ||
1183 reportEmptyContextError(ME);
1187 void EmptyLocalizationContextChecker::MethodCrawler::reportEmptyContextError(
1191 "Localizability Issue (Apple)",
1192 "Localized string macro should include a non-empty " 1193 "comment for translators",
1198 class PluralMisuseChecker :
public Checker<check::ASTCodeBody> {
1212 bool InMatchingStatement =
false;
1217 : BR(InBR), Checker(Checker), AC(InAC) {}
1219 bool VisitIfStmt(
const IfStmt *I);
1220 bool EndVisitIfStmt(
IfStmt *I);
1221 bool TraverseIfStmt(
IfStmt *x);
1224 bool VisitCallExpr(
const CallExpr *CE);
1228 void reportPluralMisuseError(
const Stmt *S)
const;
1229 bool isCheckingPlurality(
const Expr *E)
const;
1236 Visitor.TraverseDecl(const_cast<Decl *>(D));
1245 bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality(
1246 const Expr *Condition)
const {
1249 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Condition)) {
1250 if (
const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
1251 const Expr *InitExpr = VD->getInit();
1258 if (VD->getName().lower().find(
"plural") != StringRef::npos ||
1259 VD->getName().lower().find(
"singular") != StringRef::npos) {
1263 }
else if (
const BinaryOperator *B = dyn_cast<BinaryOperator>(Condition)) {
1272 llvm::APInt
Value = IL->getValue();
1273 if (Value == 1 || Value == 2) {
1284 bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(
const CallExpr *CE) {
1285 if (InMatchingStatement) {
1287 std::string NormalizedName =
1288 StringRef(FD->getNameInfo().getAsString()).lower();
1289 if (NormalizedName.find(
"loc") != std::string::npos) {
1291 if (isa<ObjCStringLiteral>(Arg))
1292 reportPluralMisuseError(CE);
1305 bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr(
1313 if (odInfo->
isStr(
"NSBundle") &&
1315 if (InMatchingStatement) {
1316 reportPluralMisuseError(ME);
1323 bool PluralMisuseChecker::MethodCrawler::TraverseIfStmt(
IfStmt *I) {
1325 return EndVisitIfStmt(I);
1331 bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(
IfStmt *I) {
1332 MatchingStatements.pop_back();
1333 if (!MatchingStatements.empty()) {
1334 if (MatchingStatements.back() !=
nullptr) {
1335 InMatchingStatement =
true;
1339 InMatchingStatement =
false;
1343 bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(
const IfStmt *I) {
1345 if (isCheckingPlurality(Condition)) {
1346 MatchingStatements.push_back(I);
1347 InMatchingStatement =
true;
1349 MatchingStatements.push_back(
nullptr);
1350 InMatchingStatement =
false;
1357 bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator(
1360 MatchingStatements.pop_back();
1361 if (!MatchingStatements.empty()) {
1362 if (MatchingStatements.back() !=
nullptr)
1363 InMatchingStatement =
true;
1365 InMatchingStatement =
false;
1367 InMatchingStatement =
false;
1372 bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator(
1375 if (isCheckingPlurality(Condition)) {
1376 MatchingStatements.push_back(C);
1377 InMatchingStatement =
true;
1379 MatchingStatements.push_back(
nullptr);
1380 InMatchingStatement =
false;
1385 void PluralMisuseChecker::MethodCrawler::reportPluralMisuseError(
1386 const Stmt *S)
const {
1389 "Localizability Issue (Apple)",
1390 "Plural cases are not supported across all languages. " 1391 "Use a .stringsdict file instead",
1399 void ento::registerNonLocalizedStringChecker(
CheckerManager &mgr) {
1400 NonLocalizedStringChecker *checker =
1402 checker->IsAggressive =
1406 void ento::registerEmptyLocalizationContextChecker(
CheckerManager &mgr) {
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
#define NEW_RECEIVER(receiver)
Represents a function declaration or definition.
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
Smart pointer class that efficiently represents Objective-C method names.
This is a discriminated union of FileInfo and ExpansionInfo.
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
Selector getSelector() const
SourceLocation getSpellingLoc() const
bool operator==(CanQual< T > x, CanQual< U > y)
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
specific_attr_iterator< T > specific_attr_begin() const
Stmt - This represents one statement.
#define ADD_METHOD(receiver, method_list, count, argument)
IfStmt - This represents an if/then/else.
A helper class which wraps a boolean value set to false by default.
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
Decl - This represents one declaration (or definition), e.g.
REGISTER_MAP_WITH_PROGRAMSTATE(LocalizedMemMap, const MemRegion *, LocalizedState) NonLocalizedStringChecker
static bool isDebuggingName(std::string name)
static bool isDebuggingContext(CheckerContext &C)
Returns true when, heuristically, the analyzer may be analyzing debugging code.
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
Gets the location of the immediate macro caller, one level up the stack toward the initial macro type...
Represents a variable declaration or definition.
const T * getAs() const
Member-template getAs<specific type>'.
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token...
ObjCMethodDecl - Represents an instance or class method declaration.
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
tok::TokenKind getKind() const
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
One of these records is kept for each identifier that is lexed.
The region associated with an ObjCStringLiteral.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
AnalysisDeclContext contains the context data for the function or method under analysis.
method_range methods() const
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
Token - This structure provides full information about a lexed token.
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
specific_attr_iterator< T > specific_attr_end() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
ArrayRef< ParmVarDecl * > parameters() const
Represents any expression that calls an Objective-C method.
A builtin binary operation expression such as "x + y" or "x <= y".
SVal getReturnValue() const
Returns the return value of the call.
ObjCStringLiteral, used for Objective-C string literals i.e.
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
ObjCInterfaceDecl * getInterface() const
Gets the interface declaration for this object type, if the base type really is an interface...
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
ConditionalOperator - The ?: ternary operator.
#define LSM_INSERT_NULLARY(receiver, method_name)
SymbolicRegion - A special, "non-concrete" region.
Expr - This represents one expression.
DeclContext * getDeclContext()
const IdentifierInfo * getCalleeIdentifier() const
Returns the name of the callee, if its name is a simple identifier.
virtual const Decl * getDecl() const
Returns the declaration of the function or method that will be called.
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
An expression that sends a message to the given Objective-C object or class.
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option's string value as a boolean.
const ExpansionInfo & getExpansion() const
CHECKER * registerChecker(AT... Args)
Used to register checkers.
#define ADD_UNARY_METHOD(receiver, method, argument)
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
BugReporter is a utility class for generating PathDiagnostics for analysis.
virtual SourceRange getSourceRange() const
Returns a source range for the entire call, suitable for outputting in diagnostics.
std::string getAsString() const
Derive the full selector name (e.g.
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
static bool isNSStringType(QualType T, ASTContext &Ctx)
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
const MemRegion * getAsRegion() const
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
#define LSF_INSERT(function_name)
const Decl * getDecl() const
FullSourceLoc asLocation() const
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
const ObjCMethodDecl * getDecl() const override
SourceManager & getSourceManager() override
Selector getSelector() const
Dataflow Directional Tag Classes.
ASTContext & getASTContext()
bool isValid() const
Return true if this is a valid SourceLocation object.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
Represents an abstract call to a function or method along a particular path.
AnalyzerOptions & getAnalyzerOptions()
unsigned getLength() const
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
Represents a pointer to an Objective C object.
bool isInstanceMessage() const
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
const ProgramStateRef & getState() const
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
QualType getResultType() const
Returns the result type, adjusted for references.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
SourceManager & getSourceManager()
#define LSM_INSERT_UNARY(receiver, method_name)
AnalysisDeclContext * getCurrentAnalysisDeclContext() const
StringRef getRawIdentifier() const
getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode), returns a reference to the text substring in the buffer if known.
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
StringRegion - Region associated with a StringLiteral.
A reference to a declared variable, function, enum, etc.
__DEVICE__ int min(int __a, int __b)
#define LSM_INSERT_SELECTOR(receiver, method_list, arguments)
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
const Expr * getCond() const
A trivial tuple used to represent a source range.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
This class provides an interface through which checkers can create individual bug reports...
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
SourceLocation getBegin() const
bool isAnyIdentifier(TokenKind K)
Return true if this is a raw identifier or an identifier kind.
SourceManager & getSourceManager()
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.