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