|
| 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/Tooling/FixIt.h" |
| 12 | + |
| 13 | +#include "robust_against_operator_ampersand.hpp" |
| 14 | + |
| 15 | +// This clang-tidy check ensures that we don't use operator& on dependant |
| 16 | +// types. If the type is user supplied it may call the type's operator&. |
| 17 | +// Instead use std::addressof. |
| 18 | + |
| 19 | +namespace libcpp { |
| 20 | +robust_against_operator_ampersand::robust_against_operator_ampersand( |
| 21 | + llvm::StringRef name, clang::tidy::ClangTidyContext* context) |
| 22 | + : clang::tidy::ClangTidyCheck(name, context), disabled_(!context->getLangOpts().CPlusPlus11) {} |
| 23 | + |
| 24 | +void robust_against_operator_ampersand::registerMatchers(clang::ast_matchers::MatchFinder* finder) { |
| 25 | + if (disabled_) |
| 26 | + return; |
| 27 | + |
| 28 | + using namespace clang::ast_matchers; |
| 29 | + finder->addMatcher( |
| 30 | + cxxOperatorCallExpr(allOf(hasOperatorName("&"), argumentCountIs(1), isTypeDependent()), |
| 31 | + unless(hasUnaryOperand(dependentScopeDeclRefExpr()))) |
| 32 | + .bind("match"), |
| 33 | + this); |
| 34 | +} |
| 35 | + |
| 36 | +void robust_against_operator_ampersand::check(const clang::ast_matchers::MatchFinder::MatchResult& result) { |
| 37 | + if (const auto* call = result.Nodes.getNodeAs< clang::CXXOperatorCallExpr >("match"); call != nullptr) { |
| 38 | + diag(call->getBeginLoc(), "Guard against user provided operator& for dependent types.") |
| 39 | + << clang::FixItHint::CreateReplacement( |
| 40 | + call->getSourceRange(), |
| 41 | + (llvm::Twine( |
| 42 | + "std::addressof(" + clang::tooling::fixit::getText(*call->getArg(0), *result.Context) + ")")) |
| 43 | + .str()); |
| 44 | + } |
| 45 | +} |
| 46 | + |
| 47 | +} // namespace libcpp |
0 commit comments