diff options
| author | Angel Garcia Gomez <angelgarcia@google.com> | 2015-10-14 09:22:32 +0000 | 
|---|---|---|
| committer | Angel Garcia Gomez <angelgarcia@google.com> | 2015-10-14 09:22:32 +0000 | 
| commit | baf573eb4cecd5f3a8ebc55210fbf45de2ff7c78 (patch) | |
| tree | 616e253a8c83e21206db6c457b483328e5eab062 | |
| parent | cb57fdd98d288713b112aab2ce94d12758376a1e (diff) | |
| download | bcm5719-llvm-baf573eb4cecd5f3a8ebc55210fbf45de2ff7c78.tar.gz bcm5719-llvm-baf573eb4cecd5f3a8ebc55210fbf45de2ff7c78.zip  | |
Support every kind of initialization.
Summary: modernize-make-unique now correctly supports the different kinds of list initialization.
Reviewers: klimek
Subscribers: cfe-commits, alexfh
Differential Revision: http://reviews.llvm.org/D13590
llvm-svn: 250283
| -rw-r--r-- | clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp | 44 | ||||
| -rw-r--r-- | clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp | 94 | 
2 files changed, 118 insertions, 20 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp index bdf5538a59c..d90cf7ce6bc 100644 --- a/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MakeUniqueCheck.cpp @@ -54,8 +54,11 @@ void MakeUniqueCheck::check(const MatchFinder::MatchResult &Result) {    SourceManager &SM = *Result.SourceManager;    const auto *Construct =        Result.Nodes.getNodeAs<CXXConstructExpr>(ConstructorCall); -  const auto *New = Result.Nodes.getNodeAs<CXXNewExpr>(NewExpression);    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(); @@ -86,6 +89,20 @@ void MakeUniqueCheck::check(const MatchFinder::MatchResult &Result) {        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()) { @@ -101,9 +118,30 @@ void MakeUniqueCheck::check(const MatchFinder::MatchResult &Result) {      break;    }    case CXXNewExpr::ListInit: { -    SourceRange InitRange = New->getInitializer()->getSourceRange(); +    // 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( -        SourceRange(NewStart, InitRange.getBegin().getLocWithOffset(-1))); +        CharSourceRange::getCharRange(NewStart, InitRange.getBegin()));      Diag << FixItHint::CreateRemoval(          SourceRange(InitRange.getEnd().getLocWithOffset(1), NewEnd));      break; diff --git a/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp b/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp index f8851b51077..4fbc7dd22c4 100644 --- a/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp +++ b/clang-tools-extra/test/clang-tidy/modernize-make-unique.cpp @@ -34,12 +34,22 @@ struct Derived : public Base {    Derived(int, int);  }; -struct Pair { +struct APair {    int a, b;  }; +struct DPair { +  DPair() : a(0), b(0) {} +  DPair(int x, int y) : a(y), b(x) {} +  int a, b; +}; + +struct Empty {}; +  template<class T> using unique_ptr_ = std::unique_ptr<T>; +void *operator new(unsigned long Count, void *Ptr); +  int g(std::unique_ptr<int> P);  std::unique_ptr<Base> getPointer() { @@ -48,7 +58,7 @@ std::unique_ptr<Base> getPointer() {    // CHECK-FIXES: return std::make_unique<Base>();  } -void f() { +void basic() {    std::unique_ptr<int> P1 = std::unique_ptr<int>(new int());    // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]    // CHECK-FIXES: std::unique_ptr<int> P1 = std::make_unique<int>(); @@ -78,16 +88,6 @@ void f() {    // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead    // CHECK-FIXES: int T = g(std::make_unique<int>()); -  // Arguments are correctly handled. -  std::unique_ptr<Base> Pbase = std::unique_ptr<Base>(new Base(5, T)); -  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead -  // CHECK-FIXES: std::unique_ptr<Base> Pbase = std::make_unique<Base>(5, T); - -  // Works with init lists. -  std::unique_ptr<Pair> Ppair = std::unique_ptr<Pair>(new Pair{T, 1}); -  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead -  // CHECK-FIXES: std::unique_ptr<Pair> Ppair = std::make_unique<Pair>({T, 1}); -    // Only replace if the type in the template is the same than the type returned    // by the new operator.    auto Pderived = std::unique_ptr<Base>(new Derived()); @@ -95,7 +95,69 @@ void f() {    // The pointer is returned by the function, nothing to do.    std::unique_ptr<Base> RetPtr = getPointer(); -  // Aliases. +  // This emulates std::move. +  std::unique_ptr<int> Move = static_cast<std::unique_ptr<int>&&>(P1); + +  // Placemenet arguments should not be removed. +  int *PInt = new int; +  std::unique_ptr<int> Placement = std::unique_ptr<int>(new (PInt) int{3}); +} + +void initialization(int T, Base b) { +  // Test different kinds of initialization of the pointee. + +  // Direct initialization with parenthesis. +  std::unique_ptr<DPair> PDir1 = std::unique_ptr<DPair>(new DPair(1, T)); +  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead +  // CHECK-FIXES: std::unique_ptr<DPair> PDir1 = std::make_unique<DPair>(1, T); + +  // Direct initialization with braces. +  std::unique_ptr<DPair> PDir2 = std::unique_ptr<DPair>(new DPair{2, T}); +  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead +  // CHECK-FIXES: std::unique_ptr<DPair> PDir2 = std::make_unique<DPair>(2, T); + +  // Aggregate initialization. +  std::unique_ptr<APair> PAggr = std::unique_ptr<APair>(new APair{T, 1}); +  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead +  // CHECK-FIXES: std::unique_ptr<APair> PAggr = std::make_unique<APair>(APair{T, 1}); + + +  // Test different kinds of initialization of the pointee, when the unique_ptr +  // is initialized with braces. + +  // Direct initialization with parenthesis. +  std::unique_ptr<DPair> PDir3 = std::unique_ptr<DPair>{new DPair(3, T)}; +  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead +  // CHECK-FIXES: std::unique_ptr<DPair> PDir3 = std::make_unique<DPair>(3, T); + +  // Direct initialization with braces. +  std::unique_ptr<DPair> PDir4 = std::unique_ptr<DPair>{new DPair{4, T}}; +  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead +  // CHECK-FIXES: std::unique_ptr<DPair> PDir4 = std::make_unique<DPair>(4, T); + +  // Aggregate initialization. +  std::unique_ptr<APair> PAggr2 = std::unique_ptr<APair>{new APair{T, 2}}; +  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead +  // CHECK-FIXES: std::unique_ptr<APair> PAggr2 = std::make_unique<APair>(APair{T, 2}); + + +  // Direct initialization with parenthesis, without arguments. +  std::unique_ptr<DPair> PDir5 = std::unique_ptr<DPair>(new DPair()); +  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead +  // CHECK-FIXES: std::unique_ptr<DPair> PDir5 = std::make_unique<DPair>(); + +  // Direct initialization with braces, without arguments. +  std::unique_ptr<DPair> PDir6 = std::unique_ptr<DPair>(new DPair{}); +  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_unique instead +  // CHECK-FIXES: std::unique_ptr<DPair> PDir6 = std::make_unique<DPair>(); + +  // Aggregate initialization without arguments. +  std::unique_ptr<Empty> PEmpty = std::unique_ptr<Empty>(new Empty{}); +  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead +  // CHECK-FIXES: std::unique_ptr<Empty> PEmpty = std::make_unique<Empty>(Empty{}); +} + +void aliases() {    typedef std::unique_ptr<int> IntPtr;    IntPtr Typedef = IntPtr(new int);    // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_unique instead @@ -110,11 +172,9 @@ void f() {    std::unique_ptr<int> Using = unique_ptr_<int>(new int);    // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead    // CHECK-FIXES: std::unique_ptr<int> Using = std::make_unique<int>(); +} -  // This emulates std::move. -  std::unique_ptr<int> Move = static_cast<std::unique_ptr<int>&&>(P1); - -  // Adding whitespaces. +void whitespaces() {    auto Space = std::unique_ptr <int>(new int());    // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead    // CHECK-FIXES: auto Space = std::make_unique<int>();  | 

