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