1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang-tidy/ClangTidyCheck.h"
10 #include "clang-tidy/ClangTidyModuleRegistry.h"
12 #include "robust_against_adl.hpp"
17 AST_MATCHER(clang::UnresolvedLookupExpr
, requiresADL
) { return Node
.requiresADL(); }
19 AST_MATCHER(clang::CallExpr
, isOperator
) { return llvm::isa
<clang::CXXOperatorCallExpr
>(Node
); }
21 AST_MATCHER(clang::UnresolvedLookupExpr
, isCustomizationPoint
) {
22 return std::ranges::any_of(
23 std::array
{"swap", "make_error_code", "make_error_condition", "begin", "end", "size", "rend", "rbegin"},
24 [&](const char* func
) { return Node
.getName().getAsString() == func
; });
27 AST_MATCHER(clang::CXXMethodDecl
, isStatic
) { return Node
.isStatic(); }
32 robust_against_adl_check::robust_against_adl_check(llvm::StringRef name
, clang::tidy::ClangTidyContext
* context
)
33 : clang::tidy::ClangTidyCheck(name
, context
) {}
35 void robust_against_adl_check::registerMatchers(clang::ast_matchers::MatchFinder
* finder
) {
36 using namespace clang::ast_matchers
;
38 callExpr(unless(isOperator()),
39 unless(argumentCountIs(0)),
40 has(unresolvedLookupExpr(requiresADL(), unless(isCustomizationPoint()))),
41 unless(callee(cxxMethodDecl(isStatic()))))
46 void robust_against_adl_check::check(const clang::ast_matchers::MatchFinder::MatchResult
& result
) {
47 if (const auto* call
= result
.Nodes
.getNodeAs
<clang::CallExpr
>("ADLcall"); call
!= nullptr) {
48 diag(call
->getBeginLoc(), "ADL lookup");