Index: clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.cpp +++ clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultCheck.cpp @@ -20,37 +20,6 @@ static const char SpecialFunction[] = "SpecialFunction"; -/// \brief Finds the SourceLocation of the colon ':' before the initialization -/// list in the definition of a constructor. -static SourceLocation getColonLoc(const ASTContext *Context, - const CXXConstructorDecl *Ctor) { - // FIXME: First init is the first initialization that is going to be - // performed, no matter what was the real order in the source code. If the - // order of the inits is wrong in the code, it may result in a false negative. - SourceLocation FirstInit = (*Ctor->init_begin())->getSourceLocation(); - SourceLocation LastArg = - Ctor->getParamDecl(Ctor->getNumParams() - 1)->getLocEnd(); - // We need to find the colon between the ')' and the first initializer. - bool Invalid = false; - StringRef Text = Lexer::getSourceText( - CharSourceRange::getCharRange(LastArg, FirstInit), - Context->getSourceManager(), Context->getLangOpts(), &Invalid); - if (Invalid) - return SourceLocation(); - - size_t ColonPos = Text.rfind(':'); - if (ColonPos == StringRef::npos) - return SourceLocation(); - - Text = Text.drop_front(ColonPos + 1); - if (std::strspn(Text.data(), " \t\r\n") != Text.size()) { - // If there are comments, preprocessor directives or anything, abort. - return SourceLocation(); - } - // FIXME: don't remove comments in the middle of the initializers. - return LastArg.getLocWithOffset(ColonPos); -} - /// \brief Finds all the named non-static fields of \p Record. static std::set getAllNamedFields(const CXXRecordDecl *Record) { @@ -262,7 +231,6 @@ void UseDefaultCheck::check(const MatchFinder::MatchResult &Result) { std::string SpecialFunctionName; - SourceLocation StartLoc, EndLoc; // Both CXXConstructorDecl and CXXDestructorDecl inherit from CXXMethodDecl. const auto *SpecialFunctionDecl = @@ -280,15 +248,13 @@ if (!Body) return; - // Default locations. - StartLoc = Body->getLBracLoc(); - EndLoc = Body->getRBracLoc(); - // If there are comments inside the body, don't do the change. if (!SpecialFunctionDecl->isCopyAssignmentOperator() && !bodyEmpty(Result.Context, Body)) return; + std::vector RemoveInitializers; + if (const auto *Ctor = dyn_cast(SpecialFunctionDecl)) { if (Ctor->getNumParams() == 0) { SpecialFunctionName = "default constructor"; @@ -297,10 +263,9 @@ return; SpecialFunctionName = "copy constructor"; // If there are constructor initializers, they must be removed. - if (Ctor->getNumCtorInitializers() != 0) { - StartLoc = getColonLoc(Result.Context, Ctor); - if (!StartLoc.isValid()) - return; + for (const CXXCtorInitializer *Init : Ctor->inits()) { + RemoveInitializers.emplace_back( + FixItHint::CreateRemoval(Init->getSourceRange())); } } } else if (isa(SpecialFunctionDecl)) { @@ -313,8 +278,8 @@ diag(SpecialFunctionDecl->getLocStart(), "use '= default' to define a trivial " + SpecialFunctionName) - << FixItHint::CreateReplacement( - CharSourceRange::getTokenRange(StartLoc, EndLoc), "= default;"); + << FixItHint::CreateReplacement(Body->getSourceRange(), "= default;") + << RemoveInitializers; } } // namespace modernize Index: clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-copy.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-copy.cpp +++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-copy.cpp @@ -8,7 +8,7 @@ }; OL::OL(const OL &Other) : Field(Other.Field) {} // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy constructor [modernize-use-default] -// CHECK-FIXES: OL::OL(const OL &Other) = default; +// CHECK-FIXES: OL::OL(const OL &Other) = default; OL &OL::operator=(const OL &Other) { Field = Other.Field; return *this; @@ -20,7 +20,7 @@ struct IL { IL(const IL &Other) : Field(Other.Field) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' - // CHECK-FIXES: IL(const IL &Other) = default; + // CHECK-FIXES: IL(const IL &Other) = default; IL &operator=(const IL &Other) { Field = Other.Field; return *this; @@ -43,7 +43,8 @@ Mutable(Other.Mutable), Reference(Other.Reference), Const(Other.Const) {} // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default' - // CHECK-FIXES: Qual(const Qual &Other) = default; + // CHECK-FIXES: Qual(const Qual &Other) + // CHECK-FIXES: = default; int Field; volatile char Volatile; @@ -80,6 +81,8 @@ struct Comments { Comments(const Comments &Other) /* don't delete */ : /* this comment */ Field(Other.Field) {} + // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default' + // CHECK-FIXES: /* don't delete */ = default; int Field; }; @@ -95,7 +98,7 @@ struct ColonInComment { ColonInComment(const ColonInComment &Other) /* : */ : Field(Other.Field) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' - // CHECK-FIXES: ColonInComment(const ColonInComment &Other) /* : */ = default; + // CHECK-FIXES: ColonInComment(const ColonInComment &Other) /* : */ = default; int Field; }; @@ -116,7 +119,8 @@ BF(const BF &Other) : Field1(Other.Field1), Field2(Other.Field2), Field3(Other.Field3), Field4(Other.Field4) {} // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default' - // CHECK-FIXES: BF(const BF &Other) = default; + // CHECK-FIXES: BF(const BF &Other) {{$}} + // CHECK-FIXES: = default; BF &operator=(const BF &); unsigned Field1 : 3; @@ -140,7 +144,7 @@ struct BC : IL, OL, BF { BC(const BC &Other) : IL(Other), OL(Other), BF(Other) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' - // CHECK-FIXES: BC(const BC &Other) = default; + // CHECK-FIXES: BC(const BC &Other) = default; BC &operator=(const BC &Other); }; BC &BC::operator=(const BC &Other) { @@ -156,7 +160,7 @@ struct BCWM : IL, OL { BCWM(const BCWM &Other) : IL(Other), OL(Other), Bf(Other.Bf) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' - // CHECK-FIXES: BCWM(const BCWM &Other) = default; + // CHECK-FIXES: BCWM(const BCWM &Other) = default; BCWM &operator=(const BCWM &); BF Bf; }; @@ -200,7 +204,7 @@ // is a virtual OL at the beginning of VA (which is the same). VBC(const VBC &Other) : OL(Other), VA(Other), VB(Other) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' - // CHECK-FIXES: VBC(const VBC &Other) = default; + // CHECK-FIXES: VBC(const VBC &Other) = default; VBC &operator=(const VBC &Other); }; VBC &VBC::operator=(const VBC &Other) { @@ -335,7 +339,7 @@ struct NCRef { NCRef(NCRef &Other) : Field1(Other.Field1), Field2(Other.Field2) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' - // CHECK-FIXES: NCRef(NCRef &Other) = default; + // CHECK-FIXES: NCRef(NCRef &Other) = default; NCRef &operator=(NCRef &); int Field1, Field2; };