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