Index: clang-tidy/misc/StringConstructorCheck.cpp =================================================================== --- clang-tidy/misc/StringConstructorCheck.cpp +++ clang-tidy/misc/StringConstructorCheck.cpp @@ -10,6 +10,7 @@ #include "StringConstructorCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Tooling/FixIt.h" using namespace clang::ast_matchers; @@ -54,7 +55,7 @@ isDefinition(), hasType(pointerType(pointee(isAnyCharacter(), isConstQualified()))), hasInitializer(ignoringParenImpCasts(BoundStringLiteral))); - auto ConstStrLiteral = expr(ignoringParenImpCasts(anyOf( + const auto ConstStrLiteral = expr(ignoringParenImpCasts(anyOf( BoundStringLiteral, declRefExpr(hasDeclaration(anyOf( ConstPtrStrLiteralDecl, ConstStrLiteralDecl)))))); @@ -88,7 +89,7 @@ // Detect the expression: string("...", 0); hasArgument(1, ZeroExpr.bind("empty-string")), // Detect the expression: string("...", -4); - hasArgument(1, NegativeExpr.bind("negative-length")), + hasArgument(1, NegativeExpr.bind("negative-length")), // Detect the expression: string("lit", 0x1234567); hasArgument(1, LargeLengthExpr.bind("large-length")), // Detect the expression: string("lit", 5) @@ -100,11 +101,18 @@ } void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) { - const auto *E = Result.Nodes.getNodeAs("constructor"); + const ASTContext &Ctx = *Result.Context; + const auto *E = Result.Nodes.getNodeAs("constructor"); + assert(E && "missing constructor expression"); SourceLocation Loc = E->getLocStart(); if (Result.Nodes.getNodeAs("swapped-parameter")) { - diag(Loc, "constructor parameters are probably swapped"); + const Expr* P0 = E->getArg(0); + const Expr* P1 = E->getArg(1); + diag(Loc, "string constructor parameters are probably swapped;" + " expecting string(count, character)") + << tooling::fixit::createReplacement(*P0, *P1, Ctx) + << tooling::fixit::createReplacement(*P1, *P0, Ctx); } else if (Result.Nodes.getNodeAs("empty-string")) { diag(Loc, "constructor creating an empty string"); } else if (Result.Nodes.getNodeAs("negative-length")) { Index: test/clang-tidy/misc-string-constructor.cpp =================================================================== --- test/clang-tidy/misc-string-constructor.cpp +++ test/clang-tidy/misc-string-constructor.cpp @@ -21,9 +21,11 @@ void Test() { std::string str('x', 4); - // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor parameters are probably swapped [misc-string-constructor] + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: string constructor parameters are probably swapped; expecting string(count, character) [misc-string-constructor] + // CHECK-FIXES: std::string str(4, 'x'); std::wstring wstr(L'x', 4); - // CHECK-MESSAGES: [[@LINE-1]]:16: warning: constructor parameters are probably swapped + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: string constructor parameters are probably swapped + // CHECK-FIXES: std::wstring wstr(4, L'x'); std::string s0(0, 'x'); // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructor creating an empty string std::string s1(-4, 'x');