xref: /freebsd/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //=======- ASTUtis.h ---------------------------------------------*- C++ -*-==//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #ifndef LLVM_CLANG_ANALYZER_WEBKIT_ASTUTILS_H
105ffd83dbSDimitry Andric #define LLVM_CLANG_ANALYZER_WEBKIT_ASTUTILS_H
115ffd83dbSDimitry Andric 
125ffd83dbSDimitry Andric #include "clang/AST/Decl.h"
135ffd83dbSDimitry Andric #include "llvm/ADT/APInt.h"
145ffd83dbSDimitry Andric #include "llvm/Support/Casting.h"
155ffd83dbSDimitry Andric 
16*0fca6ea1SDimitry Andric #include <functional>
175ffd83dbSDimitry Andric #include <string>
185ffd83dbSDimitry Andric #include <utility>
195ffd83dbSDimitry Andric 
205ffd83dbSDimitry Andric namespace clang {
215ffd83dbSDimitry Andric class Expr;
225ffd83dbSDimitry Andric 
235ffd83dbSDimitry Andric /// This function de-facto defines a set of transformations that we consider
245ffd83dbSDimitry Andric /// safe (in heuristical sense). These transformation if passed a safe value as
255ffd83dbSDimitry Andric /// an input should provide a safe value (or an object that provides safe
265ffd83dbSDimitry Andric /// values).
275ffd83dbSDimitry Andric ///
285ffd83dbSDimitry Andric /// For more context see Static Analyzer checkers documentation - specifically
29349cc55cSDimitry Andric /// webkit.UncountedCallArgsChecker checker. Allowed list of transformations:
305ffd83dbSDimitry Andric /// - constructors of ref-counted types (including factory methods)
315ffd83dbSDimitry Andric /// - getters of ref-counted types
325ffd83dbSDimitry Andric /// - member overloaded operators
335ffd83dbSDimitry Andric /// - casts
345ffd83dbSDimitry Andric /// - unary operators like ``&`` or ``*``
355ffd83dbSDimitry Andric ///
365ffd83dbSDimitry Andric /// If passed expression is of type uncounted pointer/reference we try to find
375ffd83dbSDimitry Andric /// the "origin" of the pointer value.
385ffd83dbSDimitry Andric /// Origin can be for example a local variable, nullptr, constant or
395ffd83dbSDimitry Andric /// this-pointer.
405ffd83dbSDimitry Andric ///
415ffd83dbSDimitry Andric /// Certain subexpression nodes represent transformations that don't affect
425ffd83dbSDimitry Andric /// where the memory address originates from. We try to traverse such
435ffd83dbSDimitry Andric /// subexpressions to get to the relevant child nodes. Whenever we encounter a
445ffd83dbSDimitry Andric /// subexpression that either can't be ignored, we don't model its semantics or
455ffd83dbSDimitry Andric /// that has multiple children we stop.
465ffd83dbSDimitry Andric ///
475ffd83dbSDimitry Andric /// \p E is an expression of uncounted pointer/reference type.
485ffd83dbSDimitry Andric /// If \p StopAtFirstRefCountedObj is true and we encounter a subexpression that
495ffd83dbSDimitry Andric /// represents ref-counted object during the traversal we return relevant
505ffd83dbSDimitry Andric /// sub-expression and true.
515ffd83dbSDimitry Andric ///
52*0fca6ea1SDimitry Andric /// Calls \p callback with the subexpression that we traversed to and if \p
53*0fca6ea1SDimitry Andric /// StopAtFirstRefCountedObj is true we also specify whether we stopped early.
54*0fca6ea1SDimitry Andric /// Returns false if any of calls to callbacks returned false. Otherwise true.
55*0fca6ea1SDimitry Andric bool tryToFindPtrOrigin(
56*0fca6ea1SDimitry Andric     const clang::Expr *E, bool StopAtFirstRefCountedObj,
57*0fca6ea1SDimitry Andric     std::function<bool(const clang::Expr *, bool)> callback);
585ffd83dbSDimitry Andric 
595ffd83dbSDimitry Andric /// For \p E referring to a ref-countable/-counted pointer/reference we return
605ffd83dbSDimitry Andric /// whether it's a safe call argument. Examples: function parameter or
615ffd83dbSDimitry Andric /// this-pointer. The logic relies on the set of recursive rules we enforce for
625ffd83dbSDimitry Andric /// WebKit codebase.
635ffd83dbSDimitry Andric ///
645ffd83dbSDimitry Andric /// \returns Whether \p E is a safe call arugment.
655ffd83dbSDimitry Andric bool isASafeCallArg(const clang::Expr *E);
665ffd83dbSDimitry Andric 
675ffd83dbSDimitry Andric /// \returns name of AST node or empty string.
safeGetName(const T * ASTNode)685ffd83dbSDimitry Andric template <typename T> std::string safeGetName(const T *ASTNode) {
695ffd83dbSDimitry Andric   const auto *const ND = llvm::dyn_cast_or_null<clang::NamedDecl>(ASTNode);
705ffd83dbSDimitry Andric   if (!ND)
715ffd83dbSDimitry Andric     return "";
725ffd83dbSDimitry Andric 
735ffd83dbSDimitry Andric   // In case F is for example "operator|" the getName() method below would
745ffd83dbSDimitry Andric   // assert.
755ffd83dbSDimitry Andric   if (!ND->getDeclName().isIdentifier())
765ffd83dbSDimitry Andric     return "";
775ffd83dbSDimitry Andric 
785ffd83dbSDimitry Andric   return ND->getName().str();
795ffd83dbSDimitry Andric }
805ffd83dbSDimitry Andric 
815ffd83dbSDimitry Andric } // namespace clang
825ffd83dbSDimitry Andric 
835ffd83dbSDimitry Andric #endif
84