Index: clang-tidy/bugprone/BugproneTidyModule.cpp =================================================================== --- clang-tidy/bugprone/BugproneTidyModule.cpp +++ clang-tidy/bugprone/BugproneTidyModule.cpp @@ -24,6 +24,7 @@ #include "LambdaFunctionNameCheck.h" #include "MacroParenthesesCheck.h" #include "MacroRepeatedSideEffectsCheck.h" +#include "MapSubscriptOperatorLookupCheck.h" #include "MisplacedOperatorInStrlenInAllocCheck.h" #include "MisplacedWideningCastCheck.h" #include "MoveForwardingReferenceCheck.h" @@ -83,6 +84,8 @@ "bugprone-macro-parentheses"); CheckFactories.registerCheck( "bugprone-macro-repeated-side-effects"); + CheckFactories.registerCheck( + "bugprone-map-subscript-operator-lookup"); CheckFactories.registerCheck( "bugprone-misplaced-operator-in-strlen-in-alloc"); CheckFactories.registerCheck( Index: clang-tidy/bugprone/CMakeLists.txt =================================================================== --- clang-tidy/bugprone/CMakeLists.txt +++ clang-tidy/bugprone/CMakeLists.txt @@ -16,6 +16,7 @@ LambdaFunctionNameCheck.cpp MacroParenthesesCheck.cpp MacroRepeatedSideEffectsCheck.cpp + MapSubscriptOperatorLookupCheck.cpp MisplacedOperatorInStrlenInAllocCheck.cpp MisplacedWideningCastCheck.cpp MoveForwardingReferenceCheck.cpp Index: clang-tidy/bugprone/MapSubscriptOperatorLookupCheck.h =================================================================== --- /dev/null +++ clang-tidy/bugprone/MapSubscriptOperatorLookupCheck.h @@ -0,0 +1,35 @@ +//===--- MapSubscriptOperatorLookupCheck.h - clang-tidy----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MAPSUBSCRIPTOPERATORLOOKUPCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MAPSUBSCRIPTOPERATORLOOKUPCHECK_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace bugprone { + +/// FIXME: Write a short description. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-map-subscript-operator-lookup.html +class MapSubscriptOperatorLookupCheck : public ClangTidyCheck { +public: + MapSubscriptOperatorLookupCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace bugprone +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MAPSUBSCRIPTOPERATORLOOKUPCHECK_H Index: clang-tidy/bugprone/MapSubscriptOperatorLookupCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/bugprone/MapSubscriptOperatorLookupCheck.cpp @@ -0,0 +1,45 @@ +//===--- MapSubscriptOperatorLookupCheck.cpp - clang-tidy------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MapSubscriptOperatorLookupCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace bugprone { + +void MapSubscriptOperatorLookupCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + cxxOperatorCallExpr( + callee(cxxMethodDecl( + hasName("operator[]"), + ofClass(hasAnyName("::std::map", "::std::unordered_map")))), + hasParent(implicitCastExpr( + anyOf(hasImplicitDestinationType(isConstQualified()), + hasCastKind(CK_LValueToRValue))))) + .bind("match"), + this); +} + +void MapSubscriptOperatorLookupCheck::check( + const MatchFinder::MatchResult &Result) { + if (const auto *Matched = Result.Nodes.getNodeAs("match")) { + diag(Matched->getLocStart(), "do not use operator[] for map lookup") + << Matched->getSourceRange(); + diag(Matched->getLocStart(), "consider using find() instead", + DiagnosticIDs::Note); + } +} + +} // namespace bugprone +} // namespace tidy +} // namespace clang Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -57,6 +57,11 @@ Improvements to clang-tidy -------------------------- +- New :doc:`bugprone-map-subscript-operator-lookup + ` check + + FIXME: add release notes. + - New module `abseil` for checks related to the `Abseil `_ library. Index: docs/clang-tidy/checks/bugprone-map-subscript-operator-lookup.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/bugprone-map-subscript-operator-lookup.rst @@ -0,0 +1,6 @@ +.. title:: clang-tidy - bugprone-map-subscript-operator-lookup + +bugprone-map-subscript-operator-lookup +====================================== + +FIXME: Describe what patterns does the check detect and why. Give examples. Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -33,6 +33,7 @@ bugprone-lambda-function-name bugprone-macro-parentheses bugprone-macro-repeated-side-effects + bugprone-map-subscript-operator-lookup bugprone-misplaced-operator-in-strlen-in-alloc bugprone-misplaced-widening-cast bugprone-move-forwarding-reference @@ -91,8 +92,8 @@ cppcoreguidelines-pro-type-vararg cppcoreguidelines-slicing cppcoreguidelines-special-member-functions - fuchsia-header-anon-namespaces (redirects to google-build-namespaces) fuchsia-default-arguments + fuchsia-header-anon-namespaces (redirects to google-build-namespaces) fuchsia-multiple-inheritance fuchsia-overloaded-operator fuchsia-statically-constructed-objects Index: test/clang-tidy/bugprone-map-subscript-operator-lookup.cpp =================================================================== --- /dev/null +++ test/clang-tidy/bugprone-map-subscript-operator-lookup.cpp @@ -0,0 +1,67 @@ +// RUN: %check_clang_tidy %s bugprone-map-subscript-operator-lookup %t + +namespace std { + +template +struct allocator {}; + +template +struct equal_to {}; + +template +struct hash {}; + +template +struct less {}; + +template +struct pair {}; + +template , + typename Allocator = std::allocator>> +struct map { + T &operator[](const Key &); + T &operator[](Key &&); +}; + +// the check should be able to match std lib calls even if the functions are +// declared inside inline namespaces +inline namespace v1 { + +template , + typename KeyEqual = std::equal_to, + typename Allocator = std::allocator>> +struct unordered_map { + T &operator[](const Key &); + T &operator[](Key &&); +}; + +} // namespace v1 +} // namespace std + +struct Foo { + int getter() const; + void setter(int); +}; + +void warning() { + std::map Map; + auto Foo1 = Map[42]; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: do not use operator[] for map lookup [bugprone-map-subscript-operator-lookup] + + std::unordered_map UMap; + auto Foo2 = UMap[42]; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: do not use operator[] for map lookup [bugprone-map-subscript-operator-lookup] +} + +void noWarning() { + std::map MapOk; + MapOk[42] = Foo{}; + + std::unordered_map UMapOk; + UMapOk[42] = Foo{}; +}