diff --git a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.h b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.h --- a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.h +++ b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.h @@ -37,6 +37,9 @@ llvm::Optional getCheckTraversalKind() const override { return TK_IgnoreUnlessSpelledInSource; } + +private: + const std::vector IgnoredContainers; }; } // namespace readability } // namespace tidy diff --git a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp @@ -8,6 +8,7 @@ #include "ContainerDataPointerCheck.h" +#include "../utils/OptionsUtils.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/StringRef.h" @@ -22,14 +23,18 @@ constexpr llvm::StringLiteral AddrOfContainerExprName = "addr-of-container-expr"; constexpr llvm::StringLiteral AddressOfName = "address-of"; +const auto DefaultIgnoredContainers = "::std::array"; ContainerDataPointerCheck::ContainerDataPointerCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + : ClangTidyCheck(Name, Context), + IgnoredContainers(utils::options::parseStringList( + Options.get("IgnoredContainers", DefaultIgnoredContainers))) {} void ContainerDataPointerCheck::registerMatchers(MatchFinder *Finder) { const auto Record = cxxRecordDecl( + unless(hasAnyName(IgnoredContainers)), isSameOrDerivedFrom( namedDecl( has(cxxMethodDecl(isPublic(), hasName("data")).bind("data"))) 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 @@ -141,6 +141,10 @@ The check now skips unions since in this case a default constructor with empty body is not equivalent to the explicitly defaulted one. +- Improved `readability-container-data-pointer ` check. + + The check now skips containers that are defined in the option `IgnoredContainers`. The default value is `::std::array`. + Removed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp @@ -1,4 +1,6 @@ -// RUN: %check_clang_tidy %s readability-container-data-pointer %t -- -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy -check-suffix=CLASSIC %s readability-container-data-pointer %t -- -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy -check-suffix=WITH-CONFIG %s readability-container-data-pointer %t -- -config="{CheckOptions: [{key: readability-container-data-pointer.IgnoredContainers, value: '::std::basic_string'}]}" -- -fno-delayed-template-parsing + typedef __SIZE_TYPE__ size_t; @@ -58,20 +60,24 @@ void g(size_t s) { std::vector b(s); f(&((b)[(z)])); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}f(b.data());{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}f(b.data());{{$}} + // CHECK-MESSAGES-WITH-CONFIG: :[[@LINE-3]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-WITH-CONFIG: {{^ }}f(b.data());{{$}} } void h() { std::string s; f(&((s).operator[]((z)))); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}f(s.data());{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}f(s.data());{{$}} + // CHECK-MESSAGES-WITH-CONFIG-NOT: :[[@LINE-3]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] std::wstring w; f(&((&(w))->operator[]((z)))); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}f(w.data());{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}f(w.data());{{$}} + // CHECK-MESSAGES-WITH-CONFIG-NOT: :[[@LINE-3]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] } template b(s); f(&b[0]); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}f(b.data());{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}f(b.data());{{$}} + // CHECK-MESSAGES-WITH-CONFIG: :[[@LINE-3]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-WITH-CONFIG: {{^ }}f(b.data());{{$}} } template void i(size_t); void j(std::vector * const v) { f(&(*v)[0]); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}f(v->data());{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}f(v->data());{{$}} + // CHECK-MESSAGES-WITH-CONFIG: :[[@LINE-3]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-WITH-CONFIG: {{^ }}f(v->data());{{$}} } void k(const std::vector &v) { f(&v[0]); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}f(v.data());{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}f(v.data());{{$}} + // CHECK-MESSAGES-WITH-CONFIG: :[[@LINE-3]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-WITH-CONFIG: {{^ }}f(v.data());{{$}} } void l() { unsigned char b[32]; f(&b[0]); - // CHECK-MESSAGES-NOT: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-MESSAGES-CLASSIC-NOT: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-MESSAGES-WITH-CONFIG-NOT: :[[@LINE-2]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] } template void m(const std::vector &v) { return &v[0]; - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}return v.data();{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}return v.data();{{$}} + // CHECK-MESSAGES-WITH-CONFIG: :[[@LINE-3]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-WITH-CONFIG: {{^ }}return v.data();{{$}} } template @@ -125,8 +140,10 @@ const int *o(const std::vector>> &v, const size_t idx1, const size_t idx2) { return &v[idx1][idx2][0]; - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}return v[idx1][idx2].data();{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}return v[idx1][idx2].data();{{$}} + // CHECK-MESSAGES-WITH-CONFIG: :[[@LINE-3]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-WITH-CONFIG: {{^ }}return v[idx1][idx2].data();{{$}} } std::vector &select(std::vector &u, std::vector &v) { @@ -135,14 +152,18 @@ int *p(std::vector &v1, std::vector &v2) { return &select(*&v1, v2)[0]; - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}return select(*&v1, v2).data();{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}return select(*&v1, v2).data();{{$}} + // CHECK-MESSAGES-WITH-CONFIG: :[[@LINE-3]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-WITH-CONFIG: {{^ }}return select(*&v1, v2).data();{{$}} } int *q(std::vector ***v) { return &(***v)[0]; - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}return (**v)->data();{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}return (**v)->data();{{$}} + // CHECK-MESSAGES-WITH-CONFIG: :[[@LINE-3]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-WITH-CONFIG: {{^ }}return (**v)->data();{{$}} } struct VectorHolder { @@ -152,6 +173,8 @@ int *r() { VectorHolder holder; return &holder.v[0]; - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] - // CHECK-FIXES: {{^ }}return holder.v.data();{{$}} + // CHECK-MESSAGES-CLASSIC: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-CLASSIC: {{^ }}return holder.v.data();{{$}} + // CHECK-MESSAGES-WITH-CONFIG: :[[@LINE-3]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES-WITH-CONFIG: {{^ }}return holder.v.data();{{$}} }