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