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