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 QualPolicy; }; } // 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,17 @@ namespace clang { namespace tidy { + +template <> struct OptionEnumMapping { + static llvm::ArrayRef> + getEnumMapping() { + static constexpr std::pair + Mapping[] = {{utils::fixit::QualifierPolicy::Left, "left"}, + {utils::fixit::QualifierPolicy::Right, "right"}}; + return makeArrayRef(Mapping); + } +}; + namespace misc { namespace { @@ -45,7 +55,9 @@ TransformValues(Options.get("TransformValues", true)), TransformReferences(Options.get("TransformReferences", true)), TransformPointersAsValues( - Options.get("TransformPointersAsValues", false)) { + Options.get("TransformPointersAsValues", false)), + QualPolicy(Options.get("QualifierAlignment", + utils::fixit::QualifierPolicy::Right)) { if (AnalyzeValues == false && AnalyzeReferences == false) this->configurationDiag( "The check 'misc-const-correctness' will not " @@ -173,7 +185,7 @@ if (VC == VariableCategory::Value && TransformValues) { Diag << addQualifierToVarDecl(*Variable, *Result.Context, DeclSpec::TQ_const, QualifierTarget::Value, - QualifierPolicy::Right); + QualPolicy); // FIXME: Add '{}' for default initialization if no user-defined default // constructor exists and there is no initializer. return; @@ -182,7 +194,7 @@ if (VC == VariableCategory::Reference && TransformReferences) { Diag << addQualifierToVarDecl(*Variable, *Result.Context, DeclSpec::TQ_const, QualifierTarget::Value, - QualifierPolicy::Right); + QualPolicy); return; } @@ -190,7 +202,7 @@ if (WarnPointersAsValues && TransformPointersAsValues) { Diag << addQualifierToVarDecl(*Variable, *Result.Context, DeclSpec::TQ_const, QualifierTarget::Value, - QualifierPolicy::Right); + QualPolicy); } 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 ``QualifierAlignment`` option to control the location of + ``const`` in the fixit-hints. + 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 @@ -25,18 +25,18 @@ .. code-block:: c++ // Normal values like built-ins or objects. - int potential_const_int = 42; // 'const int potential_const_int = 42' suggestion. + int potential_const_int = 42; // 'int const potential_const_int = 42' suggestion. int copy_of_value = potential_const_int; - MyClass could_be_const; // 'const MyClass could_be_const' suggestion; + MyClass could_be_const; // 'MyClass const could_be_const' suggestion; could_be_const.const_qualified_method(); // References can be declared const as well. - int &reference_value = potential_const_int; // 'const int &reference_value' suggestion. + int &reference_value = potential_const_int; // 'int const &reference_value' suggestion. int another_copy = reference_value; // The similar semantics of pointers are not (yet) analyzed. - int *pointer_variable = &potential_const_int; // Not 'const int *pointer_variable' suggestion. + int *pointer_variable = &potential_const_int; // Not 'int const *pointer_variable' suggestion. int last_copy = *pointer_variable; The automatic code transformation is only applied to variables that are declared in single @@ -63,7 +63,7 @@ int constant_value = 42; // Declare a pointer to that variable, that does not modify either, but misses 'const'. - // Could be 'const int *pointer_to_constant = &constant_value;' + // Could be 'int const *pointer_to_constant = &constant_value;' int *pointer_to_constant = &constant_value; // Usage: @@ -99,11 +99,11 @@ .. option:: TransformValues (default = 1) - Provides fixit-hints for value types that automatically adds ``const`` if its a single declaration. + Provides fixit-hints for value types that automatically adds ``const`` if it's a single declaration. .. code-block:: c++ - // Emits a hint for 'value' to become 'const int value = 42;'. + // Emits a hint for 'value' to become 'int const value = 42;'. int value = 42; // Result is modified later in its life-time. No diagnostic and fixit hint will be emitted. int result = value * 3; @@ -119,7 +119,7 @@ // This variable could still be a constant. But because there is a non-const reference to // it, it can not be transformed (yet). int value = 42; - // The reference 'ref_value' is not modified and can be made 'const int &ref_value = value;' + // The reference 'ref_value' is not modified and can be made 'int const &ref_value = value;' int &ref_value = value; // Result is modified later in its life-time. No diagnostic and fixit hint will be emitted. @@ -148,3 +148,28 @@ int *changing_pointee = &value; changing_pointee = &result; +.. option:: QualifierAlignment (default = right) + + Determines the position of the ``const`` in the fixit-hints: + + * ``right`` places the ``const`` at the right hand side, also known as east const. + + .. code-block:: c++ + + // Emits a hint for 'value' to become 'int const value = 42;'. + int value = 42; + + // Emits a hint for 'ref_value' to become 'int const &ref_value = value;' + int &ref_value = value; + + + * ``left`` places the ``const`` at the left hand side, also known as west const. + + .. code-block:: c++ + + // Emits a hint for 'value' to become 'const int value = 42;'. + int value = 42;a + + // Emits a hint for 'ref_value' to become 'const int &ref_value = value;' + int &ref_value = value; + diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-pointer-as-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-pointer-as-values.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-pointer-as-values.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-pointer-as-values.cpp @@ -5,6 +5,22 @@ // RUN: {key: "misc-const-correctness.TransformPointersAsValues", value: true},\ // RUN: ]}' -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy %s misc-const-correctness %t \ +// RUN: -config='{CheckOptions: \ +// RUN: [{key: "misc-const-correctness.AnalyzeValues", value: true},\ +// RUN: {key: "misc-const-correctness.WarnPointersAsValues", value: true}, \ +// RUN: {key: "misc-const-correctness.TransformPointersAsValues", value: true},\ +// RUN: {key: 'misc-const-correctness.QualifierAlignment', value: right}, \ +// RUN: ]}' -- -fno-delayed-template-parsing + +// RUN: %check_clang_tidy %s misc-const-correctness %t \ +// RUN: -config='{CheckOptions: \ +// RUN: [{key: "misc-const-correctness.AnalyzeValues", value: true},\ +// RUN: {key: "misc-const-correctness.WarnPointersAsValues", value: true}, \ +// RUN: {key: "misc-const-correctness.TransformPointersAsValues", value: true},\ +// RUN: {key: 'misc-const-correctness.QualifierAlignment', value: left}, \ +// RUN: ]}' -- -fno-delayed-template-parsing + void potential_const_pointer() { double np_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; double *p_local0 = &np_local0[1]; diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-values.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-values.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-transform-values.cpp @@ -1,10 +1,26 @@ -// RUN: %check_clang_tidy %s misc-const-correctness %t -- \ +// RUN: %check_clang_tidy -check-suffix=RIGHT %s misc-const-correctness %t -- \ // RUN: -config="{CheckOptions: [\ // RUN: {key: 'misc-const-correctness.TransformValues', value: true},\ // RUN: {key: 'misc-const-correctness.WarnPointersAsValues', value: false}, \ // RUN: {key: 'misc-const-correctness.TransformPointersAsValues', value: false}, \ // RUN: ]}" -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy -check-suffix=RIGHT %s misc-const-correctness %t -- \ +// RUN: -config="{CheckOptions: [\ +// RUN: {key: 'misc-const-correctness.TransformValues', value: true},\ +// RUN: {key: 'misc-const-correctness.WarnPointersAsValues', value: false}, \ +// RUN: {key: 'misc-const-correctness.TransformPointersAsValues', value: false}, \ +// RUN: {key: 'misc-const-correctness.QualifierAlignment', value: right}, \ +// RUN: ]}" -- -fno-delayed-template-parsing + +// RUN: %check_clang_tidy -check-suffix=LEFT %s misc-const-correctness %t -- \ +// RUN: -config="{CheckOptions: [\ +// RUN: {key: 'misc-const-correctness.TransformValues', value: true},\ +// RUN: {key: 'misc-const-correctness.WarnPointersAsValues', value: false}, \ +// RUN: {key: 'misc-const-correctness.TransformPointersAsValues', value: false}, \ +// RUN: {key: 'misc-const-correctness.QualifierAlignment', value: left}, \ +// RUN: ]}" -- -fno-delayed-template-parsing + bool global; char np_global = 0; // globals can't be known to be const @@ -23,15 +39,17 @@ void some_function(double np_arg0, wchar_t np_arg1) { int p_local0 = 2; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' - // CHECK-FIXES: int const p_local0 = 2; + // CHECK-MESSAGES-RIGHT: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' + // CHECK-FIXES-RIGHT: int const p_local0 = 2; + // CHECK-FIXES-LEFT: const int p_local0 = 2; } void nested_scopes() { { int p_local1 = 42; - // CHECK-MESSAGES: [[@LINE-1]]:5: warning: variable 'p_local1' of type 'int' can be declared 'const' - // CHECK-FIXES: int const p_local1 = 42; + // CHECK-MESSAGES-RIGHT: [[@LINE-1]]:5: warning: variable 'p_local1' of type 'int' can be declared 'const' + // CHECK-FIXES-RIGHT: int const p_local1 = 42; + // CHECK-FIXES-LEFT: const int p_local1 = 42; } } @@ -39,8 +57,9 @@ void define_locals(T np_arg0, T &np_arg1, int np_arg2) { T np_local0 = 0; int p_local1 = 42; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const' - // CHECK-FIXES: int const p_local1 = 42; + // CHECK-MESSAGES-RIGHT: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'int' can be declared 'const' + // CHECK-FIXES-RIGHT: int const p_local1 = 42; + // CHECK-FIXES-LEFT: const int p_local1 = 42; } void template_instantiation() { @@ -70,15 +89,17 @@ void direct_class_access() { ConstNonConstClass p_local0; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass' can be declared 'const' - // CHECK-FIXES: ConstNonConstClass const p_local0; + // CHECK-MESSAGES-RIGHT: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass' can be declared 'const' + // CHECK-FIXES-RIGHT: ConstNonConstClass const p_local0; + // CHECK-FIXES-LEFT: const ConstNonConstClass p_local0; p_local0.constMethod(); } void class_access_array() { ConstNonConstClass p_local0[2]; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass[2]' can be declared 'const' - // CHECK-FIXES: ConstNonConstClass const p_local0[2]; + // CHECK-MESSAGES-RIGHT: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'ConstNonConstClass[2]' can be declared 'const' + // CHECK-FIXES-RIGHT: ConstNonConstClass const p_local0[2]; + // CHECK-FIXES-LEFT: const ConstNonConstClass p_local0[2]; p_local0[0].constMethod(); } @@ -97,8 +118,9 @@ void vector_usage() { double p_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double[10]' can be declared 'const' - // CHECK-FIXES: double const p_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; + // CHECK-MESSAGES-RIGHT: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double[10]' can be declared 'const' + // CHECK-FIXES-RIGHT: double const p_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; + // CHECK-FIXES-LEFT: const double p_local0[10] = {0., 1., 2., 3., 4., 5., 6., 7., 8., 9.}; } void range_for() { @@ -117,8 +139,9 @@ void decltype_declaration() { decltype(sizeof(void *)) p_local0 = 42; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'decltype(sizeof(void *))' - // CHECK-FIXES: decltype(sizeof(void *)) const p_local0 = 42; + // CHECK-MESSAGES-RIGHT: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'decltype(sizeof(void *))' + // CHECK-FIXES-RIGHT: decltype(sizeof(void *)) const p_local0 = 42; + // CHECK-FIXES-LEFT: const decltype(sizeof(void *)) p_local0 = 42; } // Taken from libcxx/include/type_traits and improved readability. @@ -160,14 +183,16 @@ void meta_type() { TMPClass p_local0; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'TMPClass' can be declared 'const' - // CHECK-FIXES: TMPClass const p_local0; + // CHECK-MESSAGES-RIGHT: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'TMPClass' can be declared 'const' + // CHECK-FIXES-RIGHT: TMPClass const p_local0; + // CHECK-FIXES-LEFT: const TMPClass p_local0; p_local0.alwaysConst(); p_local0.sometimesConst(); TMPClass p_local1; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'TMPClass' can be declared 'const' - // CHECK-FIXES: TMPClass const p_local1; + // CHECK-MESSAGES-RIGHT: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'TMPClass' can be declared 'const' + // CHECK-FIXES-RIGHT: TMPClass const p_local1; + // CHECK-FIXES-LEFT: const TMPClass p_local1; p_local1.alwaysConst(); TMPClass p_local2; // Don't attempt to make this const diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-wrong-config.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-wrong-config.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-wrong-config.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-wrong-config.cpp @@ -2,9 +2,11 @@ // RUN: -config='{CheckOptions: \ // RUN: [{key: "misc-const-correctness.AnalyzeValues", value: false},\ // RUN: {key: "misc-const-correctness.AnalyzeReferences", value: false},\ +// RUN: {key: 'misc-const-correctness.QualifierAlignment', value: centre}, \ // RUN: ]}' -- -fno-delayed-template-parsing // CHECK-MESSAGES: warning: The check 'misc-const-correctness' will not perform any analysis because both 'AnalyzeValues' and 'AnalyzeReferences' are false. [clang-tidy-config] +// CHECK-MESSAGES: warning: invalid configuration value 'centre' for option 'misc-const-correctness.QualifierAlignment' [clang-tidy-config] void g() { int p_local0 = 42;