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)65ec727ea7Spatricktemplate <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