1//===----------------------------------------------------------------------===//
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-tidy/ClangTidyCheck.h"
10#include "clang-tidy/ClangTidyModuleRegistry.h"
11#include "clang/ASTMatchers/ASTMatchers.h"
12#include "clang/Tooling/FixIt.h"
13
14#include "robust_against_operator_ampersand.hpp"
15
16// This clang-tidy check ensures that we don't use operator& on dependant
17// types. If the type is user supplied it may call the type's operator&.
18// Instead use std::addressof.
19//
20// This is part of libc++'s policy
21// https://libcxx.llvm.org/CodingGuidelines.html#don-t-use-argument-dependent-lookup-unless-required-by-the-standard
22
23// TODO(LLVM-21) Remove dependentScopeDeclRefExpr
24// dependentScopeDeclRefExpr requires Clang 20, this uses the same definition as Clang
25#if defined(__clang_major__) && __clang_major__ < 20
26namespace clang::ast_matchers {
27const internal::VariadicDynCastAllOfMatcher<Stmt, DependentScopeDeclRefExpr> dependentScopeDeclRefExpr;
28} // namespace clang::ast_matchers
29#endif
30
31namespace libcpp {
32robust_against_operator_ampersand::robust_against_operator_ampersand(
33 llvm::StringRef name, clang::tidy::ClangTidyContext* context)
34 : clang::tidy::ClangTidyCheck(name, context) {}
35
36void robust_against_operator_ampersand::registerMatchers(clang::ast_matchers::MatchFinder* finder) {
37 using namespace clang::ast_matchers;
38 finder->addMatcher(
39 cxxOperatorCallExpr(allOf(hasOperatorName(Name: "&"), argumentCountIs(N: 1), isTypeDependent()),
40 unless(hasUnaryOperand(InnerMatcher: dependentScopeDeclRefExpr())))
41 .bind(ID: "match"),
42 this);
43}
44
45void robust_against_operator_ampersand::check(const clang::ast_matchers::MatchFinder::MatchResult& result) {
46 if (const auto* call = result.Nodes.getNodeAs< clang::CXXOperatorCallExpr >("match"); call != nullptr) {
47 diag(call->getBeginLoc(), "Guard against user provided operator& for dependent types.")
48 << clang::FixItHint::CreateReplacement(
49 call->getSourceRange(),
50 (llvm::Twine(
51 "std::addressof(" + clang::tooling::fixit::getText(*call->getArg(0), *result.Context) + ")"))
52 .str());
53 }
54}
55
56} // namespace libcpp
57

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of libcxx/test/tools/clang_tidy_checks/robust_against_operator_ampersand.cpp