diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.h b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.h --- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.h +++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.h @@ -10,6 +10,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_CONSTCORRECTNESSCHECK_H #include "../ClangTidyCheck.h" +#include "../utils/FixItHintUtils.h" #include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" #include "llvm/ADT/DenseSet.h" @@ -48,6 +49,8 @@ const bool TransformValues; const bool TransformReferences; const bool TransformPointersAsValues; + + const utils::fixit::QualifierPolicy ConstAlignment; }; } // namespace misc diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp --- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "ConstCorrectnessCheck.h" -#include "../utils/FixItHintUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -18,6 +17,22 @@ namespace clang { namespace tidy { + +template <> struct OptionEnumMapping { + static ArrayRef> + getEnumMapping() { + static constexpr std::pair + Mapping[] = { + {utils::fixit::QualifierPolicy::Left, "left"}, + {utils::fixit::QualifierPolicy::Right, "right"}, + // Let people use east/west spelling. + {utils::fixit::QualifierPolicy::Left, "west"}, + {utils::fixit::QualifierPolicy::Right, "east"}, + }; + return Mapping; + } +}; + namespace misc { namespace { @@ -45,7 +60,9 @@ TransformValues(Options.get("TransformValues", true)), TransformReferences(Options.get("TransformReferences", true)), TransformPointersAsValues( - Options.get("TransformPointersAsValues", false)) { + Options.get("TransformPointersAsValues", false)), + ConstAlignment( + Options.get("ConstAlignment", utils::fixit::QualifierPolicy::Right)) { if (AnalyzeValues == false && AnalyzeReferences == false) this->configurationDiag( "The check 'misc-const-correctness' will not " @@ -61,6 +78,8 @@ Options.store(Opts, "TransformValues", TransformValues); Options.store(Opts, "TransformReferences", TransformReferences); Options.store(Opts, "TransformPointersAsValues", TransformPointersAsValues); + + Options.store(Opts, "ConstAlignment", ConstAlignment); } void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) { @@ -173,7 +192,7 @@ if (VC == VariableCategory::Value && TransformValues) { Diag << addQualifierToVarDecl(*Variable, *Result.Context, DeclSpec::TQ_const, QualifierTarget::Value, - QualifierPolicy::Right); + ConstAlignment); // FIXME: Add '{}' for default initialization if no user-defined default // constructor exists and there is no initializer. return; @@ -182,7 +201,7 @@ if (VC == VariableCategory::Reference && TransformReferences) { Diag << addQualifierToVarDecl(*Variable, *Result.Context, DeclSpec::TQ_const, QualifierTarget::Value, - QualifierPolicy::Right); + ConstAlignment); return; } @@ -190,7 +209,7 @@ if (WarnPointersAsValues && TransformPointersAsValues) { Diag << addQualifierToVarDecl(*Variable, *Result.Context, DeclSpec::TQ_const, QualifierTarget::Value, - QualifierPolicy::Right); + ConstAlignment); } return; } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -121,6 +121,10 @@ support for C++14 signal handler rules was added. Bug report generation was improved. +- :doc:`misc-const-correctness ` + check now supports a ``ConstAlignment`` option to control the location of the + ``const`` keyword when emitting fixes. + Removed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst --- a/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst @@ -148,3 +148,25 @@ int *changing_pointee = &value; changing_pointee = &result; +.. option:: ConstAlignment + + Controls where to insert ``const`` when creating fix-it hints, defaults to ``right``. + + - ``left``: + + .. code-block:: c++ + + const int I = 0; + const int &IRef = I; + int *const IPtr = &I; + + + - ``right``: + + .. code-block:: c++ + + int const I = 0; + int const &IRef = I; + int *const IPtr = &I; + + ``east`` and ``west`` aliases are also supported. diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-alignment.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-alignment.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-alignment.cpp @@ -0,0 +1,46 @@ +// RUN: %check_clang_tidy %s misc-const-correctness %t -check-suffixes=",WEST" \ +// RUN: -config="{CheckOptions: { \ +// RUN: misc-const-correctness.ConstAlignment: west, \ +// RUN: misc-const-correctness.WarnPointersAsValues: true, \ +// RUN: misc-const-correctness.TransformPointersAsValues: true \ +// RUN: }}" +// RUN: %check_clang_tidy %s misc-const-correctness %t -check-suffixes=",WEST" \ +// RUN: -config="{CheckOptions: { \ +// RUN: misc-const-correctness.ConstAlignment: left, \ +// RUN: misc-const-correctness.WarnPointersAsValues: true, \ +// RUN: misc-const-correctness.TransformPointersAsValues: true \ +// RUN: }}" +// RUN: %check_clang_tidy %s misc-const-correctness %t -check-suffixes=",EAST" \ +// RUN: -config="{CheckOptions: { \ +// RUN: misc-const-correctness.ConstAlignment: east, \ +// RUN: misc-const-correctness.WarnPointersAsValues: true, \ +// RUN: misc-const-correctness.TransformPointersAsValues: true \ +// RUN: }}" +// RUN: %check_clang_tidy %s misc-const-correctness %t -check-suffixes=",EAST" \ +// RUN: -config="{CheckOptions: { \ +// RUN: misc-const-correctness.ConstAlignment: right, \ +// RUN: misc-const-correctness.WarnPointersAsValues: true, \ +// RUN: misc-const-correctness.TransformPointersAsValues: true \ +// RUN: }}" + +void foo() { + int I = 0; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'I' of type 'int' can be declared 'const' + // CHECK-FIXES-WEST: const int I = 0; + // CHECK-FIXES-EAST: int const I = 0; +} + +void foo(int I) { + int & IRef = I; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'IRef' of type 'int &' can be declared 'const' + // CHECK-FIXES-WEST: const int & IRef = I; + // Having the double space and the const attached the the `&` is unfortunate, + // however it shouldn't matter for users as fixes get clang-formatted. + // CHECK-FIXES-EAST: int const& IRef = I; + + // When decorating a pointer with const, the const always goes to the right + // of the `*`. + int *IPtr = &I; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'IPtr' of type 'int *' can be declared 'const' + // CHECK-FIXES: int *const IPtr = &I; +}