Index: clang-tidy/misc/BracesAroundStatementsCheck.h =================================================================== --- clang-tidy/misc/BracesAroundStatementsCheck.h +++ clang-tidy/misc/BracesAroundStatementsCheck.h @@ -1,59 +0,0 @@ -//===--- BracesAroundStatementsCheck.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_MISC_BRACES_AROUND_STATEMENTS_CHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BRACES_AROUND_STATEMENTS_CHECK_H - -#include "../ClangTidy.h" - -namespace clang { -namespace tidy { - -/// \brief Checks that bodies of 'if' statements and loops ('for', 'range-for', -/// 'do-while', and 'while') are inside braces -/// -/// Before: -/// if (condition) -/// statement; -/// -/// After: -/// if (condition) { -/// statement; -/// } -/// -/// Additionally, one can define an option `ShortStatementLines` defining the -/// minimal number of lines that the statement should have in order to trigger -/// this check. -/// The number of lines is counted from the end of condition or initial keyword -/// (do/else) until the last line of the inner statement. -/// Default value 0 means that braces will be added to all statements (not -/// having them already). -class BracesAroundStatementsCheck : public ClangTidyCheck { -public: - BracesAroundStatementsCheck(StringRef Name, ClangTidyContext *Context); - void storeOptions(ClangTidyOptions::OptionMap &Opts) override; - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; - -private: - void checkStmt(const ast_matchers::MatchFinder::MatchResult &Result, - const Stmt *S, SourceLocation StartLoc, - SourceLocation EndLocHint = SourceLocation()); - template - SourceLocation findRParenLoc(const IfOrWhileStmt *S, const SourceManager &SM, - const ASTContext *Context); - -private: - const unsigned ShortStatementLines; -}; - -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BRACES_AROUND_STATEMENTS_CHECK_H Index: clang-tidy/misc/BracesAroundStatementsCheck.cpp =================================================================== --- clang-tidy/misc/BracesAroundStatementsCheck.cpp +++ clang-tidy/misc/BracesAroundStatementsCheck.cpp @@ -1,255 +0,0 @@ -//===--- BracesAroundStatementsCheck.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 "BracesAroundStatementsCheck.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchers.h" -#include "clang/Lex/Lexer.h" - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { -namespace { - -tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM, - const ASTContext *Context) { - Token Tok; - SourceLocation Beginning = - Lexer::GetBeginningOfToken(Loc, SM, Context->getLangOpts()); - const bool Invalid = - Lexer::getRawToken(Beginning, Tok, SM, Context->getLangOpts()); - assert(!Invalid && "Expected a valid token."); - - if (Invalid) - return tok::NUM_TOKENS; - - return Tok.getKind(); -} - -SourceLocation forwardSkipWhitespaceAndComments(SourceLocation Loc, - const SourceManager &SM, - const ASTContext *Context) { - assert(Loc.isValid()); - for (;;) { - while (isWhitespace(*FullSourceLoc(Loc, SM).getCharacterData())) - Loc = Loc.getLocWithOffset(1); - - tok::TokenKind TokKind = getTokenKind(Loc, SM, Context); - if (TokKind == tok::NUM_TOKENS || TokKind != tok::comment) - return Loc; - - // Fast-forward current token. - Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts()); - } -} - -SourceLocation findEndLocation(SourceLocation LastTokenLoc, - const SourceManager &SM, - const ASTContext *Context) { - SourceLocation Loc = LastTokenLoc; - // Loc points to the beginning of the last (non-comment non-ws) token - // before end or ';'. - assert(Loc.isValid()); - bool SkipEndWhitespaceAndComments = true; - tok::TokenKind TokKind = getTokenKind(Loc, SM, Context); - if (TokKind == tok::NUM_TOKENS || TokKind == tok::semi || - TokKind == tok::r_brace) { - // If we are at ";" or "}", we found the last token. We could use as well - // `if (isa(S))`, but it wouldn't work for nested statements. - SkipEndWhitespaceAndComments = false; - } - - Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts()); - // Loc points past the last token before end or after ';'. - - if (SkipEndWhitespaceAndComments) { - Loc = forwardSkipWhitespaceAndComments(Loc, SM, Context); - tok::TokenKind TokKind = getTokenKind(Loc, SM, Context); - if (TokKind == tok::semi) - Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts()); - } - - for (;;) { - assert(Loc.isValid()); - while (isHorizontalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData())) - Loc = Loc.getLocWithOffset(1); - - if (isVerticalWhitespace(*FullSourceLoc(Loc, SM).getCharacterData())) { - // EOL, insert brace before. - break; - } - tok::TokenKind TokKind = getTokenKind(Loc, SM, Context); - if (TokKind != tok::comment) { - // Non-comment token, insert brace before. - break; - } - - SourceLocation TokEndLoc = - Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts()); - SourceRange TokRange(Loc, TokEndLoc); - StringRef Comment = Lexer::getSourceText( - CharSourceRange::getTokenRange(TokRange), SM, Context->getLangOpts()); - if (Comment.startswith("/*") && Comment.find('\n') != StringRef::npos) { - // Multi-line block comment, insert brace before. - break; - } - // else: Trailing comment, insert brace after the newline. - - // Fast-forward current token. - Loc = TokEndLoc; - } - return Loc; -} - -} // namespace - -BracesAroundStatementsCheck::BracesAroundStatementsCheck( - StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), - // Always add braces by default. - ShortStatementLines(Options.get("ShortStatementLines", 0U)) {} - -void -BracesAroundStatementsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "ShortStatementLines", ShortStatementLines); -} - -void BracesAroundStatementsCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(ifStmt().bind("if"), this); - Finder->addMatcher(whileStmt().bind("while"), this); - Finder->addMatcher(doStmt().bind("do"), this); - Finder->addMatcher(forStmt().bind("for"), this); - Finder->addMatcher(forRangeStmt().bind("for-range"), this); -} - -void -BracesAroundStatementsCheck::check(const MatchFinder::MatchResult &Result) { - const SourceManager &SM = *Result.SourceManager; - const ASTContext *Context = Result.Context; - - // Get location of closing parenthesis or 'do' to insert opening brace. - if (auto S = Result.Nodes.getNodeAs("for")) { - checkStmt(Result, S->getBody(), S->getRParenLoc()); - } else if (auto S = Result.Nodes.getNodeAs("for-range")) { - checkStmt(Result, S->getBody(), S->getRParenLoc()); - } else if (auto S = Result.Nodes.getNodeAs("do")) { - checkStmt(Result, S->getBody(), S->getDoLoc(), S->getWhileLoc()); - } else if (auto S = Result.Nodes.getNodeAs("while")) { - SourceLocation StartLoc = findRParenLoc(S, SM, Context); - if (StartLoc.isInvalid()) - return; - checkStmt(Result, S->getBody(), StartLoc); - } else if (auto S = Result.Nodes.getNodeAs("if")) { - SourceLocation StartLoc = findRParenLoc(S, SM, Context); - if (StartLoc.isInvalid()) - return; - checkStmt(Result, S->getThen(), StartLoc, S->getElseLoc()); - const Stmt *Else = S->getElse(); - if (Else && !isa(Else)) { - // Omit 'else if' statements here, they will be handled directly. - checkStmt(Result, Else, S->getElseLoc()); - } - } else { - llvm_unreachable("Invalid match"); - } -} - -/// Find location of right parenthesis closing condition -template -SourceLocation -BracesAroundStatementsCheck::findRParenLoc(const IfOrWhileStmt *S, - const SourceManager &SM, - const ASTContext *Context) { - // Skip macros - if (S->getLocStart().isMacroID()) - return SourceLocation(); - - static const char *const ErrorMessage = - "cannot find location of closing parenthesis ')'"; - SourceLocation CondEndLoc = S->getCond()->getLocEnd(); - if (const DeclStmt *CondVar = S->getConditionVariableDeclStmt()) - CondEndLoc = CondVar->getLocEnd(); - - assert(CondEndLoc.isValid()); - SourceLocation PastCondEndLoc = - Lexer::getLocForEndOfToken(CondEndLoc, 0, SM, Context->getLangOpts()); - if (PastCondEndLoc.isInvalid()) { - diag(CondEndLoc, ErrorMessage); - return SourceLocation(); - } - SourceLocation RParenLoc = - forwardSkipWhitespaceAndComments(PastCondEndLoc, SM, Context); - if (RParenLoc.isInvalid()) { - diag(PastCondEndLoc, ErrorMessage); - return SourceLocation(); - } - tok::TokenKind TokKind = getTokenKind(RParenLoc, SM, Context); - if (TokKind != tok::r_paren) { - diag(RParenLoc, ErrorMessage); - return SourceLocation(); - } - return RParenLoc; -} - -void -BracesAroundStatementsCheck::checkStmt(const MatchFinder::MatchResult &Result, - const Stmt *S, SourceLocation InitialLoc, - SourceLocation EndLocHint) { - // 1) If there's a corresponding "else" or "while", the check inserts "} " - // right before that token. - // 2) If there's a multi-line block comment starting on the same line after - // the location we're inserting the closing brace at, or there's a non-comment - // token, the check inserts "\n}" right before that token. - // 3) Otherwise the check finds the end of line (possibly after some block or - // line comments) and inserts "\n}" right before that EOL. - if (!S || isa(S)) { - // Already inside braces. - return; - } - // Skip macros. - if (S->getLocStart().isMacroID()) - return; - - const SourceManager &SM = *Result.SourceManager; - const ASTContext *Context = Result.Context; - - // InitialLoc points at the last token before opening brace to be inserted. - assert(InitialLoc.isValid()); - SourceLocation StartLoc = - Lexer::getLocForEndOfToken(InitialLoc, 0, SM, Context->getLangOpts()); - // StartLoc points at the location of the opening brace to be inserted. - SourceLocation EndLoc; - std::string ClosingInsertion; - if (EndLocHint.isValid()) { - EndLoc = EndLocHint; - ClosingInsertion = "} "; - } else { - EndLoc = findEndLocation(S->getLocEnd(), SM, Context); - ClosingInsertion = "\n}"; - } - - assert(StartLoc.isValid()); - assert(EndLoc.isValid()); - // Don't require braces for statements spanning less than certain number of - // lines. - if (ShortStatementLines) { - unsigned StartLine = SM.getSpellingLineNumber(StartLoc); - unsigned EndLine = SM.getSpellingLineNumber(EndLoc); - if (EndLine - StartLine < ShortStatementLines) - return; - } - - auto Diag = diag(StartLoc, "statement should be inside braces"); - Diag << FixItHint::CreateInsertion(StartLoc, " {") - << FixItHint::CreateInsertion(EndLoc, ClosingInsertion); -} - -} // namespace tidy -} // namespace clang Index: clang-tidy/misc/CMakeLists.txt =================================================================== --- clang-tidy/misc/CMakeLists.txt +++ clang-tidy/misc/CMakeLists.txt @@ -3,10 +3,7 @@ add_clang_library(clangTidyMiscModule ArgumentCommentCheck.cpp BoolPointerImplicitConversion.cpp - BracesAroundStatementsCheck.cpp - FunctionSize.cpp MiscTidyModule.cpp - RedundantSmartptrGet.cpp SwappedArgumentsCheck.cpp UndelegatedConstructor.cpp UnusedRAII.cpp @@ -18,4 +15,6 @@ clangBasic clangLex clangTidy + # Some readability checks are currently registered in the misc module. + clangTidyReadability ) Index: clang-tidy/misc/FunctionSize.h =================================================================== --- clang-tidy/misc/FunctionSize.h +++ clang-tidy/misc/FunctionSize.h @@ -1,46 +0,0 @@ -//===--- FunctionSize.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_MISC_FUNCTIONSIZE_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FUNCTIONSIZE_H - -#include "../ClangTidy.h" - -namespace clang { -namespace tidy { - -/// \brief Checks for large functions based on various metrics. -class FunctionSizeCheck : public ClangTidyCheck { -public: - FunctionSizeCheck(StringRef Name, ClangTidyContext *Context); - - void storeOptions(ClangTidyOptions::OptionMap &Opts) override; - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; - void onEndOfTranslationUnit() override; - -private: - struct FunctionInfo { - FunctionInfo() : Lines(0), Statements(0), Branches(0) {} - unsigned Lines; - unsigned Statements; - unsigned Branches; - }; - - const unsigned LineThreshold; - const unsigned StatementThreshold; - const unsigned BranchThreshold; - - llvm::DenseMap FunctionInfos; -}; - -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FUNCTIONSIZE_H Index: clang-tidy/misc/FunctionSize.cpp =================================================================== --- clang-tidy/misc/FunctionSize.cpp +++ clang-tidy/misc/FunctionSize.cpp @@ -1,104 +0,0 @@ -//===--- FunctionSize.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 "FunctionSize.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { - -FunctionSizeCheck::FunctionSizeCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), - LineThreshold(Options.get("LineThreshold", -1U)), - StatementThreshold(Options.get("StatementThreshold", 800U)), - BranchThreshold(Options.get("BranchThreshold", -1U)) {} - -void FunctionSizeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "LineThreshold", LineThreshold); - Options.store(Opts, "StatementThreshold", StatementThreshold); - Options.store(Opts, "BranchThreshold", BranchThreshold); -} - -void FunctionSizeCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher( - functionDecl( - unless(isInstantiated()), - forEachDescendant( - stmt(unless(compoundStmt()), - hasParent(stmt(anyOf(compoundStmt(), ifStmt(), - anyOf(whileStmt(), doStmt(), - forRangeStmt(), forStmt()))))) - .bind("stmt"))).bind("func"), - this); -} - -void FunctionSizeCheck::check(const MatchFinder::MatchResult &Result) { - const auto *Func = Result.Nodes.getNodeAs("func"); - - FunctionInfo &FI = FunctionInfos[Func]; - - // Count the lines including whitespace and comments. Really simple. - if (!FI.Lines) { - if (const Stmt *Body = Func->getBody()) { - SourceManager *SM = Result.SourceManager; - if (SM->isWrittenInSameFile(Body->getLocStart(), Body->getLocEnd())) { - FI.Lines = SM->getSpellingLineNumber(Body->getLocEnd()) - - SM->getSpellingLineNumber(Body->getLocStart()); - } - } - } - - const auto *Statement = Result.Nodes.getNodeAs("stmt"); - ++FI.Statements; - - // TODO: switch cases, gotos - if (isa(Statement) || isa(Statement) || - isa(Statement) || isa(Statement) || - isa(Statement) || isa(Statement)) - ++FI.Branches; -} - -void FunctionSizeCheck::onEndOfTranslationUnit() { - // If we're above the limit emit a warning. - for (const auto &P : FunctionInfos) { - const FunctionInfo &FI = P.second; - if (FI.Lines > LineThreshold || FI.Statements > StatementThreshold || - FI.Branches > BranchThreshold) { - diag(P.first->getLocation(), - "function '%0' exceeds recommended size/complexity thresholds") - << P.first->getNameAsString(); - } - - if (FI.Lines > LineThreshold) { - diag(P.first->getLocation(), - "%0 lines including whitespace and comments (threshold %1)", - DiagnosticIDs::Note) - << FI.Lines << LineThreshold; - } - - if (FI.Statements > StatementThreshold) { - diag(P.first->getLocation(), "%0 statements (threshold %1)", - DiagnosticIDs::Note) - << FI.Statements << StatementThreshold; - } - - if (FI.Branches > BranchThreshold) { - diag(P.first->getLocation(), "%0 branches (threshold %1)", - DiagnosticIDs::Note) - << FI.Branches << BranchThreshold; - } - } - - FunctionInfos.clear(); -} - -} // namespace tidy -} // namespace clang Index: clang-tidy/misc/MiscTidyModule.cpp =================================================================== --- clang-tidy/misc/MiscTidyModule.cpp +++ clang-tidy/misc/MiscTidyModule.cpp @@ -10,11 +10,13 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +// FIXME: Figure out if we want to create a separate module for readability +// checks instead of registering them here. +#include "../readability/BracesAroundStatementsCheck.h" +#include "../readability/FunctionSize.h" +#include "../readability/RedundantSmartptrGet.h" #include "ArgumentCommentCheck.h" #include "BoolPointerImplicitConversion.h" -#include "BracesAroundStatementsCheck.h" -#include "FunctionSize.h" -#include "RedundantSmartptrGet.h" #include "SwappedArgumentsCheck.h" #include "UndelegatedConstructor.h" #include "UnusedRAII.h" @@ -29,10 +31,11 @@ CheckFactories.registerCheck("misc-argument-comment"); CheckFactories.registerCheck( "misc-bool-pointer-implicit-conversion"); - CheckFactories.registerCheck( + CheckFactories.registerCheck( "misc-braces-around-statements"); - CheckFactories.registerCheck("misc-function-size"); - CheckFactories.registerCheck( + CheckFactories.registerCheck( + "misc-function-size"); + CheckFactories.registerCheck( "misc-redundant-smartptr-get"); CheckFactories.registerCheck( "misc-swapped-arguments"); Index: clang-tidy/misc/RedundantSmartptrGet.h =================================================================== --- clang-tidy/misc/RedundantSmartptrGet.h +++ clang-tidy/misc/RedundantSmartptrGet.h @@ -1,36 +0,0 @@ -//===--- RedundantSmartptrGet.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_MISC_REDUNDANT_SMARTPTR_GET_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_SMARTPTR_GET_H - -#include "../ClangTidy.h" - -namespace clang { -namespace tidy { - -/// \brief Find and remove redundant calls to smart pointer's .get() method. -/// -/// Examples: -/// ptr.get()->Foo() ==> ptr->Foo() -/// *ptr.get() ==> *ptr -/// *ptr->get() ==> **ptr -class RedundantSmartptrGet : public ClangTidyCheck { -public: - RedundantSmartptrGet(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; -}; - -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_SMARTPTR_GET_H - Index: clang-tidy/misc/RedundantSmartptrGet.cpp =================================================================== --- clang-tidy/misc/RedundantSmartptrGet.cpp +++ clang-tidy/misc/RedundantSmartptrGet.cpp @@ -1,121 +0,0 @@ -//===--- RedundantSmartptrGet.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 "RedundantSmartptrGet.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/Lex/Lexer.h" - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { - -namespace { -internal::Matcher callToGet(internal::Matcher OnClass) { - return memberCallExpr( - on(expr(anyOf(hasType(OnClass), - hasType(qualType(pointsTo(decl(OnClass).bind( - "ptr_to_ptr")))))).bind("smart_pointer")), - unless(callee(memberExpr(hasObjectExpression(thisExpr())))), - callee(methodDecl(hasName("get")))).bind("redundant_get"); -} - -void registerMatchersForGetArrowStart(MatchFinder *Finder, - MatchFinder::MatchCallback *Callback) { - const auto QuacksLikeASmartptr = recordDecl( - recordDecl().bind("duck_typing"), - has(methodDecl(hasName("operator->"), - returns(qualType(pointsTo(type().bind("op->Type")))))), - has(methodDecl(hasName("operator*"), - returns(qualType(references(type().bind("op*Type")))))), - has(methodDecl(hasName("get"), - returns(qualType(pointsTo(type().bind("getType"))))))); - - // Catch 'ptr.get()->Foo()' - Finder->addMatcher(memberExpr(expr().bind("memberExpr"), isArrow(), - hasObjectExpression(ignoringImpCasts( - callToGet(QuacksLikeASmartptr)))), - Callback); - - // Catch '*ptr.get()' or '*ptr->get()' - Finder->addMatcher( - unaryOperator(hasOperatorName("*"), - hasUnaryOperand(callToGet(QuacksLikeASmartptr))), - Callback); -} - -void registerMatchersForGetEquals(MatchFinder *Finder, - MatchFinder::MatchCallback *Callback) { - // This one is harder to do with duck typing. - // The operator==/!= that we are looking for might be member or non-member, - // might be on global namespace or found by ADL, might be a template, etc. - // For now, lets keep a list of known standard types. - - const auto IsAKnownSmartptr = recordDecl( - anyOf(hasName("::std::unique_ptr"), hasName("::std::shared_ptr"))); - - // Matches against nullptr. - Finder->addMatcher( - binaryOperator(anyOf(hasOperatorName("=="), hasOperatorName("!=")), - hasEitherOperand(ignoringImpCasts(nullPtrLiteralExpr())), - hasEitherOperand(callToGet(IsAKnownSmartptr))), - Callback); - // TODO: Catch ptr.get() == other_ptr.get() -} - - -} // namespace - -void RedundantSmartptrGet::registerMatchers(MatchFinder *Finder) { - registerMatchersForGetArrowStart(Finder, this); - registerMatchersForGetEquals(Finder, this); -} - -namespace { -bool allReturnTypesMatch(const MatchFinder::MatchResult &Result) { - if (Result.Nodes.getNodeAs("duck_typing") == nullptr) - return true; - // Verify that the types match. - // We can't do this on the matcher because the type nodes can be different, - // even though they represent the same type. This difference comes from how - // the type is referenced (eg. through a typedef, a type trait, etc). - const Type *OpArrowType = - Result.Nodes.getNodeAs("op->Type")->getUnqualifiedDesugaredType(); - const Type *OpStarType = - Result.Nodes.getNodeAs("op*Type")->getUnqualifiedDesugaredType(); - const Type *GetType = - Result.Nodes.getNodeAs("getType")->getUnqualifiedDesugaredType(); - return OpArrowType == OpStarType && OpArrowType == GetType; -} -} // namespace - -void RedundantSmartptrGet::check(const MatchFinder::MatchResult &Result) { - if (!allReturnTypesMatch(Result)) return; - - bool IsPtrToPtr = Result.Nodes.getNodeAs("ptr_to_ptr") != nullptr; - bool IsMemberExpr = Result.Nodes.getNodeAs("memberExpr") != nullptr; - const Expr *GetCall = Result.Nodes.getNodeAs("redundant_get"); - const Expr *Smartptr = Result.Nodes.getNodeAs("smart_pointer"); - - if (IsPtrToPtr && IsMemberExpr) { - // Ignore this case (eg. Foo->get()->DoSomething()); - return; - } - - StringRef SmartptrText = Lexer::getSourceText( - CharSourceRange::getTokenRange(Smartptr->getSourceRange()), - *Result.SourceManager, LangOptions()); - // Replace foo->get() with *foo, and foo.get() with foo. - std::string Replacement = Twine(IsPtrToPtr ? "*" : "", SmartptrText).str(); - diag(GetCall->getLocStart(), "Redundant get() call on smart pointer.") - << FixItHint::CreateReplacement(GetCall->getSourceRange(), Replacement); -} - -} // namespace tidy -} // namespace clang Index: clang-tidy/readability/BracesAroundStatementsCheck.h =================================================================== --- clang-tidy/readability/BracesAroundStatementsCheck.h +++ clang-tidy/readability/BracesAroundStatementsCheck.h @@ -7,13 +7,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BRACES_AROUND_STATEMENTS_CHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BRACES_AROUND_STATEMENTS_CHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_BRACESAROUNDSTATEMENTSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_BRACESAROUNDSTATEMENTSCHECK_H #include "../ClangTidy.h" namespace clang { namespace tidy { +namespace readability { /// \brief Checks that bodies of 'if' statements and loops ('for', 'range-for', /// 'do-while', and 'while') are inside braces @@ -53,7 +54,8 @@ const unsigned ShortStatementLines; }; +} // namespace readability } // namespace tidy } // namespace clang -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BRACES_AROUND_STATEMENTS_CHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_BRACESAROUNDSTATEMENTSCHECK_H Index: clang-tidy/readability/BracesAroundStatementsCheck.cpp =================================================================== --- clang-tidy/readability/BracesAroundStatementsCheck.cpp +++ clang-tidy/readability/BracesAroundStatementsCheck.cpp @@ -16,6 +16,7 @@ namespace clang { namespace tidy { +namespace readability { namespace { tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM, @@ -251,5 +252,6 @@ << FixItHint::CreateInsertion(EndLoc, ClosingInsertion); } +} // namespace readability } // namespace tidy } // namespace clang Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -1,7 +1,10 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyReadability + BracesAroundStatementsCheck.cpp + FunctionSize.cpp NamespaceCommentCheck.cpp + RedundantSmartptrGet.cpp LINK_LIBS clangAST Index: clang-tidy/readability/FunctionSize.h =================================================================== --- clang-tidy/readability/FunctionSize.h +++ clang-tidy/readability/FunctionSize.h @@ -7,13 +7,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FUNCTIONSIZE_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FUNCTIONSIZE_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_FUNCTIONSIZE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_FUNCTIONSIZE_H #include "../ClangTidy.h" namespace clang { namespace tidy { +namespace readability { /// \brief Checks for large functions based on various metrics. class FunctionSizeCheck : public ClangTidyCheck { @@ -40,7 +41,8 @@ llvm::DenseMap FunctionInfos; }; +} // namespace readability } // namespace tidy } // namespace clang -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FUNCTIONSIZE_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_FUNCTIONSIZE_H Index: clang-tidy/readability/FunctionSize.cpp =================================================================== --- clang-tidy/readability/FunctionSize.cpp +++ clang-tidy/readability/FunctionSize.cpp @@ -14,6 +14,7 @@ namespace clang { namespace tidy { +namespace readability { FunctionSizeCheck::FunctionSizeCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), @@ -100,5 +101,6 @@ FunctionInfos.clear(); } +} // namespace readability } // namespace tidy } // namespace clang Index: clang-tidy/readability/RedundantSmartptrGet.h =================================================================== --- clang-tidy/readability/RedundantSmartptrGet.h +++ clang-tidy/readability/RedundantSmartptrGet.h @@ -7,13 +7,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_SMARTPTR_GET_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_SMARTPTR_GET_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTSMARTPTRGET_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTSMARTPTRGET_H #include "../ClangTidy.h" namespace clang { namespace tidy { +namespace readability { /// \brief Find and remove redundant calls to smart pointer's .get() method. /// @@ -29,8 +30,9 @@ void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; +} // namespace readability } // namespace tidy } // namespace clang -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_SMARTPTR_GET_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTSMARTPTRGET_H Index: clang-tidy/readability/RedundantSmartptrGet.cpp =================================================================== --- clang-tidy/readability/RedundantSmartptrGet.cpp +++ clang-tidy/readability/RedundantSmartptrGet.cpp @@ -15,6 +15,7 @@ namespace clang { namespace tidy { +namespace readability { namespace { internal::Matcher callToGet(internal::Matcher OnClass) { @@ -117,5 +118,6 @@ << FixItHint::CreateReplacement(GetCall->getSourceRange(), Replacement); } +} // namespace readability } // namespace tidy } // namespace clang Index: unittests/clang-tidy/MiscModuleTest.cpp =================================================================== --- unittests/clang-tidy/MiscModuleTest.cpp +++ unittests/clang-tidy/MiscModuleTest.cpp @@ -1,10 +1,13 @@ #include "ClangTidyTest.h" #include "misc/ArgumentCommentCheck.h" -#include "misc/BracesAroundStatementsCheck.h" +#include "readability/BracesAroundStatementsCheck.h" #include "gtest/gtest.h" namespace clang { namespace tidy { + +using readability::BracesAroundStatementsCheck; + namespace test { #define EXPECT_NO_CHANGES(Check, Code) \