31#include "llvm/ADT/STLExtras.h"
32#include "llvm/Support/Unicode.h"
39struct LocalizedState {
41 enum Kind { NonLocalized, Localized } K;
42 LocalizedState(Kind InK) : K(InK) {}
45 bool isLocalized()
const {
return K == Localized; }
46 bool isNonLocalized()
const {
return K == NonLocalized; }
48 static LocalizedState getLocalized() {
return LocalizedState(Localized); }
49 static LocalizedState getNonLocalized() {
50 return LocalizedState(NonLocalized);
54 bool operator==(
const LocalizedState &
X)
const {
return K ==
X.K; }
57 void Profile(llvm::FoldingSetNodeID &ID)
const {
ID.AddInteger(K); }
60class NonLocalizedStringChecker
61 :
public Checker<check::PreCall, check::PostCall, check::PreObjCMessage,
62 check::PostObjCMessage,
63 check::PostStmt<ObjCStringLiteral>> {
65 const BugType BT{
this,
"Unlocalizable string",
66 "Localizability Issue (Apple)"};
70 llvm::DenseMap<Selector, uint8_t>> UIMethods;
72 mutable llvm::SmallSet<std::pair<const IdentifierInfo *, Selector>, 12> LSM;
74 mutable llvm::SmallSet<const IdentifierInfo *, 5> LSF;
77 void initLocStringsMethods(
ASTContext &Ctx)
const;
84 bool isAnnotatedAsReturningLocalized(
const Decl *
D)
const;
85 bool isAnnotatedAsTakingLocalized(
const Decl *
D)
const;
87 int argumentNumber = 0)
const;
89 int getLocalizedArgumentForSelector(
const IdentifierInfo *Receiver,
96 bool IsAggressive =
false;
117 NonLocalizedStringBRVisitor(
const MemRegion *NonLocalizedString)
118 : NonLocalizedString(NonLocalizedString), Satisfied(
false) {
119 assert(NonLocalizedString);
126 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
127 ID.Add(NonLocalizedString);
132#define NEW_RECEIVER(receiver) \
133 llvm::DenseMap<Selector, uint8_t> &receiver##M = \
134 UIMethods.insert({&Ctx.Idents.get(#receiver), \
135 llvm::DenseMap<Selector, uint8_t>()}) \
137#define ADD_NULLARY_METHOD(receiver, method, argument) \
138 receiver##M.insert( \
139 {Ctx.Selectors.getNullarySelector(&Ctx.Idents.get(#method)), argument});
140#define ADD_UNARY_METHOD(receiver, method, argument) \
141 receiver##M.insert( \
142 {Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(#method)), argument});
143#define ADD_METHOD(receiver, method_list, count, argument) \
144 receiver##M.insert({Ctx.Selectors.getSelector(count, method_list), argument});
148void NonLocalizedStringChecker::initUIMethods(
ASTContext &Ctx)
const {
149 if (!UIMethods.empty())
160 ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemTag, 3, 0)
164 ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemImage, 3, 0)
174 const IdentifierInfo *rowActionWithStyleUITableViewRowAction[] = {
177 ADD_METHOD(UITableViewRowAction, rowActionWithStyleUITableViewRowAction, 3, 1)
189 ADD_METHOD(NSButton, radioButtonWithTitleNSButton, 3, 0)
193 ADD_METHOD(NSButton, buttonWithTitleNSButtonImage, 4, 0)
197 ADD_METHOD(NSButton, checkboxWithTitleNSButton, 3, 0)
201 ADD_METHOD(NSButton, buttonWithTitleNSButtonTarget, 3, 0)
220 ADD_METHOD(NSBrowser, setTitleNSBrowser, 2, 0)
231 ADD_METHOD(UIAlertAction, actionWithTitleUIAlertAction, 3, 0)
237 ADD_METHOD(NSPopUpButton, insertItemWithTitleNSPopUpButton, 2, 0)
243 const IdentifierInfo *rowActionWithStyleNSTableViewRowAction[] = {
246 ADD_METHOD(NSTableViewRowAction, rowActionWithStyleNSTableViewRowAction, 3, 1)
278 ADD_METHOD(NSSegmentedControl, setLabelNSSegmentedControl, 2, 0)
281 ADD_METHOD(NSSegmentedControl, setToolTipNSSegmentedControl, 2, 0)
306 ADD_METHOD(NSMatrix, setToolTipNSMatrix, 2, 0)
322 ADD_METHOD(UIMenuItem, initWithTitleUIMenuItem, 2, 0)
326 const IdentifierInfo *alertControllerWithTitleUIAlertController[] = {
329 ADD_METHOD(UIAlertController, alertControllerWithTitleUIAlertController, 3, 1)
334 const IdentifierInfo *initWithTypeUIApplicationShortcutItemIcon[] = {
339 initWithTypeUIApplicationShortcutItemIcon, 5, 1)
342 ADD_METHOD(UIApplicationShortcutItem, initWithTypeUIApplicationShortcutItem,
349 &Ctx.
Idents.
get(
"destructiveButtonTitle"),
351 ADD_METHOD(UIActionSheet, initWithTitleUIActionSheet, 5, 0)
356 const IdentifierInfo *initWithNameUIAccessibilityCustomAction[] = {
360 initWithNameUIAccessibilityCustomAction, 3, 0)
387 ADD_METHOD(NSAttributedString, initWithStringNSAttributedString, 2, 0)
396 ADD_METHOD(UIKeyCommand, keyCommandWithInputUIKeyCommand, 4, 3)
406 &Ctx.
Idents.
get(
"informativeTextWithFormat")};
407 ADD_METHOD(NSAlert, alertWithMessageTextNSAlert, 5, 0)
426 ADD_METHOD(NSWindow, minFrameWidthWithTitleNSWindow, 2, 0)
433 const IdentifierInfo *addOptionWithTitleUIDocumentMenuViewController[] = {
437 addOptionWithTitleUIDocumentMenuViewController, 4, 0)
449 ADD_METHOD(UIAlertView, initWithTitleUIAlertView, 5, 0)
479 ADD_METHOD(NSSegmentedCell, setLabelNSSegmentedCell, 2, 0)
482 ADD_METHOD(NSSegmentedCell, setToolTipNSSegmentedCell, 2, 0)
493 ADD_METHOD(NSMenuItem, initWithTitleNSMenuItem, 3, 0)
500 ADD_METHOD(NSPopUpButtonCell, initTextCellNSPopUpButtonCell, 2, 0)
504 ADD_METHOD(NSPopUpButtonCell, insertItemWithTitleNSPopUpButtonCell, 2, 0)
517 ADD_METHOD(NSMenu, insertItemWithTitleNSMenu, 4, 0)
521 ADD_METHOD(NSMenu, addItemWithTitleNSMenu, 3, 0)
537 const IdentifierInfo *actionWithIdentifierNSUserNotificationAction[] = {
540 actionWithIdentifierNSUserNotificationAction, 2, 1)
550 ADD_METHOD(UIBarButtonItem, initWithTitleUIBarButtonItem, 4, 0)
556 const IdentifierInfo *insertSegmentWithTitleUISegmentedControl[] = {
559 ADD_METHOD(UISegmentedControl, insertSegmentWithTitleUISegmentedControl, 3, 0)
562 ADD_METHOD(UISegmentedControl, setTitleUISegmentedControl, 2, 0)
566 *initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult[] = {
567 &Ctx.
Idents.
get(
"initWithItemLoadingToken"),
569 ADD_METHOD(NSAccessibilityCustomRotorItemResult,
570 initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult, 2, 1)
574 const IdentifierInfo *contextualActionWithStyleUIContextualAction[] = {
577 ADD_METHOD(UIContextualAction, contextualActionWithStyleUIContextualAction, 3,
582 const IdentifierInfo *initWithLabelNSAccessibilityCustomRotor[] = {
585 initWithLabelNSAccessibilityCustomRotor, 2, 0)
593 const IdentifierInfo *initWithNameNSAccessibilityCustomAction[] = {
596 initWithNameNSAccessibilityCustomAction, 2, 0)
597 const IdentifierInfo *initWithNameTargetNSAccessibilityCustomAction[] = {
601 initWithNameTargetNSAccessibilityCustomAction, 3, 0)
605#define LSF_INSERT(function_name) LSF.insert(&Ctx.Idents.get(function_name));
606#define LSM_INSERT_NULLARY(receiver, method_name) \
607 LSM.insert({&Ctx.Idents.get(receiver), Ctx.Selectors.getNullarySelector( \
608 &Ctx.Idents.get(method_name))});
609#define LSM_INSERT_UNARY(receiver, method_name) \
610 LSM.insert({&Ctx.Idents.get(receiver), \
611 Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(method_name))});
612#define LSM_INSERT_SELECTOR(receiver, method_list, arguments) \
613 LSM.insert({&Ctx.Idents.get(receiver), \
614 Ctx.Selectors.getSelector(arguments, method_list)});
617void NonLocalizedStringChecker::initLocStringsMethods(
ASTContext &Ctx)
const {
635 LSF_INSERT(
"CFDateFormatterCreateStringWithDate");
636 LSF_INSERT(
"CFDateFormatterCreateStringWithAbsoluteTime");
637 LSF_INSERT(
"CFNumberFormatterCreateStringWithNumber");
642bool NonLocalizedStringChecker::isAnnotatedAsReturningLocalized(
643 const Decl *
D)
const {
649 return Ann->getAnnotation() ==
"returns_localized_nsstring";
655bool NonLocalizedStringChecker::isAnnotatedAsTakingLocalized(
656 const Decl *
D)
const {
662 return Ann->getAnnotation() ==
"takes_localized_nsstring";
667bool NonLocalizedStringChecker::hasLocalizedState(
SVal S,
671 const LocalizedState *LS =
C.getState()->get<LocalizedMemMap>(mt);
672 if (LS && LS->isLocalized())
680bool NonLocalizedStringChecker::hasNonLocalizedState(
SVal S,
684 const LocalizedState *LS =
C.getState()->get<LocalizedMemMap>(mt);
685 if (LS && LS->isNonLocalized())
692void NonLocalizedStringChecker::setLocalizedState(
const SVal S,
697 C.getState()->set<LocalizedMemMap>(mt, LocalizedState::getLocalized());
698 C.addTransition(State);
703void NonLocalizedStringChecker::setNonLocalizedState(
const SVal S,
708 mt, LocalizedState::getNonLocalized());
709 C.addTransition(State);
715 return StringRef(name).contains_insensitive(
"debug");
723 const Decl *
D =
C.getCurrentAnalysisDeclContext()->getDecl();
727 if (
auto *ND = dyn_cast<NamedDecl>(
D)) {
734 if (
auto *CD = dyn_cast<ObjCContainerDecl>(DC)) {
744void NonLocalizedStringChecker::reportLocalizationError(
753 "UnlocalizedString");
754 ExplodedNode *ErrNode =
C.addTransition(
C.getState(),
C.getPredecessor(), &Tag);
760 auto R = std::make_unique<PathSensitiveBugReport>(
761 BT,
"User-facing text should use localized string macro", ErrNode);
762 if (argumentNumber) {
767 R->markInteresting(S);
771 R->addVisitor(std::make_unique<NonLocalizedStringBRVisitor>(
StringRegion));
773 C.emitReport(std::move(R));
778int NonLocalizedStringChecker::getLocalizedArgumentForSelector(
780 auto method = UIMethods.find(Receiver);
782 if (method == UIMethods.end())
785 auto argumentIterator = method->getSecond().find(S);
787 if (argumentIterator == method->getSecond().end())
790 int argumentNumber = argumentIterator->getSecond();
791 return argumentNumber;
795void NonLocalizedStringChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
797 initUIMethods(
C.getASTContext());
806 std::string SelectorString = S.getAsString();
807 StringRef SelectorName = SelectorString;
808 assert(!SelectorName.empty());
810 if (odInfo->
isStr(
"NSString")) {
814 if (!(SelectorName.starts_with(
"drawAtPoint") ||
815 SelectorName.starts_with(
"drawInRect") ||
816 SelectorName.starts_with(
"drawWithRect")))
821 bool isNonLocalized = hasNonLocalizedState(svTitle,
C);
823 if (isNonLocalized) {
824 reportLocalizationError(svTitle, msg,
C);
828 int argumentNumber = getLocalizedArgumentForSelector(odInfo, S);
830 while (argumentNumber < 0 && OD->getSuperClass() !=
nullptr) {
832 argumentNumber = getLocalizedArgumentForSelector(
P->getIdentifier(), S);
833 if (argumentNumber >= 0)
836 if (argumentNumber < 0) {
838 argumentNumber = getLocalizedArgumentForSelector(OD->
getIdentifier(), S);
842 if (argumentNumber < 0) {
845 for (
auto [Idx, FormalParam] : llvm::enumerate(OMD->parameters())) {
846 if (isAnnotatedAsTakingLocalized(FormalParam)) {
847 argumentNumber = Idx;
855 if (argumentNumber < 0)
861 dyn_cast_or_null<ObjCStringRegion>(svTitle.
getAsRegion())) {
862 StringRef stringValue =
863 SR->getObjCStringLiteral()->getString()->getString();
864 if ((stringValue.trim().size() == 0 && stringValue.size() > 0) ||
867 if (!IsAggressive && llvm::sys::unicode::columnWidthUTF8(stringValue) < 2)
871 bool isNonLocalized = hasNonLocalizedState(svTitle,
C);
873 if (isNonLocalized) {
874 reportLocalizationError(svTitle, msg,
C, argumentNumber + 1);
878void NonLocalizedStringChecker::checkPreCall(
const CallEvent &
Call,
880 const auto *FD = dyn_cast_or_null<FunctionDecl>(
Call.getDecl());
884 auto formals = FD->parameters();
885 for (
unsigned i = 0, ei = std::min(
static_cast<unsigned>(formals.size()),
886 Call.getNumArgs()); i != ei; ++i) {
887 if (isAnnotatedAsTakingLocalized(formals[i])) {
888 auto actual =
Call.getArgSVal(i);
889 if (hasNonLocalizedState(actual,
C)) {
890 reportLocalizationError(actual,
Call,
C, i + 1);
909 return ClsName == &Ctx.
Idents.
get(
"NSString") ||
910 ClsName == &Ctx.
Idents.
get(
"NSMutableString");
918void NonLocalizedStringChecker::checkPostCall(
const CallEvent &
Call,
920 initLocStringsMethods(
C.getASTContext());
922 if (!
Call.getOriginExpr())
930 for (
unsigned i = 0; i <
Call.getNumArgs(); ++i) {
932 if (hasLocalizedState(argValue,
C)) {
934 setLocalizedState(sv,
C);
947 if (isAnnotatedAsReturningLocalized(
D) || LSF.contains(
Identifier)) {
948 setLocalizedState(sv,
C);
950 !hasLocalizedState(sv,
C)) {
952 setNonLocalizedState(sv,
C);
955 dyn_cast_or_null<SymbolicRegion>(sv.
getAsRegion());
957 setNonLocalizedState(sv,
C);
964void NonLocalizedStringChecker::checkPostObjCMessage(
const ObjCMethodCall &msg,
966 initLocStringsMethods(
C.getASTContext());
977 std::string SelectorName = S.getAsString();
979 std::pair<const IdentifierInfo *, Selector> MethodDescription = {odInfo, S};
981 if (LSM.count(MethodDescription) ||
982 isAnnotatedAsReturningLocalized(msg.
getDecl())) {
984 setLocalizedState(sv,
C);
991 SVal sv =
C.getSVal(SL);
992 setNonLocalizedState(sv,
C);
996NonLocalizedStringBRVisitor::VisitNode(
const ExplodedNode *Succ,
1006 auto *LiteralExpr = dyn_cast<ObjCStringLiteral>(Point->getStmt());
1011 if (LiteralSVal.
getAsRegion() != NonLocalizedString)
1022 auto Piece = std::make_shared<PathDiagnosticEventPiece>(
1023 L,
"Non-localized string literal here");
1024 Piece->addRange(LiteralExpr->getSourceRange());
1026 return std::move(Piece);
1030class EmptyLocalizationContextChecker
1031 :
public Checker<check::ASTDecl<ObjCImplementationDecl>> {
1045 : MD(InMD), BR(InBR), Mgr(InMgr),
Checker(
Checker), DCtx(InDCtx) {}
1047 void VisitStmt(
const Stmt *S) { VisitChildren(S); }
1053 void VisitChildren(
const Stmt *S) {
1054 for (
const Stmt *Child : S->children()) {
1067void EmptyLocalizationContextChecker::checkASTDecl(
1074 const Stmt *Body = M->getBody();
1076 assert(M->isSynthesizedAccessorStub());
1080 MethodCrawler MC(M->getCanonicalDecl(), BR,
this, Mgr, DCtx);
1100void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr(
1111 if (!(odInfo->
isStr(
"NSBundle") &&
1113 "localizedStringForKey:value:table:")) {
1126 std::pair<FileID, unsigned> SLInfo =
1139 std::optional<llvm::MemoryBufferRef> BF =
1144 Lexer TheLexer(SL, LangOpts, BF->getBufferStart(),
1145 BF->getBufferStart() + SLInfo.second, BF->getBufferEnd());
1150 while (!TheLexer.LexFromRawLexer(I)) {
1151 if (I.
getKind() == tok::l_paren)
1153 if (I.
getKind() == tok::r_paren) {
1162 if (Result.getRawIdentifier() ==
"nil") {
1163 reportEmptyContextError(ME);
1172 StringRef(Result.getLiteralData(), Result.getLength()).trim(
'"');
1174 if ((Comment.trim().size() == 0 && Comment.size() > 0) ||
1176 reportEmptyContextError(ME);
1180void EmptyLocalizationContextChecker::MethodCrawler::reportEmptyContextError(
1184 "Localizability Issue (Apple)",
1185 "Localized string macro should include a non-empty "
1186 "comment for translators",
1191class PluralMisuseChecker :
public Checker<check::ASTCodeBody> {
1205 bool InMatchingStatement =
false;
1212 bool VisitIfStmt(
const IfStmt *I);
1213 bool EndVisitIfStmt(
IfStmt *I);
1214 bool TraverseIfStmt(
IfStmt *x);
1217 bool VisitCallExpr(
const CallExpr *CE);
1221 void reportPluralMisuseError(
const Stmt *S)
const;
1222 bool isCheckingPlurality(
const Expr *
E)
const;
1229 Visitor.TraverseDecl(
const_cast<Decl *
>(
D));
1238bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality(
1243 if (
const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
1244 const Expr *InitExpr = VD->getInit();
1251 if (VD->getName().contains_insensitive(
"plural") ||
1252 VD->getName().contains_insensitive(
"singular")) {
1265 llvm::APInt
Value = IL->getValue();
1277bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(
const CallExpr *CE) {
1278 if (InMatchingStatement) {
1280 std::string NormalizedName =
1281 StringRef(FD->getNameInfo().getAsString()).lower();
1282 if (NormalizedName.find(
"loc") != std::string::npos) {
1284 if (isa<ObjCStringLiteral>(Arg))
1285 reportPluralMisuseError(CE);
1298bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr(
1306 if (odInfo->
isStr(
"NSBundle") &&
1308 if (InMatchingStatement) {
1309 reportPluralMisuseError(ME);
1316bool PluralMisuseChecker::MethodCrawler::TraverseIfStmt(
IfStmt *I) {
1318 return EndVisitIfStmt(I);
1324bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(
IfStmt *I) {
1325 MatchingStatements.pop_back();
1326 if (!MatchingStatements.empty()) {
1327 if (MatchingStatements.back() !=
nullptr) {
1328 InMatchingStatement =
true;
1332 InMatchingStatement =
false;
1336bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(
const IfStmt *I) {
1342 MatchingStatements.push_back(I);
1343 InMatchingStatement =
true;
1345 MatchingStatements.push_back(
nullptr);
1346 InMatchingStatement =
false;
1353bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator(
1356 MatchingStatements.pop_back();
1357 if (!MatchingStatements.empty()) {
1358 if (MatchingStatements.back() !=
nullptr)
1359 InMatchingStatement =
true;
1361 InMatchingStatement =
false;
1363 InMatchingStatement =
false;
1368bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator(
1372 MatchingStatements.push_back(
C);
1373 InMatchingStatement =
true;
1375 MatchingStatements.push_back(
nullptr);
1376 InMatchingStatement =
false;
1381void PluralMisuseChecker::MethodCrawler::reportPluralMisuseError(
1382 const Stmt *S)
const {
1385 "Localizability Issue (Apple)",
1386 "Plural cases are not supported across all languages. "
1387 "Use a .stringsdict file instead",
1395void ento::registerNonLocalizedStringChecker(
CheckerManager &mgr) {
1396 NonLocalizedStringChecker *checker =
1398 checker->IsAggressive =
1400 checker,
"AggressiveReport");
1403bool ento::shouldRegisterNonLocalizedStringChecker(
const CheckerManager &mgr) {
1407void ento::registerEmptyLocalizationContextChecker(
CheckerManager &mgr) {
1411bool ento::shouldRegisterEmptyLocalizationContextChecker(
1420bool ento::shouldRegisterPluralMisuseChecker(
const CheckerManager &mgr) {
#define LSM_INSERT_SELECTOR(receiver, method_list, arguments)
#define NEW_RECEIVER(receiver)
#define LSM_INSERT_NULLARY(receiver, method_name)
#define LSF_INSERT(function_name)
#define ADD_UNARY_METHOD(receiver, method, argument)
#define ADD_METHOD(receiver, method_list, count, argument)
#define LSM_INSERT_UNARY(receiver, method_name)
static bool isDebuggingContext(CheckerContext &C)
Returns true when, heuristically, the analyzer may be analyzing debugging code.
static bool isDebuggingName(std::string name)
static bool isNSStringType(QualType T, ASTContext &Ctx)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
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, method or block under analysis.
bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, bool SearchInParents=false) const
Interprets an option's string value as a boolean.
A builtin binary operation expression such as "x + y" or "x <= y".
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
ConditionalOperator - The ?: ternary operator.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
DeclContext * getDeclContext()
specific_attr_iterator< T > specific_attr_end() const
specific_attr_iterator< T > specific_attr_begin() const
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Represents a function declaration or definition.
One of these records is kept for each identifier that is lexed.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
all_protocol_range all_referenced_protocols() const
ObjCInterfaceDecl * getSuperClass() const
An expression that sends a message to the given Objective-C object or class.
Selector getSelector() const
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
ObjCMethodDecl - Represents an instance or class method declaration.
Represents a pointer to an Objective C object.
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
ObjCInterfaceDecl * getInterface() const
Gets the interface declaration for this object type, if the base type really is an interface.
ObjCStringLiteral, used for Objective-C string literals i.e.
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
A (possibly-)qualified type.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Smart pointer class that efficiently represents Objective-C method names.
std::string getAsString() const
Derive the full selector name (e.g.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
Gets the location of the immediate macro caller, one level up the stack toward the initial macro type...
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
SourceLocation getSpellingLoc() const
This is a discriminated union of FileInfo and ExpansionInfo.
const ExpansionInfo & getExpansion() const
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Token - This structure provides full information about a lexed token.
tok::TokenKind getKind() const
const T * getAs() const
Member-template getAs<specific type>'.
Represents a variable declaration or definition.
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
SourceManager & getSourceManager() override
const SourceManager & getSourceManager() const
BugReporterVisitors are used to add custom diagnostics along a path.
virtual void Profile(llvm::FoldingSetNodeID &ID) const =0
virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, PathSensitiveBugReport &BR)=0
Return a diagnostic piece which should be associated with the given node.
BugReporter is a utility class for generating PathDiagnostics for analysis.
const SourceManager & getSourceManager()
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=std::nullopt, ArrayRef< FixItHint > Fixits=std::nullopt)
Represents an abstract call to a function or method along a particular path.
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
SVal getReturnValue() const
Returns the return value of the call.
virtual SourceRange getSourceRange() const
Returns a source range for the entire call, suitable for outputting in diagnostics.
const AnalyzerOptions & getAnalyzerOptions() const
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
MemRegion - The root abstract class for all memory regions.
Represents any expression that calls an Objective-C method.
const ObjCMethodDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
bool isInstanceMessage() const
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
Selector getSelector() const
The region associated with an ObjCStringLiteral.
FullSourceLoc asLocation() const
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
const MemRegion * getAsRegion() const
StringRegion - Region associated with a StringLiteral.
SymbolicRegion - A special, "non-concrete" region.
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.
bool isAnyIdentifier(TokenKind K)
Return true if this is a raw identifier or an identifier kind.
The JSON file list parser is used to communicate input to InstallAPI.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
const FunctionProtoType * T