ExplicitMakePairCheck.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. //===--- ExplicitMakePairCheck.cpp - clang-tidy -----------------*- 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. #include "ExplicitMakePairCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/ASTMatchers/ASTMatchFinder.h"
  11. #include "clang/ASTMatchers/ASTMatchers.h"
  12. using namespace clang::ast_matchers;
  13. namespace clang {
  14. namespace {
  15. AST_MATCHER(DeclRefExpr, hasExplicitTemplateArgs) {
  16. return Node.hasExplicitTemplateArgs();
  17. }
  18. } // namespace
  19. namespace tidy::google::build {
  20. void ExplicitMakePairCheck::registerMatchers(
  21. ast_matchers::MatchFinder *Finder) {
  22. // Look for std::make_pair with explicit template args. Ignore calls in
  23. // templates.
  24. Finder->addMatcher(
  25. callExpr(unless(isInTemplateInstantiation()),
  26. callee(expr(ignoringParenImpCasts(
  27. declRefExpr(hasExplicitTemplateArgs(),
  28. to(functionDecl(hasName("::std::make_pair"))))
  29. .bind("declref")))))
  30. .bind("call"),
  31. this);
  32. }
  33. void ExplicitMakePairCheck::check(const MatchFinder::MatchResult &Result) {
  34. const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
  35. const auto *DeclRef = Result.Nodes.getNodeAs<DeclRefExpr>("declref");
  36. // Sanity check: The use might have overriden ::std::make_pair.
  37. if (Call->getNumArgs() != 2)
  38. return;
  39. const Expr *Arg0 = Call->getArg(0)->IgnoreParenImpCasts();
  40. const Expr *Arg1 = Call->getArg(1)->IgnoreParenImpCasts();
  41. // If types don't match, we suggest replacing with std::pair and explicit
  42. // template arguments. Otherwise just remove the template arguments from
  43. // make_pair.
  44. if (Arg0->getType() != Call->getArg(0)->getType() ||
  45. Arg1->getType() != Call->getArg(1)->getType()) {
  46. diag(Call->getBeginLoc(), "for C++11-compatibility, use pair directly")
  47. << FixItHint::CreateReplacement(
  48. SourceRange(DeclRef->getBeginLoc(), DeclRef->getLAngleLoc()),
  49. "std::pair<");
  50. } else {
  51. diag(Call->getBeginLoc(),
  52. "for C++11-compatibility, omit template arguments from make_pair")
  53. << FixItHint::CreateRemoval(
  54. SourceRange(DeclRef->getLAngleLoc(), DeclRef->getRAngleLoc()));
  55. }
  56. }
  57. } // namespace tidy::google::build
  58. } // namespace clang