summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp151
1 files changed, 18 insertions, 133 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp
index a585fe3e813..cef8e9d9a5e 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp
@@ -8,9 +8,6 @@
//===----------------------------------------------------------------------===//
#include "MakeUniqueCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
@@ -18,136 +15,24 @@ namespace clang {
namespace tidy {
namespace modernize {
-static const char PointerType[] = "pointerType";
-static const char ConstructorCall[] = "constructorCall";
-static const char NewExpression[] = "newExpression";
-
-void MakeUniqueCheck::registerMatchers(MatchFinder *Finder) {
- if (getLangOpts().CPlusPlus11) {
- Finder->addMatcher(
- cxxBindTemporaryExpr(has(
- cxxConstructExpr(
- hasType(qualType(hasDeclaration(classTemplateSpecializationDecl(
- matchesName("::std::unique_ptr"),
- templateArgumentCountIs(2),
- hasTemplateArgument(0, templateArgument(refersToType(
- qualType().bind(PointerType)))),
- hasTemplateArgument(
- 1, templateArgument(refersToType(qualType(
- hasDeclaration(classTemplateSpecializationDecl(
- matchesName("::std::default_delete"),
- templateArgumentCountIs(1),
- hasTemplateArgument(
- 0, templateArgument(refersToType(
- qualType(equalsBoundNode(
- PointerType))))))))))))))),
- argumentCountIs(1),
- hasArgument(
- 0, cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
- equalsBoundNode(PointerType))))))
- .bind(NewExpression)))
- .bind(ConstructorCall))),
- this);
- }
-}
-
-void MakeUniqueCheck::check(const MatchFinder::MatchResult &Result) {
- SourceManager &SM = *Result.SourceManager;
- const auto *Construct =
- Result.Nodes.getNodeAs<CXXConstructExpr>(ConstructorCall);
- const auto *Type = Result.Nodes.getNodeAs<QualType>(PointerType);
- const auto *New = Result.Nodes.getNodeAs<CXXNewExpr>(NewExpression);
-
- if (New->getNumPlacementArgs() != 0)
- return;
-
- SourceLocation ConstructCallStart = Construct->getExprLoc();
-
- bool Invalid = false;
- StringRef ExprStr = Lexer::getSourceText(
- CharSourceRange::getCharRange(
- ConstructCallStart, Construct->getParenOrBraceRange().getBegin()),
- SM, LangOptions(), &Invalid);
- if (Invalid)
- return;
-
- auto Diag = diag(ConstructCallStart, "use std::make_unique instead");
-
- // Find the location of the template's left angle.
- size_t LAngle = ExprStr.find("<");
- SourceLocation ConstructCallEnd;
- if (LAngle == StringRef::npos) {
- // If the template argument is missing (because it is part of the alias)
- // we have to add it back.
- ConstructCallEnd = ConstructCallStart.getLocWithOffset(ExprStr.size());
- Diag << FixItHint::CreateInsertion(
- ConstructCallEnd, "<" + Type->getAsString(getLangOpts()) + ">");
- } else {
- ConstructCallEnd = ConstructCallStart.getLocWithOffset(LAngle);
- }
-
- Diag << FixItHint::CreateReplacement(
- CharSourceRange::getCharRange(ConstructCallStart, ConstructCallEnd),
- "std::make_unique");
-
- // If the unique_ptr is built with brace enclosed direct initialization, use
- // parenthesis instead.
- if (Construct->isListInitialization()) {
- SourceRange BraceRange = Construct->getParenOrBraceRange();
- Diag << FixItHint::CreateReplacement(
- CharSourceRange::getCharRange(
- BraceRange.getBegin(), BraceRange.getBegin().getLocWithOffset(1)),
- "(");
- Diag << FixItHint::CreateReplacement(
- CharSourceRange::getCharRange(BraceRange.getEnd(),
- BraceRange.getEnd().getLocWithOffset(1)),
- ")");
- }
-
- SourceLocation NewStart = New->getSourceRange().getBegin();
- SourceLocation NewEnd = New->getSourceRange().getEnd();
- switch (New->getInitializationStyle()) {
- case CXXNewExpr::NoInit: {
- Diag << FixItHint::CreateRemoval(SourceRange(NewStart, NewEnd));
- break;
- }
- case CXXNewExpr::CallInit: {
- SourceRange InitRange = New->getDirectInitRange();
- Diag << FixItHint::CreateRemoval(
- SourceRange(NewStart, InitRange.getBegin()));
- Diag << FixItHint::CreateRemoval(SourceRange(InitRange.getEnd(), NewEnd));
- break;
- }
- case CXXNewExpr::ListInit: {
- // Range of the substring that we do not want to remove.
- SourceRange InitRange;
- if (const auto *NewConstruct = New->getConstructExpr()) {
- // Direct initialization with initialization list.
- // struct S { S(int x) {} };
- // std::unique_ptr<S>(new S{5});
- // The arguments in the initialization list are going to be forwarded to
- // the constructor, so this has to be replaced with:
- // struct S { S(int x) {} };
- // std::make_unique<S>(5);
- InitRange = SourceRange(
- NewConstruct->getParenOrBraceRange().getBegin().getLocWithOffset(1),
- NewConstruct->getParenOrBraceRange().getEnd().getLocWithOffset(-1));
- } else {
- // Aggregate initialization.
- // std::unique_ptr<Pair>(new Pair{first, second});
- // Has to be replaced with:
- // std::make_unique<Pair>(Pair{first, second});
- InitRange = SourceRange(
- New->getAllocatedTypeSourceInfo()->getTypeLoc().getLocStart(),
- New->getInitializer()->getSourceRange().getEnd());
- }
- Diag << FixItHint::CreateRemoval(
- CharSourceRange::getCharRange(NewStart, InitRange.getBegin()));
- Diag << FixItHint::CreateRemoval(
- SourceRange(InitRange.getEnd().getLocWithOffset(1), NewEnd));
- break;
- }
- }
+MakeUniqueCheck::MakeUniqueCheck(StringRef Name,
+ clang::tidy::ClangTidyContext *Context)
+ : MakeSmartPtrCheck(Name, Context, "std::make_unique") {}
+
+MakeUniqueCheck::SmartPtrTypeMatcher
+MakeUniqueCheck::getSmartPointerTypeMatcher() const {
+ return qualType(hasDeclaration(classTemplateSpecializationDecl(
+ matchesName("::std::unique_ptr"), templateArgumentCountIs(2),
+ hasTemplateArgument(
+ 0, templateArgument(refersToType(qualType().bind(PointerType)))),
+ hasTemplateArgument(
+ 1, templateArgument(refersToType(
+ qualType(hasDeclaration(classTemplateSpecializationDecl(
+ matchesName("::std::default_delete"),
+ templateArgumentCountIs(1),
+ hasTemplateArgument(
+ 0, templateArgument(refersToType(qualType(
+ equalsBoundNode(PointerType))))))))))))));
}
} // namespace modernize
OpenPOWER on IntegriCloud