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