Index: clang-tidy/google/NonConstReferences.h =================================================================== --- clang-tidy/google/NonConstReferences.h +++ clang-tidy/google/NonConstReferences.h @@ -22,10 +22,13 @@ /// https://google.github.io/styleguide/cppguide.html#Reference_Arguments class NonConstReferences : public ClangTidyCheck { public: - NonConstReferences(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + NonConstReferences(StringRef Name, ClangTidyContext *Context); void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + +private: + const std::vector WhiteListTypes; }; } // namespace runtime Index: clang-tidy/google/NonConstReferences.cpp =================================================================== --- clang-tidy/google/NonConstReferences.cpp +++ clang-tidy/google/NonConstReferences.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "NonConstReferences.h" +#include "../utils/OptionsUtils.h" #include "clang/AST/DeclBase.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -19,7 +20,21 @@ namespace google { namespace runtime { +NonConstReferences::NonConstReferences(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + WhiteListTypes( + utils::options::parseStringList(Options.get("WhiteListTypes", ""))) {} + +void NonConstReferences::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "WhiteListTypes", + utils::options::serializeStringList(WhiteListTypes)); +} + void NonConstReferences::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + Finder->addMatcher( parmVarDecl( unless(isInstantiated()), @@ -52,6 +67,15 @@ } auto ReferencedType = *Result.Nodes.getNodeAs("referenced_type"); + + if (std::find_if(WhiteListTypes.begin(), WhiteListTypes.end(), + [&](llvm::StringRef WhiteListType) { + return ReferencedType.getCanonicalType().getAsString( + Result.Context->getPrintingPolicy()) == + WhiteListType; + }) != WhiteListTypes.end()) + return; + // Don't warn on function references, they shouldn't be constant. if (ReferencedType->isFunctionProtoType()) return; Index: docs/clang-tidy/checks/google-runtime-references.rst =================================================================== --- docs/clang-tidy/checks/google-runtime-references.rst +++ docs/clang-tidy/checks/google-runtime-references.rst @@ -7,3 +7,11 @@ The corresponding style guide rule: https://google.github.io/styleguide/cppguide.html#Reference_Arguments + + +Options +------- + +.. option:: WhiteListTypes + + A semicolon-separated list of names of whitelist types. Defualt is empty. Index: test/clang-tidy/google-runtime-references.cpp =================================================================== --- test/clang-tidy/google-runtime-references.cpp +++ test/clang-tidy/google-runtime-references.cpp @@ -1,4 +1,8 @@ -// RUN: %check_clang_tidy %s google-runtime-references %t +// RUN: %check_clang_tidy %s google-runtime-references %t -- \ +// RUN: -extra-arg="-std=c++11" \ +// RUN: -config="{CheckOptions: \ +// RUN: [{key: google-runtime-references.WhiteListTypes, \ +// RUN: value: 'whitelist::A; whitelist::B'}]}" -- int a; int &b = a; @@ -137,3 +141,12 @@ A& operator|=(A& a, const A& b) { return a; } A& operator^=(A& a, const A& b) { return a; } A& operator&=(A& a, const A& b) { return a; } + +namespace whitelist { +class A {}; +class B {}; +void f7(A &); +void f8(B &); +} +void f9(whitelist::A &); +void f10(whitelist::B &);