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)"));
116 class NonLocalizedStringBRVisitor final
123 NonLocalizedStringBRVisitor(
const MemRegion *NonLocalizedString)
124 : NonLocalizedString(NonLocalizedString), Satisfied(
false) {
125 assert(NonLocalizedString);
128 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *Succ,
133 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
134 ID.Add(NonLocalizedString);
139 #define NEW_RECEIVER(receiver) \ 140 llvm::DenseMap<Selector, uint8_t> &receiver##M = \ 141 UIMethods.insert({&Ctx.Idents.get(#receiver), \ 142 llvm::DenseMap<Selector, uint8_t>()}) \ 144 #define ADD_NULLARY_METHOD(receiver, method, argument) \ 145 receiver##M.insert( \ 146 {Ctx.Selectors.getNullarySelector(&Ctx.Idents.get(#method)), argument}); 147 #define ADD_UNARY_METHOD(receiver, method, argument) \ 148 receiver##M.insert( \ 149 {Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(#method)), argument}); 150 #define ADD_METHOD(receiver, method_list, count, argument) \ 151 receiver##M.insert({Ctx.Selectors.getSelector(count, method_list), argument}); 155 void NonLocalizedStringChecker::initUIMethods(
ASTContext &Ctx)
const {
156 if (!UIMethods.empty())
167 ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemTag, 3, 0)
171 ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemImage, 3, 0)
184 ADD_METHOD(UITableViewRowAction, rowActionWithStyleUITableViewRowAction, 3, 1)
196 ADD_METHOD(NSButton, radioButtonWithTitleNSButton, 3, 0)
200 ADD_METHOD(NSButton, buttonWithTitleNSButtonImage, 4, 0)
204 ADD_METHOD(NSButton, checkboxWithTitleNSButton, 3, 0)
208 ADD_METHOD(NSButton, buttonWithTitleNSButtonTarget, 3, 0)
227 ADD_METHOD(NSBrowser, setTitleNSBrowser, 2, 0)
238 ADD_METHOD(UIAlertAction, actionWithTitleUIAlertAction, 3, 0)
244 ADD_METHOD(NSPopUpButton, insertItemWithTitleNSPopUpButton, 2, 0)
253 ADD_METHOD(NSTableViewRowAction, rowActionWithStyleNSTableViewRowAction, 3, 1)
285 ADD_METHOD(NSSegmentedControl, setLabelNSSegmentedControl, 2, 0)
288 ADD_METHOD(NSSegmentedControl, setToolTipNSSegmentedControl, 2, 0)
313 ADD_METHOD(NSMatrix, setToolTipNSMatrix, 2, 0)
329 ADD_METHOD(UIMenuItem, initWithTitleUIMenuItem, 2, 0)
336 ADD_METHOD(UIAlertController, alertControllerWithTitleUIAlertController, 3, 1)
346 initWithTypeUIApplicationShortcutItemIcon, 5, 1)
349 ADD_METHOD(UIApplicationShortcutItem, initWithTypeUIApplicationShortcutItem,
356 &Ctx.
Idents.
get(
"destructiveButtonTitle"),
358 ADD_METHOD(UIActionSheet, initWithTitleUIActionSheet, 5, 0)
367 initWithNameUIAccessibilityCustomAction, 3, 0)
394 ADD_METHOD(NSAttributedString, initWithStringNSAttributedString, 2, 0)
403 ADD_METHOD(UIKeyCommand, keyCommandWithInputUIKeyCommand, 4, 3)
413 &Ctx.
Idents.
get(
"informativeTextWithFormat")};
414 ADD_METHOD(NSAlert, alertWithMessageTextNSAlert, 5, 0)
433 ADD_METHOD(NSWindow, minFrameWidthWithTitleNSWindow, 2, 0)
440 IdentifierInfo *addOptionWithTitleUIDocumentMenuViewController[] = {
444 addOptionWithTitleUIDocumentMenuViewController, 4, 0)
456 ADD_METHOD(UIAlertView, initWithTitleUIAlertView, 5, 0)
486 ADD_METHOD(NSSegmentedCell, setLabelNSSegmentedCell, 2, 0)
489 ADD_METHOD(NSSegmentedCell, setToolTipNSSegmentedCell, 2, 0)
500 ADD_METHOD(NSMenuItem, initWithTitleNSMenuItem, 3, 0)
507 ADD_METHOD(NSPopUpButtonCell, initTextCellNSPopUpButtonCell, 2, 0)
511 ADD_METHOD(NSPopUpButtonCell, insertItemWithTitleNSPopUpButtonCell, 2, 0)
524 ADD_METHOD(NSMenu, insertItemWithTitleNSMenu, 4, 0)
528 ADD_METHOD(NSMenu, addItemWithTitleNSMenu, 3, 0)
544 IdentifierInfo *actionWithIdentifierNSUserNotificationAction[] = {
547 actionWithIdentifierNSUserNotificationAction, 2, 1)
557 ADD_METHOD(UIBarButtonItem, initWithTitleUIBarButtonItem, 4, 0)
566 ADD_METHOD(UISegmentedControl, insertSegmentWithTitleUISegmentedControl, 3, 0)
569 ADD_METHOD(UISegmentedControl, setTitleUISegmentedControl, 2, 0)
573 *initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult[] = {
574 &Ctx.
Idents.
get(
"initWithItemLoadingToken"),
576 ADD_METHOD(NSAccessibilityCustomRotorItemResult,
577 initWithItemLoadingTokenNSAccessibilityCustomRotorItemResult, 2, 1)
584 ADD_METHOD(UIContextualAction, contextualActionWithStyleUIContextualAction, 3,
592 initWithLabelNSAccessibilityCustomRotor, 2, 0)
603 initWithNameNSAccessibilityCustomAction, 2, 0)
604 IdentifierInfo *initWithNameTargetNSAccessibilityCustomAction[] = {
608 initWithNameTargetNSAccessibilityCustomAction, 3, 0)
612 #define LSF_INSERT(function_name) LSF.insert(&Ctx.Idents.get(function_name)); 613 #define LSM_INSERT_NULLARY(receiver, method_name) \ 614 LSM.insert({&Ctx.Idents.get(receiver), Ctx.Selectors.getNullarySelector( \ 615 &Ctx.Idents.get(method_name))}); 616 #define LSM_INSERT_UNARY(receiver, method_name) \ 617 LSM.insert({&Ctx.Idents.get(receiver), \ 618 Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(method_name))}); 619 #define LSM_INSERT_SELECTOR(receiver, method_list, arguments) \ 620 LSM.insert({&Ctx.Idents.get(receiver), \ 621 Ctx.Selectors.getSelector(arguments, method_list)}); 624 void NonLocalizedStringChecker::initLocStringsMethods(
ASTContext &Ctx)
const {
642 LSF_INSERT(
"CFDateFormatterCreateStringWithDate");
643 LSF_INSERT(
"CFDateFormatterCreateStringWithAbsoluteTime");
644 LSF_INSERT(
"CFNumberFormatterCreateStringWithNumber");
649 bool NonLocalizedStringChecker::isAnnotatedAsReturningLocalized(
650 const Decl *D)
const {
656 return Ann->getAnnotation() ==
"returns_localized_nsstring";
662 bool NonLocalizedStringChecker::isAnnotatedAsTakingLocalized(
663 const Decl *D)
const {
669 return Ann->getAnnotation() ==
"takes_localized_nsstring";
674 bool NonLocalizedStringChecker::hasLocalizedState(
SVal S,
678 const LocalizedState *LS = C.
getState()->get<LocalizedMemMap>(mt);
679 if (LS && LS->isLocalized())
687 bool NonLocalizedStringChecker::hasNonLocalizedState(
SVal S,
691 const LocalizedState *LS = C.
getState()->get<LocalizedMemMap>(mt);
692 if (LS && LS->isNonLocalized())
699 void NonLocalizedStringChecker::setLocalizedState(
const SVal S,
704 C.
getState()->set<LocalizedMemMap>(mt, LocalizedState::getLocalized());
710 void NonLocalizedStringChecker::setNonLocalizedState(
const SVal S,
715 mt, LocalizedState::getNonLocalized());
722 return StringRef(name).lower().find(
"debug") != StringRef::npos;
734 if (
auto *ND = dyn_cast<NamedDecl>(D)) {
741 if (
auto *CD = dyn_cast<ObjCContainerDecl>(DC)) {
751 void NonLocalizedStringChecker::reportLocalizationError(
761 "UnlocalizedString");
768 std::unique_ptr<BugReport> R(
new BugReport(
769 *BT,
"User-facing text should use localized string macro", ErrNode));
770 if (argumentNumber) {
775 R->markInteresting(S);
779 R->addVisitor(llvm::make_unique<NonLocalizedStringBRVisitor>(StringRegion));
786 int NonLocalizedStringChecker::getLocalizedArgumentForSelector(
788 auto method = UIMethods.find(Receiver);
790 if (method == UIMethods.end())
793 auto argumentIterator = method->getSecond().find(S);
795 if (argumentIterator == method->getSecond().end())
798 int argumentNumber = argumentIterator->getSecond();
799 return argumentNumber;
803 void NonLocalizedStringChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
815 StringRef SelectorName = SelectorString;
816 assert(!SelectorName.empty());
818 if (odInfo->
isStr(
"NSString")) {
822 if (!(SelectorName.startswith(
"drawAtPoint") ||
823 SelectorName.startswith(
"drawInRect") ||
824 SelectorName.startswith(
"drawWithRect")))
829 bool isNonLocalized = hasNonLocalizedState(svTitle, C);
831 if (isNonLocalized) {
832 reportLocalizationError(svTitle, msg, C);
836 int argumentNumber = getLocalizedArgumentForSelector(odInfo, S);
838 while (argumentNumber < 0 && OD->getSuperClass() !=
nullptr) {
839 for (
const auto *
P : OD->all_referenced_protocols()) {
840 argumentNumber = getLocalizedArgumentForSelector(
P->getIdentifier(), S);
841 if (argumentNumber >= 0)
844 if (argumentNumber < 0) {
845 OD = OD->getSuperClass();
846 argumentNumber = getLocalizedArgumentForSelector(OD->getIdentifier(), S);
850 if (argumentNumber < 0) {
852 if (
const ObjCMethodDecl *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) {
853 auto formals = OMD->parameters();
854 for (
unsigned i = 0, ei = formals.size(); i != ei; ++i) {
855 if (isAnnotatedAsTakingLocalized(formals[i])) {
864 if (argumentNumber < 0)
867 SVal svTitle = msg.getArgSVal(argumentNumber);
870 dyn_cast_or_null<ObjCStringRegion>(svTitle.
getAsRegion())) {
871 StringRef stringValue =
872 SR->getObjCStringLiteral()->getString()->getString();
873 if ((stringValue.trim().size() == 0 && stringValue.size() > 0) ||
876 if (!IsAggressive && llvm::sys::unicode::columnWidthUTF8(stringValue) < 2)
880 bool isNonLocalized = hasNonLocalizedState(svTitle, C);
882 if (isNonLocalized) {
883 reportLocalizationError(svTitle, msg, C, argumentNumber + 1);
887 void NonLocalizedStringChecker::checkPreCall(
const CallEvent &Call,
890 if (D && isa<FunctionDecl>(D)) {
896 if (isAnnotatedAsTakingLocalized(formals[i])) {
898 if (hasNonLocalizedState(actual, C)) {
899 reportLocalizationError(actual, Call, C, i + 1);
919 return ClsName == &Ctx.
Idents.
get(
"NSString") ||
920 ClsName == &Ctx.
Idents.
get(
"NSMutableString");
928 void NonLocalizedStringChecker::checkPostCall(
const CallEvent &Call,
940 for (
unsigned i = 0; i < Call.
getNumArgs(); ++i) {
942 if (hasLocalizedState(argValue, C)) {
944 setLocalizedState(sv, C);
957 if (isAnnotatedAsReturningLocalized(D) || LSF.count(Identifier) != 0) {
958 setLocalizedState(sv, C);
960 !hasLocalizedState(sv, C)) {
962 setNonLocalizedState(sv, C);
965 dyn_cast_or_null<SymbolicRegion>(sv.
getAsRegion());
967 setNonLocalizedState(sv, C);
974 void NonLocalizedStringChecker::checkPostObjCMessage(
const ObjCMethodCall &msg,
989 std::pair<const IdentifierInfo *, Selector> MethodDescription = {odInfo, S};
991 if (LSM.count(MethodDescription) ||
992 isAnnotatedAsReturningLocalized(msg.
getDecl())) {
993 SVal sv = msg.getReturnValue();
994 setLocalizedState(sv, C);
1002 setNonLocalizedState(sv, C);
1005 std::shared_ptr<PathDiagnosticPiece>
1006 NonLocalizedStringBRVisitor::VisitNode(
const ExplodedNode *Succ,
1013 if (!Point.hasValue())
1022 if (LiteralSVal.
getAsRegion() != NonLocalizedString)
1033 auto Piece = std::make_shared<PathDiagnosticEventPiece>(
1034 L,
"Non-localized string literal here");
1035 Piece->addRange(LiteralExpr->getSourceRange());
1037 return std::move(Piece);
1041 class EmptyLocalizationContextChecker
1042 :
public Checker<check::ASTDecl<ObjCImplementationDecl>> {
1056 : MD(InMD), BR(InBR), Mgr(InMgr), Checker(Checker), DCtx(InDCtx) {}
1058 void VisitStmt(
const Stmt *S) { VisitChildren(S); }
1064 void VisitChildren(
const Stmt *S) {
1078 void EmptyLocalizationContextChecker::checkASTDecl(
1085 const Stmt *Body = M->getBody();
1088 MethodCrawler MC(M->getCanonicalDecl(), BR,
this, Mgr, DCtx);
1108 void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr(
1119 if (!(odInfo->
isStr(
"NSBundle") &&
1121 "localizedStringForKey:value:table:")) {
1134 std::pair<FileID, unsigned> SLInfo =
1147 bool Invalid =
false;
1148 llvm::MemoryBuffer *BF =
1154 BF->getBufferStart() + SLInfo.second, BF->getBufferEnd());
1159 while (!TheLexer.LexFromRawLexer(I)) {
1160 if (I.getKind() == tok::l_paren)
1162 if (I.getKind() == tok::r_paren) {
1172 reportEmptyContextError(ME);
1183 if ((Comment.trim().size() == 0 && Comment.size() > 0) ||
1185 reportEmptyContextError(ME);
1189 void EmptyLocalizationContextChecker::MethodCrawler::reportEmptyContextError(
1193 "Localizability Issue (Apple)",
1194 "Localized string macro should include a non-empty " 1195 "comment for translators",
1200 class PluralMisuseChecker :
public Checker<check::ASTCodeBody> {
1214 bool InMatchingStatement =
false;
1219 : BR(InBR), Checker(Checker), AC(InAC) {}
1221 bool VisitIfStmt(
const IfStmt *I);
1222 bool EndVisitIfStmt(
IfStmt *I);
1223 bool TraverseIfStmt(
IfStmt *x);
1226 bool VisitCallExpr(
const CallExpr *CE);
1230 void reportPluralMisuseError(
const Stmt *S)
const;
1231 bool isCheckingPlurality(
const Expr *E)
const;
1238 Visitor.TraverseDecl(const_cast<Decl *>(D));
1247 bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality(
1248 const Expr *Condition)
const {
1251 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Condition)) {
1252 if (
const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
1253 const Expr *InitExpr = VD->getInit();
1260 if (VD->getName().lower().find(
"plural") != StringRef::npos ||
1261 VD->getName().lower().find(
"singular") != StringRef::npos) {
1265 }
else if (
const BinaryOperator *B = dyn_cast<BinaryOperator>(Condition)) {
1274 llvm::APInt
Value = IL->getValue();
1275 if (Value == 1 || Value == 2) {
1286 bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(
const CallExpr *CE) {
1287 if (InMatchingStatement) {
1289 std::string NormalizedName =
1290 StringRef(FD->getNameInfo().getAsString()).lower();
1291 if (NormalizedName.find(
"loc") != std::string::npos) {
1293 if (isa<ObjCStringLiteral>(Arg))
1294 reportPluralMisuseError(CE);
1307 bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr(
1315 if (odInfo->
isStr(
"NSBundle") &&
1317 if (InMatchingStatement) {
1318 reportPluralMisuseError(ME);
1325 bool PluralMisuseChecker::MethodCrawler::TraverseIfStmt(
IfStmt *I) {
1327 return EndVisitIfStmt(I);
1333 bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(
IfStmt *I) {
1334 MatchingStatements.pop_back();
1335 if (!MatchingStatements.empty()) {
1336 if (MatchingStatements.back() !=
nullptr) {
1337 InMatchingStatement =
true;
1341 InMatchingStatement =
false;
1345 bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(
const IfStmt *I) {
1347 if (isCheckingPlurality(Condition)) {
1348 MatchingStatements.push_back(I);
1349 InMatchingStatement =
true;
1351 MatchingStatements.push_back(
nullptr);
1352 InMatchingStatement =
false;
1359 bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator(
1362 MatchingStatements.pop_back();
1363 if (!MatchingStatements.empty()) {
1364 if (MatchingStatements.back() !=
nullptr)
1365 InMatchingStatement =
true;
1367 InMatchingStatement =
false;
1369 InMatchingStatement =
false;
1374 bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator(
1377 if (isCheckingPlurality(Condition)) {
1378 MatchingStatements.push_back(C);
1379 InMatchingStatement =
true;
1381 MatchingStatements.push_back(
nullptr);
1382 InMatchingStatement =
false;
1387 void PluralMisuseChecker::MethodCrawler::reportPluralMisuseError(
1388 const Stmt *S)
const {
1391 "Localizability Issue (Apple)",
1392 "Plural cases are not supported accross all languages. " 1393 "Use a .stringsdict file instead",
1401 void ento::registerNonLocalizedStringChecker(
CheckerManager &mgr) {
1402 NonLocalizedStringChecker *checker =
1404 checker->IsAggressive =
1408 void ento::registerEmptyLocalizationContextChecker(
CheckerManager &mgr) {
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
#define NEW_RECEIVER(receiver)
An instance of this class is created to represent 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)
const ProgramStateRef & getState() const
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...
VarDecl - An instance of this class is created to represent 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
getIdentifier - 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.
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
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.
const LocationContext * getLocationContext() const
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.
const FunctionProtoType * T
DeclContext * getDeclContext()
const IdentifierInfo * getCalleeIdentifier() const
Returns the name of the callee, if its name is a simple identifier.
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
virtual const Decl * getDecl() const
Returns the declaration of the function or method that will be called.
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
#define ADD_UNARY_METHOD(receiver, method, argument)
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
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.
CHECKER * registerChecker()
Used to register checkers.
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.
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
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
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.
#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...
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.