Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/ASTMatchers/LowLevelHelpers.cpp
213766 views
1
//===- LowLevelHelpers.cpp -------------------------------------*- 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
#include "clang/ASTMatchers/LowLevelHelpers.h"
10
#include "clang/AST/Decl.h"
11
#include "clang/AST/DeclCXX.h"
12
#include "clang/AST/Expr.h"
13
#include "clang/AST/ExprCXX.h"
14
#include <type_traits>
15
16
namespace clang {
17
namespace ast_matchers {
18
19
static const FunctionDecl *getCallee(const CXXConstructExpr &D) {
20
return D.getConstructor();
21
}
22
static const FunctionDecl *getCallee(const CallExpr &D) {
23
return D.getDirectCallee();
24
}
25
26
template <class ExprNode>
27
static void matchEachArgumentWithParamTypeImpl(
28
const ExprNode &Node,
29
llvm::function_ref<void(QualType /*Param*/, const Expr * /*Arg*/)>
30
OnParamAndArg) {
31
static_assert(std::is_same_v<CallExpr, ExprNode> ||
32
std::is_same_v<CXXConstructExpr, ExprNode>);
33
// The first argument of an overloaded member operator is the implicit object
34
// argument of the method which should not be matched against a parameter, so
35
// we skip over it here.
36
unsigned ArgIndex = 0;
37
if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(&Node)) {
38
const auto *MD = dyn_cast_or_null<CXXMethodDecl>(CE->getDirectCallee());
39
if (MD && !MD->isExplicitObjectMemberFunction()) {
40
// This is an overloaded operator call.
41
// We need to skip the first argument, which is the implicit object
42
// argument of the method which should not be matched against a
43
// parameter.
44
++ArgIndex;
45
}
46
}
47
48
const FunctionProtoType *FProto = nullptr;
49
50
if (const auto *Call = dyn_cast<CallExpr>(&Node)) {
51
if (const auto *Value =
52
dyn_cast_or_null<ValueDecl>(Call->getCalleeDecl())) {
53
QualType QT = Value->getType().getCanonicalType();
54
55
// This does not necessarily lead to a `FunctionProtoType`,
56
// e.g. K&R functions do not have a function prototype.
57
if (QT->isFunctionPointerType())
58
FProto = QT->getPointeeType()->getAs<FunctionProtoType>();
59
60
if (QT->isMemberFunctionPointerType()) {
61
const auto *MP = QT->getAs<MemberPointerType>();
62
assert(MP && "Must be member-pointer if its a memberfunctionpointer");
63
FProto = MP->getPointeeType()->getAs<FunctionProtoType>();
64
assert(FProto &&
65
"The call must have happened through a member function "
66
"pointer");
67
}
68
}
69
}
70
71
unsigned ParamIndex = 0;
72
unsigned NumArgs = Node.getNumArgs();
73
if (FProto && FProto->isVariadic())
74
NumArgs = std::min(NumArgs, FProto->getNumParams());
75
76
for (; ArgIndex < NumArgs; ++ArgIndex, ++ParamIndex) {
77
QualType ParamType;
78
if (FProto && FProto->getNumParams() > ParamIndex)
79
ParamType = FProto->getParamType(ParamIndex);
80
else if (const FunctionDecl *FD = getCallee(Node);
81
FD && FD->getNumParams() > ParamIndex)
82
ParamType = FD->getParamDecl(ParamIndex)->getType();
83
else
84
continue;
85
86
OnParamAndArg(ParamType, Node.getArg(ArgIndex)->IgnoreParenCasts());
87
}
88
}
89
90
void matchEachArgumentWithParamType(
91
const CallExpr &Node,
92
llvm::function_ref<void(QualType /*Param*/, const Expr * /*Arg*/)>
93
OnParamAndArg) {
94
matchEachArgumentWithParamTypeImpl(Node, OnParamAndArg);
95
}
96
97
void matchEachArgumentWithParamType(
98
const CXXConstructExpr &Node,
99
llvm::function_ref<void(QualType /*Param*/, const Expr * /*Arg*/)>
100
OnParamAndArg) {
101
matchEachArgumentWithParamTypeImpl(Node, OnParamAndArg);
102
}
103
104
} // namespace ast_matchers
105
106
} // namespace clang
107
108