Path: blob/main/contrib/llvm-project/clang/lib/ASTMatchers/LowLevelHelpers.cpp
213766 views
//===- LowLevelHelpers.cpp -------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/ASTMatchers/LowLevelHelpers.h"9#include "clang/AST/Decl.h"10#include "clang/AST/DeclCXX.h"11#include "clang/AST/Expr.h"12#include "clang/AST/ExprCXX.h"13#include <type_traits>1415namespace clang {16namespace ast_matchers {1718static const FunctionDecl *getCallee(const CXXConstructExpr &D) {19return D.getConstructor();20}21static const FunctionDecl *getCallee(const CallExpr &D) {22return D.getDirectCallee();23}2425template <class ExprNode>26static void matchEachArgumentWithParamTypeImpl(27const ExprNode &Node,28llvm::function_ref<void(QualType /*Param*/, const Expr * /*Arg*/)>29OnParamAndArg) {30static_assert(std::is_same_v<CallExpr, ExprNode> ||31std::is_same_v<CXXConstructExpr, ExprNode>);32// The first argument of an overloaded member operator is the implicit object33// argument of the method which should not be matched against a parameter, so34// we skip over it here.35unsigned ArgIndex = 0;36if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(&Node)) {37const auto *MD = dyn_cast_or_null<CXXMethodDecl>(CE->getDirectCallee());38if (MD && !MD->isExplicitObjectMemberFunction()) {39// This is an overloaded operator call.40// We need to skip the first argument, which is the implicit object41// argument of the method which should not be matched against a42// parameter.43++ArgIndex;44}45}4647const FunctionProtoType *FProto = nullptr;4849if (const auto *Call = dyn_cast<CallExpr>(&Node)) {50if (const auto *Value =51dyn_cast_or_null<ValueDecl>(Call->getCalleeDecl())) {52QualType QT = Value->getType().getCanonicalType();5354// This does not necessarily lead to a `FunctionProtoType`,55// e.g. K&R functions do not have a function prototype.56if (QT->isFunctionPointerType())57FProto = QT->getPointeeType()->getAs<FunctionProtoType>();5859if (QT->isMemberFunctionPointerType()) {60const auto *MP = QT->getAs<MemberPointerType>();61assert(MP && "Must be member-pointer if its a memberfunctionpointer");62FProto = MP->getPointeeType()->getAs<FunctionProtoType>();63assert(FProto &&64"The call must have happened through a member function "65"pointer");66}67}68}6970unsigned ParamIndex = 0;71unsigned NumArgs = Node.getNumArgs();72if (FProto && FProto->isVariadic())73NumArgs = std::min(NumArgs, FProto->getNumParams());7475for (; ArgIndex < NumArgs; ++ArgIndex, ++ParamIndex) {76QualType ParamType;77if (FProto && FProto->getNumParams() > ParamIndex)78ParamType = FProto->getParamType(ParamIndex);79else if (const FunctionDecl *FD = getCallee(Node);80FD && FD->getNumParams() > ParamIndex)81ParamType = FD->getParamDecl(ParamIndex)->getType();82else83continue;8485OnParamAndArg(ParamType, Node.getArg(ArgIndex)->IgnoreParenCasts());86}87}8889void matchEachArgumentWithParamType(90const CallExpr &Node,91llvm::function_ref<void(QualType /*Param*/, const Expr * /*Arg*/)>92OnParamAndArg) {93matchEachArgumentWithParamTypeImpl(Node, OnParamAndArg);94}9596void matchEachArgumentWithParamType(97const CXXConstructExpr &Node,98llvm::function_ref<void(QualType /*Param*/, const Expr * /*Arg*/)>99OnParamAndArg) {100matchEachArgumentWithParamTypeImpl(Node, OnParamAndArg);101}102103} // namespace ast_matchers104105} // namespace clang106107108