clang 8.0.0

NumberObjectConversionChecker.cpp
Go to the documentation of this file.
1 //===- NumberObjectConversionChecker.cpp -------------------------*- C++ -*-==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines NumberObjectConversionChecker, which checks for a
11 // particular common mistake when dealing with numbers represented as objects
12 // passed around by pointers. Namely, the language allows to reinterpret the
13 // pointer as a number directly, often without throwing any warnings,
14 // but in most cases the result of such conversion is clearly unexpected,
15 // as pointer value, rather than number value represented by the pointee object,
16 // becomes the result of such operation.
17 //
18 // Currently the checker supports the Objective-C NSNumber class,
19 // and the OSBoolean class found in macOS low-level code; the latter
20 // can only hold boolean values.
21 //
22 // This checker has an option "Pedantic" (boolean), which enables detection of
23 // more conversion patterns (which are most likely more harmless, and therefore
24 // are more likely to produce false positives) - disabled by default,
25 // enabled with `-analyzer-config osx.NumberObjectConversion:Pedantic=true'.
26 //
27 //===----------------------------------------------------------------------===//
28
29 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
30 #include "clang/ASTMatchers/ASTMatchFinder.h"
31 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
32 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
33 #include "clang/StaticAnalyzer/Core/Checker.h"
34 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
35 #include "clang/Lex/Lexer.h"
36 #include "llvm/ADT/APSInt.h"
37
38 using namespace clang;
39 using namespace ento;
40 using namespace ast_matchers;
41
42 namespace {
43
44 class NumberObjectConversionChecker : public Checker<check::ASTCodeBody> {
45 public:
46 bool Pedantic;
47
48 void checkASTCodeBody(const Decl *D, AnalysisManager &AM,
49 BugReporter &BR) const;
50 };
51
52 class Callback : public MatchFinder::MatchCallback {
53 const NumberObjectConversionChecker *C;
54 BugReporter &BR;
55 AnalysisDeclContext *ADC;
56
57 public:
58 Callback(const NumberObjectConversionChecker *C,
59 BugReporter &BR, AnalysisDeclContext *ADC)
60 : C(C), BR(BR), ADC(ADC) {}
61 virtual void run(const MatchFinder::MatchResult &Result);
62 };
63 } // end of anonymous namespace
64
65 void Callback::run(const MatchFinder::MatchResult &Result) {
66 bool IsPedanticMatch =
67 (Result.Nodes.getNodeAs<Stmt>("pedantic") != nullptr);
68 if (IsPedanticMatch && !C->Pedantic)
69 return;
70
71 ASTContext &ACtx = ADC->getASTContext();
72
73 if (const Expr *CheckIfNull =
74 Result.Nodes.getNodeAs<Expr>("check_if_null")) {
75 // Unless the macro indicates that the intended type is clearly not
76 // a pointer type, we should avoid warning on comparing pointers
77 // to zero literals in non-pedantic mode.
78 // FIXME: Introduce an AST matcher to implement the macro-related logic?
79 bool MacroIndicatesWeShouldSkipTheCheck = false;
80 SourceLocation Loc = CheckIfNull->getBeginLoc();
81 if (Loc.isMacroID()) {
82 StringRef MacroName = Lexer::getImmediateMacroName(
83 Loc, ACtx.getSourceManager(), ACtx.getLangOpts());
84 if (MacroName == "NULL" || MacroName == "nil")
85 return;
86 if (MacroName == "YES" || MacroName == "NO")
87 MacroIndicatesWeShouldSkipTheCheck = true;
88 }
89 if (!MacroIndicatesWeShouldSkipTheCheck) {
90 Expr::EvalResult EVResult;
91 if (CheckIfNull->IgnoreParenCasts()->EvaluateAsInt(
92 EVResult, ACtx, Expr::SE_AllowSideEffects)) {
93 llvm::APSInt Result = EVResult.Val.getInt();
94 if (Result == 0) {
95 if (!C->Pedantic)
96 return;
97 IsPedanticMatch = true;
98 }
99 }
100 }
101 }
102
103 const Stmt *Conv = Result.Nodes.getNodeAs<Stmt>("conv");
104 assert(Conv);
105
106 const Expr *ConvertedCObject = Result.Nodes.getNodeAs<Expr>("c_object");
107 const Expr *ConvertedCppObject = Result.Nodes.getNodeAs<Expr>("cpp_object");
108 const Expr *ConvertedObjCObject = Result.Nodes.getNodeAs<Expr>("objc_object");
109 bool IsCpp = (ConvertedCppObject != nullptr);
110 bool IsObjC = (ConvertedObjCObject != nullptr);
111 const Expr *Obj = IsObjC ? ConvertedObjCObject
112 : IsCpp ? ConvertedCppObject
113 : ConvertedCObject;
114 assert(Obj);
115
116 bool IsComparison =
117 (Result.Nodes.getNodeAs<Stmt>("comparison") != nullptr);
118
119 bool IsOSNumber =
120 (Result.Nodes.getNodeAs<Decl>("osnumber") != nullptr);
121
122 bool IsInteger =
123 (Result.Nodes.getNodeAs<QualType>("int_type") != nullptr);
124 bool IsObjCBool =
125 (Result.Nodes.getNodeAs<QualType>("objc_bool_type") != nullptr);
126 bool IsCppBool =
127 (Result.Nodes.getNodeAs<QualType>("cpp_bool_type") != nullptr);
128
129 llvm::SmallString<64> Msg;
130 llvm::raw_svector_ostream OS(Msg);
131
132 // Remove ObjC ARC qualifiers.
133 QualType ObjT = Obj->getType().getUnqualifiedType();
134
135 // Remove consts from pointers.
136 if (IsCpp) {
137 assert(ObjT.getCanonicalType()->isPointerType());
138 ObjT = ACtx.getPointerType(
139 ObjT->getPointeeType().getCanonicalType().getUnqualifiedType());
140 }
141
142 if (IsComparison)
143 OS << "Comparing ";
144 else
145 OS << "Converting ";
146
147 OS << "a pointer value of type '" << ObjT.getAsString() << "' to a ";
148
149 std::string EuphemismForPlain = "primitive";
150 std::string SuggestedApi = IsObjC ? (IsInteger ? "" : "-boolValue")
151 : IsCpp ? (IsOSNumber ? "" : "getValue()")
152 : "CFNumberGetValue()";
153 if (SuggestedApi.empty()) {
154 // A generic message if we're not sure what API should be called.
155 // FIXME: Pattern-match the integer type to make a better guess?
156 SuggestedApi =
157 "a method on '" + ObjT.getAsString() + "' to get the scalar value";
158 // "scalar" is not quite correct or common, but some documentation uses it
159 // when describing object methods we suggest. For consistency, we use
160 // "scalar" in the whole sentence when we need to use this word in at least
161 // one place, otherwise we use "primitive".
162 EuphemismForPlain = "scalar";
163 }
164
165 if (IsInteger)
166 OS << EuphemismForPlain << " integer value";
167 else if (IsObjCBool)
168 OS << EuphemismForPlain << " BOOL value";
169 else if (IsCppBool)
170 OS << EuphemismForPlain << " bool value";
171 else // Branch condition?
172 OS << EuphemismForPlain << " boolean value";
173
174
175 if (IsPedanticMatch)
176 OS << "; instead, either compare the pointer to "
177 << (IsObjC ? "nil" : IsCpp ? "nullptr" : "NULL") << " or ";
178 else
179 OS << "; did you mean to ";
180
181 if (IsComparison)
182 OS << "compare the result of calling " << SuggestedApi;
183 else
184 OS << "call " << SuggestedApi;
185
186 if (!IsPedanticMatch)
187 OS << "?";
188
189 BR.EmitBasicReport(
190 ADC->getDecl(), C, "Suspicious number object conversion", "Logic error",
191 OS.str(),
192 PathDiagnosticLocation::createBegin(Obj, BR.getSourceManager(), ADC),
193 Conv->getSourceRange());
194 }
195
196 void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D,
197 AnalysisManager &AM,
198 BugReporter &BR) const {
199 // Currently this matches CoreFoundation opaque pointer typedefs.
200 auto CSuspiciousNumberObjectExprM =
201 expr(ignoringParenImpCasts(
202 expr(hasType(
203 typedefType(hasDeclaration(anyOf(
204 typedefDecl(hasName("CFNumberRef")),
205 typedefDecl(hasName("CFBooleanRef")))))))
206 .bind("c_object")));
207
208 // Currently this matches XNU kernel number-object pointers.
209 auto CppSuspiciousNumberObjectExprM =
210 expr(ignoringParenImpCasts(
211 expr(hasType(hasCanonicalType(
212 pointerType(pointee(hasCanonicalType(
213 recordType(hasDeclaration(
214 anyOf(
215 cxxRecordDecl(hasName("OSBoolean")),
216 cxxRecordDecl(hasName("OSNumber"))
217 .bind("osnumber"))))))))))
218 .bind("cpp_object")));
219
220 // Currently this matches NeXTSTEP number objects.
221 auto ObjCSuspiciousNumberObjectExprM =
222 expr(ignoringParenImpCasts(
223 expr(hasType(hasCanonicalType(
224 objcObjectPointerType(pointee(
225 qualType(hasCanonicalType(
226 qualType(hasDeclaration(
227 objcInterfaceDecl(hasName("NSNumber")))))))))))
228 .bind("objc_object")));
229
230 auto SuspiciousNumberObjectExprM = anyOf(
231 CSuspiciousNumberObjectExprM,
232 CppSuspiciousNumberObjectExprM,
233 ObjCSuspiciousNumberObjectExprM);
234
235 // Useful for predicates like "Unless we've seen the same object elsewhere".
236 auto AnotherSuspiciousNumberObjectExprM =
237 expr(anyOf(
238 equalsBoundNode("c_object"),
239 equalsBoundNode("objc_object"),
240 equalsBoundNode("cpp_object")));
241
242 // The .bind here is in order to compose the error message more accurately.
243 auto ObjCSuspiciousScalarBooleanTypeM =
244 qualType(typedefType(hasDeclaration(
245 typedefDecl(hasName("BOOL"))))).bind("objc_bool_type");
246
247 // The .bind here is in order to compose the error message more accurately.
248 auto SuspiciousScalarBooleanTypeM =
249 qualType(anyOf(qualType(booleanType()).bind("cpp_bool_type"),
250 ObjCSuspiciousScalarBooleanTypeM));
251
252 // The .bind here is in order to compose the error message more accurately.
253 // Also avoid intptr_t and uintptr_t because they were specifically created
254 // for storing pointers.
255 auto SuspiciousScalarNumberTypeM =
256 qualType(hasCanonicalType(isInteger()),
257 unless(typedefType(hasDeclaration(
258 typedefDecl(matchesName("^::u?intptr_t$"))))))
259 .bind("int_type");
260
261 auto SuspiciousScalarTypeM =
262 qualType(anyOf(SuspiciousScalarBooleanTypeM,
263 SuspiciousScalarNumberTypeM));
264
265 auto SuspiciousScalarExprM =
266 expr(ignoringParenImpCasts(expr(hasType(SuspiciousScalarTypeM))));
267
268 auto ConversionThroughAssignmentM =
269 binaryOperator(allOf(hasOperatorName("="),
270 hasLHS(SuspiciousScalarExprM),
271 hasRHS(SuspiciousNumberObjectExprM)));
272
273 auto ConversionThroughBranchingM =
274 ifStmt(allOf(
275 hasCondition(SuspiciousNumberObjectExprM),
276 unless(hasConditionVariableStatement(declStmt())
277 ))).bind("pedantic");
278
279 auto ConversionThroughCallM =
280 callExpr(hasAnyArgument(allOf(hasType(SuspiciousScalarTypeM),
281 ignoringParenImpCasts(
282 SuspiciousNumberObjectExprM))));
283
284 // We bind "check_if_null" to modify the warning message
285 // in case it was intended to compare a pointer to 0 with a relatively-ok
286 // construct "x == 0" or "x != 0".
287 auto ConversionThroughEquivalenceM =
288 binaryOperator(allOf(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
289 hasEitherOperand(SuspiciousNumberObjectExprM),
290 hasEitherOperand(SuspiciousScalarExprM
291 .bind("check_if_null"))))
292 .bind("comparison");
293
294 auto ConversionThroughComparisonM =
295 binaryOperator(allOf(anyOf(hasOperatorName(">="), hasOperatorName(">"),
296 hasOperatorName("<="), hasOperatorName("<")),
297 hasEitherOperand(SuspiciousNumberObjectExprM),
298 hasEitherOperand(SuspiciousScalarExprM)))
299 .bind("comparison");
300
301 auto ConversionThroughConditionalOperatorM =
302 conditionalOperator(allOf(
303 hasCondition(SuspiciousNumberObjectExprM),
304 unless(hasTrueExpression(
305 hasDescendant(AnotherSuspiciousNumberObjectExprM))),
306 unless(hasFalseExpression(
307 hasDescendant(AnotherSuspiciousNumberObjectExprM)))))
308 .bind("pedantic");
309
310 auto ConversionThroughExclamationMarkM =
311 unaryOperator(allOf(hasOperatorName("!"),
312 has(expr(SuspiciousNumberObjectExprM))))
313 .bind("pedantic");
314
315 auto ConversionThroughExplicitBooleanCastM =
316 explicitCastExpr(allOf(hasType(SuspiciousScalarBooleanTypeM),
317 has(expr(SuspiciousNumberObjectExprM))));
318
319 auto ConversionThroughExplicitNumberCastM =
320 explicitCastExpr(allOf(hasType(SuspiciousScalarNumberTypeM),
321 has(expr(SuspiciousNumberObjectExprM))));
322
323 auto ConversionThroughInitializerM =
324 declStmt(hasSingleDecl(
325 varDecl(hasType(SuspiciousScalarTypeM),
326 hasInitializer(SuspiciousNumberObjectExprM))));
327
328 auto FinalM = stmt(anyOf(ConversionThroughAssignmentM,
329 ConversionThroughBranchingM,
330 ConversionThroughCallM,
331 ConversionThroughComparisonM,
332 ConversionThroughConditionalOperatorM,
333 ConversionThroughEquivalenceM,
334 ConversionThroughExclamationMarkM,
335 ConversionThroughExplicitBooleanCastM,
336 ConversionThroughExplicitNumberCastM,
337 ConversionThroughInitializerM)).bind("conv");
338
339 MatchFinder F;
340 Callback CB(this, BR, AM.getAnalysisDeclContext(D));
341
342 F.addMatcher(stmt(forEachDescendant(FinalM)), &CB);
343 F.match(*D->getBody(), AM.getASTContext());
344 }
345
346 void ento::registerNumberObjectConversionChecker(CheckerManager &Mgr) {
347 NumberObjectConversionChecker *Chk =
348 Mgr.registerChecker<NumberObjectConversionChecker>();
349 Chk->Pedantic =
350 Mgr.getAnalyzerOptions().getCheckerBooleanOption("Pedantic", false, Chk);
351 }
clang::ast_matchers::MatchFinder
A class to allow finding matches over the Clang AST.
Definition: ASTMatchFinder.h:69
ento
clang::ast_matchers::callExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
Definition: ASTMatchersInternal.cpp:622
clang::ast_matchers::typedefDecl
const internal::VariadicDynCastAllOfMatcher< Decl, TypedefDecl > typedefDecl
Matches typedef declarations.
Definition: ASTMatchersInternal.cpp:555
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:638
clang::ast_matchers::stmt
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
Definition: ASTMatchersInternal.cpp:615
clang::ast_matchers::objcInterfaceDecl
const internal::VariadicDynCastAllOfMatcher< Decl, ObjCInterfaceDecl > objcInterfaceDecl
Matches Objective-C interface declarations.
Definition: ASTMatchersInternal.cpp:629
clang::ast_matchers::has
const internal::ArgumentAdaptingMatcherFunc< internal::HasMatcher > has
Matches AST nodes that have child AST nodes that match the provided matcher.
Definition: ASTMatchersInternal.cpp:783
clang::Decl::getBody
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:979
ASTMatchFinder.h
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:66
clang::ast_matchers::hasDeclaration
internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher< Decl >, void(internal::HasDeclarationSupportedTypes)> hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
Definition: ASTMatchers.h:2865
clang::ast_matchers::anyOf
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> anyOf
Matches if any of the given matchers matches.
Definition: ASTMatchersInternal.cpp:773
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:87
clang::ast_matchers::hasDescendant
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher. ...
Definition: ASTMatchersInternal.cpp:785
BugType.h
clang::ast_matchers::pointerType
const AstTypeMatcher< PointerType > pointerType
Matches pointer types, but does not match Objective-C object pointer types.
Definition: ASTMatchersInternal.cpp:822
clang::ast_matchers::expr
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
Definition: ASTMatchersInternal.cpp:690
clang::ast_matchers::allOf
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> allOf
Matches if all given matchers match.
Definition: ASTMatchersInternal.cpp:776
clang::ast_matchers::binaryOperator
const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator > binaryOperator
Matches binary operator expressions.
Definition: ASTMatchersInternal.cpp:735
clang::ast_matchers::varDecl
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
Definition: ASTMatchersInternal.cpp:607
clang::ast_matchers::recordType
const AstTypeMatcher< RecordType > recordType
Matches record types (e.g.
Definition: ASTMatchersInternal.cpp:831
clang::ast_matchers::MatchFinder::match
void match(const T &Node, ASTContext &Context)
Calls the registered callbacks on all matches on the given Node.
Definition: ASTMatchFinder.h:185
clang::ASTContext
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:155
clang::AnalysisDeclContext
AnalysisDeclContext contains the context data for the function or method under analysis.
Definition: AnalysisDeclContext.h:70
Checker.h
clang::ast_matchers::typedefType
const AstTypeMatcher< TypedefType > typedefType
Matches typedef types.
Definition: ASTMatchersInternal.cpp:827
clang::ast_matchers::declStmt
const internal::VariadicDynCastAllOfMatcher< Stmt, DeclStmt > declStmt
Matches declaration statements.
Definition: ASTMatchersInternal.cpp:616
clang::ast_matchers::MatchFinder::addMatcher
void addMatcher(const DeclarationMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.
Definition: ASTMatchFinder.cpp:953
clang::ast_matchers::ifStmt
const internal::VariadicDynCastAllOfMatcher< Stmt, IfStmt > ifStmt
Matches if statements.
Definition: ASTMatchersInternal.cpp:694
clang::Expr::EvalResult::Val
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:573
clang::ast_matchers::BoundNodes::getNodeAs
const T * getNodeAs(StringRef ID) const
Returns the AST node bound to ID.
Definition: ASTMatchers.h:109
llvm::SmallString
Definition: LLVM.h:35
clang::ast_matchers::forEachDescendant
const internal::ArgumentAdaptingMatcherFunc< internal::ForEachDescendantMatcher > forEachDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher. ...
Definition: ASTMatchersInternal.cpp:789
BugReporter.h
clang::ast_matchers::explicitCastExpr
const internal::VariadicDynCastAllOfMatcher< Stmt, ExplicitCastExpr > explicitCastExpr
Matches explicit cast expressions.
Definition: ASTMatchersInternal.cpp:756
clang::Expr
This represents one expression.
Definition: Expr.h:106
clang::Expr::SE_AllowSideEffects
Allow any unmodeled side effect.
Definition: Expr.h:599
AnalysisManager.h
Lexer.h
clang::ast_matchers::conditionalOperator
const internal::VariadicDynCastAllOfMatcher< Stmt, ConditionalOperator > conditionalOperator
Matches conditional operator expressions.
Definition: ASTMatchersInternal.cpp:738
clang::ast_matchers::MatchFinder::MatchResult
Contains all information for a given match.
Definition: ASTMatchFinder.h:75
clang::Expr::getType
QualType getType() const
Definition: Expr.h:128
BuiltinCheckerRegistration.h
clang::ento::PathDiagnosticLocation::createBegin
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Definition: PathDiagnostic.cpp:636
clang::QualType::getCanonicalType
QualType getCanonicalType() const
Definition: Type.h:6111
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:88
clang::ast_matchers::qualType
const internal::VariadicAllOfMatcher< QualType > qualType
Matches QualTypes in the clang AST.
Definition: ASTMatchersInternal.cpp:591
clang::ast_matchers::unless
const internal::VariadicOperatorMatcherFunc< 1, 1 > unless
Matches if the provided matcher does not match.
Definition: ASTMatchersInternal.cpp:800
clang::Lexer::getImmediateMacroName
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
Definition: Lexer.cpp:968
clang::ast_matchers::MatchFinder::MatchResult::Nodes
const BoundNodes Nodes
Contains the nodes bound on the current match.
Definition: ASTMatchFinder.h:81
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:22
clang::Expr::EvalResult
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:571
ast_matchers
clang::ast_matchers::cxxRecordDecl
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
Definition: ASTMatchersInternal.cpp:570
clang::SourceLocation::isMacroID
bool isMacroID() const
Definition: SourceLocation.h:101
clang::ento::ObjKind::OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
clang::ASTContext::getSourceManager
SourceManager & getSourceManager()
Definition: ASTContext.h:662
clang::ast_matchers::hasEitherOperand
internal::Matcher< BinaryOperator > hasEitherOperand(const internal::Matcher< Expr > &InnerMatcher)
Matches if either the left hand side or the right hand side of a binary operator matches.
Definition: ASTMatchers.h:4391
clang::ast_matchers::unaryOperator
const internal::VariadicDynCastAllOfMatcher< Stmt, UnaryOperator > unaryOperator
Matches unary operator expressions.
Definition: ASTMatchersInternal.cpp:736
clang::QualType::getUnqualifiedType
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:6152
clang::ast_matchers::hasName
internal::Matcher< NamedDecl > hasName(const std::string &Name)
Matches NamedDecl nodes that have the specified name.
Definition: ASTMatchers.h:2526
clang::ASTContext::getPointerType
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
Definition: ASTContext.cpp:2847
clang::ast_matchers::objcObjectPointerType
const AstTypeMatcher< ObjCObjectPointerType > objcObjectPointerType
Matches an Objective-C object pointer type, which is different from a pointer type, despite being syntactically similar.
Definition: ASTMatchersInternal.cpp:823
clang::Stmt::getSourceRange
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:276
clang::Type::isPointerType
bool isPointerType() const
Definition: Type.h:6296
AttributeLangSupport::C
Definition: SemaDeclAttr.cpp:45
clang::ast_matchers::MatchFinder::MatchCallback
Called when the Match registered for it was successfully found in the AST.
Definition: ASTMatchFinder.h:92
clang::APValue::getInt
APSInt & getInt()
Definition: APValue.h:252
clang::ASTContext::getLangOpts
const LangOptions & getLangOpts() const
Definition: ASTContext.h:707