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*e038c9c4Sjoergtemplate <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