xref: /freebsd-src/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry Andric //=======- ASTUtis.h ---------------------------------------------*- C++ -*-==//
2*5ffd83dbSDimitry Andric //
3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd83dbSDimitry Andric //
7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric 
9*5ffd83dbSDimitry Andric #ifndef LLVM_CLANG_ANALYZER_WEBKIT_ASTUTILS_H
10*5ffd83dbSDimitry Andric #define LLVM_CLANG_ANALYZER_WEBKIT_ASTUTILS_H
11*5ffd83dbSDimitry Andric 
12*5ffd83dbSDimitry Andric #include "clang/AST/Decl.h"
13*5ffd83dbSDimitry Andric #include "llvm/ADT/APInt.h"
14*5ffd83dbSDimitry Andric #include "llvm/Support/Casting.h"
15*5ffd83dbSDimitry Andric 
16*5ffd83dbSDimitry Andric #include <string>
17*5ffd83dbSDimitry Andric #include <utility>
18*5ffd83dbSDimitry Andric 
19*5ffd83dbSDimitry Andric namespace clang {
20*5ffd83dbSDimitry Andric class CXXRecordDecl;
21*5ffd83dbSDimitry Andric class CXXBaseSpecifier;
22*5ffd83dbSDimitry Andric class FunctionDecl;
23*5ffd83dbSDimitry Andric class CXXMethodDecl;
24*5ffd83dbSDimitry Andric class Expr;
25*5ffd83dbSDimitry Andric 
26*5ffd83dbSDimitry Andric /// This function de-facto defines a set of transformations that we consider
27*5ffd83dbSDimitry Andric /// safe (in heuristical sense). These transformation if passed a safe value as
28*5ffd83dbSDimitry Andric /// an input should provide a safe value (or an object that provides safe
29*5ffd83dbSDimitry Andric /// values).
30*5ffd83dbSDimitry Andric ///
31*5ffd83dbSDimitry Andric /// For more context see Static Analyzer checkers documentation - specifically
32*5ffd83dbSDimitry Andric /// webkit.UncountedCallArgsChecker checker. Whitelist of transformations:
33*5ffd83dbSDimitry Andric /// - constructors of ref-counted types (including factory methods)
34*5ffd83dbSDimitry Andric /// - getters of ref-counted types
35*5ffd83dbSDimitry Andric /// - member overloaded operators
36*5ffd83dbSDimitry Andric /// - casts
37*5ffd83dbSDimitry Andric /// - unary operators like ``&`` or ``*``
38*5ffd83dbSDimitry Andric ///
39*5ffd83dbSDimitry Andric /// If passed expression is of type uncounted pointer/reference we try to find
40*5ffd83dbSDimitry Andric /// the "origin" of the pointer value.
41*5ffd83dbSDimitry Andric /// Origin can be for example a local variable, nullptr, constant or
42*5ffd83dbSDimitry Andric /// this-pointer.
43*5ffd83dbSDimitry Andric ///
44*5ffd83dbSDimitry Andric /// Certain subexpression nodes represent transformations that don't affect
45*5ffd83dbSDimitry Andric /// where the memory address originates from. We try to traverse such
46*5ffd83dbSDimitry Andric /// subexpressions to get to the relevant child nodes. Whenever we encounter a
47*5ffd83dbSDimitry Andric /// subexpression that either can't be ignored, we don't model its semantics or
48*5ffd83dbSDimitry Andric /// that has multiple children we stop.
49*5ffd83dbSDimitry Andric ///
50*5ffd83dbSDimitry Andric /// \p E is an expression of uncounted pointer/reference type.
51*5ffd83dbSDimitry Andric /// If \p StopAtFirstRefCountedObj is true and we encounter a subexpression that
52*5ffd83dbSDimitry Andric /// represents ref-counted object during the traversal we return relevant
53*5ffd83dbSDimitry Andric /// sub-expression and true.
54*5ffd83dbSDimitry Andric ///
55*5ffd83dbSDimitry Andric /// \returns subexpression that we traversed to and if \p
56*5ffd83dbSDimitry Andric /// StopAtFirstRefCountedObj is true we also return whether we stopped early.
57*5ffd83dbSDimitry Andric std::pair<const clang::Expr *, bool>
58*5ffd83dbSDimitry Andric tryToFindPtrOrigin(const clang::Expr *E, bool StopAtFirstRefCountedObj);
59*5ffd83dbSDimitry Andric 
60*5ffd83dbSDimitry Andric /// For \p E referring to a ref-countable/-counted pointer/reference we return
61*5ffd83dbSDimitry Andric /// whether it's a safe call argument. Examples: function parameter or
62*5ffd83dbSDimitry Andric /// this-pointer. The logic relies on the set of recursive rules we enforce for
63*5ffd83dbSDimitry Andric /// WebKit codebase.
64*5ffd83dbSDimitry Andric ///
65*5ffd83dbSDimitry Andric /// \returns Whether \p E is a safe call arugment.
66*5ffd83dbSDimitry Andric bool isASafeCallArg(const clang::Expr *E);
67*5ffd83dbSDimitry Andric 
68*5ffd83dbSDimitry Andric /// \returns name of AST node or empty string.
69*5ffd83dbSDimitry Andric template <typename T> std::string safeGetName(const T *ASTNode) {
70*5ffd83dbSDimitry Andric   const auto *const ND = llvm::dyn_cast_or_null<clang::NamedDecl>(ASTNode);
71*5ffd83dbSDimitry Andric   if (!ND)
72*5ffd83dbSDimitry Andric     return "";
73*5ffd83dbSDimitry Andric 
74*5ffd83dbSDimitry Andric   // In case F is for example "operator|" the getName() method below would
75*5ffd83dbSDimitry Andric   // assert.
76*5ffd83dbSDimitry Andric   if (!ND->getDeclName().isIdentifier())
77*5ffd83dbSDimitry Andric     return "";
78*5ffd83dbSDimitry Andric 
79*5ffd83dbSDimitry Andric   return ND->getName().str();
80*5ffd83dbSDimitry Andric }
81*5ffd83dbSDimitry Andric 
82*5ffd83dbSDimitry Andric } // namespace clang
83*5ffd83dbSDimitry Andric 
84*5ffd83dbSDimitry Andric #endif
85