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