32 #include "llvm/Support/Unicode.h"
33 #include "llvm/ADT/StringSet.h"
35 using namespace clang;
39 struct 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); }
60 class NonLocalizedStringChecker
61 :
public Checker<check::PostCall, check::PreObjCMessage,
62 check::PostObjCMessage,
63 check::PostStmt<ObjCStringLiteral>> {
65 mutable std::unique_ptr<BugType> BT;
69 llvm::DenseMap<Selector, uint8_t>> UIMethods;
71 mutable llvm::SmallSet<std::pair<const IdentifierInfo *, Selector>, 12> LSM;
73 mutable llvm::SmallSet<const IdentifierInfo *, 5> LSF;
76 void initLocStringsMethods(
ASTContext &Ctx)
const;
83 bool isAnnotatedAsLocalized(
const Decl *D)
const;
87 int getLocalizedArgumentForSelector(
const IdentifierInfo *Receiver,
91 NonLocalizedStringChecker();
109 NonLocalizedStringChecker::NonLocalizedStringChecker() {
110 BT.reset(
new BugType(
this,
"Unlocalizable string",
111 "Localizability Issue (Apple)"));
114 #define NEW_RECEIVER(receiver) \
115 llvm::DenseMap<Selector, uint8_t> &receiver##M = \
116 UIMethods.insert({&Ctx.Idents.get(#receiver), \
117 llvm::DenseMap<Selector, uint8_t>()}) \
119 #define ADD_NULLARY_METHOD(receiver, method, argument) \
120 receiver##M.insert( \
121 {Ctx.Selectors.getNullarySelector(&Ctx.Idents.get(#method)), argument});
122 #define ADD_UNARY_METHOD(receiver, method, argument) \
123 receiver##M.insert( \
124 {Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(#method)), argument});
125 #define ADD_METHOD(receiver, method_list, count, argument) \
126 receiver##M.insert({Ctx.Selectors.getSelector(count, method_list), argument});
130 void NonLocalizedStringChecker::initUIMethods(
ASTContext &Ctx)
const {
131 if (!UIMethods.empty())
142 ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemTag, 3, 0)
146 ADD_METHOD(UITabBarItem, initWithTitleUITabBarItemImage, 3, 0)
159 ADD_METHOD(UITableViewRowAction, rowActionWithStyleUITableViewRowAction, 3, 1)
186 ADD_METHOD(NSBrowser, setTitleNSBrowser, 2, 0)
197 ADD_METHOD(UIAlertAction, actionWithTitleUIAlertAction, 3, 0)
203 ADD_METHOD(NSPopUpButton, insertItemWithTitleNSPopUpButton, 2, 0)
212 ADD_METHOD(NSTableViewRowAction, rowActionWithStyleNSTableViewRowAction, 3, 1)
244 ADD_METHOD(NSSegmentedControl, setLabelNSSegmentedControl, 2, 0)
266 ADD_METHOD(NSMatrix, setToolTipNSMatrix, 2, 0)
282 ADD_METHOD(UIMenuItem, initWithTitleUIMenuItem, 2, 0)
289 ADD_METHOD(UIAlertController, alertControllerWithTitleUIAlertController, 3, 1)
299 initWithTypeUIApplicationShortcutItemIcon, 5, 1)
302 ADD_METHOD(UIApplicationShortcutItem, initWithTypeUIApplicationShortcutItem,
309 &Ctx.
Idents.
get(
"destructiveButtonTitle"),
311 ADD_METHOD(UIActionSheet, initWithTitleUIActionSheet, 5, 0)
323 initWithNameUIAccessibilityCustomAction, 3, 0)
347 ADD_METHOD(NSAttributedString, initWithStringNSAttributedString, 2, 0)
356 ADD_METHOD(UIKeyCommand, keyCommandWithInputUIKeyCommand, 4, 3)
366 &Ctx.
Idents.
get(
"informativeTextWithFormat")};
367 ADD_METHOD(NSAlert, alertWithMessageTextNSAlert, 5, 0)
386 ADD_METHOD(NSWindow, minFrameWidthWithTitleNSWindow, 2, 0)
393 IdentifierInfo *addOptionWithTitleUIDocumentMenuViewController[] = {
397 addOptionWithTitleUIDocumentMenuViewController, 4, 0)
409 ADD_METHOD(UIAlertView, initWithTitleUIAlertView, 5, 0)
439 ADD_METHOD(NSSegmentedCell, setLabelNSSegmentedCell, 2, 0)
442 ADD_METHOD(NSSegmentedCell, setToolTipNSSegmentedCell, 2, 0)
453 ADD_METHOD(NSMenuItem, initWithTitleNSMenuItem, 3, 0)
460 ADD_METHOD(NSPopUpButtonCell, initTextCellNSPopUpButtonCell, 2, 0)
464 ADD_METHOD(NSPopUpButtonCell, insertItemWithTitleNSPopUpButtonCell, 2, 0)
477 ADD_METHOD(NSMenu, insertItemWithTitleNSMenu, 4, 0)
481 ADD_METHOD(NSMenu, addItemWithTitleNSMenu, 3, 0)
497 IdentifierInfo *actionWithIdentifierNSUserNotificationAction[] = {
500 actionWithIdentifierNSUserNotificationAction, 2, 1)
513 ADD_METHOD(UIBarButtonItem, initWithTitleUIBarButtonItem, 4, 0)
522 ADD_METHOD(UISegmentedControl, insertSegmentWithTitleUISegmentedControl, 3, 0)
525 ADD_METHOD(UISegmentedControl, setTitleUISegmentedControl, 2, 0)
528 #define LSF_INSERT(function_name) LSF.insert(&Ctx.Idents.get(function_name));
529 #define LSM_INSERT_NULLARY(receiver, method_name) \
530 LSM.insert({&Ctx.Idents.get(receiver), Ctx.Selectors.getNullarySelector( \
531 &Ctx.Idents.get(method_name))});
532 #define LSM_INSERT_UNARY(receiver, method_name) \
533 LSM.insert({&Ctx.Idents.get(receiver), \
534 Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(method_name))});
535 #define LSM_INSERT_SELECTOR(receiver, method_list, arguments) \
536 LSM.insert({&Ctx.Idents.get(receiver), \
537 Ctx.Selectors.getSelector(arguments, method_list)});
540 void NonLocalizedStringChecker::initLocStringsMethods(
ASTContext &Ctx)
const {
558 LSF_INSERT(
"CFDateFormatterCreateStringWithDate");
559 LSF_INSERT(
"CFDateFormatterCreateStringWithAbsoluteTime");
560 LSF_INSERT(
"CFNumberFormatterCreateStringWithNumber");
565 bool NonLocalizedStringChecker::isAnnotatedAsLocalized(
const Decl *D)
const {
571 return Ann->getAnnotation() ==
"returns_localized_nsstring";
576 bool NonLocalizedStringChecker::hasLocalizedState(
SVal S,
580 const LocalizedState *LS = C.
getState()->get<LocalizedMemMap>(mt);
581 if (LS && LS->isLocalized())
589 bool NonLocalizedStringChecker::hasNonLocalizedState(
SVal S,
593 const LocalizedState *LS = C.
getState()->get<LocalizedMemMap>(mt);
594 if (LS && LS->isNonLocalized())
601 void NonLocalizedStringChecker::setLocalizedState(
const SVal S,
606 C.
getState()->set<LocalizedMemMap>(mt, LocalizedState::getLocalized());
612 void NonLocalizedStringChecker::setNonLocalizedState(
const SVal S,
617 mt, LocalizedState::getNonLocalized());
623 void NonLocalizedStringChecker::reportLocalizationError(
625 int argumentNumber)
const {
629 "UnlocalizedString");
636 std::unique_ptr<BugReport> R(
new BugReport(
637 *BT,
"User-facing text should use localized string macro", ErrNode));
638 if (argumentNumber) {
639 R->addRange(M.
getArgExpr(argumentNumber - 1)->getSourceRange());
643 R->markInteresting(S);
649 int NonLocalizedStringChecker::getLocalizedArgumentForSelector(
651 auto method = UIMethods.find(Receiver);
653 if (method == UIMethods.end())
656 auto argumentIterator = method->getSecond().find(S);
658 if (argumentIterator == method->getSecond().end())
661 int argumentNumber = argumentIterator->getSecond();
662 return argumentNumber;
666 void NonLocalizedStringChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
678 StringRef SelectorName = SelectorString;
679 assert(!SelectorName.empty());
681 if (odInfo->
isStr(
"NSString")) {
685 if (!(SelectorName.startswith(
"drawAtPoint") ||
686 SelectorName.startswith(
"drawInRect") ||
687 SelectorName.startswith(
"drawWithRect")))
692 bool isNonLocalized = hasNonLocalizedState(svTitle, C);
694 if (isNonLocalized) {
695 reportLocalizationError(svTitle, msg, C);
699 int argumentNumber = getLocalizedArgumentForSelector(odInfo, S);
701 while (argumentNumber < 0 && OD->getSuperClass() !=
nullptr) {
702 for (
const auto *
P : OD->all_referenced_protocols()) {
703 argumentNumber = getLocalizedArgumentForSelector(
P->getIdentifier(),
S);
704 if (argumentNumber >= 0)
707 if (argumentNumber < 0) {
708 OD = OD->getSuperClass();
709 argumentNumber = getLocalizedArgumentForSelector(OD->getIdentifier(),
S);
713 if (argumentNumber < 0)
716 SVal svTitle = msg.getArgSVal(argumentNumber);
719 dyn_cast_or_null<ObjCStringRegion>(svTitle.
getAsRegion())) {
720 StringRef stringValue =
721 SR->getObjCStringLiteral()->getString()->getString();
722 if ((stringValue.trim().size() == 0 && stringValue.size() > 0) ||
725 if (!IsAggressive && llvm::sys::unicode::columnWidthUTF8(stringValue) < 2)
729 bool isNonLocalized = hasNonLocalizedState(svTitle, C);
731 if (isNonLocalized) {
732 reportLocalizationError(svTitle, msg, C, argumentNumber + 1);
749 return ClsName == &Ctx.
Idents.
get(
"NSString") ||
750 ClsName == &Ctx.
Idents.
get(
"NSMutableString");
758 void NonLocalizedStringChecker::checkPostCall(
const CallEvent &Call,
770 for (
unsigned i = 0; i < Call.
getNumArgs(); ++i) {
772 if (hasLocalizedState(argValue, C)) {
774 setLocalizedState(sv, C);
787 if (isAnnotatedAsLocalized(D) || LSF.count(Identifier) != 0) {
788 setLocalizedState(sv, C);
790 !hasLocalizedState(sv, C)) {
792 setNonLocalizedState(sv, C);
795 dyn_cast_or_null<SymbolicRegion>(sv.
getAsRegion());
797 setNonLocalizedState(sv, C);
804 void NonLocalizedStringChecker::checkPostObjCMessage(
const ObjCMethodCall &msg,
819 std::pair<const IdentifierInfo *, Selector> MethodDescription = {odInfo, S};
821 if (LSM.count(MethodDescription) || isAnnotatedAsLocalized(msg.
getDecl())) {
822 SVal sv = msg.getReturnValue();
823 setLocalizedState(sv, C);
831 setNonLocalizedState(sv, C);
835 class EmptyLocalizationContextChecker
836 :
public Checker<check::ASTDecl<ObjCImplementationDecl>> {
850 : MD(InMD), BR(InBR), Mgr(InMgr), Checker(Checker), DCtx(InDCtx) {}
852 void VisitStmt(
const Stmt *S) { VisitChildren(S); }
858 void VisitChildren(
const Stmt *S) {
859 for (
const Stmt *Child : S->children()) {
872 void EmptyLocalizationContextChecker::checkASTDecl(
879 const Stmt *Body = M->getBody();
882 MethodCrawler MC(M->getCanonicalDecl(), BR,
this, Mgr, DCtx);
902 void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr(
911 if (!(odInfo->
isStr(
"NSBundle") &&
913 "localizedStringForKey:value:table:")) {
926 std::pair<FileID, unsigned> SLInfo =
941 BF->getBufferStart() + SLInfo.second, BF->getBufferEnd());
946 while (!TheLexer.LexFromRawLexer(I)) {
947 if (I.getKind() == tok::l_paren)
949 if (I.getKind() == tok::r_paren) {
959 reportEmptyContextError(ME);
970 if ((Comment.trim().size() == 0 && Comment.size() > 0) ||
972 reportEmptyContextError(ME);
976 void EmptyLocalizationContextChecker::MethodCrawler::reportEmptyContextError(
980 "Localizability Issue (Apple)",
981 "Localized string macro should include a non-empty "
982 "comment for translators",
987 class PluralMisuseChecker :
public Checker<check::ASTCodeBody> {
1001 bool InMatchingStatement =
false;
1006 : BR(InBR), Checker(Checker), AC(InAC) {}
1008 bool VisitIfStmt(
const IfStmt *I);
1009 bool EndVisitIfStmt(
IfStmt *I);
1010 bool TraverseIfStmt(
IfStmt *x);
1013 bool VisitCallExpr(
const CallExpr *CE);
1017 void reportPluralMisuseError(
const Stmt *S)
const;
1018 bool isCheckingPlurality(
const Expr *
E)
const;
1025 Visitor.TraverseDecl(const_cast<Decl *>(D));
1034 bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality(
1035 const Expr *Condition)
const {
1038 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Condition)) {
1039 if (
const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
1040 const Expr *InitExpr = VD->getInit();
1047 if (VD->getName().lower().find(
"plural") != StringRef::npos ||
1048 VD->getName().lower().find(
"singular") != StringRef::npos) {
1052 }
else if (
const BinaryOperator *B = dyn_cast<BinaryOperator>(Condition)) {
1061 llvm::APInt
Value = IL->getValue();
1062 if (Value == 1 || Value == 2) {
1073 bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(
const CallExpr *CE) {
1074 if (InMatchingStatement) {
1076 std::string NormalizedName =
1077 StringRef(FD->getNameInfo().getAsString()).lower();
1078 if (NormalizedName.find(
"loc") != std::string::npos) {
1080 if (isa<ObjCStringLiteral>(Arg))
1081 reportPluralMisuseError(CE);
1094 bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr(
1102 if (odInfo->
isStr(
"NSBundle") &&
1104 if (InMatchingStatement) {
1105 reportPluralMisuseError(ME);
1112 bool PluralMisuseChecker::MethodCrawler::TraverseIfStmt(
IfStmt *I) {
1114 return EndVisitIfStmt(I);
1120 bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(
IfStmt *I) {
1121 MatchingStatements.pop_back();
1122 if (!MatchingStatements.empty()) {
1123 if (MatchingStatements.back() !=
nullptr) {
1124 InMatchingStatement =
true;
1128 InMatchingStatement =
false;
1132 bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(
const IfStmt *I) {
1134 if (isCheckingPlurality(Condition)) {
1135 MatchingStatements.push_back(I);
1136 InMatchingStatement =
true;
1138 MatchingStatements.push_back(
nullptr);
1139 InMatchingStatement =
false;
1146 bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator(
1149 MatchingStatements.pop_back();
1150 if (!MatchingStatements.empty()) {
1151 if (MatchingStatements.back() !=
nullptr)
1152 InMatchingStatement =
true;
1154 InMatchingStatement =
false;
1156 InMatchingStatement =
false;
1161 bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator(
1164 if (isCheckingPlurality(Condition)) {
1165 MatchingStatements.push_back(C);
1166 InMatchingStatement =
true;
1168 MatchingStatements.push_back(
nullptr);
1169 InMatchingStatement =
false;
1174 void PluralMisuseChecker::MethodCrawler::reportPluralMisuseError(
1175 const Stmt *S)
const {
1178 "Localizability Issue (Apple)",
1179 "Plural cases are not supported accross all languages. "
1180 "Use a .stringsdict file instead",
1188 void ento::registerNonLocalizedStringChecker(
CheckerManager &mgr) {
1189 NonLocalizedStringChecker *checker =
1191 checker->IsAggressive =
1195 void ento::registerEmptyLocalizationContextChecker(
CheckerManager &mgr) {
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
#define NEW_RECEIVER(receiver)
FunctionDecl - 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.
bool isInstanceMessage() const
specific_attr_iterator< T > specific_attr_begin() const
bool operator==(CanQual< T > x, CanQual< U > y)
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
#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.
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.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
REGISTER_MAP_WITH_PROGRAMSTATE(LocalizedMemMap, const MemRegion *, LocalizedState) NonLocalizedStringChecker
const ExpansionInfo & getExpansion() const
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
SourceRange getSourceRange() const override
VarDecl - An instance of this class is created to represent a variable declaration or definition...
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...
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
One of these records is kept for each identifier that is lexed.
The region associated with an ObjCStringLiteral.
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.
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
Token - This structure provides full information about a lexed token.
method_range methods() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents any expression that calls an Objective-C method.
SVal getReceiverSVal() const
Returns the value of the receiver at the time 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...
A builtin binary operation expression such as "x + y" or "x <= y".
Selector getSelector() const
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.
tok::TokenKind getKind() const
A class that does preorder depth-first traversal on the entire Clang AST and visits each node...
Represents an ObjC class declaration.
detail::InMemoryDirectory::const_iterator I
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
specific_attr_iterator< T > specific_attr_end() 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.
ConditionalOperator - The ?: ternary operator.
#define LSM_INSERT_NULLARY(receiver, method_name)
ID
Defines the set of possible language-specific address spaces.
SymbolicRegion - A special, "non-concrete" region.
Expr - This represents one expression.
const ProgramStateRef & getState() const
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
An expression that sends a message to the given Objective-C object or class.
The result type of a method or function.
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option's string value as a boolean.
#define ADD_UNARY_METHOD(receiver, method, argument)
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
BugReporter is a utility class for generating PathDiagnostics for analysis.
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)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Selector getSelector() const
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
#define LSF_INSERT(function_name)
const FileInfo & getFile() const
std::string getAsString() const
Derive the full selector name (e.g.
SourceLocation getBegin() const
const IdentifierInfo * getCalleeIdentifier() const
Returns the name of the callee, if its name is a simple identifier.
const ObjCMethodDecl * getDecl() const override
SourceManager & getSourceManager() override
virtual const Decl * getDecl() const
Returns the declaration of the function or method that will be called.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
ASTContext & getASTContext()
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
const ContentCache * getContentCache() const
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
Represents an abstract call to a function or method along a particular path.
AnalyzerOptions & getAnalyzerOptions()
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
Represents a pointer to an Objective C object.
QualType getResultType() const
Returns the result type, adjusted for references.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
const T * getAs() const
Member-template getAs<specific type>'.
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)
const Expr * getArgExpr(unsigned Index) const override
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
const Expr * getCond() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A reference to a declared variable, function, enum, etc.
unsigned getLength() const
#define LSM_INSERT_SELECTOR(receiver, method_list, arguments)
A trivial tuple used to represent a source range.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
This class provides an interface through which checkers can create individual bug reports...
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
SVal getReturnValue() const
Returns the return value of the call.
bool isAnyIdentifier(TokenKind K)
Return true if this is a raw identifier or an identifier kind.
SourceLocation getSpellingLoc() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.