[clang-tidy] Don't generate incorrect fixes for class with deleted copy constructor in smart_ptr check.

Summary:
The fix for aggregate initialization (`std::make_unique<Foo>(Foo {1, 2})` needs
to see Foo copy constructor, otherwise we will have a compiler error. So we
only emit the check warning.

Reviewers: JonasToth, aaron.ballman

Subscribers: xazax.hun, cfe-commits

Differential Revision: https://reviews.llvm.org/D54745

llvm-svn: 347537
This commit is contained in:
Haojian Wu 2018-11-26 09:33:08 +00:00
parent 717412b5f9
commit dbfa9c3e0a
2 changed files with 72 additions and 0 deletions

View File

@ -387,6 +387,19 @@ bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag,
// smart_ptr<Pair>(new Pair{first, second});
// Has to be replaced with:
// smart_ptr<Pair>(Pair{first, second});
//
// The fix (std::make_unique) needs to see copy/move constructor of
// Pair. If we found any invisible or deleted copy/move constructor, we
// stop generating fixes -- as the C++ rule is complicated and we are less
// certain about the correct fixes.
if (const CXXRecordDecl *RD = New->getType()->getPointeeCXXRecordDecl()) {
if (llvm::find_if(RD->ctors(), [](const CXXConstructorDecl *Ctor) {
return Ctor->isCopyOrMoveConstructor() &&
(Ctor->isDeleted() || Ctor->getAccess() == AS_private);
}) != RD->ctor_end()) {
return false;
}
}
InitRange = SourceRange(
New->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(),
New->getInitializer()->getSourceRange().getEnd());

View File

@ -32,6 +32,38 @@ struct MyVector {
struct Empty {};
struct NoCopyMoveCtor {
NoCopyMoveCtor(const NoCopyMoveCtor &) = delete; // implies move ctor is deleted
};
struct NoCopyMoveCtorVisible {
private:
NoCopyMoveCtorVisible(const NoCopyMoveCtorVisible&) = default;
NoCopyMoveCtorVisible(NoCopyMoveCtorVisible&&) = default;
};
struct OnlyMoveCtor {
OnlyMoveCtor() = default;
OnlyMoveCtor(OnlyMoveCtor&&) = default;
OnlyMoveCtor(const OnlyMoveCtor &) = delete;
};
struct OnlyCopyCtor {
OnlyCopyCtor(const OnlyCopyCtor&) = default;
OnlyCopyCtor(OnlyCopyCtor&&) = delete;
};
struct OnlyCopyCtorVisible {
OnlyCopyCtorVisible(const OnlyCopyCtorVisible &) = default;
private:
OnlyCopyCtorVisible(OnlyCopyCtorVisible &&) = default;
};
struct ImplicitDeletedCopyCtor {
const OnlyMoveCtor ctor;
};
struct E {
E(std::initializer_list<int>);
E();
@ -274,6 +306,33 @@ void initialization(int T, Base b) {
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead
// CHECK-FIXES: std::unique_ptr<Empty> PEmpty = std::make_unique<Empty>(Empty{});
// No fixes for classes with deleted copy&move constructors.
auto PNoCopyMoveCtor = std::unique_ptr<NoCopyMoveCtor>(new NoCopyMoveCtor{});
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use std::make_unique instead
// CHECK-FIXES: auto PNoCopyMoveCtor = std::unique_ptr<NoCopyMoveCtor>(new NoCopyMoveCtor{});
auto PNoCopyMoveCtorVisible = std::unique_ptr<NoCopyMoveCtorVisible>(new NoCopyMoveCtorVisible{});
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
// CHECK-FIXES: auto PNoCopyMoveCtorVisible = std::unique_ptr<NoCopyMoveCtorVisible>(new NoCopyMoveCtorVisible{});
auto POnlyMoveCtor = std::unique_ptr<OnlyMoveCtor>(new OnlyMoveCtor{});
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
// CHECK-FIXES: auto POnlyMoveCtor = std::unique_ptr<OnlyMoveCtor>(new OnlyMoveCtor{});
// Fix for classes with classes with move constructor.
auto POnlyCopyCtor = std::unique_ptr<OnlyCopyCtor>(new OnlyCopyCtor{});
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
// CHECK-FIXES: auto POnlyCopyCtor = std::unique_ptr<OnlyCopyCtor>(new OnlyCopyCtor{});
// Fix for classes with classes with move constructor.
auto POnlyCopyCtorVisible = std::unique_ptr<OnlyCopyCtorVisible>(new OnlyCopyCtorVisible{});
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use std::make_unique instead
// CHECK-FIXES: auto POnlyCopyCtorVisible = std::unique_ptr<OnlyCopyCtorVisible>(new OnlyCopyCtorVisible{});
auto PImplicitDeletedCopyCtor = std::unique_ptr<ImplicitDeletedCopyCtor>(new ImplicitDeletedCopyCtor{});
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_unique instead
// CHECK-FIXES: auto PImplicitDeletedCopyCtor = std::unique_ptr<ImplicitDeletedCopyCtor>(new ImplicitDeletedCopyCtor{});
// Initialization with default constructor.
std::unique_ptr<E> PE1 = std::unique_ptr<E>(new E{});
// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use std::make_unique instead