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