2020#include " clang/AST/Stmt.h"
2121#include " clang/AST/StmtVisitor.h"
2222#include " clang/AST/Type.h"
23+ #include " clang/ASTMatchers/LowLevelHelpers.h"
2324#include " clang/Basic/SourceLocation.h"
2425#include " clang/Lex/Lexer.h"
2526#include " clang/Lex/Preprocessor.h"
@@ -300,98 +301,6 @@ static void findStmtsInUnspecifiedLvalueContext(
300301 OnResult (BO->getLHS ());
301302}
302303
303- // / Note: Copied and modified from ASTMatchers.
304- // / Matches all arguments and their respective types for a \c CallExpr.
305- // / It is very similar to \c forEachArgumentWithParam but
306- // / it works on calls through function pointers as well.
307- // /
308- // / The difference is, that function pointers do not provide access to a
309- // / \c ParmVarDecl, but only the \c QualType for each argument.
310- // /
311- // / Given
312- // / \code
313- // / void f(int i);
314- // / int y;
315- // / f(y);
316- // / void (*f_ptr)(int) = f;
317- // / f_ptr(y);
318- // / \endcode
319- // / callExpr(
320- // / forEachArgumentWithParamType(
321- // / declRefExpr(to(varDecl(hasName("y")))),
322- // / qualType(isInteger()).bind("type)
323- // / ))
324- // / matches f(y) and f_ptr(y)
325- // / with declRefExpr(...)
326- // / matching int y
327- // / and qualType(...)
328- // / matching int
329- static void forEachArgumentWithParamType (
330- const CallExpr &Node,
331- const llvm::function_ref<void (QualType /* Param*/ , const Expr * /* Arg*/ )>
332- OnParamAndArg) {
333- // The first argument of an overloaded member operator is the implicit object
334- // argument of the method which should not be matched against a parameter, so
335- // we skip over it here.
336- unsigned ArgIndex = 0 ;
337- if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(&Node)) {
338- const auto *MD = dyn_cast_or_null<CXXMethodDecl>(CE->getDirectCallee ());
339- if (MD && !MD->isExplicitObjectMemberFunction ()) {
340- // This is an overloaded operator call.
341- // We need to skip the first argument, which is the implicit object
342- // argument of the method which should not be matched against a
343- // parameter.
344- ++ArgIndex;
345- }
346- }
347-
348- const FunctionProtoType *FProto = nullptr ;
349-
350- if (const auto *Call = dyn_cast<CallExpr>(&Node)) {
351- if (const auto *Value =
352- dyn_cast_or_null<ValueDecl>(Call->getCalleeDecl ())) {
353- QualType QT = Value->getType ().getCanonicalType ();
354-
355- // This does not necessarily lead to a `FunctionProtoType`,
356- // e.g. K&R functions do not have a function prototype.
357- if (QT->isFunctionPointerType ())
358- FProto = QT->getPointeeType ()->getAs <FunctionProtoType>();
359-
360- if (QT->isMemberFunctionPointerType ()) {
361- const auto *MP = QT->getAs <MemberPointerType>();
362- assert (MP && " Must be member-pointer if its a memberfunctionpointer" );
363- FProto = MP->getPointeeType ()->getAs <FunctionProtoType>();
364- assert (FProto &&
365- " The call must have happened through a member function "
366- " pointer" );
367- }
368- }
369- }
370-
371- unsigned ParamIndex = 0 ;
372- unsigned NumArgs = Node.getNumArgs ();
373- if (FProto && FProto->isVariadic ())
374- NumArgs = std::min (NumArgs, FProto->getNumParams ());
375-
376- const auto GetParamType =
377- [&FProto, &Node](unsigned int ParamIndex) -> std::optional<QualType> {
378- if (FProto && FProto->getNumParams () > ParamIndex) {
379- return FProto->getParamType (ParamIndex);
380- }
381- const auto *FD = Node.getDirectCallee ();
382- if (FD && FD->getNumParams () > ParamIndex) {
383- return FD->getParamDecl (ParamIndex)->getType ();
384- }
385- return std::nullopt ;
386- };
387-
388- for (; ArgIndex < NumArgs; ++ArgIndex, ++ParamIndex) {
389- auto ParamType = GetParamType (ParamIndex);
390- if (ParamType)
391- OnParamAndArg (*ParamType, Node.getArg (ArgIndex)->IgnoreParenCasts ());
392- }
393- }
394-
395304// Finds any expression `e` such that `InnerMatcher` matches `e` and
396305// `e` is in an Unspecified Pointer Context (UPC).
397306static void findStmtsInUnspecifiedPointerContext (
@@ -408,7 +317,7 @@ static void findStmtsInUnspecifiedPointerContext(
408317 if (const auto *FnDecl = CE->getDirectCallee ();
409318 FnDecl && FnDecl->hasAttr <UnsafeBufferUsageAttr>())
410319 return ;
411- forEachArgumentWithParamType (
320+ ast_matchers::matchEachArgumentWithParamType (
412321 *CE, [&InnerMatcher](QualType Type, const Expr *Arg) {
413322 if (Type->isAnyPointerType ())
414323 InnerMatcher (Arg);
0 commit comments