diff options
Diffstat (limited to 'clang-tools-extra/clang-tidy/google')
20 files changed, 129 insertions, 386 deletions
diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp deleted file mode 100644 index 174ecb0..0000000 --- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp +++ /dev/null @@ -1,279 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "AvoidCStyleCastsCheck.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/ASTMatchers/ASTMatchers.h" -#include "clang/Lex/Lexer.h" - -using namespace clang::ast_matchers; - -namespace clang::tidy::google::readability { - -void AvoidCStyleCastsCheck::registerMatchers( - ast_matchers::MatchFinder *Finder) { - Finder->addMatcher( - cStyleCastExpr( - // Filter out (EnumType)IntegerLiteral construct, which is generated - // for non-type template arguments of enum types. - // FIXME: Remove this once this is fixed in the AST. - unless(hasParent(substNonTypeTemplateParmExpr()))) - .bind("cast"), - this); - - Finder->addMatcher( - cxxFunctionalCastExpr( - hasDestinationType(hasCanonicalType(anyOf( - builtinType(), references(qualType()), pointsTo(qualType())))), - unless( - hasSourceExpression(anyOf(cxxConstructExpr(), initListExpr())))) - .bind("cast"), - this); -} - -static bool needsConstCast(QualType SourceType, QualType DestType) { - while ((SourceType->isPointerType() && DestType->isPointerType()) || - (SourceType->isReferenceType() && DestType->isReferenceType())) { - SourceType = SourceType->getPointeeType(); - DestType = DestType->getPointeeType(); - if (SourceType.isConstQualified() && !DestType.isConstQualified()) { - return (SourceType->isPointerType() == DestType->isPointerType()) && - (SourceType->isReferenceType() == DestType->isReferenceType()); - } - } - return false; -} - -static bool pointedUnqualifiedTypesAreEqual(QualType T1, QualType T2) { - while ((T1->isPointerType() && T2->isPointerType()) || - (T1->isReferenceType() && T2->isReferenceType())) { - T1 = T1->getPointeeType(); - T2 = T2->getPointeeType(); - } - return T1.getUnqualifiedType() == T2.getUnqualifiedType(); -} - -static clang::CharSourceRange getReplaceRange(const ExplicitCastExpr *Expr) { - if (const auto *CastExpr = dyn_cast<CStyleCastExpr>(Expr)) - return CharSourceRange::getCharRange( - CastExpr->getLParenLoc(), - CastExpr->getSubExprAsWritten()->getBeginLoc()); - if (const auto *CastExpr = dyn_cast<CXXFunctionalCastExpr>(Expr)) - return CharSourceRange::getCharRange(CastExpr->getBeginLoc(), - CastExpr->getLParenLoc()); - llvm_unreachable("Unsupported CastExpr"); -} - -static StringRef getDestTypeString(const SourceManager &SM, - const LangOptions &LangOpts, - const ExplicitCastExpr *Expr) { - SourceLocation BeginLoc; - SourceLocation EndLoc; - - if (const auto *CastExpr = dyn_cast<CStyleCastExpr>(Expr)) { - BeginLoc = CastExpr->getLParenLoc().getLocWithOffset(1); - EndLoc = CastExpr->getRParenLoc().getLocWithOffset(-1); - } else if (const auto *CastExpr = dyn_cast<CXXFunctionalCastExpr>(Expr)) { - BeginLoc = CastExpr->getBeginLoc(); - EndLoc = CastExpr->getLParenLoc().getLocWithOffset(-1); - } else - llvm_unreachable("Unsupported CastExpr"); - - return Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc), - SM, LangOpts); -} - -static bool sameTypeAsWritten(QualType X, QualType Y) { - if (X.getCanonicalType() != Y.getCanonicalType()) - return false; - - auto TC = X->getTypeClass(); - if (TC != Y->getTypeClass()) - return false; - - switch (TC) { - case Type::Typedef: - return declaresSameEntity(cast<TypedefType>(X)->getDecl(), - cast<TypedefType>(Y)->getDecl()); - case Type::Pointer: - return sameTypeAsWritten(cast<PointerType>(X)->getPointeeType(), - cast<PointerType>(Y)->getPointeeType()); - case Type::RValueReference: - case Type::LValueReference: - return sameTypeAsWritten(cast<ReferenceType>(X)->getPointeeType(), - cast<ReferenceType>(Y)->getPointeeType()); - default: - return true; - } -} - -void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) { - const auto *CastExpr = Result.Nodes.getNodeAs<ExplicitCastExpr>("cast"); - - // Ignore casts in macros. - if (CastExpr->getExprLoc().isMacroID()) - return; - - // Casting to void is an idiomatic way to mute "unused variable" and similar - // warnings. - if (CastExpr->getCastKind() == CK_ToVoid) - return; - - auto IsFunction = [](QualType T) { - T = T.getCanonicalType().getNonReferenceType(); - return T->isFunctionType() || T->isFunctionPointerType() || - T->isMemberFunctionPointerType(); - }; - - const QualType DestTypeAsWritten = - CastExpr->getTypeAsWritten().getUnqualifiedType(); - const QualType SourceTypeAsWritten = - CastExpr->getSubExprAsWritten()->getType().getUnqualifiedType(); - const QualType SourceType = SourceTypeAsWritten.getCanonicalType(); - const QualType DestType = DestTypeAsWritten.getCanonicalType(); - - CharSourceRange ReplaceRange = getReplaceRange(CastExpr); - - bool FnToFnCast = - IsFunction(SourceTypeAsWritten) && IsFunction(DestTypeAsWritten); - - const bool ConstructorCast = !CastExpr->getTypeAsWritten().hasQualifiers() && - DestTypeAsWritten->isRecordType() && - !DestTypeAsWritten->isElaboratedTypeSpecifier(); - - if (CastExpr->getCastKind() == CK_NoOp && !FnToFnCast) { - // Function pointer/reference casts may be needed to resolve ambiguities in - // case of overloaded functions, so detection of redundant casts is trickier - // in this case. Don't emit "redundant cast" warnings for function - // pointer/reference types. - if (sameTypeAsWritten(SourceTypeAsWritten, DestTypeAsWritten)) { - diag(CastExpr->getBeginLoc(), "redundant cast to the same type") - << FixItHint::CreateRemoval(ReplaceRange); - return; - } - } - - // The rest of this check is only relevant to C++. - // We also disable it for Objective-C++. - if (!getLangOpts().CPlusPlus || getLangOpts().ObjC) - return; - // Ignore code inside extern "C" {} blocks. - if (!match(expr(hasAncestor(linkageSpecDecl())), *CastExpr, *Result.Context) - .empty()) - return; - // Ignore code in .c files and headers included from them, even if they are - // compiled as C++. - if (getCurrentMainFile().ends_with(".c")) - return; - - SourceManager &SM = *Result.SourceManager; - - // Ignore code in .c files #included in other files (which shouldn't be done, - // but people still do this for test and other purposes). - if (SM.getFilename(SM.getSpellingLoc(CastExpr->getBeginLoc())) - .ends_with(".c")) - return; - - // Leave type spelling exactly as it was (unlike - // getTypeAsWritten().getAsString() which would spell enum types 'enum X'). - StringRef DestTypeString = getDestTypeString(SM, getLangOpts(), CastExpr); - - auto Diag = - diag(CastExpr->getBeginLoc(), "C-style casts are discouraged; use %0"); - - auto ReplaceWithCast = [&](std::string CastText) { - const Expr *SubExpr = CastExpr->getSubExprAsWritten()->IgnoreImpCasts(); - if (!isa<ParenExpr>(SubExpr) && !isa<CXXFunctionalCastExpr>(CastExpr)) { - CastText.push_back('('); - Diag << FixItHint::CreateInsertion( - Lexer::getLocForEndOfToken(SubExpr->getEndLoc(), 0, SM, - getLangOpts()), - ")"); - } - Diag << FixItHint::CreateReplacement(ReplaceRange, CastText); - }; - auto ReplaceWithNamedCast = [&](StringRef CastType) { - Diag << CastType; - ReplaceWithCast((CastType + "<" + DestTypeString + ">").str()); - }; - auto ReplaceWithConstructorCall = [&]() { - Diag << "constructor call syntax"; - // FIXME: Validate DestTypeString, maybe. - ReplaceWithCast(DestTypeString.str()); - }; - // Suggest appropriate C++ cast. See [expr.cast] for cast notation semantics. - switch (CastExpr->getCastKind()) { - case CK_FunctionToPointerDecay: - ReplaceWithNamedCast("static_cast"); - return; - case CK_ConstructorConversion: - if (ConstructorCast) { - ReplaceWithConstructorCall(); - } else { - ReplaceWithNamedCast("static_cast"); - } - return; - case CK_NoOp: - if (FnToFnCast) { - ReplaceWithNamedCast("static_cast"); - return; - } - if (SourceType == DestType) { - Diag << "static_cast (if needed, the cast may be redundant)"; - ReplaceWithCast(("static_cast<" + DestTypeString + ">").str()); - return; - } - if (needsConstCast(SourceType, DestType) && - pointedUnqualifiedTypesAreEqual(SourceType, DestType)) { - ReplaceWithNamedCast("const_cast"); - return; - } - if (ConstructorCast) { - ReplaceWithConstructorCall(); - return; - } - if (DestType->isReferenceType()) { - QualType Dest = DestType.getNonReferenceType(); - QualType Source = SourceType.getNonReferenceType(); - if (Source == Dest.withConst() || - SourceType.getNonReferenceType() == DestType.getNonReferenceType()) { - ReplaceWithNamedCast("const_cast"); - return; - } - break; - } - [[fallthrough]]; - case clang::CK_IntegralCast: - // Convert integral and no-op casts between builtin types and enums to - // static_cast. A cast from enum to integer may be unnecessary, but it's - // still retained. - if ((SourceType->isBuiltinType() || SourceType->isEnumeralType()) && - (DestType->isBuiltinType() || DestType->isEnumeralType())) { - ReplaceWithNamedCast("static_cast"); - return; - } - break; - case CK_BitCast: - // FIXME: Suggest const_cast<...>(reinterpret_cast<...>(...)) replacement. - if (!needsConstCast(SourceType, DestType)) { - if (SourceType->isVoidPointerType()) - ReplaceWithNamedCast("static_cast"); - else - ReplaceWithNamedCast("reinterpret_cast"); - return; - } - break; - default: - break; - } - - Diag << "static_cast/const_cast/reinterpret_cast"; -} - -} // namespace clang::tidy::google::readability diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h deleted file mode 100644 index a305bd5..0000000 --- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h +++ /dev/null @@ -1,41 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDCSTYLECASTSCHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDCSTYLECASTSCHECK_H - -#include "../ClangTidyCheck.h" - -namespace clang::tidy::google::readability { - -/// Finds usages of C-style casts. -/// -/// https://google.github.io/styleguide/cppguide.html#Casting -/// -/// Corresponding cpplint.py check name: 'readability/casting'. -/// -/// This check is similar to `-Wold-style-cast`, but it suggests automated fixes -/// in some cases. The reported locations should not be different from the -/// ones generated by `-Wold-style-cast`. -/// -/// For the user-facing documentation see: -/// https://clang.llvm.org/extra/clang-tidy/checks/google/readability-casting.html -class AvoidCStyleCastsCheck : public ClangTidyCheck { -public: - AvoidCStyleCastsCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; - std::optional<TraversalKind> getCheckTraversalKind() const override { - return TK_IgnoreUnlessSpelledInSource; - } -}; - -} // namespace clang::tidy::google::readability - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDCSTYLECASTSCHECK_H diff --git a/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp index daf4948..5221e4b 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp @@ -22,11 +22,11 @@ using namespace clang::ast_matchers; namespace clang::tidy::google::objc { static bool isMessageExpressionInsideMacro(const ObjCMessageExpr *Expr) { - SourceLocation ReceiverLocation = Expr->getReceiverRange().getBegin(); + const SourceLocation ReceiverLocation = Expr->getReceiverRange().getBegin(); if (ReceiverLocation.isMacroID()) return true; - SourceLocation SelectorLocation = Expr->getSelectorStartLoc(); + const SourceLocation SelectorLocation = Expr->getSelectorStartLoc(); if (SelectorLocation.isMacroID()) return true; @@ -58,7 +58,7 @@ static bool isInitMethodAvailable(const ObjCInterfaceDecl *ClassDecl) { static StringRef getReceiverString(SourceRange ReceiverRange, const SourceManager &SM, const LangOptions &LangOpts) { - CharSourceRange CharRange = Lexer::makeFileCharRange( + const CharSourceRange CharRange = Lexer::makeFileCharRange( CharSourceRange::getTokenRange(ReceiverRange), SM, LangOpts); return Lexer::getSourceText(CharRange, SM, LangOpts); } @@ -77,13 +77,13 @@ static FixItHint getCallFixItHint(const ObjCMessageExpr *Expr, if (FoundClassFactory != ClassToFactoryMethodMap.end()) { StringRef ClassName = FoundClassFactory->first; StringRef FactorySelector = FoundClassFactory->second; - std::string NewCall = + const std::string NewCall = std::string(llvm::formatv("[{0} {1}]", ClassName, FactorySelector)); return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall); } if (isInitMethodAvailable(Expr->getReceiverInterface())) { - std::string NewCall = + const std::string NewCall = std::string(llvm::formatv("[[{0} alloc] init]", Receiver)); return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall); } diff --git a/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp index 7347657..92d590c 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp @@ -14,7 +14,6 @@ using namespace clang::ast_matchers; namespace clang::tidy::google::objc { void AvoidThrowingObjCExceptionCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(objcThrowStmt().bind("throwStmt"), this); Finder->addMatcher( objcMessageExpr(anyOf(hasSelector("raise:format:"), @@ -40,7 +39,7 @@ void AvoidThrowingObjCExceptionCheck::check( // If the match location was in a macro, check if the macro was in a system // header. if (SourceLoc.isMacroID()) { - SourceManager &SM = *Result.SourceManager; + const SourceManager &SM = *Result.SourceManager; auto MacroLoc = SM.getImmediateMacroCallerLoc(SourceLoc); // Matches in system header macros should be ignored. diff --git a/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h b/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h index 26a0465..417bb8f 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h +++ b/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDTHROWINGOBJCEXCEPTIONCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDTHROWINGOBJCEXCEPTIONCHECK_H #include "../ClangTidyCheck.h" @@ -32,4 +32,4 @@ public: } // namespace clang::tidy::google::objc -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_AVOID_THROWING_EXCEPTION_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDTHROWINGOBJCEXCEPTIONCHECK_H diff --git a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp index b335463..b156d75 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp @@ -39,10 +39,11 @@ public: void MacroExpands(const Token &MacroNameToken, const MacroDefinition &MacroDefinition, SourceRange Range, const MacroArgs *Args) override { - IdentifierInfo *NameIdentifierInfo = MacroNameToken.getIdentifierInfo(); + const IdentifierInfo *NameIdentifierInfo = + MacroNameToken.getIdentifierInfo(); if (!NameIdentifierInfo) return; - StringRef MacroName = NameIdentifierInfo->getName(); + const StringRef MacroName = NameIdentifierInfo->getName(); if (!isGoogletestTestMacro(MacroName) || !Args || Args->getNumMacroArguments() < 2) return; @@ -50,7 +51,7 @@ public: const Token *TestNameToken = Args->getUnexpArgument(1); if (!TestSuiteNameToken || !TestNameToken) return; - std::string TestSuiteNameMaybeDisabled = + const std::string TestSuiteNameMaybeDisabled = PP->getSpelling(*TestSuiteNameToken); StringRef TestSuiteName = TestSuiteNameMaybeDisabled; TestSuiteName.consume_front(KDisabledTestPrefix); @@ -60,7 +61,7 @@ public: "Googletest FAQ") << TestSuiteName; - std::string TestNameMaybeDisabled = PP->getSpelling(*TestNameToken); + const std::string TestNameMaybeDisabled = PP->getSpelling(*TestNameToken); StringRef TestName = TestNameMaybeDisabled; TestName.consume_front(KDisabledTestPrefix); if (TestName.contains('_')) diff --git a/clang-tools-extra/clang-tidy/google/CMakeLists.txt b/clang-tools-extra/clang-tidy/google/CMakeLists.txt index 1d4229e..982a188 100644 --- a/clang-tools-extra/clang-tidy/google/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/google/CMakeLists.txt @@ -4,7 +4,6 @@ set(LLVM_LINK_COMPONENTS ) add_clang_library(clangTidyGoogleModule STATIC - AvoidCStyleCastsCheck.cpp AvoidNSObjectNewCheck.cpp AvoidThrowingObjCExceptionCheck.cpp AvoidUnderscoreInGoogletestNameCheck.cpp @@ -25,6 +24,7 @@ add_clang_library(clangTidyGoogleModule STATIC LINK_LIBS clangTidy + clangTidyModernizeModule clangTidyReadabilityModule clangTidyUtils diff --git a/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h b/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h index 1d1e4e3..0f397b4 100644 --- a/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h +++ b/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_DEFAULT_ARGUMENTS_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_DEFAULT_ARGUMENTS_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_DEFAULTARGUMENTSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_DEFAULTARGUMENTSCHECK_H #include "../ClangTidyCheck.h" @@ -32,4 +32,4 @@ public: } // namespace clang::tidy::google -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_DEFAULT_ARGUMENTS_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_DEFAULTARGUMENTSCHECK_H diff --git a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp index 6d5182d..ac604b7 100644 --- a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp @@ -39,8 +39,8 @@ static SourceRange findToken(const SourceManager &Sources, bool (*Pred)(const Token &)) { if (StartLoc.isMacroID() || EndLoc.isMacroID()) return {}; - FileID File = Sources.getFileID(Sources.getSpellingLoc(StartLoc)); - StringRef Buf = Sources.getBufferData(File); + const FileID File = Sources.getFileID(Sources.getSpellingLoc(StartLoc)); + const StringRef Buf = Sources.getBufferData(File); const char *StartChar = Sources.getCharacterData(StartLoc); Lexer Lex(StartLoc, LangOpts, StartChar, StartChar, Buf.end()); Lex.SetCommentRetentionState(true); @@ -88,7 +88,7 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { Result.Nodes.getNodeAs<CXXConversionDecl>("conversion")) { if (Conversion->isOutOfLine()) return; - SourceLocation Loc = Conversion->getLocation(); + const SourceLocation Loc = Conversion->getLocation(); // Ignore all macros until we learn to ignore specific ones (e.g. used in // gmock to define matchers). if (Loc.isMacroID()) @@ -105,7 +105,7 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { const ExplicitSpecifier ExplicitSpec = Ctor->getExplicitSpecifier(); - bool TakesInitializerList = isStdInitializerList( + const bool TakesInitializerList = isStdInitializerList( Ctor->getParamDecl(0)->getType().getNonReferenceType()); if (ExplicitSpec.isExplicit() && (Ctor->isCopyOrMoveConstructor() || TakesInitializerList)) { @@ -113,7 +113,7 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { return Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "explicit"; }; - SourceRange ExplicitTokenRange = + const SourceRange ExplicitTokenRange = findToken(*Result.SourceManager, getLangOpts(), Ctor->getOuterLocStart(), Ctor->getEndLoc(), IsKwExplicit); StringRef ConstructorDescription; @@ -149,7 +149,7 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { const bool SingleArgument = Ctor->getNumParams() == 1 && !Ctor->getParamDecl(0)->isParameterPack(); - SourceLocation Loc = Ctor->getLocation(); + const SourceLocation Loc = Ctor->getLocation(); auto Diag = diag(Loc, ExplicitExpr ? WithExpressionWarningMessage : NoExpressionWarningMessage) diff --git a/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp b/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp index 3d75f4d..2b9183c 100644 --- a/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp @@ -14,9 +14,7 @@ using namespace clang::ast_matchers; namespace clang::tidy::google::objc { -namespace { - -std::string validFunctionNameRegex(bool RequirePrefix) { +static std::string validFunctionNameRegex(bool RequirePrefix) { // Allow the following name patterns for all functions: // • ABFoo (prefix + UpperCamelCase) // • ABURL (prefix + capitalized acronym/initialism) @@ -35,7 +33,7 @@ std::string validFunctionNameRegex(bool RequirePrefix) { // If a prefix is required, the regex checks for a capital letter followed by // another capital letter or number that is part of the prefix and another // capital letter or number that begins the name following the prefix. - std::string FunctionNameMatcher = + const std::string FunctionNameMatcher = std::string(RequirePrefix ? "[A-Z][A-Z0-9]+" : "") + "[A-Z][a-zA-Z0-9]*"; return std::string("::(") + FunctionNameMatcher + ")$"; } @@ -43,20 +41,20 @@ std::string validFunctionNameRegex(bool RequirePrefix) { /// For now we will only fix functions of static storage class with names like /// 'functionName' or 'function_name' and convert them to 'FunctionName'. For /// other cases the user must determine an appropriate name on their own. -FixItHint generateFixItHint(const FunctionDecl *Decl) { +static FixItHint generateFixItHint(const FunctionDecl *Decl) { // A fixit can be generated for functions of static storage class but // otherwise the check cannot determine the appropriate function name prefix // to use. if (Decl->getStorageClass() != SC_Static) return {}; - StringRef Name = Decl->getName(); + const StringRef Name = Decl->getName(); std::string NewName = Decl->getName().str(); size_t Index = 0; bool AtWordBoundary = true; while (Index < NewName.size()) { - char Ch = NewName[Index]; + const char Ch = NewName[Index]; if (isalnum(Ch)) { // Capitalize the first letter after every word boundary. if (AtWordBoundary) { @@ -82,8 +80,6 @@ FixItHint generateFixItHint(const FunctionDecl *Decl) { return {}; } -} // namespace - void FunctionNamingCheck::registerMatchers(MatchFinder *Finder) { // Enforce Objective-C function naming conventions on all functions except: // • Functions defined in system headers. @@ -105,7 +101,7 @@ void FunctionNamingCheck::registerMatchers(MatchFinder *Finder) { void FunctionNamingCheck::check(const MatchFinder::MatchResult &Result) { const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("function"); - bool IsGlobal = MatchedDecl->getStorageClass() != SC_Static; + const bool IsGlobal = MatchedDecl->getStorageClass() != SC_Static; diag(MatchedDecl->getLocation(), "%select{static function|function in global namespace}1 named %0 must " "%select{be in|have an appropriate prefix followed by}1 Pascal case as " diff --git a/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.h b/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.h index e4efadf..6acc184 100644 --- a/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.h +++ b/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_FUNCTION_NAMING_CHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_FUNCTION_NAMING_CHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_FUNCTIONNAMINGCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_FUNCTIONNAMINGCHECK_H #include "../ClangTidyCheck.h" #include "llvm/ADT/StringRef.h" @@ -36,4 +36,4 @@ public: } // namespace clang::tidy::google::objc -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_FUNCTION_NAMING_CHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_FUNCTIONNAMINGCHECK_H diff --git a/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp b/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp index a4c76be9..7470b1eb 100644 --- a/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.cpp @@ -30,7 +30,7 @@ static FixItHint generateFixItHint(const VarDecl *Decl, bool IsConst) { return {}; } - char FC = Decl->getName()[0]; + const char FC = Decl->getName()[0]; if (!llvm::isAlpha(FC) || Decl->getName().size() == 1) { // No fix available if first character is not alphabetical character, or it // is a single-character variable, since it is difficult to determine the @@ -38,7 +38,7 @@ static FixItHint generateFixItHint(const VarDecl *Decl, bool IsConst) { // their own. return {}; } - char SC = Decl->getName()[1]; + const char SC = Decl->getName()[1]; if ((FC == 'k' || FC == 'g') && !llvm::isAlpha(SC)) { // No fix available if the prefix is correct but the second character is // not alphabetical, since it is difficult to determine the proper fix in diff --git a/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.h b/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.h index 9b55855..e0693d4 100644 --- a/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.h +++ b/clang-tools-extra/clang-tidy/google/GlobalVariableDeclarationCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_GLOBAL_VARIABLE_DECLARATION_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_GLOBAL_VARIABLE_DECLARATION_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_GLOBALVARIABLEDECLARATIONCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_GLOBALVARIABLEDECLARATIONCHECK_H #include "../ClangTidyCheck.h" @@ -32,4 +32,4 @@ public: } // namespace clang::tidy::google::objc -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_OBJC_GLOBAL_VARIABLE_DECLARATION_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_GLOBALVARIABLEDECLARATIONCHECK_H diff --git a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp index aff8b45..ce46b3f 100644 --- a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp @@ -9,10 +9,10 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "../modernize/AvoidCStyleCastCheck.h" #include "../readability/BracesAroundStatementsCheck.h" #include "../readability/FunctionSizeCheck.h" #include "../readability/NamespaceCommentCheck.h" -#include "AvoidCStyleCastsCheck.h" #include "AvoidNSObjectNewCheck.h" #include "AvoidThrowingObjCExceptionCheck.h" #include "AvoidUnderscoreInGoogletestNameCheck.h" @@ -67,7 +67,7 @@ public: CheckFactories .registerCheck<readability::AvoidUnderscoreInGoogletestNameCheck>( "google-readability-avoid-underscore-in-googletest-name"); - CheckFactories.registerCheck<readability::AvoidCStyleCastsCheck>( + CheckFactories.registerCheck<modernize::AvoidCStyleCastCheck>( "google-readability-casting"); CheckFactories.registerCheck<readability::TodoCommentCheck>( "google-readability-todo"); diff --git a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp index 52777fa..52bcf1b 100644 --- a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp @@ -103,7 +103,7 @@ void IntegerTypesCheck::registerMatchers(MatchFinder *Finder) { void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) { auto TL = *Result.Nodes.getNodeAs<TypeLoc>("tl"); - SourceLocation Loc = TL.getBeginLoc(); + const SourceLocation Loc = TL.getBeginLoc(); // Look through qualification. if (auto QualLoc = TL.getAs<QualifiedTypeLoc>()) @@ -113,7 +113,7 @@ void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) { if (!BuiltinLoc) return; - Token Tok = getTokenAtLoc(Loc, Result, *IdentTable); + const Token Tok = getTokenAtLoc(Loc, Result, *IdentTable); // Ensure the location actually points to one of the builting integral type // names we're interested in. Otherwise, we might be getting this match from // implicit code (e.g. an implicit assignment operator of a class containing @@ -164,7 +164,7 @@ void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) { !isAsciiIdentifierContinue(Data[Port.size()])) return; - std::string Replacement = + const std::string Replacement = ((IsSigned ? SignedTypePrefix : UnsignedTypePrefix) + Twine(Width) + TypeSuffix) .str(); diff --git a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp index 8554870..2789e4d 100644 --- a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp @@ -11,41 +11,102 @@ #include "clang/Lex/Preprocessor.h" #include <optional> -namespace clang::tidy::google::readability { +namespace clang::tidy { + +namespace google::readability { + +enum class StyleKind { Parentheses, Hyphen }; + +} // namespace google::readability + +template <> struct OptionEnumMapping<google::readability::StyleKind> { + static ArrayRef<std::pair<google::readability::StyleKind, StringRef>> + getEnumMapping() { + static constexpr std::pair<google::readability::StyleKind, StringRef> + Mapping[] = { + {google::readability::StyleKind::Hyphen, "Hyphen"}, + {google::readability::StyleKind::Parentheses, "Parentheses"}, + }; + return {Mapping}; + } +}; + +} // namespace clang::tidy +namespace clang::tidy::google::readability { class TodoCommentCheck::TodoCommentHandler : public CommentHandler { public: TodoCommentHandler(TodoCommentCheck &Check, std::optional<std::string> User) : Check(Check), User(User ? *User : "unknown"), - TodoMatch("^// *TODO *(\\(.*\\))?:?( )?(.*)$") {} + TodoMatch(R"(^// *TODO *((\((.*)\))?:?( )?|: *(.*) *- *)?(.*)$)") { + const llvm::StringRef TodoStyleString = + Check.Options.get("Style", "Hyphen"); + for (const auto &[Value, Name] : + OptionEnumMapping<StyleKind>::getEnumMapping()) { + if (Name == TodoStyleString) { + TodoStyle = Value; + return; + } + } + Check.configurationDiag( + "invalid value '%0' for " + "google-readability-todo.Style; valid values are " + "'Parentheses' and 'Hyphen'. Defaulting to 'Hyphen'") + << TodoStyleString; + } bool HandleComment(Preprocessor &PP, SourceRange Range) override { - StringRef Text = + const StringRef Text = Lexer::getSourceText(CharSourceRange::getCharRange(Range), PP.getSourceManager(), PP.getLangOpts()); - SmallVector<StringRef, 4> Matches; + SmallVector<StringRef, 7> Matches; if (!TodoMatch.match(Text, &Matches)) return false; - StringRef Username = Matches[1]; - StringRef Comment = Matches[3]; + const StyleKind ParsedStyle = + !Matches[3].empty() ? StyleKind::Parentheses : StyleKind::Hyphen; + const StringRef Username = + ParsedStyle == StyleKind::Parentheses ? Matches[3] : Matches[5]; + const StringRef Comment = Matches[6]; - if (!Username.empty()) + if (!Username.empty() && + (ParsedStyle == StyleKind::Parentheses || !Comment.empty())) { return false; + } - std::string NewText = ("// TODO(" + Twine(User) + "): " + Comment).str(); + if (Username.empty()) { + Check.diag(Range.getBegin(), "missing username/bug in TODO") + << FixItHint::CreateReplacement( + CharSourceRange::getCharRange(Range), + createReplacementString(Username, Comment)); + } + + if (Comment.empty()) + Check.diag(Range.getBegin(), "missing details in TODO"); - Check.diag(Range.getBegin(), "missing username/bug in TODO") - << FixItHint::CreateReplacement(CharSourceRange::getCharRange(Range), - NewText); return false; } + std::string createReplacementString(const StringRef Username, + const StringRef Comment) const { + if (TodoStyle == StyleKind::Parentheses) { + return ("// TODO(" + Twine(User) + + "): " + (Comment.empty() ? "some details" : Comment)) + .str(); + } + return ("// TODO: " + Twine(User) + " - " + + (Comment.empty() ? "some details" : Comment)) + .str(); + } + + StyleKind getTodoStyle() const { return TodoStyle; } + private: TodoCommentCheck &Check; std::string User; llvm::Regex TodoMatch; + StyleKind TodoStyle = StyleKind::Hyphen; }; TodoCommentCheck::TodoCommentCheck(StringRef Name, ClangTidyContext *Context) @@ -61,4 +122,8 @@ void TodoCommentCheck::registerPPCallbacks(const SourceManager &SM, PP->addCommentHandler(Handler.get()); } +void TodoCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "Style", Handler->getTodoStyle()); +} + } // namespace clang::tidy::google::readability diff --git a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h index 08cea13..800bc0f 100644 --- a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h +++ b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h @@ -27,6 +27,8 @@ public: void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + private: class TodoCommentHandler; std::unique_ptr<TodoCommentHandler> Handler; diff --git a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp index 3066dd0..054bdc8 100644 --- a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp @@ -28,7 +28,7 @@ void UnnamedNamespaceInHeaderCheck::registerMatchers( void UnnamedNamespaceInHeaderCheck::check( const MatchFinder::MatchResult &Result) { const auto *N = Result.Nodes.getNodeAs<NamespaceDecl>("anonymousNamespace"); - SourceLocation Loc = N->getBeginLoc(); + const SourceLocation Loc = N->getBeginLoc(); if (!Loc.isValid()) return; diff --git a/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp b/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp index 9da1915..87fd046 100644 --- a/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp @@ -64,7 +64,7 @@ public: // We check if the newly defined macro is one of the target replacements. // This ensures that the check creates warnings only if it is including a // recent enough version of Google Test. - llvm::StringRef FileName = PP->getSourceManager().getFilename( + const llvm::StringRef FileName = PP->getSourceManager().getFilename( MD->getMacroInfo()->getDefinitionLoc()); ReplacementFound = FileName.ends_with("gtest/gtest-typed-test.h") && PP->getSpelling(MacroNameTok) == "TYPED_TEST_SUITE"; @@ -94,18 +94,18 @@ private: if (!ReplacementFound) return; - std::string Name = PP->getSpelling(MacroNameTok); + const std::string Name = PP->getSpelling(MacroNameTok); std::optional<llvm::StringRef> Replacement = getNewMacroName(Name); if (!Replacement) return; - llvm::StringRef FileName = PP->getSourceManager().getFilename( + const llvm::StringRef FileName = PP->getSourceManager().getFilename( MD.getMacroInfo()->getDefinitionLoc()); if (!FileName.ends_with("gtest/gtest-typed-test.h")) return; - DiagnosticBuilder Diag = Check->diag(Loc, RenameCaseToSuiteMessage); + const DiagnosticBuilder Diag = Check->diag(Loc, RenameCaseToSuiteMessage); if (Action == CheckAction::Rename) Diag << FixItHint::CreateReplacement( @@ -234,7 +234,7 @@ static bool isInInstantiation(const NodeType &Node, template <typename NodeType> static bool isInTemplate(const NodeType &Node, const MatchFinder::MatchResult &Result) { - internal::Matcher<NodeType> IsInsideTemplate = + const internal::Matcher<NodeType> IsInsideTemplate = hasAncestor(decl(anyOf(classTemplateDecl(), functionTemplateDecl()))); return !match(IsInsideTemplate, Node, *Result.Context).empty(); } @@ -340,7 +340,7 @@ void UpgradeGoogletestCaseCheck::check(const MatchFinder::MatchResult &Result) { // will only be instantiated with the true type name, `TestSuite`. } - DiagnosticBuilder Diag = + const DiagnosticBuilder Diag = diag(ReplacementRange.getBegin(), RenameCaseToSuiteMessage); ReplacementRange = Lexer::makeFileCharRange( diff --git a/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp b/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp index fbfd5d34..00446dc 100644 --- a/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp @@ -22,7 +22,7 @@ void UsingNamespaceDirectiveCheck::registerMatchers( void UsingNamespaceDirectiveCheck::check( const MatchFinder::MatchResult &Result) { const auto *U = Result.Nodes.getNodeAs<UsingDirectiveDecl>("usingNamespace"); - SourceLocation Loc = U->getBeginLoc(); + const SourceLocation Loc = U->getBeginLoc(); if (U->isImplicit() || !Loc.isValid()) return; |
