107 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_ANALYZER_WEBKIT_ASTUTILS_H10#define LLVM_CLANG_ANALYZER_WEBKIT_ASTUTILS_H11 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 20namespace clang {21class Expr;22 23/// This function de-facto defines a set of transformations that we consider24/// safe (in heuristical sense). These transformation if passed a safe value as25/// an input should provide a safe value (or an object that provides safe26/// values).27///28/// For more context see Static Analyzer checkers documentation - specifically29/// webkit.UncountedCallArgsChecker checker. Allowed list of transformations:30/// - constructors of ref-counted types (including factory methods)31/// - getters of ref-counted types32/// - member overloaded operators33/// - casts34/// - unary operators like ``&`` or ``*``35///36/// If passed expression is of type uncounted pointer/reference we try to find37/// the "origin" of the pointer value.38/// Origin can be for example a local variable, nullptr, constant or39/// this-pointer.40///41/// Certain subexpression nodes represent transformations that don't affect42/// where the memory address originates from. We try to traverse such43/// subexpressions to get to the relevant child nodes. Whenever we encounter a44/// subexpression that either can't be ignored, we don't model its semantics or45/// 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 that49/// represents ref-counted object during the traversal we return relevant50/// sub-expression and true.51///52/// Calls \p callback with the subexpression that we traversed to and if \p53/// StopAtFirstRefCountedObj is true we also specify whether we stopped early.54/// Returns false if any of calls to callbacks returned false. Otherwise true.55bool tryToFindPtrOrigin(56 const clang::Expr *E, bool StopAtFirstRefCountedObj,57 std::function<bool(const clang::CXXRecordDecl *)> isSafePtr,58 std::function<bool(const clang::QualType)> isSafePtrType,59 std::function<bool(const clang::Decl *)> isSafeGlobalDecl,60 std::function<bool(const clang::Expr *, bool)> callback);61 62/// For \p E referring to a ref-countable/-counted pointer/reference we return63/// whether it's a safe call argument. Examples: function parameter or64/// this-pointer. The logic relies on the set of recursive rules we enforce for65/// WebKit codebase.66///67/// \returns Whether \p E is a safe call arugment.68bool isASafeCallArg(const clang::Expr *E);69 70/// \returns true if E is nullptr or __null.71bool isNullPtr(const clang::Expr *E);72 73/// \returns true if E is a MemberExpr accessing a const smart pointer type.74bool isConstOwnerPtrMemberExpr(const clang::Expr *E);75 76/// \returns true if E is a MemberExpr accessing a member variable which77/// supports CheckedPtr.78bool isExprToGetCheckedPtrCapableMember(const clang::Expr *E);79 80/// \returns true if E is a CXXMemberCallExpr which returns a const smart81/// pointer type.82class EnsureFunctionAnalysis {83 using CacheTy = llvm::DenseMap<const FunctionDecl *, bool>;84 mutable CacheTy Cache{};85 86public:87 bool isACallToEnsureFn(const Expr *E) const;88};89 90/// \returns name of AST node or empty string.91template <typename T> std::string safeGetName(const T *ASTNode) {92 const auto *const ND = llvm::dyn_cast_or_null<clang::NamedDecl>(ASTNode);93 if (!ND)94 return "";95 96 // In case F is for example "operator|" the getName() method below would97 // assert.98 if (!ND->getDeclName().isIdentifier())99 return "";100 101 return ND->getName().str();102}103 104} // namespace clang105 106#endif107