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