Index: clang-tools-extra/trunk/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp =================================================================== --- clang-tools-extra/trunk/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp +++ clang-tools-extra/trunk/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp @@ -9,6 +9,7 @@ #include "NoexceptMoveConstructorCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Tooling/FixIt.h" using namespace clang::ast_matchers; @@ -47,9 +48,20 @@ return; if (!isNoexceptExceptionSpec(ProtoType->getExceptionSpecType())) { - diag(Decl->getLocation(), "move %0s should be marked noexcept") + auto Diag = + diag(Decl->getLocation(), "move %0s should be marked noexcept") << MethodType; - // FIXME: Add a fixit. + // Add FixIt hints. + SourceManager &SM = *Result.SourceManager; + assert(Decl->getNumParams() > 0); + SourceLocation NoexceptLoc = Decl->getParamDecl(Decl->getNumParams() - 1) + ->getSourceRange() + .getEnd(); + if (NoexceptLoc.isValid()) + NoexceptLoc = Lexer::findLocationAfterToken( + NoexceptLoc, tok::r_paren, SM, Result.Context->getLangOpts(), true); + if (NoexceptLoc.isValid()) + Diag << FixItHint::CreateInsertion(NoexceptLoc, " noexcept "); return; } Index: clang-tools-extra/trunk/test/clang-tidy/performance-noexcept-move-constructor-fix.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-tidy/performance-noexcept-move-constructor-fix.cpp +++ clang-tools-extra/trunk/test/clang-tidy/performance-noexcept-move-constructor-fix.cpp @@ -0,0 +1,67 @@ +// RUN: %check_clang_tidy %s performance-noexcept-move-constructor %t + +struct C_1 { + ~C_1() {} + C_1(int a) {} + C_1(C_1&& a) :C_1(5) {} + // CHECK-FIXES: ){{.*}}noexcept{{.*}}: + C_1& operator=(C_1&&) { return *this; } + // CHECK-FIXES: ){{.*}}noexcept{{.*}} { +}; + +struct C_2 { + ~C_2() {} + C_2(C_2&& a); +// CHECK-FIXES: ){{.*}}noexcept{{.*}}; + C_2& operator=(C_2&&); +// CHECK-FIXES: ){{.*}}noexcept{{.*}}; +}; + +C_2::C_2(C_2&& a) {} +// CHECK-FIXES: ){{.*}}noexcept{{.*}} {} +C_2& C_2::operator=(C_2&&) { return *this; } +// CHECK-FIXES: ){{.*}}noexcept{{.*}} { + +struct C_3 { + ~C_3() {} + C_3(C_3&& a); +// CHECK-FIXES: ){{.*}}noexcept{{.*}}; + C_3& operator=(C_3&& a); +// CHECK-FIXES: ){{.*}}noexcept{{.*}}; +}; + +C_3::C_3(C_3&& a) = default; +// CHECK-FIXES: ){{.*}}noexcept{{.*}} = default; +C_3& C_3::operator=(C_3&& a) = default; +// CHECK-FIXES: ){{.*}}noexcept{{.*}} = default; + +template +struct C_4 { + C_4(C_4&&) {} +// CHECK-FIXES: ){{.*}}noexcept{{.*}} {} + ~C_4() {} + C_4& operator=(C_4&& a) = default; +// CHECK-FIXES: ){{.*}}noexcept{{.*}} = default; +}; + +template +struct C_5 { + C_5(C_5&&) {} +// CHECK-FIXES:){{.*}}noexcept{{.*}} {} + ~C_5() {} + auto operator=(C_5&& a)->C_5 = default; +// CHECK-FIXES:){{.*}}noexcept{{.*}} = default; +}; + +template +struct C_6 { + C_6(C_6&&) {} +// CHECK-FIXES:){{.*}}noexcept{{.*}} {} + ~C_6() {} + auto operator=(C_6&& a)->C_6; +// CHECK-FIXES:){{.*}}noexcept{{.*}}; +}; + +template +auto C_6::operator=(C_6&& a) -> C_6 {} +// CHECK-FIXES: ){{.*}}noexcept{{.*}} {} \ No newline at end of file