diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000000000..2781d9cc0e63d --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1 @@ +Github action workflows should be stored in this directrory. diff --git a/.github/workflows/main-branch-sync.yml b/.github/workflows/main-branch-sync.yml deleted file mode 100644 index 5ea360e281d61..0000000000000 --- a/.github/workflows/main-branch-sync.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: main branch sync - -on: - push: - branches: - - 'main' - -jobs: - branch_sync: - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v2 - with: - # persist-credentials: false allows us to use our own credentials for - # pushing to the repository. Otherwise, the default github actions token - # is used. - persist-credentials: false - fetch-depth: 0 - - - name: Update branch - env: - LLVMBOT_TOKEN: ${{ secrets.LLVMBOT_MAIN_SYNC }} - run: | - git push https://$LLVMBOT_TOKEN@github.com/${{ github.repository }} HEAD:master diff --git a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp index babc207cb0e0c..5f30cbf8fb477 100644 --- a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp +++ b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp @@ -99,8 +99,13 @@ llvm::ErrorOr> GetAllowedSymbolPatterns() { int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); - tooling::CommonOptionsParser OptionsParser(argc, argv, - ChangeNamespaceCategory); + auto ExpectedParser = + tooling::CommonOptionsParser::create(argc, argv, ChangeNamespaceCategory); + if (!ExpectedParser) { + llvm::errs() << ExpectedParser.takeError(); + return 1; + } + tooling::CommonOptionsParser &OptionsParser = ExpectedParser.get(); const auto &Files = OptionsParser.getSourcePathList(); tooling::RefactoringTool Tool(OptionsParser.getCompilations(), Files); llvm::ErrorOr> AllowedPatterns = diff --git a/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp b/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp index 97015f2468e97..cbd79b64eae09 100644 --- a/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp +++ b/clang-tools-extra/clang-include-fixer/SymbolIndexManager.cpp @@ -149,6 +149,7 @@ SymbolIndexManager::search(llvm::StringRef Identifier, rank(MatchedSymbols, FileName); // Strip signals, they are no longer needed. std::vector Res; + Res.reserve(MatchedSymbols.size()); for (auto &SymAndSig : MatchedSymbols) Res.push_back(std::move(SymAndSig.Symbol)); return Res; diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp index 8508721bb85a3..b2d0efecc2069 100644 --- a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp +++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp @@ -128,7 +128,14 @@ bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) { } // namespace find_all_symbols int main(int argc, const char **argv) { - CommonOptionsParser OptionsParser(argc, argv, FindAllSymbolsCategory); + auto ExpectedParser = + CommonOptionsParser::create(argc, argv, FindAllSymbolsCategory); + if (!ExpectedParser) { + llvm::errs() << ExpectedParser.takeError(); + return 1; + } + + CommonOptionsParser &OptionsParser = ExpectedParser.get(); ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList()); diff --git a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp index 50a0c49ba6474..3a11a22def194 100644 --- a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp +++ b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp @@ -263,7 +263,13 @@ void writeToJson(llvm::raw_ostream &OS, const IncludeFixerContext& Context) { } int includeFixerMain(int argc, const char **argv) { - tooling::CommonOptionsParser options(argc, argv, IncludeFixerCategory); + auto ExpectedParser = + tooling::CommonOptionsParser::create(argc, argv, IncludeFixerCategory); + if (!ExpectedParser) { + llvm::errs() << ExpectedParser.takeError(); + return 1; + } + tooling::CommonOptionsParser &options = ExpectedParser.get(); tooling::ClangTool tool(options.getCompilations(), options.getSourcePathList()); diff --git a/clang-tools-extra/clang-move/tool/ClangMove.cpp b/clang-tools-extra/clang-move/tool/ClangMove.cpp index 7e16dc2b3b945..d4bd9a36517d6 100644 --- a/clang-tools-extra/clang-move/tool/ClangMove.cpp +++ b/clang-tools-extra/clang-move/tool/ClangMove.cpp @@ -95,7 +95,13 @@ cl::opt DumpDecls( int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); - tooling::CommonOptionsParser OptionsParser(argc, argv, ClangMoveCategory); + auto ExpectedParser = + tooling::CommonOptionsParser::create(argc, argv, ClangMoveCategory); + if (!ExpectedParser) { + llvm::errs() << ExpectedParser.takeError(); + return 1; + } + tooling::CommonOptionsParser &OptionsParser = ExpectedParser.get(); if (OldDependOnNew && NewDependOnOld) { llvm::errs() << "Provide either --old_depend_on_new or " diff --git a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp index 5150dc4bc5577..375306765a52b 100644 --- a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp +++ b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp @@ -50,8 +50,14 @@ static cl::opt Inplace("i", cl::desc("Overwrite edited files."), const char Usage[] = "A tool to reorder fields in C/C++ structs/classes.\n"; int main(int argc, const char **argv) { - tooling::CommonOptionsParser OP(argc, argv, ClangReorderFieldsCategory, - Usage); + auto ExpectedParser = tooling::CommonOptionsParser::create( + argc, argv, ClangReorderFieldsCategory, cl::OneOrMore, Usage); + if (!ExpectedParser) { + llvm::errs() << ExpectedParser.takeError(); + return 1; + } + + tooling::CommonOptionsParser &OP = ExpectedParser.get(); auto Files = OP.getSourcePathList(); tooling::RefactoringTool Tool(OP.getCompilations(), Files); diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 12d2134026c41..dc523d0731d5a 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -67,7 +67,7 @@ class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer { AnalyzerDiagnosticConsumer(ClangTidyContext &Context) : Context(Context) {} void FlushDiagnosticsImpl(std::vector &Diags, - FilesMade *filesMade) override { + FilesMade *FilesMade) override { for (const ento::PathDiagnostic *PD : Diags) { SmallString<64> CheckName(AnalyzerCheckNamePrefix); CheckName += PD->getCheckerName(); @@ -186,7 +186,7 @@ class ErrorReporter { reportNote(Note); } - void Finish() { + void finish() { if (ApplyFixes && TotalFixes > 0) { Rewriter Rewrite(SourceMgr, LangOpts); for (const auto &FileAndReplacements : FileReplacements) { @@ -596,7 +596,7 @@ void handleErrors(llvm::ArrayRef Errors, // Return to the initial directory to correctly resolve next Error. FileSystem.setCurrentWorkingDirectory(InitialWorkingDir.get()); } - Reporter.Finish(); + Reporter.finish(); WarningsAsErrorsCount += Reporter.getWarningsAsErrorsCount(); } diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp index 346fa66a662a1..48c5b0b2f4b79 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -37,10 +37,6 @@ using namespace clang; using namespace tidy; -#ifdef LLVM_CLANG_AST_ATTR_H -//#error -#endif - namespace { class ClangTidyDiagnosticRenderer : public DiagnosticRenderer { public: diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp index be068aa8da4a3..1e62d1c5f5eda 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -47,7 +47,7 @@ template <> struct MappingTraits { IO.mapRequired("name", File.Name); IO.mapOptional("lines", File.LineRanges); } - static std::string validate(IO &io, FileFilter &File) { + static std::string validate(IO &Io, FileFilter &File) { if (File.Name.empty()) return "No file name specified"; for (const FileFilter::LineRange &Range : File.LineRanges) { diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp index 1d008c23617cc..12795f0468fdb 100644 --- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp +++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp @@ -125,7 +125,7 @@ void ExpandModularHeadersPPCallbacks::handleModuleFile( Recorder->addNecessaryFile(IF.getFile()); }); // Recursively handle all transitively imported modules. - for (auto Import : MF->Imports) + for (auto *Import : MF->Imports) handleModuleFile(Import); } diff --git a/clang-tools-extra/clang-tidy/GlobList.cpp b/clang-tools-extra/clang-tidy/GlobList.cpp index 5b70b8d8c5771..43945fcdc074c 100644 --- a/clang-tools-extra/clang-tidy/GlobList.cpp +++ b/clang-tools-extra/clang-tidy/GlobList.cpp @@ -14,7 +14,7 @@ using namespace tidy; // Returns true if GlobList starts with the negative indicator ('-'), removes it // from the GlobList. -static bool ConsumeNegativeIndicator(StringRef &GlobList) { +static bool consumeNegativeIndicator(StringRef &GlobList) { GlobList = GlobList.trim(" \r\n"); if (GlobList.startswith("-")) { GlobList = GlobList.substr(1); @@ -25,7 +25,7 @@ static bool ConsumeNegativeIndicator(StringRef &GlobList) { // Converts first glob from the comma-separated list of globs to Regex and // removes it and the trailing comma from the GlobList. -static llvm::Regex ConsumeGlob(StringRef &GlobList) { +static llvm::Regex consumeGlob(StringRef &GlobList) { StringRef UntrimmedGlob = GlobList.substr(0, GlobList.find(',')); StringRef Glob = UntrimmedGlob.trim(' '); GlobList = GlobList.substr(UntrimmedGlob.size() + 1); @@ -46,8 +46,8 @@ GlobList::GlobList(StringRef Globs) { Items.reserve(Globs.count(',') + 1); do { GlobListItem Item; - Item.IsPositive = !ConsumeNegativeIndicator(Globs); - Item.Regex = ConsumeGlob(Globs); + Item.IsPositive = !consumeNegativeIndicator(Globs); + Item.Regex = consumeGlob(Globs); Items.push_back(std::move(Item)); } while (!Globs.empty()); } diff --git a/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp b/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp index 5ded02a2097b4..0fb750c694754 100644 --- a/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp @@ -17,10 +17,10 @@ namespace abseil { using namespace clang::ast_matchers; -void DurationDivisionCheck::registerMatchers(MatchFinder *finder) { +void DurationDivisionCheck::registerMatchers(MatchFinder *Finder) { const auto DurationExpr = expr(hasType(cxxRecordDecl(hasName("::absl::Duration")))); - finder->addMatcher( + Finder->addMatcher( traverse(TK_AsIs, implicitCastExpr( hasSourceExpression(ignoringParenCasts( @@ -35,8 +35,8 @@ void DurationDivisionCheck::registerMatchers(MatchFinder *finder) { this); } -void DurationDivisionCheck::check(const MatchFinder::MatchResult &result) { - const auto *OpCall = result.Nodes.getNodeAs("OpCall"); +void DurationDivisionCheck::check(const MatchFinder::MatchResult &Result) { + const auto *OpCall = Result.Nodes.getNodeAs("OpCall"); diag(OpCall->getOperatorLoc(), "operator/ on absl::Duration objects performs integer division; " "did you mean to use FDivDuration()?") @@ -47,8 +47,8 @@ void DurationDivisionCheck::check(const MatchFinder::MatchResult &result) { ", ") << FixItHint::CreateInsertion( Lexer::getLocForEndOfToken( - result.SourceManager->getSpellingLoc(OpCall->getEndLoc()), 0, - *result.SourceManager, result.Context->getLangOpts()), + Result.SourceManager->getSpellingLoc(OpCall->getEndLoc()), 0, + *Result.SourceManager, Result.Context->getLangOpts()), ")"); } diff --git a/clang-tools-extra/clang-tidy/abseil/DurationFactoryFloatCheck.cpp b/clang-tools-extra/clang-tidy/abseil/DurationFactoryFloatCheck.cpp index ed7e9fd0dfade..1f1dc07351ba4 100644 --- a/clang-tools-extra/clang-tidy/abseil/DurationFactoryFloatCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/DurationFactoryFloatCheck.cpp @@ -20,7 +20,7 @@ namespace tidy { namespace abseil { // Returns `true` if `Range` is inside a macro definition. -static bool InsideMacroDefinition(const MatchFinder::MatchResult &Result, +static bool insideMacroDefinition(const MatchFinder::MatchResult &Result, SourceRange Range) { return !clang::Lexer::makeFileCharRange( clang::CharSourceRange::getCharRange(Range), @@ -46,7 +46,7 @@ void DurationFactoryFloatCheck::check(const MatchFinder::MatchResult &Result) { const auto *MatchedCall = Result.Nodes.getNodeAs("call"); // Don't try and replace things inside of macro definitions. - if (InsideMacroDefinition(Result, MatchedCall->getSourceRange())) + if (insideMacroDefinition(Result, MatchedCall->getSourceRange())) return; const Expr *Arg = MatchedCall->getArg(0)->IgnoreImpCasts(); diff --git a/clang-tools-extra/clang-tidy/abseil/DurationFactoryScaleCheck.cpp b/clang-tools-extra/clang-tidy/abseil/DurationFactoryScaleCheck.cpp index 0e537fc3cc4eb..7da75fad589b4 100644 --- a/clang-tools-extra/clang-tidy/abseil/DurationFactoryScaleCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/DurationFactoryScaleCheck.cpp @@ -35,7 +35,7 @@ getScaleForFactory(llvm::StringRef FactoryName) { // Given either an integer or float literal, return its value. // One and only one of `IntLit` and `FloatLit` should be provided. -static double GetValue(const IntegerLiteral *IntLit, +static double getValue(const IntegerLiteral *IntLit, const FloatingLiteral *FloatLit) { if (IntLit) return IntLit->getValue().getLimitedValue(); @@ -48,7 +48,7 @@ static double GetValue(const IntegerLiteral *IntLit, // would produce a new scale. If so, return a tuple containing the new scale // and a suitable Multiplier for that scale, otherwise `None`. static llvm::Optional> -GetNewScaleSingleStep(DurationScale OldScale, double Multiplier) { +getNewScaleSingleStep(DurationScale OldScale, double Multiplier) { switch (OldScale) { case DurationScale::Hours: if (Multiplier <= 1.0 / 60.0) @@ -94,17 +94,17 @@ GetNewScaleSingleStep(DurationScale OldScale, double Multiplier) { // Given the scale of a duration and a `Multiplier`, determine if `Multiplier` // would produce a new scale. If so, return it, otherwise `None`. -static llvm::Optional GetNewScale(DurationScale OldScale, +static llvm::Optional getNewScale(DurationScale OldScale, double Multiplier) { while (Multiplier != 1.0) { - llvm::Optional> result = - GetNewScaleSingleStep(OldScale, Multiplier); - if (!result) + llvm::Optional> Result = + getNewScaleSingleStep(OldScale, Multiplier); + if (!Result) break; - if (std::get<1>(*result) == 1.0) - return std::get<0>(*result); - Multiplier = std::get<1>(*result); - OldScale = std::get<0>(*result); + if (std::get<1>(*Result) == 1.0) + return std::get<0>(*Result); + Multiplier = std::get<1>(*Result); + OldScale = std::get<0>(*Result); } return llvm::None; @@ -173,7 +173,7 @@ void DurationFactoryScaleCheck::check(const MatchFinder::MatchResult &Result) { const auto *IntLit = llvm::dyn_cast(MultBinOp->getLHS()); const auto *FloatLit = llvm::dyn_cast(MultBinOp->getLHS()); if (IntLit || FloatLit) { - NewScale = GetNewScale(Scale, GetValue(IntLit, FloatLit)); + NewScale = getNewScale(Scale, getValue(IntLit, FloatLit)); if (NewScale) Remainder = MultBinOp->getRHS(); } @@ -183,7 +183,7 @@ void DurationFactoryScaleCheck::check(const MatchFinder::MatchResult &Result) { IntLit = llvm::dyn_cast(MultBinOp->getRHS()); FloatLit = llvm::dyn_cast(MultBinOp->getRHS()); if (IntLit || FloatLit) { - NewScale = GetNewScale(Scale, GetValue(IntLit, FloatLit)); + NewScale = getNewScale(Scale, getValue(IntLit, FloatLit)); if (NewScale) Remainder = MultBinOp->getLHS(); } @@ -195,7 +195,7 @@ void DurationFactoryScaleCheck::check(const MatchFinder::MatchResult &Result) { const auto *FloatLit = llvm::dyn_cast(DivBinOp->getRHS()); llvm::Optional NewScale = - GetNewScale(Scale, 1.0 / FloatLit->getValueAsApproximateDouble()); + getNewScale(Scale, 1.0 / FloatLit->getValueAsApproximateDouble()); if (NewScale) { const Expr *Remainder = DivBinOp->getLHS(); diff --git a/clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp b/clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp index 39ee86b34f3fe..125812f4f3a81 100644 --- a/clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp +++ b/clang-tools-extra/clang-tidy/abseil/DurationRewriter.cpp @@ -138,8 +138,8 @@ llvm::StringRef getTimeFactoryForScale(DurationScale Scale) { } /// Returns the Time factory function name for a given `Scale`. -llvm::StringRef getTimeInverseForScale(DurationScale scale) { - switch (scale) { +llvm::StringRef getTimeInverseForScale(DurationScale Scale) { + switch (Scale) { case DurationScale::Hours: return "absl::ToUnixHours"; case DurationScale::Minutes: diff --git a/clang-tools-extra/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp b/clang-tools-extra/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp index 28f970e175099..b357d80f43624 100644 --- a/clang-tools-extra/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/DurationUnnecessaryConversionCheck.cpp @@ -30,31 +30,31 @@ void DurationUnnecessaryConversionCheck::registerMatchers(MatchFinder *Finder) { // Matcher which matches the current scale's factory with a `1` argument, // e.g. `absl::Seconds(1)`. - auto factory_matcher = ignoringElidableConstructorCall( + auto FactoryMatcher = ignoringElidableConstructorCall( callExpr(callee(functionDecl(hasName(DurationFactory))), hasArgument(0, ignoringImpCasts(integerLiteral(equals(1)))))); // Matcher which matches either inverse function and binds its argument, // e.g. `absl::ToDoubleSeconds(dur)`. - auto inverse_function_matcher = callExpr( + auto InverseFunctionMatcher = callExpr( callee(functionDecl(hasAnyName(FloatConversion, IntegerConversion))), hasArgument(0, expr().bind("arg"))); // Matcher which matches a duration divided by the factory_matcher above, // e.g. `dur / absl::Seconds(1)`. - auto division_operator_matcher = cxxOperatorCallExpr( + auto DivisionOperatorMatcher = cxxOperatorCallExpr( hasOverloadedOperatorName("/"), hasArgument(0, expr().bind("arg")), - hasArgument(1, factory_matcher)); + hasArgument(1, FactoryMatcher)); // Matcher which matches a duration argument to `FDivDuration`, // e.g. `absl::FDivDuration(dur, absl::Seconds(1))` - auto fdiv_matcher = callExpr( + auto FdivMatcher = callExpr( callee(functionDecl(hasName("::absl::FDivDuration"))), - hasArgument(0, expr().bind("arg")), hasArgument(1, factory_matcher)); + hasArgument(0, expr().bind("arg")), hasArgument(1, FactoryMatcher)); // Matcher which matches a duration argument being scaled, // e.g. `absl::ToDoubleSeconds(dur) * 2` - auto scalar_matcher = ignoringImpCasts( + auto ScalarMatcher = ignoringImpCasts( binaryOperator(hasOperatorName("*"), hasEitherOperand(expr(ignoringParenImpCasts( callExpr(callee(functionDecl(hasAnyName( @@ -65,9 +65,9 @@ void DurationUnnecessaryConversionCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( callExpr(callee(functionDecl(hasName(DurationFactory))), - hasArgument(0, anyOf(inverse_function_matcher, - division_operator_matcher, fdiv_matcher, - scalar_matcher))) + hasArgument(0, anyOf(InverseFunctionMatcher, + DivisionOperatorMatcher, FdivMatcher, + ScalarMatcher))) .bind("call"), this); } diff --git a/clang-tools-extra/clang-tidy/abseil/NoNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/abseil/NoNamespaceCheck.cpp index 3f93d4a2f570c..4e7b09378db0c 100644 --- a/clang-tools-extra/clang-tidy/abseil/NoNamespaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/NoNamespaceCheck.cpp @@ -25,10 +25,10 @@ void NoNamespaceCheck::registerMatchers(MatchFinder *Finder) { } void NoNamespaceCheck::check(const MatchFinder::MatchResult &Result) { - const auto *abslNamespaceDecl = + const auto *AbslNamespaceDecl = Result.Nodes.getNodeAs("abslNamespace"); - diag(abslNamespaceDecl->getLocation(), + diag(AbslNamespaceDecl->getLocation(), "namespace 'absl' is reserved for implementation of the Abseil library " "and should not be opened in user code"); } diff --git a/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp b/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp index abcf570abc6ef..15171be5de2d8 100644 --- a/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp @@ -46,7 +46,7 @@ struct StrCatCheckResult { std::vector Hints; }; -void RemoveCallLeaveArgs(const CallExpr* Call, StrCatCheckResult* CheckResult) { +void removeCallLeaveArgs(const CallExpr *Call, StrCatCheckResult *CheckResult) { if (Call->getNumArgs() == 0) return; // Remove 'Foo(' @@ -59,9 +59,9 @@ void RemoveCallLeaveArgs(const CallExpr* Call, StrCatCheckResult* CheckResult) { Call->getRParenLoc(), Call->getEndLoc().getLocWithOffset(1)))); } -const clang::CallExpr* ProcessArgument(const Expr* Arg, - const MatchFinder::MatchResult& Result, - StrCatCheckResult* CheckResult) { +const clang::CallExpr *processArgument(const Expr *Arg, + const MatchFinder::MatchResult &Result, + StrCatCheckResult *CheckResult) { const auto IsAlphanum = hasDeclaration(cxxMethodDecl(hasName("AlphaNum"))); static const auto* const Strcat = new auto(hasName("::absl::StrCat")); const auto IsStrcat = cxxBindTemporaryExpr( @@ -73,14 +73,14 @@ const clang::CallExpr* ProcessArgument(const Expr* Arg, hasArgument(0, IsStrcat)), IsStrcat))), *Arg->IgnoreParenImpCasts(), *Result.Context))) { - RemoveCallLeaveArgs(SubStrcatCall, CheckResult); + removeCallLeaveArgs(SubStrcatCall, CheckResult); return SubStrcatCall; } return nullptr; } -StrCatCheckResult ProcessCall(const CallExpr* RootCall, bool IsAppend, - const MatchFinder::MatchResult& Result) { +StrCatCheckResult processCall(const CallExpr *RootCall, bool IsAppend, + const MatchFinder::MatchResult &Result) { StrCatCheckResult CheckResult; std::deque CallsToProcess = {RootCall}; @@ -94,8 +94,8 @@ StrCatCheckResult ProcessCall(const CallExpr* RootCall, bool IsAppend, for (const auto *Arg : CallExpr->arguments()) { if (StartArg-- > 0) continue; - if (const clang::CallExpr* Sub = - ProcessArgument(Arg, Result, &CheckResult)) { + if (const clang::CallExpr *Sub = + processArgument(Arg, Result, &CheckResult)) { CallsToProcess.push_back(Sub); } } @@ -123,8 +123,7 @@ void RedundantStrcatCallsCheck::check(const MatchFinder::MatchResult& Result) { return; } - const StrCatCheckResult CheckResult = - ProcessCall(RootCall, IsAppend, Result); + const StrCatCheckResult CheckResult = processCall(RootCall, IsAppend, Result); if (CheckResult.NumCalls == 1) { // Just one call, so nothing to fix. return; diff --git a/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp index 3054689c96535..f4a519c15b92f 100644 --- a/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp @@ -62,7 +62,7 @@ makeRewriteRule(const std::vector &StringLikeClassNames, hasArgument(1, cxxDefaultArgExpr())), onImplicitObjectArgument(expr().bind("string_being_searched"))); - RewriteRule rule = applyFirst( + RewriteRule Rule = applyFirst( {makeRule( binaryOperator(hasOperatorName("=="), hasOperands(ignoringParenImpCasts(StringNpos), @@ -80,7 +80,7 @@ makeRewriteRule(const std::vector &StringLikeClassNames, addInclude(AbseilStringsMatchHeader)}, cat("use absl::StrContains instead " "of find() != npos"))}); - return rule; + return Rule; } StringFindStrContainsCheck::StringFindStrContainsCheck( diff --git a/clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp b/clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp index 92319715fbc56..58ce1f4be622e 100644 --- a/clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp @@ -20,7 +20,7 @@ namespace tidy { namespace abseil { // Returns `true` if `Range` is inside a macro definition. -static bool InsideMacroDefinition(const MatchFinder::MatchResult &Result, +static bool insideMacroDefinition(const MatchFinder::MatchResult &Result, SourceRange Range) { return !clang::Lexer::makeFileCharRange( clang::CharSourceRange::getCharRange(Range), @@ -93,7 +93,7 @@ void TimeSubtractionCheck::emitDiagnostic(const Expr *Node, } void TimeSubtractionCheck::registerMatchers(MatchFinder *Finder) { - for (auto ScaleName : + for (const char *ScaleName : {"Hours", "Minutes", "Seconds", "Millis", "Micros", "Nanos"}) { std::string TimeInverse = (llvm::Twine("ToUnix") + ScaleName).str(); llvm::Optional Scale = getScaleForTimeInverse(TimeInverse); @@ -131,7 +131,7 @@ void TimeSubtractionCheck::check(const MatchFinder::MatchResult &Result) { const auto *BinOp = Result.Nodes.getNodeAs("binop"); std::string InverseName = Result.Nodes.getNodeAs("func_decl")->getNameAsString(); - if (InsideMacroDefinition(Result, BinOp->getSourceRange())) + if (insideMacroDefinition(Result, BinOp->getSourceRange())) return; llvm::Optional Scale = getScaleForTimeInverse(InverseName); @@ -140,7 +140,7 @@ void TimeSubtractionCheck::check(const MatchFinder::MatchResult &Result) { const auto *OuterCall = Result.Nodes.getNodeAs("outer_call"); if (OuterCall) { - if (InsideMacroDefinition(Result, OuterCall->getSourceRange())) + if (insideMacroDefinition(Result, OuterCall->getSourceRange())) return; // We're working with the first case of matcher, and need to replace the @@ -166,7 +166,7 @@ void TimeSubtractionCheck::check(const MatchFinder::MatchResult &Result) { .bind("arg"))), *BinOp, *Result.Context)); if (MaybeCallArg && MaybeCallArg->getArg(0)->IgnoreImpCasts() == BinOp && - !InsideMacroDefinition(Result, MaybeCallArg->getSourceRange())) { + !insideMacroDefinition(Result, MaybeCallArg->getSourceRange())) { // Handle the case where the matched expression is inside a call which // converts it from the inverse to a Duration. In this case, we replace // the outer with just the subtraction expression, which gives the right diff --git a/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp b/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp index eb49977cbedb2..f7c71cca71594 100644 --- a/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp +++ b/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp @@ -39,7 +39,7 @@ class KernelNameRestrictionPPCallbacks : public PPCallbacks { private: /// Returns true if the name of the file with path FilePath is 'kernel.cl', /// 'verilog.cl', or 'vhdl.cl'. The file name check is case insensitive. - bool FileNameIsRestricted(StringRef FilePath); + bool fileNameIsRestricted(StringRef FilePath); struct IncludeDirective { SourceLocation Loc; // Location in the include directive. @@ -68,7 +68,7 @@ void KernelNameRestrictionPPCallbacks::InclusionDirective( IncludeDirectives.push_back(std::move(ID)); } -bool KernelNameRestrictionPPCallbacks::FileNameIsRestricted( +bool KernelNameRestrictionPPCallbacks::fileNameIsRestricted( StringRef FileName) { return FileName.equals_lower("kernel.cl") || FileName.equals_lower("verilog.cl") || @@ -80,7 +80,7 @@ void KernelNameRestrictionPPCallbacks::EndOfMainFile() { // Check main file for restricted names. const FileEntry *Entry = SM.getFileEntryForID(SM.getMainFileID()); StringRef FileName = llvm::sys::path::filename(Entry->getName()); - if (FileNameIsRestricted(FileName)) + if (fileNameIsRestricted(FileName)) Check.diag(SM.getLocForStartOfFile(SM.getMainFileID()), "compiling '%0' may cause additional compilation errors due " "to the name of the kernel source file; consider renaming the " @@ -93,7 +93,7 @@ void KernelNameRestrictionPPCallbacks::EndOfMainFile() { // Check included files for restricted names. for (const IncludeDirective &ID : IncludeDirectives) { StringRef FileName = llvm::sys::path::filename(ID.FileName); - if (FileNameIsRestricted(FileName)) + if (fileNameIsRestricted(FileName)) Check.diag(ID.Loc, "including '%0' may cause additional compilation errors due " "to the name of the kernel source file; consider renaming the " diff --git a/clang-tools-extra/clang-tidy/android/AndroidTidyModule.cpp b/clang-tools-extra/clang-tidy/android/AndroidTidyModule.cpp index e97830972ce41..b24c0d992eab7 100644 --- a/clang-tools-extra/clang-tidy/android/AndroidTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/android/AndroidTidyModule.cpp @@ -20,8 +20,8 @@ #include "CloexecInotifyInitCheck.h" #include "CloexecMemfdCreateCheck.h" #include "CloexecOpenCheck.h" -#include "CloexecPipeCheck.h" #include "CloexecPipe2Check.h" +#include "CloexecPipeCheck.h" #include "CloexecSocketCheck.h" #include "ComparisonInTempFailureRetryCheck.h" diff --git a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp index 3e401dac8a594..32af0ee6266d2 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp @@ -280,7 +280,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx, IdentifierInfo *II = PVD->getIdentifier(); if (!II) continue; - if (auto Template = Callee->getTemplateInstantiationPattern()) { + if (FunctionDecl *Template = Callee->getTemplateInstantiationPattern()) { // Don't warn on arguments for parameters instantiated from template // parameter packs. If we find more arguments than the template // definition has, it also means that they correspond to a parameter diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp index 8f7d1d1237e92..4e2359ff4f67b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp @@ -72,7 +72,8 @@ AssertSideEffectCheck::AssertSideEffectCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), CheckFunctionCalls(Options.get("CheckFunctionCalls", false)), - RawAssertList(Options.get("AssertMacros", "assert")) { + RawAssertList(Options.get("AssertMacros", + "assert,NSAssert,NSCAssert")) { StringRef(RawAssertList).split(AssertMacros, ",", -1, false); } @@ -117,7 +118,8 @@ void AssertSideEffectCheck::check(const MatchFinder::MatchResult &Result) { if (AssertMacroName.empty()) return; - diag(Loc, "found %0() with side effect") << AssertMacroName; + diag(Loc, "side effect in %0() condition discarded in release builds") + << AssertMacroName; } } // namespace bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/BadSignalToKillThreadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/BadSignalToKillThreadCheck.cpp index 3833640b3de34..cef7fd5935ffa 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BadSignalToKillThreadCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BadSignalToKillThreadCheck.cpp @@ -65,8 +65,8 @@ void BadSignalToKillThreadCheck::check(const MatchFinder::MatchResult &Result) { } void BadSignalToKillThreadCheck::registerPPCallbacks( - const SourceManager &SM, Preprocessor *pp, Preprocessor *ModuleExpanderPP) { - PP = pp; + const SourceManager &SM, Preprocessor *Pp, Preprocessor *ModuleExpanderPP) { + PP = Pp; } } // namespace bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp index 8c89350c6d07c..9b449515f27da 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp @@ -41,12 +41,12 @@ static bool areSwitchBranchesIdentical(const SwitchBranch LHS, if (LHS.size() != RHS.size()) return false; - for (size_t i = 0, Size = LHS.size(); i < Size; i++) { + for (size_t I = 0, Size = LHS.size(); I < Size; I++) { // NOTE: We strip goto labels and annotations in addition to stripping // the `case X:` or `default:` labels, but it is very unlikely that this // would casue false positives in real-world code. - if (!areStatementsIdentical(LHS[i]->stripLabelLikeStatements(), - RHS[i]->stripLabelLikeStatements(), Context)) { + if (!areStatementsIdentical(LHS[I]->stripLabelLikeStatements(), + RHS[I]->stripLabelLikeStatements(), Context)) { return false; } } @@ -114,35 +114,35 @@ void BranchCloneCheck::check(const MatchFinder::MatchResult &Result) { size_t N = Branches.size(); llvm::BitVector KnownAsClone(N); - for (size_t i = 0; i + 1 < N; i++) { + for (size_t I = 0; I + 1 < N; I++) { // We have already seen Branches[i] as a clone of an earlier branch. - if (KnownAsClone[i]) + if (KnownAsClone[I]) continue; int NumCopies = 1; - for (size_t j = i + 1; j < N; j++) { - if (KnownAsClone[j] || - !areStatementsIdentical(Branches[i]->IgnoreContainers(), - Branches[j]->IgnoreContainers(), Context)) + for (size_t J = I + 1; J < N; J++) { + if (KnownAsClone[J] || + !areStatementsIdentical(Branches[I]->IgnoreContainers(), + Branches[J]->IgnoreContainers(), Context)) continue; NumCopies++; - KnownAsClone[j] = true; + KnownAsClone[J] = true; if (NumCopies == 2) { // We report the first occurrence only when we find the second one. - diag(Branches[i]->getBeginLoc(), + diag(Branches[I]->getBeginLoc(), "repeated branch in conditional chain"); SourceLocation End = - Lexer::getLocForEndOfToken(Branches[i]->getEndLoc(), 0, + Lexer::getLocForEndOfToken(Branches[I]->getEndLoc(), 0, *Result.SourceManager, getLangOpts()); if (End.isValid()) { diag(End, "end of the original", DiagnosticIDs::Note); } } - diag(Branches[j]->getBeginLoc(), "clone %0 starts here", + diag(Branches[J]->getBeginLoc(), "clone %0 starts here", DiagnosticIDs::Note) << (NumCopies - 1); } diff --git a/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp index 1a4d45404397d..5f0cbe0bbed06 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp @@ -110,8 +110,8 @@ void CopyConstructorInitCheck::check(const MatchFinder::MatchResult &Result) { FixItMsg += ' '; Diag << FixItHint::CreateInsertion(FixItLoc, FixItMsg); -} // namespace misc +} -} // namespace misc +} // namespace bugprone } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp index 20b6203d8c799..aeb3db92f16ec 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp @@ -41,9 +41,9 @@ AST_MATCHER(QualType, isEnableIf) { } if (!BaseType) return false; - if (CheckTemplate(BaseType->getAs())) { + if (CheckTemplate(BaseType->getAs())) return true; // Case: enable_if_t< >. - } else if (const auto *Elaborated = BaseType->getAs()) { + if (const auto *Elaborated = BaseType->getAs()) { if (const auto *Qualifier = Elaborated->getQualifier()->getAsType()) { if (CheckTemplate(Qualifier->getAs())) { return true; // Case: enable_if< >::type. @@ -68,7 +68,7 @@ void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) { unless(references(isConstQualified()))))) .bind("parm-var"); - DeclarationMatcher findOverload = + DeclarationMatcher FindOverload = cxxConstructorDecl( hasParameter(0, ForwardingRefParm), unless(hasAnyParameter( @@ -78,7 +78,7 @@ void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) { // No warning: enable_if as type parameter. hasDefaultArgument(isEnableIf()))))))) .bind("ctor"); - Finder->addMatcher(findOverload, this); + Finder->addMatcher(FindOverload, this); } void ForwardingReferenceOverloadCheck::check( diff --git a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp index 8e5a532801839..96fa7ef48348e 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp @@ -22,25 +22,18 @@ void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) { callExpr( callee(functionDecl(hasAnyName("remove", "remove_if", "unique"))), hasArgument( - 1, - anyOf(cxxConstructExpr(has(ignoringImplicit( - cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end")))) - .bind("end")))), - anything()))) + 1, optionally(cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end")))) + .bind("end")))) .bind("alg"); const auto DeclInStd = type(hasUnqualifiedDesugaredType( tagType(hasDeclaration(decl(isInStdNamespace()))))); Finder->addMatcher( - traverse( - TK_AsIs, - cxxMemberCallExpr( - on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))), - callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1), - hasArgument(0, has(ignoringImplicit(anyOf( - EndCall, has(ignoringImplicit(EndCall)))))), - unless(isInTemplateInstantiation())) - .bind("erase")), + cxxMemberCallExpr( + on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))), + callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1), + hasArgument(0, EndCall)) + .bind("erase"), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h index ef6006dca8888..dd6eb80a41d17 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.h @@ -31,6 +31,9 @@ class InaccurateEraseCheck : public ClangTidyCheck { } void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + llvm::Optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } }; } // namespace bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp index 500210748f52b..2f908e44f00c2 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp @@ -21,11 +21,11 @@ namespace bugprone { namespace { AST_MATCHER(FloatingLiteral, floatHalf) { - const auto &literal = Node.getValue(); + const auto &Literal = Node.getValue(); if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle()) - return literal.convertToFloat() == 0.5f; + return Literal.convertToFloat() == 0.5f; if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble()) - return literal.convertToDouble() == 0.5; + return Literal.convertToDouble() == 0.5; return false; } } // namespace diff --git a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp index 310fbec72a500..777d309b5ccb1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp @@ -7,10 +7,10 @@ //===----------------------------------------------------------------------===// #include "InfiniteLoopCheck.h" +#include "../utils/Aliasing.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Analysis/Analyses/ExprMutationAnalyzer.h" -#include "../utils/Aliasing.h" using namespace clang::ast_matchers; using clang::tidy::utils::hasPtrOrReferenceInFunc; @@ -21,9 +21,9 @@ namespace bugprone { static internal::Matcher loopEndingStmt(internal::Matcher Internal) { - return stmt(anyOf(breakStmt(Internal), returnStmt(Internal), - gotoStmt(Internal), cxxThrowExpr(Internal), - callExpr(Internal, callee(functionDecl(isNoReturn()))))); + return stmt(anyOf( + mapAnyOf(breakStmt, returnStmt, gotoStmt, cxxThrowExpr).with(Internal), + callExpr(Internal, callee(functionDecl(isNoReturn()))))); } /// Return whether `Var` was changed in `LoopStmt`. @@ -122,8 +122,8 @@ void InfiniteLoopCheck::registerMatchers(MatchFinder *Finder) { unless(hasBody(hasDescendant( loopEndingStmt(forFunction(equalsBoundNode("func"))))))); - Finder->addMatcher(stmt(anyOf(whileStmt(LoopCondition), doStmt(LoopCondition), - forStmt(LoopCondition))) + Finder->addMatcher(mapAnyOf(whileStmt, doStmt, forStmt) + .with(LoopCondition) .bind("loop-stmt"), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp index 2b7edc1411eb1..ba6f6bae6df1f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp @@ -35,19 +35,19 @@ class MacroExpansionsWithFileAndLine : public PPCallbacks { void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range, const MacroArgs *Args) override { - bool has_file = false; - bool has_line = false; + bool HasFile = false; + bool HasLine = false; for (const auto& T : MD.getMacroInfo()->tokens()) { if (T.is(tok::identifier)) { StringRef IdentName = T.getIdentifierInfo()->getName(); if (IdentName == "__FILE__") { - has_file = true; + HasFile = true; } else if (IdentName == "__LINE__") { - has_line = true; + HasLine = true; } } } - if (has_file && has_line) { + if (HasFile && HasLine) { SuppressMacroExpansions->insert(Range); } } diff --git a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp index 9a44ba2f58a5d..36d83b2a3ea31 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp @@ -232,7 +232,7 @@ isGivenLengthEqualToSrcLength(const MatchFinder::MatchResult &Result) { return true; if (const auto *LengthExpr = Result.Nodes.getNodeAs(LengthExprName)) - if (dyn_cast(LengthExpr->IgnoreParenImpCasts())) + if (isa(LengthExpr->IgnoreParenImpCasts())) return false; // Check the strlen()'s argument's 'VarDecl' is equal to the source 'VarDecl'. @@ -508,8 +508,8 @@ void NotNullTerminatedResultCheck::storeOptions( } void NotNullTerminatedResultCheck::registerPPCallbacks( - const SourceManager &SM, Preprocessor *pp, Preprocessor *ModuleExpanderPP) { - PP = pp; + const SourceManager &SM, Preprocessor *Pp, Preprocessor *ModuleExpanderPP) { + PP = Pp; } namespace { @@ -750,7 +750,7 @@ void NotNullTerminatedResultCheck::registerMatchers(MatchFinder *Finder) { auto Memcpy = Match({"memcpy", 0, 1, 2, false}); // errno_t memcpy_s(void *dest, size_t ds, const void *src, size_t count) - auto Memcpy_s = Match({"memcpy_s", 0, 2, 3, false}); + auto MemcpyS = Match({"memcpy_s", 0, 2, 3, false}); // void *memchr(const void *src, int c, size_t count) auto Memchr = Match({"memchr", None, 0, 2, false}); @@ -759,7 +759,7 @@ void NotNullTerminatedResultCheck::registerMatchers(MatchFinder *Finder) { auto Memmove = Match({"memmove", 0, 1, 2, false}); // errno_t memmove_s(void *dest, size_t ds, const void *src, size_t count) - auto Memmove_s = Match({"memmove_s", 0, 2, 3, false}); + auto MemmoveS = Match({"memmove_s", 0, 2, 3, false}); // int strncmp(const char *str1, const char *str2, size_t count); auto StrncmpRHS = Match({"strncmp", None, 1, 2, true}); @@ -769,10 +769,10 @@ void NotNullTerminatedResultCheck::registerMatchers(MatchFinder *Finder) { auto Strxfrm = Match({"strxfrm", 0, 1, 2, false}); // errno_t strerror_s(char *buffer, size_t bufferSize, int errnum); - auto Strerror_s = Match({"strerror_s", 0, None, 1, false}); + auto StrerrorS = Match({"strerror_s", 0, None, 1, false}); - auto AnyOfMatchers = anyOf(Memcpy, Memcpy_s, Memmove, Memmove_s, StrncmpRHS, - StrncmpLHS, Strxfrm, Strerror_s); + auto AnyOfMatchers = anyOf(Memcpy, MemcpyS, Memmove, MemmoveS, StrncmpRHS, + StrncmpLHS, Strxfrm, StrerrorS); Finder->addMatcher(callExpr(AnyOfMatchers).bind(FunctionExprName), this); @@ -920,7 +920,7 @@ void NotNullTerminatedResultCheck::memcpy_sFix( void NotNullTerminatedResultCheck::memchrFix( StringRef Name, const MatchFinder::MatchResult &Result) { const auto *FunctionExpr = Result.Nodes.getNodeAs(FunctionExprName); - if (const auto GivenCL = dyn_cast(FunctionExpr->getArg(1))) + if (const auto *GivenCL = dyn_cast(FunctionExpr->getArg(1))) if (GivenCL->getValue() != 0) return; diff --git a/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp index 47a84c225711e..df2968e2e37c4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp @@ -172,8 +172,8 @@ ReservedIdentifierCheck::GetMacroFailureInfo(const Token &MacroNameTok, RenamerClangTidyCheck::DiagInfo ReservedIdentifierCheck::GetDiagInfo(const NamingCheckId &ID, const NamingCheckFailure &Failure) const { - return DiagInfo{Message, [&](DiagnosticBuilder &diag) { - diag << ID.second + return DiagInfo{Message, [&](DiagnosticBuilder &Diag) { + Diag << ID.second << getMessageSelectIndex(Failure.Info.KindName); }}; } diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp index 5790e8f84ceec..1123c7c77be3c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp @@ -35,10 +35,12 @@ AST_MATCHER_P2(Expr, hasSizeOfDescendant, int, Depth, if (const auto *CE = dyn_cast(E)) { const auto M = hasSizeOfDescendant(Depth - 1, InnerMatcher); return M.matches(*CE->getSubExpr(), Finder, Builder); - } else if (const auto *UE = dyn_cast(E)) { + } + if (const auto *UE = dyn_cast(E)) { const auto M = hasSizeOfDescendant(Depth - 1, InnerMatcher); return M.matches(*UE->getSubExpr(), Finder, Builder); - } else if (const auto *BE = dyn_cast(E)) { + } + if (const auto *BE = dyn_cast(E)) { const auto LHS = hasSizeOfDescendant(Depth - 1, InnerMatcher); const auto RHS = hasSizeOfDescendant(Depth - 1, InnerMatcher); return LHS.matches(*BE->getLHS(), Finder, Builder) || diff --git a/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp index ee46818839644..ee45461ed8f2d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp @@ -18,14 +18,14 @@ namespace bugprone { void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) { - auto hasUniqueLock = hasDescendant(declRefExpr( + auto HasUniqueLock = hasDescendant(declRefExpr( hasDeclaration(varDecl(hasType(recordDecl(classTemplateSpecializationDecl( hasName("::std::unique_lock"), hasTemplateArgument( 0, templateArgument(refersToType(qualType(hasDeclaration( cxxRecordDecl(hasName("::std::mutex")))))))))))))); - auto hasWaitDescendantCPP = hasDescendant( + auto HasWaitDescendantCpp = hasDescendant( cxxMemberCallExpr( anyOf( allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl( @@ -34,61 +34,45 @@ void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) { onImplicitObjectArgument( declRefExpr(to(varDecl(hasType(references(recordDecl( hasName("::std::condition_variable")))))))), - hasUniqueLock), + HasUniqueLock), allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl( allOf(hasName("::std::condition_variable::wait_for"), parameterCountIs(2)))))), onImplicitObjectArgument( declRefExpr(to(varDecl(hasType(references(recordDecl( hasName("::std::condition_variable")))))))), - hasUniqueLock), + HasUniqueLock), allOf(hasDescendant(memberExpr(hasDeclaration(functionDecl( allOf(hasName("::std::condition_variable::wait_until"), parameterCountIs(2)))))), onImplicitObjectArgument( declRefExpr(to(varDecl(hasType(references(recordDecl( hasName("::std::condition_variable")))))))), - hasUniqueLock) + HasUniqueLock) )) .bind("wait")); - auto hasWaitDescendantC = hasDescendant( + auto HasWaitDescendantC = hasDescendant( callExpr(callee(functionDecl(hasAnyName("cnd_wait", "cnd_timedwait")))) .bind("wait")); if (getLangOpts().CPlusPlus) { // Check for `CON54-CPP` Finder->addMatcher( - ifStmt( - - allOf(hasWaitDescendantCPP, - unless(anyOf(hasDescendant(ifStmt(hasWaitDescendantCPP)), - hasDescendant(whileStmt(hasWaitDescendantCPP)), - hasDescendant(forStmt(hasWaitDescendantCPP)), - hasDescendant(doStmt(hasWaitDescendantCPP))))) - - ), + ifStmt(HasWaitDescendantCpp, + unless(hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt) + .with(HasWaitDescendantCpp)))), this); } else { // Check for `CON36-C` Finder->addMatcher( - - ifStmt( - allOf(hasWaitDescendantC, - unless(anyOf(hasDescendant(ifStmt(hasWaitDescendantC)), - hasDescendant(whileStmt(hasWaitDescendantC)), - hasDescendant(forStmt(hasWaitDescendantC)), - hasDescendant(doStmt(hasWaitDescendantC)), - hasParent(whileStmt()), - hasParent(compoundStmt(hasParent(whileStmt()))), - hasParent(forStmt()), - hasParent(compoundStmt(hasParent(forStmt()))), - hasParent(doStmt()), - hasParent(compoundStmt(hasParent(doStmt()))))) - - )) - - , + ifStmt(HasWaitDescendantC, + unless(anyOf( + hasDescendant(mapAnyOf(ifStmt, whileStmt, forStmt, doStmt) + .with(HasWaitDescendantC)), + hasParent(mapAnyOf(whileStmt, forStmt, doStmt)), + hasParent(compoundStmt( + hasParent(mapAnyOf(whileStmt, forStmt, doStmt))))))), this); } } diff --git a/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp index b533db760d5eb..080d4ab67d647 100644 --- a/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/StringLiteralWithEmbeddedNulCheck.cpp @@ -18,8 +18,8 @@ namespace bugprone { namespace { AST_MATCHER(StringLiteral, containsNul) { - for (size_t i = 0; i < Node.getLength(); ++i) - if (Node.getCodeUnit(i) == '\0') + for (size_t I = 0; I < Node.getLength(); ++I) + if (Node.getCodeUnit(I) == '\0') return true; return false; } diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp index cc59601066ede..3faa28c0158a0 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp @@ -117,14 +117,14 @@ void SuspiciousEnumUsageCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } void SuspiciousEnumUsageCheck::registerMatchers(MatchFinder *Finder) { - const auto enumExpr = [](StringRef RefName, StringRef DeclName) { + const auto EnumExpr = [](StringRef RefName, StringRef DeclName) { return expr(ignoringImpCasts(expr().bind(RefName)), ignoringImpCasts(hasType(enumDecl().bind(DeclName)))); }; Finder->addMatcher( - binaryOperator(hasOperatorName("|"), hasLHS(enumExpr("", "enumDecl")), - hasRHS(expr(enumExpr("", "otherEnumDecl"), + binaryOperator(hasOperatorName("|"), hasLHS(EnumExpr("", "enumDecl")), + hasRHS(expr(EnumExpr("", "otherEnumDecl"), ignoringImpCasts(hasType(enumDecl( unless(equalsBoundNode("enumDecl")))))))) .bind("diffEnumOp"), @@ -132,8 +132,8 @@ void SuspiciousEnumUsageCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( binaryOperator(hasAnyOperatorName("+", "|"), - hasLHS(enumExpr("lhsExpr", "enumDecl")), - hasRHS(expr(enumExpr("rhsExpr", ""), + hasLHS(EnumExpr("lhsExpr", "enumDecl")), + hasRHS(expr(EnumExpr("rhsExpr", ""), ignoringImpCasts(hasType( enumDecl(equalsBoundNode("enumDecl"))))))), this); @@ -141,12 +141,12 @@ void SuspiciousEnumUsageCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( binaryOperator( hasAnyOperatorName("+", "|"), - hasOperands(expr(hasType(isInteger()), unless(enumExpr("", ""))), - enumExpr("enumExpr", "enumDecl"))), + hasOperands(expr(hasType(isInteger()), unless(EnumExpr("", ""))), + EnumExpr("enumExpr", "enumDecl"))), this); Finder->addMatcher(binaryOperator(hasAnyOperatorName("|=", "+="), - hasRHS(enumExpr("enumExpr", "enumDecl"))), + hasRHS(EnumExpr("enumExpr", "enumDecl"))), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp index 8fd1abe03646e..092809eaa906a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp @@ -108,8 +108,8 @@ void SuspiciousMissingCommaCheck::check( // Count the number of occurrence of concatenated string literal. unsigned int Count = 0; - for (unsigned int i = 0; i < Size; ++i) { - const Expr *Child = InitializerList->getInit(i)->IgnoreImpCasts(); + for (unsigned int I = 0; I < Size; ++I) { + const Expr *Child = InitializerList->getInit(I)->IgnoreImpCasts(); if (const auto *Literal = dyn_cast(Child)) { if (Literal->getNumConcatenated() > 1) ++Count; diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp index b234c3d128edc..a99492d29d5fe 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp @@ -113,10 +113,8 @@ void SuspiciousStringCompareCheck::registerMatchers(MatchFinder *Finder) { // Detect suspicious calls to string compare: // 'if (strcmp())' -> 'if (strcmp() != 0)' Finder->addMatcher( - stmt(anyOf(ifStmt(hasCondition(StringCompareCallExpr)), - whileStmt(hasCondition(StringCompareCallExpr)), - doStmt(hasCondition(StringCompareCallExpr)), - forStmt(hasCondition(StringCompareCallExpr)), + stmt(anyOf(mapAnyOf(ifStmt, whileStmt, doStmt, forStmt) + .with(hasCondition(StringCompareCallExpr)), binaryOperator(hasAnyOperatorName("&&", "||"), hasEitherOperand(StringCompareCallExpr)))) .bind("missing-comparison"), diff --git a/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.cpp index beeeb2c8751e5..43402a2212182 100644 --- a/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TerminatingContinueCheck.cpp @@ -19,7 +19,7 @@ namespace tidy { namespace bugprone { void TerminatingContinueCheck::registerMatchers(MatchFinder *Finder) { - const auto doWithFalse = + const auto DoWithFalse = doStmt(hasCondition(ignoringImpCasts( anyOf(cxxBoolLiteral(equals(false)), integerLiteral(equals(0)), cxxNullPtrLiteralExpr(), gnuNullExpr()))), @@ -29,7 +29,7 @@ void TerminatingContinueCheck::registerMatchers(MatchFinder *Finder) { continueStmt(hasAncestor(stmt(anyOf(forStmt(), whileStmt(), cxxForRangeStmt(), doStmt())) .bind("closestLoop")), - hasAncestor(doWithFalse)) + hasAncestor(DoWithFalse)) .bind("continue"), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp index 7539b51ebd12f..bf4bb750da027 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp @@ -40,12 +40,9 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) { // Self-check: Code compares something with 'this' pointer. We don't check // whether it is actually the parameter what we compare. - const auto HasNoSelfCheck = cxxMethodDecl(unless(anyOf( - hasDescendant(binaryOperator(hasAnyOperatorName("==", "!="), - has(ignoringParenCasts(cxxThisExpr())))), - hasDescendant(cxxOperatorCallExpr( - hasAnyOverloadedOperatorName("==", "!="), argumentCountIs(2), - has(ignoringParenCasts(cxxThisExpr()))))))); + const auto HasNoSelfCheck = cxxMethodDecl(unless(hasDescendant( + binaryOperation(hasAnyOperatorName("==", "!="), + hasEitherOperand(ignoringParenCasts(cxxThisExpr())))))); // Both copy-and-swap and copy-and-move method creates a copy first and // assign it to 'this' with swap or move. diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp index 9d08dbe1ead7b..028fefa9b99e4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -256,7 +256,7 @@ void UseAfterMoveFinder::getDeclRefs( if (!S) continue; - auto addDeclRefs = [this, Block, + auto AddDeclRefs = [this, Block, DeclRefs](const ArrayRef Matches) { for (const auto &Match : Matches) { const auto *DeclRef = Match.getNodeAs("declref"); @@ -275,9 +275,9 @@ void UseAfterMoveFinder::getDeclRefs( unless(inDecltypeOrTemplateArg())) .bind("declref"); - addDeclRefs(match(traverse(TK_AsIs, findAll(DeclRefMatcher)), *S->getStmt(), + AddDeclRefs(match(traverse(TK_AsIs, findAll(DeclRefMatcher)), *S->getStmt(), *Context)); - addDeclRefs(match(findAll(cxxOperatorCallExpr( + AddDeclRefs(match(findAll(cxxOperatorCallExpr( hasAnyOverloadedOperatorName("*", "->", "[]"), hasArgument(0, DeclRefMatcher)) .bind("operator")), @@ -310,9 +310,7 @@ void UseAfterMoveFinder::getReinits( // Assignment. In addition to the overloaded assignment operator, // test for built-in assignment as well, since template functions // may be instantiated to use std::move() on built-in types. - binaryOperator(hasOperatorName("="), hasLHS(DeclRefMatcher)), - cxxOperatorCallExpr(hasOverloadedOperatorName("="), - hasArgument(0, DeclRefMatcher)), + binaryOperation(hasOperatorName("="), hasLHS(DeclRefMatcher)), // Declaration. We treat this as a type of reinitialization too, // so we don't need to treat it separately. declStmt(hasDescendant(equalsNode(MovedVariable))), @@ -448,9 +446,9 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) { if (!Arg->getDecl()->getDeclContext()->isFunctionOrMethod()) return; - UseAfterMoveFinder finder(Result.Context); + UseAfterMoveFinder Finder(Result.Context); UseAfterMove Use; - if (finder.find(FunctionBody, MovingCall, Arg->getDecl(), &Use)) + if (Finder.find(FunctionBody, MovingCall, Arg->getDecl(), &Use)) emitDiagnostic(MovingCall, Arg, Use, this, Result.Context); } diff --git a/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.cpp b/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.cpp index 847f05e7d9886..9733a4e7c1f56 100644 --- a/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.cpp @@ -24,12 +24,12 @@ void LimitedRandomnessCheck::registerMatchers(MatchFinder *Finder) { } void LimitedRandomnessCheck::check(const MatchFinder::MatchResult &Result) { - std::string msg = ""; + std::string Msg = ""; if (getLangOpts().CPlusPlus) - msg = "; use C++11 random library instead"; + Msg = "; use C++11 random library instead"; const auto *MatchedDecl = Result.Nodes.getNodeAs("randomGenerator"); - diag(MatchedDecl->getBeginLoc(), "rand() has limited randomness" + msg); + diag(MatchedDecl->getBeginLoc(), "rand() has limited randomness" + Msg); } } // namespace cert diff --git a/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp b/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp index fa6e82c1c12b3..d4ce995d61b62 100644 --- a/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp @@ -30,12 +30,8 @@ void MutatingCopyCheck::registerMatchers(MatchFinder *Finder) { MemberExprOrSourceObject); const auto IsSourceMutatingAssignment = traverse( - TK_AsIs, - expr(anyOf(binaryOperator(isAssignmentOperator(), hasLHS(IsPartOfSource)) - .bind(MutatingOperatorName), - cxxOperatorCallExpr(isAssignmentOperator(), - hasArgument(0, IsPartOfSource)) - .bind(MutatingOperatorName)))); + TK_AsIs, binaryOperation(hasOperatorName("="), hasLHS(IsPartOfSource)) + .bind(MutatingOperatorName)); const auto MemberExprOrSelf = anyOf(memberExpr(), cxxThisExpr()); @@ -43,9 +39,7 @@ void MutatingCopyCheck::registerMatchers(MatchFinder *Finder) { unless(hasDescendant(expr(unless(MemberExprOrSelf)))), MemberExprOrSelf); const auto IsSelfMutatingAssignment = - expr(anyOf(binaryOperator(isAssignmentOperator(), hasLHS(IsPartOfSelf)), - cxxOperatorCallExpr(isAssignmentOperator(), - hasArgument(0, IsPartOfSelf)))); + binaryOperation(isAssignmentOperator(), hasLHS(IsPartOfSelf)); const auto IsSelfMutatingMemberFunction = functionDecl(hasBody(hasDescendant(IsSelfMutatingAssignment))); diff --git a/clang-tools-extra/clang-tidy/cert/StrToNumCheck.cpp b/clang-tools-extra/clang-tidy/cert/StrToNumCheck.cpp index 9d26060c51a56..c7abbe180f606 100644 --- a/clang-tools-extra/clang-tidy/cert/StrToNumCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/StrToNumCheck.cpp @@ -8,8 +8,8 @@ #include "StrToNumCheck.h" #include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/AST/FormatString.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/ADT/StringSwitch.h" #include @@ -48,7 +48,7 @@ enum class ConversionKind { ToLongDouble }; -ConversionKind ClassifyConversionFunc(const FunctionDecl *FD) { +ConversionKind classifyConversionFunc(const FunctionDecl *FD) { return llvm::StringSwitch(FD->getName()) .Cases("atoi", "atol", ConversionKind::ToInt) .Case("atoll", ConversionKind::ToLongInt) @@ -56,7 +56,7 @@ ConversionKind ClassifyConversionFunc(const FunctionDecl *FD) { .Default(ConversionKind::None); } -ConversionKind ClassifyFormatString(StringRef Fmt, const LangOptions &LO, +ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO, const TargetInfo &TI) { // Scan the format string for the first problematic format specifier, then // report that as the conversion type. This will miss additional conversion @@ -66,8 +66,8 @@ ConversionKind ClassifyFormatString(StringRef Fmt, const LangOptions &LO, ConversionKind CK; bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, - const char *startSpecifier, - unsigned specifierLen) override { + const char *StartSpecifier, + unsigned SpecifierLen) override { // If we just consume the argument without assignment, we don't care // about it having conversion errors. if (!FS.consumesDataArgument()) @@ -130,7 +130,7 @@ ConversionKind ClassifyFormatString(StringRef Fmt, const LangOptions &LO, return H.get(); } -StringRef ClassifyConversionType(ConversionKind K) { +StringRef classifyConversionType(ConversionKind K) { switch (K) { case ConversionKind::None: llvm_unreachable("Unexpected conversion kind"); @@ -150,7 +150,7 @@ StringRef ClassifyConversionType(ConversionKind K) { llvm_unreachable("Unknown conversion kind"); } -StringRef ClassifyReplacement(ConversionKind K) { +StringRef classifyReplacement(ConversionKind K) { switch (K) { case ConversionKind::None: llvm_unreachable("Unexpected conversion kind"); @@ -186,7 +186,7 @@ void StrToNumCheck::check(const MatchFinder::MatchResult &Result) { Result.Nodes.getNodeAs("converter")) { // Converter functions are always incorrect to use. FuncDecl = ConverterFunc; - Conversion = ClassifyConversionFunc(ConverterFunc); + Conversion = classifyConversionFunc(ConverterFunc); } else if (const auto *FFD = Result.Nodes.getNodeAs("formatted")) { StringRef FmtStr; @@ -213,7 +213,7 @@ void StrToNumCheck::check(const MatchFinder::MatchResult &Result) { // Formatted input functions need further checking of the format string to // determine whether a problematic conversion may be happening. - Conversion = ClassifyFormatString(FmtStr, getLangOpts(), + Conversion = classifyFormatString(FmtStr, getLangOpts(), Result.Context->getTargetInfo()); if (Conversion != ConversionKind::None) FuncDecl = FFD; @@ -225,8 +225,8 @@ void StrToNumCheck::check(const MatchFinder::MatchResult &Result) { diag(Call->getExprLoc(), "%0 used to convert a string to %1, but function will not report " "conversion errors; consider using '%2' instead") - << FuncDecl << ClassifyConversionType(Conversion) - << ClassifyReplacement(Conversion); + << FuncDecl << classifyConversionType(Conversion) + << classifyReplacement(Conversion); } } // namespace cert diff --git a/clang-tools-extra/clang-tidy/concurrency/MtUnsafeCheck.cpp b/clang-tools-extra/clang-tidy/concurrency/MtUnsafeCheck.cpp index bc9f7403b6e92..57c2c9c0a0644 100644 --- a/clang-tools-extra/clang-tidy/concurrency/MtUnsafeCheck.cpp +++ b/clang-tools-extra/clang-tidy/concurrency/MtUnsafeCheck.cpp @@ -277,8 +277,8 @@ template <> struct OptionEnumMapping { namespace concurrency { static ast_matchers::internal::Matcher -hasAnyMtUnsafeNames(MtUnsafeCheck::FunctionSet libc) { - switch (libc) { +hasAnyMtUnsafeNames(MtUnsafeCheck::FunctionSet Libc) { + switch (Libc) { case MtUnsafeCheck::FunctionSet::Posix: return hasAnyName(PosixFunctions); case MtUnsafeCheck::FunctionSet::Glibc: diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp index cf3a16a4dd7dd..bd0d1ac323137 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidGotoCheck.cpp @@ -29,10 +29,8 @@ void AvoidGotoCheck::registerMatchers(MatchFinder *Finder) { // Check if the 'goto' is used for control flow other than jumping // out of a nested loop. - auto Loop = stmt(anyOf(forStmt(), cxxForRangeStmt(), whileStmt(), doStmt())); - auto NestedLoop = - stmt(anyOf(forStmt(hasAncestor(Loop)), cxxForRangeStmt(hasAncestor(Loop)), - whileStmt(hasAncestor(Loop)), doStmt(hasAncestor(Loop)))); + auto Loop = mapAnyOf(forStmt, cxxForRangeStmt, whileStmt, doStmt); + auto NestedLoop = Loop.with(hasAncestor(Loop)); Finder->addMatcher(gotoStmt(anyOf(unless(hasAncestor(NestedLoop)), unless(isForwardJumping()))) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp index eb21bb44f63d1..4f56df0b4ff77 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp @@ -22,8 +22,8 @@ namespace cppcoreguidelines { namespace { bool isCapsOnly(StringRef Name) { - return std::all_of(Name.begin(), Name.end(), [](const char c) { - if (std::isupper(c) || std::isdigit(c) || c == '_') + return std::all_of(Name.begin(), Name.end(), [](const char C) { + if (std::isupper(C) || std::isdigit(C) || C == '_') return true; return false; }); diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp index 6819d6a4174f8..86371fd67c533 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp @@ -111,12 +111,12 @@ static bool getFloatingConstantExprValue(const ASTContext &Context, namespace { struct IntegerRange { - bool Contains(const IntegerRange &From) const { + bool contains(const IntegerRange &From) const { return llvm::APSInt::compareValues(Lower, From.Lower) <= 0 && llvm::APSInt::compareValues(Upper, From.Upper) >= 0; } - bool Contains(const llvm::APSInt &Value) const { + bool contains(const llvm::APSInt &Value) const { return llvm::APSInt::compareValues(Lower, Value) <= 0 && llvm::APSInt::compareValues(Upper, Value) >= 0; } @@ -160,14 +160,14 @@ static bool isWideEnoughToHold(const ASTContext &Context, const BuiltinType &ToType) { IntegerRange FromIntegerRange = createFromType(Context, FromType); IntegerRange ToIntegerRange = createFromType(Context, ToType); - return ToIntegerRange.Contains(FromIntegerRange); + return ToIntegerRange.contains(FromIntegerRange); } static bool isWideEnoughToHold(const ASTContext &Context, const llvm::APSInt &IntegerConstant, const BuiltinType &ToType) { IntegerRange ToIntegerRange = createFromType(Context, ToType); - return ToIntegerRange.Contains(IntegerConstant); + return ToIntegerRange.contains(IntegerConstant); } static llvm::SmallString<64> getValueAsString(const llvm::APSInt &Value, diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp index 6873e23e7dd13..f172097863b2e 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp @@ -66,7 +66,7 @@ void ProTypeCstyleCastCheck::check(const MatchFinder::MatchResult &Result) { MatchedCast->getRParenLoc().getLocWithOffset(-1)), *Result.SourceManager, getLangOpts()); - auto diag_builder = diag( + auto DiagBuilder = diag( MatchedCast->getBeginLoc(), "do not use C-style cast to downcast from a base to a derived class; " "use dynamic_cast instead"); @@ -76,14 +76,14 @@ void ProTypeCstyleCastCheck::check(const MatchFinder::MatchResult &Result) { std::string CastText = ("dynamic_cast<" + DestTypeString + ">").str(); if (!isa(SubExpr)) { CastText.push_back('('); - diag_builder << FixItHint::CreateInsertion( + DiagBuilder << FixItHint::CreateInsertion( Lexer::getLocForEndOfToken(SubExpr->getEndLoc(), 0, *Result.SourceManager, getLangOpts()), ")"); } auto ParenRange = CharSourceRange::getTokenRange( MatchedCast->getLParenLoc(), MatchedCast->getRParenLoc()); - diag_builder << FixItHint::CreateReplacement(ParenRange, CastText); + DiagBuilder << FixItHint::CreateReplacement(ParenRange, CastText); } else { diag( MatchedCast->getBeginLoc(), diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp index 67856be843e79..6b40e525f7dd5 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp @@ -140,17 +140,17 @@ struct IntializerInsertion { assert(!Initializers.empty() && "No initializers to insert"); std::string Code; llvm::raw_string_ostream Stream(Code); - std::string joined = + std::string Joined = llvm::join(Initializers.begin(), Initializers.end(), "(), "); switch (Placement) { case InitializerPlacement::New: - Stream << " : " << joined << "()"; + Stream << " : " << Joined << "()"; break; case InitializerPlacement::Before: - Stream << " " << joined << "(),"; + Stream << " " << Joined << "(),"; break; case InitializerPlacement::After: - Stream << ", " << joined << "()"; + Stream << ", " << Joined << "()"; break; } return Stream.str(); diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp index f6aeb83213371..ec0e87ae22c05 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp @@ -17,7 +17,7 @@ namespace clang { namespace tidy { namespace cppcoreguidelines { -const internal::VariadicDynCastAllOfMatcher vAArgExpr; +const internal::VariadicDynCastAllOfMatcher VAArgExpr; static constexpr StringRef AllowedVariadics[] = { // clang-format off @@ -71,7 +71,7 @@ AST_MATCHER_P(AdjustedType, hasOriginalType, } // namespace void ProTypeVarargCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(vAArgExpr().bind("va_use"), this); + Finder->addMatcher(VAArgExpr().bind("va_use"), this); Finder->addMatcher( callExpr(callee(functionDecl(isVariadic(), diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp index 9c16436a273e7..c4684d41f78f0 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp @@ -90,8 +90,8 @@ join(ArrayRef SMFS, Stream << toString(SMFS[0]); size_t LastIndex = SMFS.size() - 1; - for (size_t i = 1; i < LastIndex; ++i) { - Stream << ", " << toString(SMFS[i]); + for (size_t I = 1; I < LastIndex; ++I) { + Stream << ", " << toString(SMFS[I]); } if (LastIndex != 0) { Stream << AndOr << toString(SMFS[LastIndex]); @@ -107,11 +107,11 @@ void SpecialMemberFunctionsCheck::check( ClassDefId ID(MatchedDecl->getLocation(), std::string(MatchedDecl->getName())); - auto StoreMember = [this, &ID](SpecialMemberFunctionData data) { + auto StoreMember = [this, &ID](SpecialMemberFunctionData Data) { llvm::SmallVectorImpl &Members = ClassWithSpecialMembers[ID]; - if (!llvm::is_contained(Members, data)) - Members.push_back(std::move(data)); + if (!llvm::is_contained(Members, Data)) + Members.push_back(std::move(Data)); }; if (const auto *Dtor = Result.Nodes.getNodeAs("dtor")) { @@ -146,14 +146,14 @@ void SpecialMemberFunctionsCheck::checkForMissingMembers( llvm::SmallVector MissingMembers; auto HasMember = [&](SpecialMemberFunctionKind Kind) { - return llvm::any_of(DefinedMembers, [Kind](const auto &data) { - return data.FunctionKind == Kind; + return llvm::any_of(DefinedMembers, [Kind](const auto &Data) { + return Data.FunctionKind == Kind; }); }; auto IsDeleted = [&](SpecialMemberFunctionKind Kind) { - return llvm::any_of(DefinedMembers, [Kind](const auto &data) { - return data.FunctionKind == Kind && data.IsDeleted; + return llvm::any_of(DefinedMembers, [Kind](const auto &Data) { + return Data.FunctionKind == Kind && Data.IsDeleted; }); }; @@ -197,7 +197,7 @@ void SpecialMemberFunctionsCheck::checkForMissingMembers( if (!MissingMembers.empty()) { llvm::SmallVector DefinedMemberKinds; llvm::transform(DefinedMembers, std::back_inserter(DefinedMemberKinds), - [](const auto &data) { return data.FunctionKind; }); + [](const auto &Data) { return Data.FunctionKind; }); diag(ID.first, "class '%0' defines %1 but does not define %2") << ID.second << cppcoreguidelines::join(DefinedMemberKinds, " and ") << cppcoreguidelines::join(MissingMembers, " or "); diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp index 76b8ac02990e1..ae3222a2bd1a4 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp @@ -28,23 +28,23 @@ AST_MATCHER(CXXRecordDecl, hasBases) { // Adds a node (by name) to the interface map, if it was not present in the map // previously. void MultipleInheritanceCheck::addNodeToInterfaceMap(const CXXRecordDecl *Node, - bool isInterface) { + bool IsInterface) { assert(Node->getIdentifier()); StringRef Name = Node->getIdentifier()->getName(); - InterfaceMap.insert(std::make_pair(Name, isInterface)); + InterfaceMap.insert(std::make_pair(Name, IsInterface)); } // Returns "true" if the boolean "isInterface" has been set to the // interface status of the current Node. Return "false" if the // interface status for the current node is not yet known. bool MultipleInheritanceCheck::getInterfaceStatus(const CXXRecordDecl *Node, - bool &isInterface) const { + bool &IsInterface) const { assert(Node->getIdentifier()); StringRef Name = Node->getIdentifier()->getName(); llvm::StringMapConstIterator Pair = InterfaceMap.find(Name); if (Pair == InterfaceMap.end()) return false; - isInterface = Pair->second; + IsInterface = Pair->second; return true; } diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp index 3125889d1918e..a32603dc2cb0b 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp @@ -67,7 +67,7 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) { if (CastExpr->getCastKind() == CK_ToVoid) return; - auto isFunction = [](QualType T) { + auto IsFunction = [](QualType T) { T = T.getCanonicalType().getNonReferenceType(); return T->isFunctionType() || T->isFunctionPointerType() || T->isMemberFunctionPointerType(); @@ -84,7 +84,7 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) { CastExpr->getLParenLoc(), CastExpr->getSubExprAsWritten()->getBeginLoc()); bool FnToFnCast = - isFunction(SourceTypeAsWritten) && isFunction(DestTypeAsWritten); + IsFunction(SourceTypeAsWritten) && IsFunction(DestTypeAsWritten); const bool ConstructorCast = !CastExpr->getTypeAsWritten().hasQualifiers() && DestTypeAsWritten->isRecordType() && diff --git a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp index 3a5aaa1e18328..783db8c0131b0 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.cpp @@ -21,7 +21,7 @@ namespace tidy { namespace google { namespace readability { -constexpr llvm::StringLiteral kDisabledTestPrefix = "DISABLED_"; +constexpr llvm::StringLiteral KDisabledTestPrefix = "DISABLED_"; // Determines whether the macro is a Googletest test macro. static bool isGoogletestTestMacro(StringRef MacroName) { @@ -63,7 +63,7 @@ class AvoidUnderscoreInGoogletestNameCallback : public PPCallbacks { std::string TestNameMaybeDisabled = PP->getSpelling(*TestNameToken); StringRef TestName = TestNameMaybeDisabled; - TestName.consume_front(kDisabledTestPrefix); + TestName.consume_front(KDisabledTestPrefix); if (TestName.contains('_')) Check->diag(TestNameToken->getLocation(), "avoid using \"_\" in test name \"%0\" according to " diff --git a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h index a9989ee51bcf6..eb2b2bfcc6aae 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h +++ b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h @@ -17,7 +17,7 @@ namespace google { namespace readability { // Check for underscores in the names of googletest tests, per -// https://github.com/google/googletest/blob/master/googletest/docs/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore +// https://github.com/google/googletest/blob/master/docs/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore /// /// For the user-facing documentation see: /// http://clang.llvm.org/extra/clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name.html diff --git a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp index 80fc139e4b9c1..59f2dfb50d6b0 100644 --- a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp @@ -35,7 +35,7 @@ void ExplicitConstructorCheck::registerMatchers(MatchFinder *Finder) { // Looks for the token matching the predicate and returns the range of the found // token including trailing whitespace. -static SourceRange FindToken(const SourceManager &Sources, +static SourceRange findToken(const SourceManager &Sources, const LangOptions &LangOpts, SourceLocation StartLoc, SourceLocation EndLoc, bool (*Pred)(const Token &)) { @@ -103,17 +103,17 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { Ctor->getMinRequiredArguments() > 1) return; - bool takesInitializerList = isStdInitializerList( + bool TakesInitializerList = isStdInitializerList( Ctor->getParamDecl(0)->getType().getNonReferenceType()); if (Ctor->isExplicit() && - (Ctor->isCopyOrMoveConstructor() || takesInitializerList)) { - auto isKWExplicit = [](const Token &Tok) { + (Ctor->isCopyOrMoveConstructor() || TakesInitializerList)) { + auto IsKwExplicit = [](const Token &Tok) { return Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "explicit"; }; SourceRange ExplicitTokenRange = - FindToken(*Result.SourceManager, getLangOpts(), - Ctor->getOuterLocStart(), Ctor->getEndLoc(), isKWExplicit); + findToken(*Result.SourceManager, getLangOpts(), + Ctor->getOuterLocStart(), Ctor->getEndLoc(), IsKwExplicit); StringRef ConstructorDescription; if (Ctor->isMoveConstructor()) ConstructorDescription = "move"; @@ -133,7 +133,7 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { } if (Ctor->isExplicit() || Ctor->isCopyOrMoveConstructor() || - takesInitializerList) + TakesInitializerList) return; bool SingleArgument = diff --git a/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp b/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp index f29d650bf5fcf..cedc3850200f5 100644 --- a/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp @@ -60,8 +60,8 @@ FixItHint generateFixItHint(const FunctionDecl *Decl) { size_t Index = 0; bool AtWordBoundary = true; while (Index < NewName.size()) { - char ch = NewName[Index]; - if (isalnum(ch)) { + char Ch = NewName[Index]; + if (isalnum(Ch)) { // Capitalize the first letter after every word boundary. if (AtWordBoundary) { NewName[Index] = toupper(NewName[Index]); diff --git a/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp index 91e2cda0c24fb..7feb0c73f4d11 100644 --- a/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp +++ b/clang-tools-extra/clang-tidy/hicpp/MultiwayPathsCoveredCheck.cpp @@ -83,10 +83,9 @@ static std::size_t getNumberOfPossibleValues(QualType T, // and would not return 2 as result. if (T->isBooleanType()) return 2; - else if (T->isIntegralType(Context)) + if (T->isIntegralType(Context)) return twoPow(Context.getTypeSize(T)); - else - return 1; + return 1; } void MultiwayPathsCoveredCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp b/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp index 132178f892eaf..201c8d23dd4db 100644 --- a/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp @@ -47,8 +47,9 @@ void PreferIsaOrDynCastInConditionalsCheck::registerMatchers( allOf(callee(namedDecl(hasAnyName("isa", "cast", "cast_or_null", "dyn_cast", "dyn_cast_or_null")) .bind("func")), - hasArgument(0, anyOf(declRefExpr().bind("arg"), - cxxMemberCallExpr().bind("arg")))))) + hasArgument( + 0, + mapAnyOf(declRefExpr, cxxMemberCallExpr).bind("arg"))))) .bind("rhs"); Finder->addMatcher( diff --git a/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp b/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp index 5b1dbf3ac33e6..1200230c53edf 100644 --- a/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/NoRecursionCheck.cpp @@ -135,10 +135,10 @@ template class SmartSmallSetVector { /// Insert a new element into the SmartSmallSetVector. /// \returns true if the element was inserted into the SmartSmallSetVector. bool insert(const T &X) { - bool result = setInsert(X); - if (result) + bool Result = setInsert(X); + if (Result) Vector.push_back(X); - return result; + return Result; } /// Clear the SmartSmallSetVector and return the underlying vector. @@ -157,7 +157,7 @@ using CallStackTy = // In given SCC, find *some* call stack that will be cyclic. // This will only find *one* such stack, it might not be the smallest one, // and there may be other loops. -CallStackTy PathfindSomeCycle(ArrayRef SCC) { +CallStackTy pathfindSomeCycle(ArrayRef SCC) { // We'll need to be able to performantly look up whether some CallGraphNode // is in SCC or not, so cache all the SCC elements in a set. const ImmutableSmallSet SCCElts(SCC); @@ -212,7 +212,7 @@ void NoRecursionCheck::handleSCC(ArrayRef SCC) { // the call graph. It doesn't *really* tell us about the cycles they form. // And there may be more than one cycle in SCC. // So let's form a call stack that eventually exposes *some* cycle. - const CallStackTy EventuallyCyclicCallStack = PathfindSomeCycle(SCC); + const CallStackTy EventuallyCyclicCallStack = pathfindSomeCycle(SCC); assert(!EventuallyCyclicCallStack.empty() && "We should've found the cycle"); // While last node of the call stack does cause a loop, due to the way we diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index 9217c22b07bc5..6a8436054b337 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -144,8 +144,7 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) { if (LeftUnaryExpr->isArgumentType() && RightUnaryExpr->isArgumentType()) return LeftUnaryExpr->getArgumentType() == RightUnaryExpr->getArgumentType(); - else if (!LeftUnaryExpr->isArgumentType() && - !RightUnaryExpr->isArgumentType()) + if (!LeftUnaryExpr->isArgumentType() && !RightUnaryExpr->isArgumentType()) return areEquivalentExpr(LeftUnaryExpr->getArgumentExpr(), RightUnaryExpr->getArgumentExpr()); @@ -166,11 +165,11 @@ static bool areEquivalentRanges(BinaryOperatorKind OpcodeLHS, return OpcodeLHS == OpcodeRHS; // Handle the case where constants are off by one: x <= 4 <==> x < 5. - APSInt ValueLHS_plus1; + APSInt ValueLhsPlus1; return ((OpcodeLHS == BO_LE && OpcodeRHS == BO_LT) || (OpcodeLHS == BO_GT && OpcodeRHS == BO_GE)) && - incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) && - APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0; + incrementWithoutOverflow(ValueLHS, ValueLhsPlus1) && + APSInt::compareValues(ValueLhsPlus1, ValueRHS) == 0; } // For a given expression 'x', returns whether the ranges covered by the @@ -208,10 +207,10 @@ static bool areExclusiveRanges(BinaryOperatorKind OpcodeLHS, return true; // Handle the case where constants are off by one: x > 5 && x < 6. - APSInt ValueLHS_plus1; + APSInt ValueLhsPlus1; if (OpcodeLHS == BO_GT && OpcodeRHS == BO_LT && - incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) && - APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0) + incrementWithoutOverflow(ValueLHS, ValueLhsPlus1) && + APSInt::compareValues(ValueLhsPlus1, ValueRHS) == 0) return true; return false; @@ -247,10 +246,10 @@ static bool rangesFullyCoverDomain(BinaryOperatorKind OpcodeLHS, } // Handle the case where constants are off by one: x <= 4 || x >= 5. - APSInt ValueLHS_plus1; + APSInt ValueLhsPlus1; if (OpcodeLHS == BO_LE && OpcodeRHS == BO_GE && - incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) && - APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0) + incrementWithoutOverflow(ValueLHS, ValueLhsPlus1) && + APSInt::compareValues(ValueLhsPlus1, ValueRHS) == 0) return true; // Handle cases where the constants are different: x > 4 || x <= 7. @@ -623,7 +622,7 @@ static bool isNonConstReferenceType(QualType ParamType) { // controlled by the parameter `ParamsToCheckCount`. static bool canOverloadedOperatorArgsBeModified(const CXXOperatorCallExpr *OperatorCall, - bool checkSecondParam) { + bool CheckSecondParam) { const auto *OperatorDecl = dyn_cast_or_null(OperatorCall->getCalleeDecl()); // if we can't find the declaration, conservatively assume it can modify @@ -643,7 +642,7 @@ canOverloadedOperatorArgsBeModified(const CXXOperatorCallExpr *OperatorCall, if (isNonConstReferenceType(OperatorDecl->getParamDecl(0)->getType())) return true; - return checkSecondParam && ParamCount == 2 && + return CheckSecondParam && ParamCount == 2 && isNonConstReferenceType(OperatorDecl->getParamDecl(1)->getType()); } diff --git a/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp b/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp index 3e3f8dbf02ff5..2d6504cae689a 100644 --- a/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp @@ -27,48 +27,37 @@ StaticAssertCheck::StaticAssertCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) {} void StaticAssertCheck::registerMatchers(MatchFinder *Finder) { - auto NegatedString = unaryOperator( - hasOperatorName("!"), hasUnaryOperand(ignoringImpCasts(stringLiteral()))); + auto NegatedString = + unaryOperator(hasOperatorName("!"), hasUnaryOperand(stringLiteral())); auto IsAlwaysFalse = expr(anyOf(cxxBoolLiteral(equals(false)), integerLiteral(equals(0)), cxxNullPtrLiteralExpr(), gnuNullExpr(), NegatedString)) .bind("isAlwaysFalse"); - auto IsAlwaysFalseWithCast = ignoringParenImpCasts(anyOf( - IsAlwaysFalse, cStyleCastExpr(has(ignoringParenImpCasts(IsAlwaysFalse))) - .bind("castExpr"))); - auto AssertExprRoot = anyOf( - binaryOperator( - hasAnyOperatorName("&&", "=="), - hasEitherOperand(ignoringImpCasts(stringLiteral().bind("assertMSG"))), - anyOf(binaryOperator(hasEitherOperand(IsAlwaysFalseWithCast)), - anything())) - .bind("assertExprRoot"), - IsAlwaysFalse); + auto IsAlwaysFalseWithCast = + anyOf(IsAlwaysFalse, cStyleCastExpr(has(IsAlwaysFalse)).bind("castExpr")); + auto AssertExprRoot = + anyOf(binaryOperator( + hasAnyOperatorName("&&", "=="), + hasEitherOperand(stringLiteral().bind("assertMSG")), + anyOf(binaryOperator(hasEitherOperand(IsAlwaysFalseWithCast)), + anything())) + .bind("assertExprRoot"), + IsAlwaysFalse); auto NonConstexprFunctionCall = callExpr(hasDeclaration(functionDecl(unless(isConstexpr())))); auto AssertCondition = - expr( - anyOf(expr(ignoringParenCasts(anyOf( - AssertExprRoot, unaryOperator(hasUnaryOperand( - ignoringParenCasts(AssertExprRoot)))))), - anything()), - unless(findAll(NonConstexprFunctionCall))) + expr(optionally(expr(anyOf(AssertExprRoot, + unaryOperator(hasUnaryOperand(AssertExprRoot))))), + unless(findAll(NonConstexprFunctionCall))) .bind("condition"); auto Condition = - anyOf(ignoringParenImpCasts(callExpr( - hasDeclaration(functionDecl(hasName("__builtin_expect"))), - hasArgument(0, AssertCondition))), + anyOf(callExpr(traverse(TK_AsIs, callExpr(hasDeclaration(functionDecl( + hasName("__builtin_expect"))))), + hasArgument(0, AssertCondition)), AssertCondition); - Finder->addMatcher(conditionalOperator(hasCondition(Condition), - unless(isInTemplateInstantiation())) - .bind("condStmt"), - this); - Finder->addMatcher( - ifStmt(hasCondition(Condition), unless(isInTemplateInstantiation())) - .bind("condStmt"), - this); + mapAnyOf(ifStmt, conditionalOperator).with(hasCondition(Condition)).bind("condStmt"), this); } void StaticAssertCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.h b/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.h index 0168d1fcd107f..796fc4827db42 100644 --- a/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.h +++ b/clang-tools-extra/clang-tidy/misc/StaticAssertCheck.h @@ -30,6 +30,9 @@ class StaticAssertCheck : public ClangTidyCheck { } void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + llvm::Optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } private: SourceLocation getLastParenLoc(const ASTContext *ASTCtx, diff --git a/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp index 535ac78b3f78a..ee2ca87ab011b 100644 --- a/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp @@ -177,8 +177,8 @@ void UnusedParametersCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *Method = dyn_cast(Function)) if (Method->isLambdaStaticInvoker()) return; - for (unsigned i = 0, e = Function->getNumParams(); i != e; ++i) { - const auto *Param = Function->getParamDecl(i); + for (unsigned I = 0, E = Function->getNumParams(); I != E; ++I) { + const auto *Param = Function->getParamDecl(I); if (Param->isUsed() || Param->isReferenced() || !Param->getDeclName() || Param->hasAttr()) continue; @@ -190,7 +190,7 @@ void UnusedParametersCheck::check(const MatchFinder::MatchResult &Result) { Function->getBody()->child_end()) || (isa(Function) && cast(Function)->getNumCtorInitializers() > 0)) - warnOnUnusedParameter(Result, Function, i); + warnOnUnusedParameter(Result, Function, I); } } diff --git a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp index 96055c29ffa8e..ca96ab67090cc 100644 --- a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp @@ -50,7 +50,7 @@ AST_MATCHER_P(DeducedTemplateSpecializationType, refsToTemplatedDecl, // A function that helps to tell whether a TargetDecl in a UsingDecl will be // checked. Only variable, function, function template, class template, class, // enum declaration and enum constant declaration are considered. -static bool ShouldCheckDecl(const Decl *TargetDecl) { +static bool shouldCheckDecl(const Decl *TargetDecl) { return isa(TargetDecl) || isa(TargetDecl) || isa(TargetDecl) || isa(TargetDecl) || isa(TargetDecl) || isa(TargetDecl) || @@ -105,7 +105,7 @@ void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) { /*SkipTrailingWhitespaceAndNewLine=*/true)); for (const auto *UsingShadow : Using->shadows()) { const auto *TargetDecl = UsingShadow->getTargetDecl()->getCanonicalDecl(); - if (ShouldCheckDecl(TargetDecl)) + if (shouldCheckDecl(TargetDecl)) Context.UsingTargetDecls.insert(TargetDecl); } if (!Context.UsingTargetDecls.empty()) diff --git a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp index 2eef9837e11c1..d6216000fe20f 100644 --- a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp @@ -59,7 +59,7 @@ void DeprecatedIosBaseAliasesCheck::check( SourceLocation EndLoc = IoStateLoc.getLocWithOffset(TypeName.size() - 1); if (Replacement) { - auto FixName = *Replacement; + const char *FixName = *Replacement; auto Builder = diag(IoStateLoc, "'std::ios_base::%0' is deprecated; use " "'std::ios_base::%1' instead") << TypeName << FixName; diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp index 65384afdf5b84..ec75be9c5f538 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -71,20 +71,20 @@ static const char EndVarName[] = "endVar"; static const char DerefByValueResultName[] = "derefByValueResult"; static const char DerefByRefResultName[] = "derefByRefResult"; // shared matchers -static const TypeMatcher AnyType() { return anything(); } +static const TypeMatcher anyType() { return anything(); } -static const StatementMatcher IntegerComparisonMatcher() { +static const StatementMatcher integerComparisonMatcher() { return expr(ignoringParenImpCasts( declRefExpr(to(varDecl(hasType(isInteger())).bind(ConditionVarName))))); } -static const DeclarationMatcher InitToZeroMatcher() { +static const DeclarationMatcher initToZeroMatcher() { return varDecl( hasInitializer(ignoringParenImpCasts(integerLiteral(equals(0))))) .bind(InitVarName); } -static const StatementMatcher IncrementVarMatcher() { +static const StatementMatcher incrementVarMatcher() { return declRefExpr(to(varDecl(hasType(isInteger())).bind(IncrementVarName))); } @@ -112,15 +112,16 @@ StatementMatcher makeArrayLoopMatcher() { return forStmt( unless(isInTemplateInstantiation()), - hasLoopInit(declStmt(hasSingleDecl(InitToZeroMatcher()))), + hasLoopInit(declStmt(hasSingleDecl(initToZeroMatcher()))), hasCondition(anyOf( binaryOperator(hasOperatorName("<"), - hasLHS(IntegerComparisonMatcher()), + hasLHS(integerComparisonMatcher()), hasRHS(ArrayBoundMatcher)), binaryOperator(hasOperatorName(">"), hasLHS(ArrayBoundMatcher), - hasRHS(IntegerComparisonMatcher())))), - hasIncrement(unaryOperator(hasOperatorName("++"), - hasUnaryOperand(IncrementVarMatcher())))) + hasRHS(integerComparisonMatcher())))), + hasIncrement( + unaryOperator(hasOperatorName("++"), + hasUnaryOperand(incrementVarMatcher())))) .bind(LoopNameArray); } @@ -187,11 +188,6 @@ StatementMatcher makeIteratorLoopMatcher(bool IsReverse) { StatementMatcher IteratorComparisonMatcher = expr( ignoringParenImpCasts(declRefExpr(to(varDecl().bind(ConditionVarName))))); - auto OverloadedNEQMatcher = ignoringImplicit( - cxxOperatorCallExpr(hasOverloadedOperatorName("!="), argumentCountIs(2), - hasArgument(0, IteratorComparisonMatcher), - hasArgument(1, IteratorBoundMatcher))); - // This matcher tests that a declaration is a CXXRecordDecl that has an // overloaded operator*(). If the operator*() returns by value instead of by // reference then the return type is tagged with DerefByValueResultName. @@ -215,18 +211,13 @@ StatementMatcher makeIteratorLoopMatcher(bool IsReverse) { containsDeclaration(0, InitDeclMatcher), containsDeclaration(1, EndDeclMatcher)), declStmt(hasSingleDecl(InitDeclMatcher)))), - hasCondition( - anyOf(binaryOperator(hasOperatorName("!="), - hasLHS(IteratorComparisonMatcher), - hasRHS(IteratorBoundMatcher)), - binaryOperator(hasOperatorName("!="), - hasLHS(IteratorBoundMatcher), - hasRHS(IteratorComparisonMatcher)), - OverloadedNEQMatcher)), + hasCondition(ignoringImplicit(binaryOperation( + hasOperatorName("!="), hasOperands(IteratorComparisonMatcher, + IteratorBoundMatcher)))), hasIncrement(anyOf( unaryOperator(hasOperatorName("++"), hasUnaryOperand(declRefExpr( - to(varDecl(hasType(pointsTo(AnyType()))) + to(varDecl(hasType(pointsTo(anyType()))) .bind(IncrementVarName))))), cxxOperatorCallExpr( hasOverloadedOperatorName("++"), @@ -313,17 +304,18 @@ StatementMatcher makePseudoArrayLoopMatcher() { unless(isInTemplateInstantiation()), hasLoopInit( anyOf(declStmt(declCountIs(2), - containsDeclaration(0, InitToZeroMatcher()), + containsDeclaration(0, initToZeroMatcher()), containsDeclaration(1, EndDeclMatcher)), - declStmt(hasSingleDecl(InitToZeroMatcher())))), + declStmt(hasSingleDecl(initToZeroMatcher())))), hasCondition(anyOf( binaryOperator(hasOperatorName("<"), - hasLHS(IntegerComparisonMatcher()), + hasLHS(integerComparisonMatcher()), hasRHS(IndexBoundMatcher)), binaryOperator(hasOperatorName(">"), hasLHS(IndexBoundMatcher), - hasRHS(IntegerComparisonMatcher())))), - hasIncrement(unaryOperator(hasOperatorName("++"), - hasUnaryOperand(IncrementVarMatcher())))) + hasRHS(integerComparisonMatcher())))), + hasIncrement( + unaryOperator(hasOperatorName("++"), + hasUnaryOperand(incrementVarMatcher())))) .bind(LoopNamePseudoArray); } @@ -720,10 +712,11 @@ StringRef LoopConvertCheck::getContainerString(ASTContext *Context, if (isa(ContainerExpr)) { ContainerString = "this"; } else { - // For CXXOperatorCallExpr (e.g. vector_ptr->size()), its first argument is - // the class object (vector_ptr) we are targeting. + // For CXXOperatorCallExpr such as vector_ptr->size() we want the class + // object vector_ptr, but for vector[2] we need the whole expression. if (const auto* E = dyn_cast(ContainerExpr)) - ContainerExpr = E->getArg(0); + if (E->getOperator() != OO_Subscript) + ContainerExpr = E->getArg(0); ContainerString = getStringFromRange(Context->getSourceManager(), Context->getLangOpts(), ContainerExpr->getSourceRange()); diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp index c20472c8de593..74dd4a3047eac 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp @@ -10,8 +10,8 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/Lambda.h" -#include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/APSInt.h" @@ -50,8 +50,8 @@ bool StmtAncestorASTVisitor::TraverseStmt(Stmt *Statement) { /// Scope, as we can map a VarDecl to its DeclStmt, then walk up the parent tree /// using StmtAncestors. bool StmtAncestorASTVisitor::VisitDeclStmt(DeclStmt *Decls) { - for (const auto *decl : Decls->decls()) { - if (const auto *V = dyn_cast(decl)) + for (const auto *Decl : Decls->decls()) { + if (const auto *V = dyn_cast(Decl)) DeclParents.insert(std::make_pair(V, Decls)); } return true; @@ -356,7 +356,7 @@ static bool isAliasDecl(ASTContext *Context, const Decl *TheDecl, bool OnlyCasts = true; const Expr *Init = VDecl->getInit()->IgnoreParenImpCasts(); - if (Init && isa(Init)) { + if (isa_and_nonnull(Init)) { Init = digThroughConstructors(Init); OnlyCasts = false; } diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp index 4130140d549c4..54a5c5ae7e9a8 100644 --- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -24,8 +24,7 @@ constexpr char ConstructorCall[] = "constructorCall"; constexpr char ResetCall[] = "resetCall"; constexpr char NewExpression[] = "newExpression"; -std::string GetNewExprName(const CXXNewExpr *NewExpr, - const SourceManager &SM, +std::string getNewExprName(const CXXNewExpr *NewExpr, const SourceManager &SM, const LangOptions &Lang) { StringRef WrittenName = Lexer::getSourceText( CharSourceRange::getTokenRange( @@ -183,8 +182,7 @@ void MakeSmartPtrCheck::checkConstruct(SourceManager &SM, ASTContext *Ctx, // we have to add it back. ConstructCallEnd = ConstructCallStart.getLocWithOffset(ExprStr.size()); Diag << FixItHint::CreateInsertion( - ConstructCallEnd, - "<" + GetNewExprName(New, SM, getLangOpts()) + ">"); + ConstructCallEnd, "<" + getNewExprName(New, SM, getLangOpts()) + ">"); } else { ConstructCallEnd = ConstructCallStart.getLocWithOffset(LAngle); } @@ -248,7 +246,7 @@ void MakeSmartPtrCheck::checkReset(SourceManager &SM, ASTContext *Ctx, Diag << FixItHint::CreateReplacement( CharSourceRange::getCharRange(OperatorLoc, ExprEnd), (llvm::Twine(" = ") + MakeSmartPtrFunctionName + "<" + - GetNewExprName(New, SM, getLangOpts()) + ">") + getNewExprName(New, SM, getLangOpts()) + ">") .str()); if (Expr->isArrow()) @@ -389,19 +387,18 @@ bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag, // std::make_smart_ptr(std::initializer_list({})); // std::make_smart_ptr(S{1, 2}, 3); return false; - } else { - // Direct initialization with ordinary constructors. - // struct S { S(int x); S(); }; - // smart_ptr(new S{5}); - // smart_ptr(new S{}); // use default constructor - // The arguments in the initialization list are going to be forwarded to - // the constructor, so this has to be replaced with: - // std::make_smart_ptr(5); - // std::make_smart_ptr(); - InitRange = SourceRange( - NewConstruct->getParenOrBraceRange().getBegin().getLocWithOffset(1), - NewConstruct->getParenOrBraceRange().getEnd().getLocWithOffset(-1)); } + // Direct initialization with ordinary constructors. + // struct S { S(int x); S(); }; + // smart_ptr(new S{5}); + // smart_ptr(new S{}); // use default constructor + // The arguments in the initialization list are going to be forwarded to + // the constructor, so this has to be replaced with: + // std::make_smart_ptr(5); + // std::make_smart_ptr(); + InitRange = SourceRange( + NewConstruct->getParenOrBraceRange().getBegin().getLocWithOffset(1), + NewConstruct->getParenOrBraceRange().getEnd().getLocWithOffset(-1)); } else { // Aggregate initialization. // smart_ptr(new Pair{first, second}); diff --git a/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp b/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp index 7e44738850983..3214ae84b74de 100644 --- a/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/RedundantVoidArgCheck.cpp @@ -20,13 +20,13 @@ namespace { // Determine if the given QualType is a nullary function or pointer to same. bool protoTypeHasNoParms(QualType QT) { - if (auto PT = QT->getAs()) { + if (const auto *PT = QT->getAs()) { QT = PT->getPointeeType(); } if (auto *MPT = QT->getAs()) { QT = MPT->getPointeeType(); } - if (auto FP = QT->getAs()) { + if (const auto *FP = QT->getAs()) { return FP->getNumParams() == 0; } return false; diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp index f21482d165f80..3cb934e4a0f4c 100644 --- a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp @@ -71,15 +71,14 @@ void ReplaceRandomShuffleCheck::check(const MatchFinder::MatchResult &Result) { MatchedArgumentThree->getSourceRange(), "std::mt19937(std::random_device()())"); return DiagL; - } else { - auto DiagL = diag(MatchedCallExpr->getBeginLoc(), - "'std::random_shuffle' has been removed in C++17; use " - "'std::shuffle' instead"); - DiagL << FixItHint::CreateInsertion( - MatchedCallExpr->getRParenLoc(), - ", std::mt19937(std::random_device()())"); - return DiagL; } + auto DiagL = diag(MatchedCallExpr->getBeginLoc(), + "'std::random_shuffle' has been removed in C++17; use " + "'std::shuffle' instead"); + DiagL << FixItHint::CreateInsertion( + MatchedCallExpr->getRParenLoc(), + ", std::mt19937(std::random_device()())"); + return DiagL; }(); std::string NewName = "shuffle"; diff --git a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp index fab13cdbfe9f4..a4a81ce6cd77f 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp @@ -27,7 +27,7 @@ const char DeclWithNewId[] = "decl_new"; const char DeclWithCastId[] = "decl_cast"; const char DeclWithTemplateCastId[] = "decl_template"; -size_t GetTypeNameLength(bool RemoveStars, StringRef Text) { +size_t getTypeNameLength(bool RemoveStars, StringRef Text) { enum CharType { Space, Alpha, Punctuation }; CharType LastChar = Space, BeforeSpace = Punctuation; size_t NumChars = 0; @@ -399,7 +399,7 @@ void UseAutoCheck::replaceExpr( SourceRange Range(Loc.getSourceRange()); if (MinTypeNameLength != 0 && - GetTypeNameLength(RemoveStars, + getTypeNameLength(RemoveStars, tooling::fixit::getText(Loc.getSourceRange(), FirstDecl->getASTContext())) < MinTypeNameLength) diff --git a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp index d1d25825ba93b..5c79e860244aa 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp @@ -7,10 +7,10 @@ //===----------------------------------------------------------------------===// #include "UseEqualsDefaultCheck.h" +#include "../utils/LexerUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Lex/Lexer.h" -#include "../utils/LexerUtils.h" using namespace clang::ast_matchers; @@ -183,15 +183,10 @@ static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context, auto LHS = memberExpr(hasObjectExpression(cxxThisExpr()), member(fieldDecl(equalsNode(Field)))); auto RHS = accessToFieldInVar(Field, Param); - if (match( - traverse(TK_AsIs, - compoundStmt(has(ignoringParenImpCasts(stmt(anyOf( - binaryOperator(hasOperatorName("="), hasLHS(LHS), - hasRHS(RHS)), - cxxOperatorCallExpr( - hasOverloadedOperatorName("="), argumentCountIs(2), - hasArgument(0, LHS), hasArgument(1, RHS)))))))), - *Compound, *Context) + if (match(traverse(TK_AsIs, + compoundStmt(has(ignoringParenImpCasts(binaryOperation( + hasOperatorName("="), hasLHS(LHS), hasRHS(RHS)))))), + *Compound, *Context) .empty()) return false; } diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp index 25a789dd08315..5ca2be2eb556d 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp @@ -41,12 +41,28 @@ StatementMatcher makeCastSequenceMatcher() { unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))), unless(hasSourceExpression(hasType(sugaredNullptrType())))); + auto IsOrHasDescendant = [](auto InnerMatcher) { + return anyOf(InnerMatcher, hasDescendant(InnerMatcher)); + }; + return traverse( TK_AsIs, - castExpr(anyOf(ImplicitCastToNull, - explicitCastExpr(hasDescendant(ImplicitCastToNull))), - unless(hasAncestor(explicitCastExpr()))) - .bind(CastSequence)); + anyOf(castExpr(anyOf(ImplicitCastToNull, + explicitCastExpr(hasDescendant(ImplicitCastToNull))), + unless(hasAncestor(explicitCastExpr())), + unless(hasAncestor(cxxRewrittenBinaryOperator()))) + .bind(CastSequence), + cxxRewrittenBinaryOperator( + // Match rewritten operators, but verify (in the check method) + // that if an implicit cast is found, it is not from another + // nested rewritten operator. + expr().bind("matchBinopOperands"), + hasEitherOperand(IsOrHasDescendant( + implicitCastExpr( + ImplicitCastToNull, + hasAncestor(cxxRewrittenBinaryOperator().bind( + "checkBinopOperands"))) + .bind(CastSequence)))))); } bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc, @@ -173,9 +189,9 @@ class MacroArgUsageVisitor : public RecursiveASTVisitor { class CastSequenceVisitor : public RecursiveASTVisitor { public: CastSequenceVisitor(ASTContext &Context, ArrayRef NullMacros, - ClangTidyCheck &check) + ClangTidyCheck &Check) : SM(Context.getSourceManager()), Context(Context), - NullMacros(NullMacros), Check(check), FirstSubExpr(nullptr), + NullMacros(NullMacros), Check(Check), FirstSubExpr(nullptr), PruneSubtree(false) {} bool TraverseStmt(Stmt *S) { @@ -480,6 +496,11 @@ void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) { const auto *NullCast = Result.Nodes.getNodeAs(CastSequence); assert(NullCast && "Bad Callback. No node provided"); + if (Result.Nodes.getNodeAs( + "matchBinopOperands") != + Result.Nodes.getNodeAs("checkBinopOperands")) + return; + // Given an implicit null-ptr cast or an explicit cast with an implicit // null-to-pointer cast within use CastSequenceVisitor to identify sequences // of explicit casts that can be converted into 'nullptr'. diff --git a/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp index bfce7a61470f8..510e17f58c811 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp @@ -43,7 +43,7 @@ void UseOverrideCheck::registerMatchers(MatchFinder *Finder) { // Re-lex the tokens to get precise locations to insert 'override' and remove // 'virtual'. static SmallVector -ParseTokens(CharSourceRange Range, const MatchFinder::MatchResult &Result) { +parseTokens(CharSourceRange Range, const MatchFinder::MatchResult &Result) { const SourceManager &Sources = *Result.SourceManager; std::pair LocInfo = Sources.getDecomposedLoc(Range.getBegin()); @@ -75,7 +75,7 @@ ParseTokens(CharSourceRange Range, const MatchFinder::MatchResult &Result) { return Tokens; } -static StringRef GetText(const Token &Tok, const SourceManager &Sources) { +static StringRef getText(const Token &Tok, const SourceManager &Sources) { return StringRef(Sources.getCharacterData(Tok.getLocation()), Tok.getLength()); } @@ -136,7 +136,7 @@ void UseOverrideCheck::check(const MatchFinder::MatchResult &Result) { // FIXME: Instead of re-lexing and looking for specific macros such as // 'ABSTRACT', properly store the location of 'virtual' and '= 0' in each // FunctionDecl. - SmallVector Tokens = ParseTokens(FileRange, Result); + SmallVector Tokens = parseTokens(FileRange, Result); // Add 'override' on inline declarations that don't already have it. if (!HasFinal && !HasOverride) { @@ -185,15 +185,15 @@ void UseOverrideCheck::check(const MatchFinder::MatchResult &Result) { // location will point until after those markings. Therefore, the override // keyword shouldn't be inserted at the end, but before the '='. if (Tokens.size() > 2 && - (GetText(Tokens.back(), Sources) == "0" || + (getText(Tokens.back(), Sources) == "0" || Tokens.back().is(tok::kw_default) || Tokens.back().is(tok::kw_delete)) && - GetText(Tokens[Tokens.size() - 2], Sources) == "=") { + getText(Tokens[Tokens.size() - 2], Sources) == "=") { InsertLoc = Tokens[Tokens.size() - 2].getLocation(); // Check if we need to insert a space. if ((Tokens[Tokens.size() - 2].getFlags() & Token::LeadingSpace) == 0) ReplacementText = " " + OverrideSpelling + " "; - } else if (GetText(Tokens.back(), Sources) == "ABSTRACT") + } else if (getText(Tokens.back(), Sources) == "ABSTRACT") InsertLoc = Tokens.back().getLocation(); } diff --git a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp index bbb1e8c65a4f1..b5c7227559013 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp @@ -31,7 +31,7 @@ struct UnqualNameVisitor : public RecursiveASTVisitor { bool shouldWalkTypesOfTypeLocs() const { return false; } - bool VisitUnqualName(StringRef UnqualName) { + bool visitUnqualName(StringRef UnqualName) { // Check for collisions with function arguments. for (ParmVarDecl *Param : F.parameters()) if (const IdentifierInfo *Ident = Param->getIdentifier()) @@ -49,17 +49,17 @@ struct UnqualNameVisitor : public RecursiveASTVisitor { if (!Elaborated) { switch (TL.getTypeLocClass()) { case TypeLoc::Record: - if (VisitUnqualName( + if (visitUnqualName( TL.getAs().getTypePtr()->getDecl()->getName())) return false; break; case TypeLoc::Enum: - if (VisitUnqualName( + if (visitUnqualName( TL.getAs().getTypePtr()->getDecl()->getName())) return false; break; case TypeLoc::TemplateSpecialization: - if (VisitUnqualName(TL.getAs() + if (visitUnqualName(TL.getAs() .getTypePtr() ->getTemplateName() .getAsTemplateDecl() @@ -67,7 +67,7 @@ struct UnqualNameVisitor : public RecursiveASTVisitor { return false; break; case TypeLoc::Typedef: - if (VisitUnqualName( + if (visitUnqualName( TL.getAs().getTypePtr()->getDecl()->getName())) return false; break; @@ -97,7 +97,7 @@ struct UnqualNameVisitor : public RecursiveASTVisitor { bool VisitDeclRefExpr(DeclRefExpr *S) { DeclarationName Name = S->getNameInfo().getName(); return S->getQualifierLoc() || !Name.isIdentifier() || - !VisitUnqualName(Name.getAsIdentifierInfo()->getName()); + !visitUnqualName(Name.getAsIdentifierInfo()->getName()); } private: @@ -160,11 +160,11 @@ SourceLocation UseTrailingReturnTypeCheck::findTrailingReturnTypeSourceLocation( return Result; } -static bool IsCVR(Token T) { +static bool isCvr(Token T) { return T.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict); } -static bool IsSpecifier(Token T) { +static bool isSpecifier(Token T) { return T.isOneOf(tok::kw_constexpr, tok::kw_inline, tok::kw_extern, tok::kw_static, tok::kw_friend, tok::kw_virtual); } @@ -192,8 +192,8 @@ classifyToken(const FunctionDecl &F, Preprocessor &PP, Token Tok) { if (T.is(tok::eof)) break; - bool Qual = IsCVR(T); - bool Spec = IsSpecifier(T); + bool Qual = isCvr(T); + bool Spec = isSpecifier(T); CT.isQualifier &= Qual; CT.isSpecifier &= Spec; ContainsQualifiers |= Qual; diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp index f3e8506b5513d..a12a056f13ea1 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp @@ -58,13 +58,13 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) { return; } - auto printPolicy = PrintingPolicy(getLangOpts()); - printPolicy.SuppressScope = true; - printPolicy.ConstantArraySizeAsWritten = true; - printPolicy.UseVoidForZeroParams = false; - printPolicy.PrintInjectedClassNameWithArguments = false; + PrintingPolicy PrintPolicy(getLangOpts()); + PrintPolicy.SuppressScope = true; + PrintPolicy.ConstantArraySizeAsWritten = true; + PrintPolicy.UseVoidForZeroParams = false; + PrintPolicy.PrintInjectedClassNameWithArguments = false; - std::string Type = MatchedDecl->getUnderlyingType().getAsString(printPolicy); + std::string Type = MatchedDecl->getUnderlyingType().getAsString(PrintPolicy); std::string Name = MatchedDecl->getNameAsString(); SourceRange ReplaceRange = MatchedDecl->getSourceRange(); diff --git a/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.cpp b/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.cpp index 8ababfe46e85f..b108f75fbc7a5 100644 --- a/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.cpp +++ b/clang-tools-extra/clang-tidy/mpi/BufferDerefCheck.cpp @@ -38,7 +38,7 @@ void BufferDerefCheck::check(const MatchFinder::MatchResult &Result) { // Adds the type and expression of a buffer that is used in the MPI call // expression to the captured containers. - auto addBuffer = [&CE, &Result, &BufferTypes, + auto AddBuffer = [&CE, &Result, &BufferTypes, &BufferExprs](const size_t BufferIdx) { // Skip null pointer constants and in place 'operators'. if (CE->getArg(BufferIdx)->isNullPointerConstant( @@ -61,18 +61,18 @@ void BufferDerefCheck::check(const MatchFinder::MatchResult &Result) { // MPI call expression. The number passed to the lambda corresponds to the // argument index of the currently verified MPI function call. if (FuncClassifier.isPointToPointType(Identifier)) { - addBuffer(0); + AddBuffer(0); } else if (FuncClassifier.isCollectiveType(Identifier)) { if (FuncClassifier.isReduceType(Identifier)) { - addBuffer(0); - addBuffer(1); + AddBuffer(0); + AddBuffer(1); } else if (FuncClassifier.isScatterType(Identifier) || FuncClassifier.isGatherType(Identifier) || FuncClassifier.isAlltoallType(Identifier)) { - addBuffer(0); - addBuffer(3); + AddBuffer(0); + AddBuffer(3); } else if (FuncClassifier.isBcastType(Identifier)) { - addBuffer(0); + AddBuffer(0); } } @@ -81,9 +81,9 @@ void BufferDerefCheck::check(const MatchFinder::MatchResult &Result) { void BufferDerefCheck::checkBuffers(ArrayRef BufferTypes, ArrayRef BufferExprs) { - for (size_t i = 0; i < BufferTypes.size(); ++i) { + for (size_t I = 0; I < BufferTypes.size(); ++I) { unsigned IndirectionCount = 0; - const Type *BufferType = BufferTypes[i]; + const Type *BufferType = BufferTypes[I]; llvm::SmallVector Indirections; // Capture the depth and types of indirections for the passed buffer. @@ -120,7 +120,7 @@ void BufferDerefCheck::checkBuffers(ArrayRef BufferTypes, } } - const auto Loc = BufferExprs[i]->getSourceRange().getBegin(); + const auto Loc = BufferExprs[I]->getSourceRange().getBegin(); diag(Loc, "buffer is insufficiently dereferenced: %0") << IndirectionDesc; } } diff --git a/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.cpp b/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.cpp index f305ddf883a03..cc60ea365c2f3 100644 --- a/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.cpp +++ b/clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.cpp @@ -216,9 +216,9 @@ static bool isTypedefTypeMatching(const TypedefType *const Typedef, {"uint8_t", "MPI_UINT8_T"}, {"uint16_t", "MPI_UINT16_T"}, {"uint32_t", "MPI_UINT32_T"}, {"uint64_t", "MPI_UINT64_T"}}; - const auto it = FixedWidthMatches.find(Typedef->getDecl()->getName()); + const auto It = FixedWidthMatches.find(Typedef->getDecl()->getName()); // Check if the typedef is known and not matching the MPI datatype. - if (it != FixedWidthMatches.end() && it->getValue() != MPIDatatype) { + if (It != FixedWidthMatches.end() && It->getValue() != MPIDatatype) { BufferTypeName = std::string(Typedef->getDecl()->getName()); return false; } @@ -228,11 +228,11 @@ static bool isTypedefTypeMatching(const TypedefType *const Typedef, /// Get the unqualified, dereferenced type of an argument. /// /// \param CE call expression -/// \param idx argument index +/// \param Idx argument index /// /// \returns type of the argument -static const Type *argumentType(const CallExpr *const CE, const size_t idx) { - const QualType QT = CE->getArg(idx)->IgnoreImpCasts()->getType(); +static const Type *argumentType(const CallExpr *const CE, const size_t Idx) { + const QualType QT = CE->getArg(Idx)->IgnoreImpCasts()->getType(); return QT.getTypePtr()->getPointeeOrArrayElementType(); } @@ -257,8 +257,8 @@ void TypeMismatchCheck::check(const MatchFinder::MatchResult &Result) { // Adds a buffer, MPI datatype pair of an MPI call expression to the // containers. For buffers, the type and expression is captured. - auto addPair = [&CE, &Result, &BufferTypes, &BufferExprs, &MPIDatatypes]( - const size_t BufferIdx, const size_t DatatypeIdx) { + auto AddPair = [&CE, &Result, &BufferTypes, &BufferExprs, &MPIDatatypes]( + const size_t BufferIdx, const size_t DatatypeIdx) { // Skip null pointer constants and in place 'operators'. if (CE->getArg(BufferIdx)->isNullPointerConstant( *Result.Context, Expr::NPC_ValueDependentIsNull) || @@ -282,18 +282,18 @@ void TypeMismatchCheck::check(const MatchFinder::MatchResult &Result) { // Collect all buffer, MPI datatype pairs for the inspected call expression. if (FuncClassifier.isPointToPointType(Identifier)) { - addPair(0, 2); + AddPair(0, 2); } else if (FuncClassifier.isCollectiveType(Identifier)) { if (FuncClassifier.isReduceType(Identifier)) { - addPair(0, 3); - addPair(1, 3); + AddPair(0, 3); + AddPair(1, 3); } else if (FuncClassifier.isScatterType(Identifier) || FuncClassifier.isGatherType(Identifier) || FuncClassifier.isAlltoallType(Identifier)) { - addPair(0, 2); - addPair(3, 5); + AddPair(0, 2); + AddPair(3, 5); } else if (FuncClassifier.isBcastType(Identifier)) { - addPair(0, 2); + AddPair(0, 2); } } checkArguments(BufferTypes, BufferExprs, MPIDatatypes, getLangOpts()); @@ -305,28 +305,28 @@ void TypeMismatchCheck::checkArguments(ArrayRef BufferTypes, const LangOptions &LO) { std::string BufferTypeName; - for (size_t i = 0; i < MPIDatatypes.size(); ++i) { - const Type *const BT = BufferTypes[i]; + for (size_t I = 0; I < MPIDatatypes.size(); ++I) { + const Type *const BT = BufferTypes[I]; bool Error = false; if (const auto *Typedef = BT->getAs()) { Error = !isTypedefTypeMatching(Typedef, BufferTypeName, - std::string(MPIDatatypes[i])); + std::string(MPIDatatypes[I])); } else if (const auto *Complex = BT->getAs()) { Error = !isCComplexTypeMatching(Complex, BufferTypeName, - std::string(MPIDatatypes[i]), LO); + std::string(MPIDatatypes[I]), LO); } else if (const auto *Template = BT->getAs()) { Error = !isCXXComplexTypeMatching(Template, BufferTypeName, - std::string(MPIDatatypes[i]), LO); + std::string(MPIDatatypes[I]), LO); } else if (const auto *Builtin = BT->getAs()) { Error = !isBuiltinTypeMatching(Builtin, BufferTypeName, - std::string(MPIDatatypes[i]), LO); + std::string(MPIDatatypes[I]), LO); } if (Error) { - const auto Loc = BufferExprs[i]->getSourceRange().getBegin(); + const auto Loc = BufferExprs[I]->getSourceRange().getBegin(); diag(Loc, "buffer type '%0' does not match the MPI datatype '%1'") - << BufferTypeName << MPIDatatypes[i]; + << BufferTypeName << MPIDatatypes[I]; } } } diff --git a/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp b/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp index 956cb79ed517e..35b5bb826f57d 100644 --- a/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp +++ b/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp @@ -7,11 +7,11 @@ //===----------------------------------------------------------------------===// #include "ForbiddenSubclassingCheck.h" +#include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" -#include "../utils/OptionsUtils.h" using namespace clang::ast_matchers; diff --git a/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.cpp b/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.cpp index b4e6d0e3d2020..758d397a445e0 100644 --- a/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.cpp +++ b/clang-tools-extra/clang-tidy/objc/PropertyDeclarationCheck.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "PropertyDeclarationCheck.h" -#include #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -15,6 +14,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Regex.h" +#include using namespace clang::ast_matchers; diff --git a/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp b/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp index 0d2efb31b7744..0b329668adc21 100644 --- a/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp @@ -21,21 +21,21 @@ namespace performance { namespace { -llvm::Optional MakeCharacterLiteral(const StringLiteral *Literal) { +llvm::Optional makeCharacterLiteral(const StringLiteral *Literal) { std::string Result; { llvm::raw_string_ostream OS(Result); Literal->outputString(OS); } // Now replace the " with '. - auto pos = Result.find_first_of('"'); - if (pos == Result.npos) + auto Pos = Result.find_first_of('"'); + if (Pos == Result.npos) return llvm::None; - Result[pos] = '\''; - pos = Result.find_last_of('"'); - if (pos == Result.npos) + Result[Pos] = '\''; + Pos = Result.find_last_of('"'); + if (Pos == Result.npos) return llvm::None; - Result[pos] = '\''; + Result[Pos] = '\''; return Result; } @@ -83,7 +83,7 @@ void FasterStringFindCheck::check(const MatchFinder::MatchResult &Result) { const auto *Literal = Result.Nodes.getNodeAs("literal"); const auto *FindFunc = Result.Nodes.getNodeAs("func"); - auto Replacement = MakeCharacterLiteral(Literal); + auto Replacement = makeCharacterLiteral(Literal); if (!Replacement) return; diff --git a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp index 38ede424be665..738e376744e36 100644 --- a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp @@ -24,10 +24,10 @@ namespace performance { // The subtelty is that in some cases (user defined conversions), we can // get to ImplicitCastExpr inside each other, with the outer one a NoOp. In this // case we skip the first cast expr. -static bool IsNonTrivialImplicitCast(const Stmt *ST) { +static bool isNonTrivialImplicitCast(const Stmt *ST) { if (const auto *ICE = dyn_cast(ST)) { return (ICE->getCastKind() != CK_NoOp) || - IsNonTrivialImplicitCast(ICE->getSubExpr()); + isNonTrivialImplicitCast(ICE->getSubExpr()); } return false; } @@ -81,7 +81,7 @@ void ImplicitConversionInLoopCheck::check( // iterator returns a value instead of a reference, and the loop variable // is a reference. This situation is fine (it probably produces the same // code at the end). - if (IsNonTrivialImplicitCast(Materialized->getSubExpr())) + if (isNonTrivialImplicitCast(Materialized->getSubExpr())) ReportAndFix(Result.Context, VD, OperatorCall); } diff --git a/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.cpp b/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.cpp index c883fc2f1f4a4..f73643f609c5d 100644 --- a/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/InefficientStringConcatenationCheck.cpp @@ -69,7 +69,7 @@ void InefficientStringConcatenationCheck::check( const auto *LhsStr = Result.Nodes.getNodeAs("lhsStr"); const auto *PlusOperator = Result.Nodes.getNodeAs("plusOperator"); - const auto DiagMsg = + const char *DiagMsg = "string concatenation results in allocation of unnecessary temporary " "strings; consider using 'operator+=' or 'string::append()' instead"; diff --git a/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp b/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp index 776a8ca1d7c1e..f7c5112d22eab 100644 --- a/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp @@ -7,11 +7,11 @@ //===----------------------------------------------------------------------===// #include "InefficientVectorOperationCheck.h" +#include "../utils/DeclRefExprUtils.h" +#include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Lex/Lexer.h" -#include "../utils/DeclRefExprUtils.h" -#include "../utils/OptionsUtils.h" using namespace clang::ast_matchers; diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp index 0cb1b82782d98..e946a1f39fe98 100644 --- a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp @@ -16,7 +16,7 @@ namespace clang { namespace tidy { namespace performance { -static void ReplaceCallWithArg(const CallExpr *Call, DiagnosticBuilder &Diag, +static void replaceCallWithArg(const CallExpr *Call, DiagnosticBuilder &Diag, const SourceManager &SM, const LangOptions &LangOpts) { const Expr *Arg = Call->getArg(0); @@ -47,13 +47,11 @@ void MoveConstArgCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(MoveCallMatcher, this); - auto ConstParamMatcher = forEachArgumentWithParam( - MoveCallMatcher, parmVarDecl(hasType(references(isConstQualified())))); - - Finder->addMatcher(callExpr(ConstParamMatcher).bind("receiving-expr"), this); Finder->addMatcher( - traverse(TK_AsIs, - cxxConstructExpr(ConstParamMatcher).bind("receiving-expr")), + invocation(forEachArgumentWithParam( + MoveCallMatcher, + parmVarDecl(hasType(references(isConstQualified()))))) + .bind("receiving-expr"), this); } @@ -104,13 +102,13 @@ void MoveConstArgCheck::check(const MatchFinder::MatchResult &Result) { << (IsConstArg && IsVariable && !IsTriviallyCopyable) << Var << Arg->getType(); - ReplaceCallWithArg(CallMove, Diag, SM, getLangOpts()); + replaceCallWithArg(CallMove, Diag, SM, getLangOpts()); } else if (ReceivingExpr) { auto Diag = diag(FileMoveRange.getBegin(), "passing result of std::move() as a const reference " "argument; no move will actually happen"); - ReplaceCallWithArg(CallMove, Diag, SM, getLangOpts()); + replaceCallWithArg(CallMove, Diag, SM, getLangOpts()); } } diff --git a/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp b/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp index a35220ad9d0f6..8f91200c28e4d 100644 --- a/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp @@ -52,10 +52,10 @@ void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) { constexpr BuiltinType::Kind DoubleTy = BuiltinType::Double; constexpr BuiltinType::Kind LongDoubleTy = BuiltinType::LongDouble; - auto hasBuiltinTyParam = [](int Pos, BuiltinType::Kind Kind) { + auto HasBuiltinTyParam = [](int Pos, BuiltinType::Kind Kind) { return hasParameter(Pos, hasType(isBuiltinType(Kind))); }; - auto hasBuiltinTyArg = [](int Pos, BuiltinType::Kind Kind) { + auto HasBuiltinTyArg = [](int Pos, BuiltinType::Kind Kind) { return hasArgument(Pos, hasType(isBuiltinType(Kind))); }; @@ -69,8 +69,8 @@ void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) { "::tanh", "::tgamma", "::trunc", "::llround", "::lround"); Finder->addMatcher( callExpr(callee(functionDecl(OneDoubleArgFns, parameterCountIs(1), - hasBuiltinTyParam(0, DoubleTy))), - hasBuiltinTyArg(0, FloatTy)) + HasBuiltinTyParam(0, DoubleTy))), + HasBuiltinTyArg(0, FloatTy)) .bind("call"), this); @@ -80,20 +80,20 @@ void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) { "::nextafter", "::pow", "::remainder"); Finder->addMatcher( callExpr(callee(functionDecl(TwoDoubleArgFns, parameterCountIs(2), - hasBuiltinTyParam(0, DoubleTy), - hasBuiltinTyParam(1, DoubleTy))), - hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy)) + HasBuiltinTyParam(0, DoubleTy), + HasBuiltinTyParam(1, DoubleTy))), + HasBuiltinTyArg(0, FloatTy), HasBuiltinTyArg(1, FloatTy)) .bind("call"), this); // Match calls to fma(double, double, double) where all args are floats. Finder->addMatcher( callExpr(callee(functionDecl(hasName("::fma"), parameterCountIs(3), - hasBuiltinTyParam(0, DoubleTy), - hasBuiltinTyParam(1, DoubleTy), - hasBuiltinTyParam(2, DoubleTy))), - hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy), - hasBuiltinTyArg(2, FloatTy)) + HasBuiltinTyParam(0, DoubleTy), + HasBuiltinTyParam(1, DoubleTy), + HasBuiltinTyParam(2, DoubleTy))), + HasBuiltinTyArg(0, FloatTy), HasBuiltinTyArg(1, FloatTy), + HasBuiltinTyArg(2, FloatTy)) .bind("call"), this); @@ -101,10 +101,10 @@ void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( callExpr(callee(functionDecl( hasName("::frexp"), parameterCountIs(2), - hasBuiltinTyParam(0, DoubleTy), + HasBuiltinTyParam(0, DoubleTy), hasParameter(1, parmVarDecl(hasType(pointerType( pointee(isBuiltinType(IntTy)))))))), - hasBuiltinTyArg(0, FloatTy)) + HasBuiltinTyArg(0, FloatTy)) .bind("call"), this); @@ -112,9 +112,9 @@ void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) { // float. Finder->addMatcher( callExpr(callee(functionDecl(hasName("::nexttoward"), parameterCountIs(2), - hasBuiltinTyParam(0, DoubleTy), - hasBuiltinTyParam(1, LongDoubleTy))), - hasBuiltinTyArg(0, FloatTy)) + HasBuiltinTyParam(0, DoubleTy), + HasBuiltinTyParam(1, LongDoubleTy))), + HasBuiltinTyArg(0, FloatTy)) .bind("call"), this); @@ -124,28 +124,28 @@ void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) { callExpr( callee(functionDecl( hasName("::remquo"), parameterCountIs(3), - hasBuiltinTyParam(0, DoubleTy), hasBuiltinTyParam(1, DoubleTy), + HasBuiltinTyParam(0, DoubleTy), HasBuiltinTyParam(1, DoubleTy), hasParameter(2, parmVarDecl(hasType(pointerType( pointee(isBuiltinType(IntTy)))))))), - hasBuiltinTyArg(0, FloatTy), hasBuiltinTyArg(1, FloatTy)) + HasBuiltinTyArg(0, FloatTy), HasBuiltinTyArg(1, FloatTy)) .bind("call"), this); // Match calls to scalbln(double, long) where the first arg is a float. Finder->addMatcher( callExpr(callee(functionDecl(hasName("::scalbln"), parameterCountIs(2), - hasBuiltinTyParam(0, DoubleTy), - hasBuiltinTyParam(1, LongTy))), - hasBuiltinTyArg(0, FloatTy)) + HasBuiltinTyParam(0, DoubleTy), + HasBuiltinTyParam(1, LongTy))), + HasBuiltinTyArg(0, FloatTy)) .bind("call"), this); // Match calls to scalbn(double, int) where the first arg is a float. Finder->addMatcher( callExpr(callee(functionDecl(hasName("::scalbn"), parameterCountIs(2), - hasBuiltinTyParam(0, DoubleTy), - hasBuiltinTyParam(1, IntTy))), - hasBuiltinTyArg(0, FloatTy)) + HasBuiltinTyParam(0, DoubleTy), + HasBuiltinTyParam(1, IntTy))), + HasBuiltinTyArg(0, FloatTy)) .bind("call"), this); diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp index 06cfb24de1ead..f63dbab093581 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -127,7 +127,7 @@ UnnecessaryCopyInitialization::UnnecessaryCopyInitialization( utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { - auto localVarCopiedFrom = [this](const internal::Matcher &CopyCtorArg) { + auto LocalVarCopiedFrom = [this](const internal::Matcher &CopyCtorArg) { return compoundStmt( forEachDescendant( declStmt( @@ -153,11 +153,11 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { .bind("blockStmt"); }; - Finder->addMatcher(localVarCopiedFrom(anyOf(isConstRefReturningFunctionCall(), + Finder->addMatcher(LocalVarCopiedFrom(anyOf(isConstRefReturningFunctionCall(), isConstRefReturningMethodCall())), this); - Finder->addMatcher(localVarCopiedFrom(declRefExpr( + Finder->addMatcher(LocalVarCopiedFrom(declRefExpr( to(varDecl(hasLocalStorage()).bind(OldVarDeclId)))), this); } @@ -181,8 +181,8 @@ void UnnecessaryCopyInitialization::check( // A constructor that looks like T(const T& t, bool arg = false) counts as a // copy only when it is called with default arguments for the arguments after // the first. - for (unsigned int i = 1; i < CtorCall->getNumArgs(); ++i) - if (!CtorCall->getArg(i)->isDefaultArgument()) + for (unsigned int I = 1; I < CtorCall->getNumArgs(); ++I) + if (!CtorCall->getArg(I)->isDefaultArgument()) return; if (OldVar == nullptr) { diff --git a/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp index cbd6fdd4605ca..b8367d6384f22 100644 --- a/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp +++ b/clang-tools-extra/clang-tidy/plugin/ClangTidyPlugin.cpp @@ -39,9 +39,8 @@ class ClangTidyPluginAction : public PluginASTAction { std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, StringRef File) override { // Create and set diagnostics engine - auto ExternalDiagEngine = &Compiler.getDiagnostics(); - auto DiagConsumer = - new ClangTidyDiagnosticConsumer(*Context, ExternalDiagEngine); + auto *DiagConsumer = + new ClangTidyDiagnosticConsumer(*Context, &Compiler.getDiagnostics()); auto DiagEngine = std::make_unique( new DiagnosticIDs, new DiagnosticOptions, DiagConsumer); Context->setDiagnosticsEngine(DiagEngine.get()); diff --git a/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp b/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp index 9391670df622b..65d7c1746b18f 100644 --- a/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp +++ b/clang-tools-extra/clang-tidy/portability/SIMDIntrinsicsCheck.cpp @@ -39,7 +39,7 @@ AST_MATCHER(FunctionDecl, isVectorFunction) { } // namespace -static StringRef TrySuggestPPC(StringRef Name) { +static StringRef trySuggestPpc(StringRef Name) { if (!Name.consume_front("vec_")) return {}; @@ -54,7 +54,7 @@ static StringRef TrySuggestPPC(StringRef Name) { .Default({}); } -static StringRef TrySuggestX86(StringRef Name) { +static StringRef trySuggestX86(StringRef Name) { if (!(Name.consume_front("_mm_") || Name.consume_front("_mm256_") || Name.consume_front("_mm512_"))) return {}; @@ -120,11 +120,11 @@ void SIMDIntrinsicsCheck::check(const MatchFinder::MatchResult &Result) { case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: - New = TrySuggestPPC(Old); + New = trySuggestPpc(Old); break; case llvm::Triple::x86: case llvm::Triple::x86_64: - New = TrySuggestX86(Old); + New = trySuggestX86(Old); break; } diff --git a/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.cpp b/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.cpp index 91e1495e060c8..aed01ab7ae7c4 100644 --- a/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.cpp +++ b/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDecls.cpp @@ -47,7 +47,7 @@ void AvoidConstParamsInDecls::registerMatchers(MatchFinder *Finder) { } // Re-lex the tokens to get precise location of last 'const' -static llvm::Optional ConstTok(CharSourceRange Range, +static llvm::Optional constTok(CharSourceRange Range, const MatchFinder::MatchResult &Result) { const SourceManager &Sources = *Result.SourceManager; std::pair LocInfo = @@ -86,9 +86,9 @@ void AvoidConstParamsInDecls::check(const MatchFinder::MatchResult &Result) { "declaration; const-qualification of parameters only has an " "effect in function definitions"); if (Param->getName().empty()) { - for (unsigned int i = 0; i < Func->getNumParams(); ++i) { - if (Param == Func->getParamDecl(i)) { - Diag << (i + 1); + for (unsigned int I = 0; I < Func->getNumParams(); ++I) { + if (Param == Func->getParamDecl(I)) { + Diag << (I + 1); break; } } @@ -109,7 +109,7 @@ void AvoidConstParamsInDecls::check(const MatchFinder::MatchResult &Result) { if (!FileRange.isValid()) return; - auto Tok = ConstTok(FileRange, Result); + auto Tok = constTok(FileRange, Result); if (!Tok) return; Diag << FixItHint::CreateRemoval( diff --git a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp index 64e182bbbbc8d..1123238c186b5 100644 --- a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp @@ -139,18 +139,19 @@ void BracesAroundStatementsCheck::check( const ASTContext *Context = Result.Context; // Get location of closing parenthesis or 'do' to insert opening brace. - if (auto S = Result.Nodes.getNodeAs("for")) { + if (const auto *S = Result.Nodes.getNodeAs("for")) { checkStmt(Result, S->getBody(), S->getRParenLoc()); - } else if (auto S = Result.Nodes.getNodeAs("for-range")) { + } else if (const auto *S = + Result.Nodes.getNodeAs("for-range")) { checkStmt(Result, S->getBody(), S->getRParenLoc()); - } else if (auto S = Result.Nodes.getNodeAs("do")) { + } else if (const auto *S = Result.Nodes.getNodeAs("do")) { checkStmt(Result, S->getBody(), S->getDoLoc(), S->getWhileLoc()); - } else if (auto S = Result.Nodes.getNodeAs("while")) { + } else if (const 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")) { + } else if (const auto *S = Result.Nodes.getNodeAs("if")) { SourceLocation StartLoc = findRParenLoc(S, SM, Context); if (StartLoc.isInvalid()) return; diff --git a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp index e7c5f0ab05be9..a1d8064d23a0f 100644 --- a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp @@ -56,26 +56,23 @@ AST_MATCHER(Expr, usedInBooleanContext) { const char *ExprName = "__booleanContextExpr"; auto Result = expr(expr().bind(ExprName), - anyOf(hasParent(varDecl(hasType(booleanType()))), + anyOf(hasParent( + mapAnyOf(varDecl, fieldDecl).with(hasType(booleanType()))), hasParent(cxxConstructorDecl( hasAnyConstructorInitializer(cxxCtorInitializer( withInitializer(expr(equalsBoundNode(ExprName))), forField(hasType(booleanType())))))), - hasParent(fieldDecl(hasType(booleanType()))), hasParent(stmt(anyOf( explicitCastExpr(hasDestinationType(booleanType())), - ifStmt(hasCondition(expr(equalsBoundNode(ExprName)))), - doStmt(hasCondition(expr(equalsBoundNode(ExprName)))), - whileStmt(hasCondition(expr(equalsBoundNode(ExprName)))), - forStmt(hasCondition(expr(equalsBoundNode(ExprName)))), - conditionalOperator( - hasCondition(expr(equalsBoundNode(ExprName)))), + mapAnyOf(ifStmt, doStmt, whileStmt, forStmt, + conditionalOperator) + .with(hasCondition(expr(equalsBoundNode(ExprName)))), parenListExpr(hasParent(varDecl(hasType(booleanType())))), parenExpr(hasParent( explicitCastExpr(hasDestinationType(booleanType())))), returnStmt(forFunction(returns(booleanType()))), cxxUnresolvedConstructExpr(hasType(booleanType())), - callExpr(hasAnyArgumentWithParam( + invocation(hasAnyArgumentWithParam( expr(equalsBoundNode(ExprName)), parmVarDecl(hasType(booleanType())))), binaryOperator(hasAnyOperatorName("&&", "||")), @@ -86,6 +83,9 @@ AST_MATCHER(Expr, usedInBooleanContext) { }); return Result; } +AST_MATCHER(CXXConstructExpr, isDefaultConstruction) { + return Node.getConstructor()->isDefaultConstructor(); +} } // namespace ast_matchers namespace tidy { namespace readability { @@ -119,24 +119,16 @@ void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) { const auto ValidContainer = qualType( anyOf(ValidContainerNonTemplateType, ValidContainerTemplateType)); - const auto WrongUse = traverse( - TK_AsIs, - anyOf( - hasParent(binaryOperator(isComparisonOperator(), - hasEitherOperand(ignoringImpCasts( - anyOf(integerLiteral(equals(1)), - integerLiteral(equals(0)))))) - .bind("SizeBinaryOp")), - hasParent(implicitCastExpr( - hasImplicitDestinationType(booleanType()), - anyOf(hasParent( - unaryOperator(hasOperatorName("!")).bind("NegOnSize")), - anything()))), - usedInBooleanContext())); + const auto WrongUse = + anyOf(hasParent(binaryOperator( + isComparisonOperator(), + hasEitherOperand(anyOf(integerLiteral(equals(1)), + integerLiteral(equals(0))))) + .bind("SizeBinaryOp")), + usedInBooleanContext()); Finder->addMatcher( - cxxMemberCallExpr(unless(isInTemplateInstantiation()), - on(expr(anyOf(hasType(ValidContainer), + cxxMemberCallExpr(on(expr(anyOf(hasType(ValidContainer), hasType(pointsTo(ValidContainer)), hasType(references(ValidContainer)))) .bind("MemberCallObject")), @@ -160,18 +152,9 @@ void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) { .bind("SizeCallExpr"), this); - // Empty constructor matcher. - const auto DefaultConstructor = cxxConstructExpr( - hasDeclaration(cxxConstructorDecl(isDefaultConstructor()))); // Comparison to empty string or empty constructor. const auto WrongComparend = anyOf( - ignoringImpCasts(stringLiteral(hasSize(0))), - ignoringImpCasts(cxxBindTemporaryExpr(has(DefaultConstructor))), - ignoringImplicit(DefaultConstructor), - cxxConstructExpr(hasDeclaration(cxxConstructorDecl(isCopyConstructor())), - has(expr(ignoringImpCasts(DefaultConstructor)))), - cxxConstructExpr(hasDeclaration(cxxConstructorDecl(isMoveConstructor())), - has(expr(ignoringImpCasts(DefaultConstructor)))), + stringLiteral(hasSize(0)), cxxConstructExpr(isDefaultConstruction()), cxxUnresolvedConstructExpr(argumentCountIs(0))); // Match the object being compared. const auto STLArg = @@ -181,21 +164,11 @@ void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) { expr(hasType(pointsTo(ValidContainer))).bind("Pointee"))), expr(hasType(ValidContainer)).bind("STLObject")); Finder->addMatcher( - cxxOperatorCallExpr( - unless(isInTemplateInstantiation()), - hasAnyOverloadedOperatorName("==", "!="), - anyOf(allOf(hasArgument(0, WrongComparend), hasArgument(1, STLArg)), - allOf(hasArgument(0, STLArg), hasArgument(1, WrongComparend))), - unless(hasAncestor( - cxxMethodDecl(ofClass(equalsBoundNode("container")))))) - .bind("BinCmp"), - this); - Finder->addMatcher( - binaryOperator(hasAnyOperatorName("==", "!="), - anyOf(allOf(hasLHS(WrongComparend), hasRHS(STLArg)), - allOf(hasLHS(STLArg), hasRHS(WrongComparend))), - unless(hasAncestor( - cxxMethodDecl(ofClass(equalsBoundNode("container")))))) + binaryOperation(hasAnyOperatorName("==", "!="), + hasOperands(WrongComparend, + STLArg), + unless(hasAncestor(cxxMethodDecl( + ofClass(equalsBoundNode("container")))))) .bind("BinCmp"), this); } @@ -206,6 +179,8 @@ void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) { Result.Nodes.getNodeAs("MemberCallObject"); const auto *BinCmp = Result.Nodes.getNodeAs("BinCmp"); const auto *BinCmpTempl = Result.Nodes.getNodeAs("BinCmp"); + const auto *BinCmpRewritten = + Result.Nodes.getNodeAs("BinCmp"); const auto *BinaryOp = Result.Nodes.getNodeAs("SizeBinaryOp"); const auto *Pointee = Result.Nodes.getNodeAs("Pointee"); const auto *E = @@ -236,6 +211,12 @@ void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) { } Hint = FixItHint::CreateReplacement(BinCmpTempl->getSourceRange(), ReplacementText); + } else if (BinCmpRewritten) { + if (BinCmpRewritten->getOpcode() == BinaryOperatorKind::BO_NE) { + ReplacementText = "!" + ReplacementText; + } + Hint = FixItHint::CreateReplacement(BinCmpRewritten->getSourceRange(), + ReplacementText); } else if (BinaryOp) { // Determine the correct transformation. bool Negation = false; const bool ContainerIsLHS = @@ -313,8 +294,11 @@ void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) { "for emptiness instead of 'size'") << Hint; } else { - WarnLoc = BinCmpTempl ? BinCmpTempl->getBeginLoc() - : (BinCmp ? BinCmp->getBeginLoc() : SourceLocation{}); + WarnLoc = BinCmpTempl + ? BinCmpTempl->getBeginLoc() + : (BinCmp ? BinCmp->getBeginLoc() + : (BinCmpRewritten ? BinCmpRewritten->getBeginLoc() + : SourceLocation{})); diag(WarnLoc, "the 'empty' method should be used to check " "for emptiness instead of comparing to an empty object") << Hint; diff --git a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h index 8afff2265b1ca..6a4236065f438 100644 --- a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h +++ b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.h @@ -33,6 +33,9 @@ class ContainerSizeEmptyCheck : public ClangTidyCheck { } void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + llvm::Optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } }; } // namespace readability diff --git a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp index 96854bf2a7ab4..88a422ab45a33 100644 --- a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp @@ -223,14 +223,14 @@ class FunctionASTVisitor final std::stack> BinaryOperatorsStack; public: - bool TraverseStmtWithIncreasedNestingLevel(Stmt *Node) { + bool traverseStmtWithIncreasedNestingLevel(Stmt *Node) { ++CurrentNestingLevel; bool ShouldContinue = Base::TraverseStmt(Node); --CurrentNestingLevel; return ShouldContinue; } - bool TraverseDeclWithIncreasedNestingLevel(Decl *Node) { + bool traverseDeclWithIncreasedNestingLevel(Decl *Node) { ++CurrentNestingLevel; bool ShouldContinue = Base::TraverseDecl(Node); --CurrentNestingLevel; @@ -272,15 +272,15 @@ class FunctionASTVisitor final if (!TraverseStmt(Node->getCond())) return false; } else { - if (!TraverseStmtWithIncreasedNestingLevel(Node->getInit())) + if (!traverseStmtWithIncreasedNestingLevel(Node->getInit())) return false; - if (!TraverseStmtWithIncreasedNestingLevel(Node->getCond())) + if (!traverseStmtWithIncreasedNestingLevel(Node->getCond())) return false; } // "Then" always increases nesting level. - if (!TraverseStmtWithIncreasedNestingLevel(Node->getThen())) + if (!traverseStmtWithIncreasedNestingLevel(Node->getThen())) return false; if (!Node->getElse()) @@ -305,7 +305,7 @@ class FunctionASTVisitor final } // "Else" always increases nesting level. - return TraverseStmtWithIncreasedNestingLevel(Node->getElse()); + return traverseStmtWithIncreasedNestingLevel(Node->getElse()); } // The currently-being-processed stack entry, which is always the top. @@ -447,7 +447,7 @@ class FunctionASTVisitor final if (!(Reasons & CognitiveComplexity::Criteria::IncrementNesting)) return Base::TraverseStmt(Node); - return TraverseStmtWithIncreasedNestingLevel(Node); + return traverseStmtWithIncreasedNestingLevel(Node); } // The parameter MainAnalyzedFunction is needed to differentiate between the @@ -481,7 +481,7 @@ class FunctionASTVisitor final CC.account(Node->getBeginLoc(), CurrentNestingLevel, CognitiveComplexity::Criteria::IncrementNesting); - return TraverseDeclWithIncreasedNestingLevel(Node); + return traverseDeclWithIncreasedNestingLevel(Node); } CognitiveComplexity CC; diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index d33040a00e150..fccff502e1833 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -352,6 +352,10 @@ static bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl, return false; if (FDecl->getAccess() != AS_public && FDecl->getAccess() != AS_none) return false; + // If the function doesn't have a name that's an identifier, can occur if the + // function is an operator overload, bail out early. + if (!FDecl->getDeclName().isIdentifier()) + return false; enum MainType { None, Main, WMain }; auto IsCharPtrPtr = [](QualType QType) -> MainType { if (QType.isNull()) @@ -393,12 +397,11 @@ static bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl, "(^[Mm]ain([_A-Z]|$))|([a-z0-9_]Main([_A-Z]|$))|(_main(_|$))"); assert(Matcher.isValid() && "Invalid Matcher for main like functions."); return Matcher.match(FDecl->getName()); - } else { - static llvm::Regex Matcher("(^((W[Mm])|(wm))ain([_A-Z]|$))|([a-z0-9_]W[Mm]" - "ain([_A-Z]|$))|(_wmain(_|$))"); - assert(Matcher.isValid() && "Invalid Matcher for wmain like functions."); - return Matcher.match(FDecl->getName()); } + static llvm::Regex Matcher("(^((W[Mm])|(wm))ain([_A-Z]|$))|([a-z0-9_]W[Mm]" + "ain([_A-Z]|$))|(_wmain(_|$))"); + assert(Matcher.isValid() && "Invalid Matcher for wmain like functions."); + return Matcher.match(FDecl->getName()); } static std::string diff --git a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp index 0ff2c066e4741..51e3e2c1260b1 100644 --- a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp @@ -260,21 +260,22 @@ void ImplicitBoolConversionCheck::storeOptions( } void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) { - auto exceptionCases = + auto ExceptionCases = expr(anyOf(allOf(isMacroExpansion(), unless(isNULLMacroExpansion())), - has(ignoringImplicit(memberExpr(hasDeclaration(fieldDecl(hasBitWidth(1)))))), + has(ignoringImplicit( + memberExpr(hasDeclaration(fieldDecl(hasBitWidth(1)))))), hasParent(explicitCastExpr()))); - auto implicitCastFromBool = implicitCastExpr( + auto ImplicitCastFromBool = implicitCastExpr( anyOf(hasCastKind(CK_IntegralCast), hasCastKind(CK_IntegralToFloating), // Prior to C++11 cast from bool literal to pointer was allowed. allOf(anyOf(hasCastKind(CK_NullToPointer), hasCastKind(CK_NullToMemberPointer)), hasSourceExpression(cxxBoolLiteral()))), hasSourceExpression(expr(hasType(booleanType()))), - unless(exceptionCases)); - auto boolXor = - binaryOperator(hasOperatorName("^"), hasLHS(implicitCastFromBool), - hasRHS(implicitCastFromBool)); + unless(ExceptionCases)); + auto BoolXor = + binaryOperator(hasOperatorName("^"), hasLHS(ImplicitCastFromBool), + hasRHS(ImplicitCastFromBool)); Finder->addMatcher( traverse(TK_AsIs, implicitCastExpr( @@ -288,7 +289,7 @@ void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) { unless(hasParent( stmt(anyOf(ifStmt(), whileStmt()), has(declStmt())))), // Exclude cases common to implicit cast to and from bool. - unless(exceptionCases), unless(has(boolXor)), + unless(ExceptionCases), unless(has(BoolXor)), // Retrieve also parent statement, to check if we need // additional parens in replacement. anyOf(hasParent(stmt().bind("parentStmt")), anything()), @@ -297,30 +298,30 @@ void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) { .bind("implicitCastToBool")), this); - auto boolComparison = binaryOperator(hasAnyOperatorName("==", "!="), - hasLHS(implicitCastFromBool), - hasRHS(implicitCastFromBool)); - auto boolOpAssignment = binaryOperator(hasAnyOperatorName("|=", "&="), + auto BoolComparison = binaryOperator(hasAnyOperatorName("==", "!="), + hasLHS(ImplicitCastFromBool), + hasRHS(ImplicitCastFromBool)); + auto BoolOpAssignment = binaryOperator(hasAnyOperatorName("|=", "&="), hasLHS(expr(hasType(booleanType())))); - auto bitfieldAssignment = binaryOperator( + auto BitfieldAssignment = binaryOperator( hasLHS(memberExpr(hasDeclaration(fieldDecl(hasBitWidth(1)))))); - auto bitfieldConstruct = cxxConstructorDecl(hasDescendant(cxxCtorInitializer( + auto BitfieldConstruct = cxxConstructorDecl(hasDescendant(cxxCtorInitializer( withInitializer(equalsBoundNode("implicitCastFromBool")), forField(hasBitWidth(1))))); Finder->addMatcher( traverse( TK_AsIs, implicitCastExpr( - implicitCastFromBool, + ImplicitCastFromBool, // Exclude comparisons of bools, as they are always cast to // integers in such context: // bool_expr_a == bool_expr_b // bool_expr_a != bool_expr_b unless(hasParent( - binaryOperator(anyOf(boolComparison, boolXor, - boolOpAssignment, bitfieldAssignment)))), + binaryOperator(anyOf(BoolComparison, BoolXor, + BoolOpAssignment, BitfieldAssignment)))), implicitCastExpr().bind("implicitCastFromBool"), - unless(hasParent(bitfieldConstruct)), + unless(hasParent(BitfieldConstruct)), // Check also for nested casts, for example: bool -> int -> float. anyOf(hasParent(implicitCastExpr().bind("furtherImplicitCast")), anything()), diff --git a/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp index 7983436257293..3e5b71fdd56b6 100644 --- a/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp @@ -91,7 +91,7 @@ class FindUsageOfThis : public RecursiveASTVisitor { // `-ImplicitCastExpr // (possibly `-UnaryOperator Deref) // `-CXXThisExpr 'S *' this - bool VisitUser(const ImplicitCastExpr *Cast) { + bool visitUser(const ImplicitCastExpr *Cast) { if (Cast->getCastKind() != CK_NoOp) return false; // Stop traversal. @@ -115,14 +115,14 @@ class FindUsageOfThis : public RecursiveASTVisitor { // ((const S*)this)->Member if (const auto *Member = dyn_cast(Parent)) - return VisitUser(Member, /*OnConstObject=*/true); + return visitUser(Member, /*OnConstObject=*/true); return false; // Stop traversal. } // If OnConstObject is true, then this is a MemberExpr using // a constant this, i.e. 'const S' or 'const S *'. - bool VisitUser(const MemberExpr *Member, bool OnConstObject) { + bool visitUser(const MemberExpr *Member, bool OnConstObject) { if (Member->isBoundMemberFunction(Ctxt)) { if (!OnConstObject || Member->getFoundDecl().getAccess() != AS_public) { // Non-public non-static member functions might not preserve the @@ -159,7 +159,7 @@ class FindUsageOfThis : public RecursiveASTVisitor { } if (const auto *M = dyn_cast_or_null(Parent)) - return VisitUser(M, /*OnConstObject=*/false); + return visitUser(M, /*OnConstObject=*/false); return false; // Stop traversal. } @@ -182,7 +182,7 @@ class FindUsageOfThis : public RecursiveASTVisitor { // ((const S*)this)->f() // when 'f' is a public member function. if (const auto *Cast = dyn_cast_or_null(Parent)) { - if (VisitUser(Cast)) + if (visitUser(Cast)) return true; // And it's also okay to @@ -190,7 +190,7 @@ class FindUsageOfThis : public RecursiveASTVisitor { // (LValueToRValue)(S->t) // when 't' is either of builtin type or a public member. } else if (const auto *Member = dyn_cast_or_null(Parent)) { - if (VisitUser(Member, /*OnConstObject=*/false)) + if (visitUser(Member, /*OnConstObject=*/false)) return true; } @@ -248,7 +248,7 @@ void MakeMemberFunctionConstCheck::check( const MatchFinder::MatchResult &Result) { const auto *Definition = Result.Nodes.getNodeAs("x"); - auto Declaration = Definition->getCanonicalDecl(); + const auto *Declaration = Definition->getCanonicalDecl(); auto Diag = diag(Definition->getLocation(), "method %0 can be made const") << Definition diff --git a/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.cpp b/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.cpp index 3167d159b74f4..77f93f1999a9d 100644 --- a/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MisleadingIndentationCheck.cpp @@ -18,10 +18,10 @@ namespace readability { static const IfStmt *getPrecedingIf(const SourceManager &SM, ASTContext *Context, const IfStmt *If) { - auto parents = Context->getParents(*If); - if (parents.size() != 1) + auto Parents = Context->getParents(*If); + if (Parents.size() != 1) return nullptr; - if (const auto *PrecedingIf = parents[0].get()) { + if (const auto *PrecedingIf = Parents[0].get()) { SourceLocation PreviousElseLoc = PrecedingIf->getElseLoc(); if (SM.getExpansionLineNumber(PreviousElseLoc) == SM.getExpansionLineNumber(If->getIfLoc())) @@ -44,7 +44,7 @@ void MisleadingIndentationCheck::danglingElseCheck(const SourceManager &SM, return; // Find location of first 'if' in a 'if else if' chain. - for (auto PrecedingIf = getPrecedingIf(SM, Context, If); PrecedingIf; + for (const auto *PrecedingIf = getPrecedingIf(SM, Context, If); PrecedingIf; PrecedingIf = getPrecedingIf(SM, Context, PrecedingIf)) IfLoc = PrecedingIf->getIfLoc(); @@ -56,8 +56,8 @@ void MisleadingIndentationCheck::danglingElseCheck(const SourceManager &SM, void MisleadingIndentationCheck::missingBracesCheck(const SourceManager &SM, const CompoundStmt *CStmt) { const static StringRef StmtNames[] = {"if", "for", "while"}; - for (unsigned int i = 0; i < CStmt->size() - 1; i++) { - const Stmt *CurrentStmt = CStmt->body_begin()[i]; + for (unsigned int I = 0; I < CStmt->size() - 1; I++) { + const Stmt *CurrentStmt = CStmt->body_begin()[I]; const Stmt *Inner = nullptr; int StmtKind = 0; @@ -89,7 +89,7 @@ void MisleadingIndentationCheck::missingBracesCheck(const SourceManager &SM, SM.getExpansionLineNumber(OuterLoc)) continue; - const Stmt *NextStmt = CStmt->body_begin()[i + 1]; + const Stmt *NextStmt = CStmt->body_begin()[I + 1]; SourceLocation NextLoc = NextStmt->getBeginLoc(); if (NextLoc.isInvalid() || NextLoc.isMacroID()) diff --git a/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp index 09b03fe79f13c..5e018ce6172c6 100644 --- a/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/NamedParameterCheck.cpp @@ -62,7 +62,7 @@ void NamedParameterCheck::check(const MatchFinder::MatchResult &Result) { continue; // Skip gmock testing::Unused parameters. - if (auto Typedef = Parm->getType()->getAs()) + if (const auto *Typedef = Parm->getType()->getAs()) if (Typedef->getDecl()->getQualifiedNameAsString() == "testing::Unused") continue; diff --git a/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp index 003c05f865ad3..9e336cb4cf15d 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp @@ -37,11 +37,10 @@ void RedundantControlFlowCheck::registerMatchers(MatchFinder *Finder) { has(compoundStmt(hasAnySubstatement(returnStmt(unless(has(expr()))))) .bind("return"))), this); - auto CompoundContinue = - has(compoundStmt(hasAnySubstatement(continueStmt())).bind("continue")); Finder->addMatcher( - stmt(anyOf(forStmt(), cxxForRangeStmt(), whileStmt(), doStmt()), - CompoundContinue), + mapAnyOf(forStmt, cxxForRangeStmt, whileStmt, doStmt) + .with(hasBody(compoundStmt(hasAnySubstatement(continueStmt())) + .bind("continue"))), this); } @@ -55,16 +54,16 @@ void RedundantControlFlowCheck::check(const MatchFinder::MatchResult &Result) { void RedundantControlFlowCheck::checkRedundantReturn( const MatchFinder::MatchResult &Result, const CompoundStmt *Block) { - CompoundStmt::const_reverse_body_iterator last = Block->body_rbegin(); - if (const auto *Return = dyn_cast(*last)) + CompoundStmt::const_reverse_body_iterator Last = Block->body_rbegin(); + if (const auto *Return = dyn_cast(*Last)) issueDiagnostic(Result, Block, Return->getSourceRange(), RedundantReturnDiag); } void RedundantControlFlowCheck::checkRedundantContinue( const MatchFinder::MatchResult &Result, const CompoundStmt *Block) { - CompoundStmt::const_reverse_body_iterator last = Block->body_rbegin(); - if (const auto *Continue = dyn_cast(*last)) + CompoundStmt::const_reverse_body_iterator Last = Block->body_rbegin(); + if (const auto *Continue = dyn_cast(*Last)) issueDiagnostic(Result, Block, Continue->getSourceRange(), RedundantContinueDiag); } diff --git a/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp index f673dad9ed066..dfe3fbc96bf1b 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantDeclarationCheck.cpp @@ -68,7 +68,7 @@ void RedundantDeclarationCheck::check(const MatchFinder::MatchResult &Result) { bool MultiVar = false; if (const auto *VD = dyn_cast(D)) { // Is this a multivariable declaration? - for (const auto Other : VD->getDeclContext()->decls()) { + for (const auto *Other : VD->getDeclContext()->decls()) { if (Other != D && Other->getBeginLoc() == VD->getBeginLoc()) { MultiVar = true; break; diff --git a/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.cpp index 822c4cd14ddc1..46dd82bd118db 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.cpp @@ -40,23 +40,23 @@ class RedundantPreprocessorCallbacks : public PPCallbacks { StringRef Condition = Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange), PP.getSourceManager(), PP.getLangOpts()); - CheckMacroRedundancy(Loc, Condition, IfStack, DK_If, DK_If, true); + checkMacroRedundancy(Loc, Condition, IfStack, DK_If, DK_If, true); } void Ifdef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MacroDefinition) override { std::string MacroName = PP.getSpelling(MacroNameTok); - CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifdef, DK_Ifdef, true); - CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifdef, DK_Ifndef, + checkMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifdef, DK_Ifdef, true); + checkMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifdef, DK_Ifndef, false); } void Ifndef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MacroDefinition) override { std::string MacroName = PP.getSpelling(MacroNameTok); - CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifndef, DK_Ifndef, + checkMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifndef, DK_Ifndef, true); - CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifndef, DK_Ifdef, + checkMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifndef, DK_Ifdef, false); } @@ -70,7 +70,7 @@ class RedundantPreprocessorCallbacks : public PPCallbacks { } private: - void CheckMacroRedundancy(SourceLocation Loc, StringRef MacroName, + void checkMacroRedundancy(SourceLocation Loc, StringRef MacroName, SmallVector &Stack, DirectiveKind WarningKind, DirectiveKind NoteKind, bool Store) { diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp index 26c8ae5a32443..7a37630433fed 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp @@ -72,18 +72,18 @@ void RedundantStringInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) { - const auto hasStringTypeName = hasAnyNameStdString(StringNames); - const auto hasStringCtorName = + const auto HasStringTypeName = hasAnyNameStdString(StringNames); + const auto HasStringCtorName = hasAnyNameStdString(removeNamespaces(StringNames)); // Match string constructor. const auto StringConstructorExpr = expr( anyOf(cxxConstructExpr(argumentCountIs(1), - hasDeclaration(cxxMethodDecl(hasStringCtorName))), + hasDeclaration(cxxMethodDecl(HasStringCtorName))), // If present, the second argument is the alloc object which must // not be present explicitly. cxxConstructExpr(argumentCountIs(2), - hasDeclaration(cxxMethodDecl(hasStringCtorName)), + hasDeclaration(cxxMethodDecl(HasStringCtorName)), hasArgument(1, cxxDefaultArgExpr())))); // Match a string constructor expression with an empty string literal. @@ -96,7 +96,7 @@ void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) { hasArgument(0, ignoringImplicit(EmptyStringCtorExpr))); const auto StringType = hasType(hasUnqualifiedDesugaredType( - recordType(hasDeclaration(cxxRecordDecl(hasStringTypeName))))); + recordType(hasDeclaration(cxxRecordDecl(HasStringTypeName))))); const auto EmptyStringInit = traverse( TK_AsIs, expr(ignoringImplicit(anyOf( EmptyStringCtorExpr, EmptyStringCtorExprWithTemporaries)))); diff --git a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp index 7e8ba4eb90c65..d450df55c6a0d 100644 --- a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp @@ -139,11 +139,11 @@ StringRef negatedOperator(const CXXOperatorCallExpr *OpCall) { return StringRef(); } -std::string asBool(StringRef text, bool NeedsStaticCast) { +std::string asBool(StringRef Text, bool NeedsStaticCast) { if (NeedsStaticCast) - return ("static_cast(" + text + ")").str(); + return ("static_cast(" + Text + ")").str(); - return std::string(text); + return std::string(Text); } bool needsNullPtrComparison(const Expr *E) { @@ -398,8 +398,8 @@ void SimplifyBooleanExprCheck::reportBinOp( bool BoolValue = Bool->getValue(); - auto replaceWithExpression = [this, &Result, LHS, RHS, Bool]( - const Expr *ReplaceWith, bool Negated) { + auto ReplaceWithExpression = [this, &Result, LHS, RHS, + Bool](const Expr *ReplaceWith, bool Negated) { std::string Replacement = replacementExpression(Result, Negated, ReplaceWith); SourceRange Range(LHS->getBeginLoc(), RHS->getEndLoc()); @@ -411,28 +411,28 @@ void SimplifyBooleanExprCheck::reportBinOp( case BO_LAnd: if (BoolValue) { // expr && true -> expr - replaceWithExpression(Other, /*Negated=*/false); + ReplaceWithExpression(Other, /*Negated=*/false); } else { // expr && false -> false - replaceWithExpression(Bool, /*Negated=*/false); + ReplaceWithExpression(Bool, /*Negated=*/false); } break; case BO_LOr: if (BoolValue) { // expr || true -> true - replaceWithExpression(Bool, /*Negated=*/false); + ReplaceWithExpression(Bool, /*Negated=*/false); } else { // expr || false -> expr - replaceWithExpression(Other, /*Negated=*/false); + ReplaceWithExpression(Other, /*Negated=*/false); } break; case BO_EQ: // expr == true -> expr, expr == false -> !expr - replaceWithExpression(Other, /*Negated=*/!BoolValue); + ReplaceWithExpression(Other, /*Negated=*/!BoolValue); break; case BO_NE: // expr != true -> !expr, expr != false -> expr - replaceWithExpression(Other, /*Negated=*/BoolValue); + ReplaceWithExpression(Other, /*Negated=*/BoolValue); break; default: break; diff --git a/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp b/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp index 3dd646b2edd44..2d14b49e0eea9 100644 --- a/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp @@ -17,13 +17,13 @@ namespace clang { namespace tidy { namespace readability { -static const char kDefaultTypes[] = +static const char KDefaultTypes[] = "::std::basic_string;::std::basic_string_view;::std::vector;::std::array"; SimplifySubscriptExprCheck::SimplifySubscriptExprCheck( StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), Types(utils::options::parseStringList( - Options.get("Types", kDefaultTypes))) { + Options.get("Types", KDefaultTypes))) { } void SimplifySubscriptExprCheck::registerMatchers(MatchFinder *Finder) { diff --git a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp index eef6253f6a1ff..c4fbeeb4777aa 100644 --- a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp @@ -62,7 +62,7 @@ struct NewSuffix { llvm::Optional FixIt; }; -llvm::Optional GetMacroAwareLocation(SourceLocation Loc, +llvm::Optional getMacroAwareLocation(SourceLocation Loc, const SourceManager &SM) { // Do nothing if the provided location is invalid. if (Loc.isInvalid()) @@ -74,11 +74,11 @@ llvm::Optional GetMacroAwareLocation(SourceLocation Loc, return SpellingLoc; } -llvm::Optional GetMacroAwareSourceRange(SourceRange Loc, +llvm::Optional getMacroAwareSourceRange(SourceRange Loc, const SourceManager &SM) { llvm::Optional Begin = - GetMacroAwareLocation(Loc.getBegin(), SM); - llvm::Optional End = GetMacroAwareLocation(Loc.getEnd(), SM); + getMacroAwareLocation(Loc.getBegin(), SM); + llvm::Optional End = getMacroAwareLocation(Loc.getEnd(), SM); if (!Begin || !End) return llvm::None; return SourceRange(*Begin, *End); @@ -120,7 +120,7 @@ shouldReplaceLiteralSuffix(const Expr &Literal, // The literal may have macro expansion, we need the final expanded src range. llvm::Optional Range = - GetMacroAwareSourceRange(ReplacementDsc.LiteralLocation, SM); + getMacroAwareSourceRange(ReplacementDsc.LiteralLocation, SM); if (!Range) return llvm::None; diff --git a/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp index 165acd40841fb..6e837509708b0 100644 --- a/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp @@ -42,32 +42,32 @@ namespace tidy { namespace readability { void UseAnyOfAllOfCheck::registerMatchers(MatchFinder *Finder) { - auto returns = [](bool V) { + auto Returns = [](bool V) { return returnStmt(hasReturnValue(cxxBoolLiteral(equals(V)))); }; - auto returnsButNotTrue = + auto ReturnsButNotTrue = returnStmt(hasReturnValue(unless(cxxBoolLiteral(equals(true))))); - auto returnsButNotFalse = + auto ReturnsButNotFalse = returnStmt(hasReturnValue(unless(cxxBoolLiteral(equals(false))))); Finder->addMatcher( cxxForRangeStmt( - nextStmt(returns(false).bind("final_return")), - hasBody(allOf(hasDescendant(returns(true)), + nextStmt(Returns(false).bind("final_return")), + hasBody(allOf(hasDescendant(Returns(true)), unless(anyOf(hasDescendant(breakStmt()), hasDescendant(gotoStmt()), - hasDescendant(returnsButNotTrue)))))) + hasDescendant(ReturnsButNotTrue)))))) .bind("any_of_loop"), this); Finder->addMatcher( cxxForRangeStmt( - nextStmt(returns(true).bind("final_return")), - hasBody(allOf(hasDescendant(returns(false)), + nextStmt(Returns(true).bind("final_return")), + hasBody(allOf(hasDescendant(Returns(false)), unless(anyOf(hasDescendant(breakStmt()), hasDescendant(gotoStmt()), - hasDescendant(returnsButNotFalse)))))) + hasDescendant(ReturnsButNotFalse)))))) .bind("all_of_loop"), this); } diff --git a/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp b/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp index 9b8eca137c3aa..dae7503856410 100644 --- a/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp @@ -25,14 +25,12 @@ const FunctionDecl *getSurroundingFunction(ASTContext &Context, } bool IsBinaryOrTernary(const Expr *E) { - const Expr *E_base = E->IgnoreImpCasts(); - if (clang::isa(E_base) || - clang::isa(E_base)) { + const Expr *EBase = E->IgnoreImpCasts(); + if (isa(EBase) || isa(EBase)) { return true; } - if (const auto *Operator = - clang::dyn_cast(E_base)) { + if (const auto *Operator = dyn_cast(EBase)) { return Operator->isInfixBinaryOp(); } @@ -56,7 +54,7 @@ bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM, } // If it's a binary OR operation. if (const auto *BO = dyn_cast(Flags)) - if (BO->getOpcode() == clang::BinaryOperatorKind::BO_Or) + if (BO->getOpcode() == BinaryOperatorKind::BO_Or) return exprHasBitFlagWithSpelling(BO->getLHS()->IgnoreParenCasts(), SM, LangOpts, FlagName) || exprHasBitFlagWithSpelling(BO->getRHS()->IgnoreParenCasts(), SM, diff --git a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp index 10d2b24a9677a..38122d5420ac2 100644 --- a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp @@ -66,10 +66,7 @@ constReferenceDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, substTemplateTypeParmType(hasReplacementType(ConstReferenceOrValue)))); auto UsedAsConstRefOrValueArg = forEachArgumentWithParam( DeclRefToVar, parmVarDecl(hasType(ConstReferenceOrValueOrReplaced))); - Matches = match(findAll(callExpr(UsedAsConstRefOrValueArg)), Stmt, Context); - extractNodesByIdTo(Matches, "declRef", DeclRefs); - Matches = - match(findAll(cxxConstructExpr(UsedAsConstRefOrValueArg)), Stmt, Context); + Matches = match(findAll(invocation(UsedAsConstRefOrValueArg)), Stmt, Context); extractNodesByIdTo(Matches, "declRef", DeclRefs); // References and pointers to const assignments. Matches = diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index 1e544f4f1b333..97895115a7d5c 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -158,8 +158,8 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( } else if (const auto *Try = dyn_cast(St)) { ExceptionInfo Uncaught = throwsException(Try->getTryBlock(), Caught, CallStack); - for (unsigned i = 0; i < Try->getNumHandlers(); ++i) { - const CXXCatchStmt *Catch = Try->getHandler(i); + for (unsigned I = 0; I < Try->getNumHandlers(); ++I) { + const CXXCatchStmt *Catch = Try->getHandler(I); // Everything is catched through 'catch(...)'. if (!Catch->getExceptionDecl()) { diff --git a/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp b/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp index 76e40a3e1d562..1d7c11f20361c 100644 --- a/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp @@ -61,7 +61,7 @@ bool isDescendantOrEqual(const Stmt *Descendant, const Stmt *Ancestor, return false; } -} +} // namespace ExprSequence::ExprSequence(const CFG *TheCFG, const Stmt *Root, ASTContext *TheContext) diff --git a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp index 56c5bcae64ba0..de75148d127a7 100644 --- a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp +++ b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp @@ -17,7 +17,7 @@ namespace utils { namespace { -StringRef RemoveFirstSuffix(StringRef Str, ArrayRef Suffixes) { +StringRef removeFirstSuffix(StringRef Str, ArrayRef Suffixes) { for (StringRef Suffix : Suffixes) { if (Str.endswith(Suffix)) { return Str.substr(0, Str.size() - Suffix.size()); @@ -26,7 +26,7 @@ StringRef RemoveFirstSuffix(StringRef Str, ArrayRef Suffixes) { return Str; } -StringRef MakeCanonicalName(StringRef Str, IncludeSorter::IncludeStyle Style) { +StringRef makeCanonicalName(StringRef Str, IncludeSorter::IncludeStyle Style) { // The list of suffixes to remove from source file names to get the // "canonical" file names. // E.g. tools/sort_includes.cc and tools/sort_includes_test.cc @@ -34,12 +34,12 @@ StringRef MakeCanonicalName(StringRef Str, IncludeSorter::IncludeStyle Style) { // (once canonicalized) will match as being the main include file associated // with the source files. if (Style == IncludeSorter::IS_LLVM) { - return RemoveFirstSuffix( - RemoveFirstSuffix(Str, {".cc", ".cpp", ".c", ".h", ".hpp"}), {"Test"}); + return removeFirstSuffix( + removeFirstSuffix(Str, {".cc", ".cpp", ".c", ".h", ".hpp"}), {"Test"}); } if (Style == IncludeSorter::IS_Google_ObjC) { StringRef Canonical = - RemoveFirstSuffix(RemoveFirstSuffix(Str, {".cc", ".cpp", ".c", ".h", + removeFirstSuffix(removeFirstSuffix(Str, {".cc", ".cpp", ".c", ".h", ".hpp", ".mm", ".m"}), {"_unittest", "_regtest", "_test", "Test"}); @@ -52,19 +52,19 @@ StringRef MakeCanonicalName(StringRef Str, IncludeSorter::IncludeStyle Style) { return Canonical.substr( 0, Canonical.find_first_of('+', StartIndex)); } - return RemoveFirstSuffix( - RemoveFirstSuffix(Str, {".cc", ".cpp", ".c", ".h", ".hpp"}), + return removeFirstSuffix( + removeFirstSuffix(Str, {".cc", ".cpp", ".c", ".h", ".hpp"}), {"_unittest", "_regtest", "_test"}); } // Scan to the end of the line and return the offset of the next line. -size_t FindNextLine(const char *Text) { +size_t findNextLine(const char *Text) { size_t EOLIndex = std::strcspn(Text, "\n"); return Text[EOLIndex] == '\0' ? EOLIndex : EOLIndex + 1; } IncludeSorter::IncludeKinds -DetermineIncludeKind(StringRef CanonicalFile, StringRef IncludeFile, +determineIncludeKind(StringRef CanonicalFile, StringRef IncludeFile, bool IsAngled, IncludeSorter::IncludeStyle Style) { // Compute the two "canonical" forms of the include's filename sans extension. // The first form is the include's filename without ".h" or "-inl.h" at the @@ -76,7 +76,7 @@ DetermineIncludeKind(StringRef CanonicalFile, StringRef IncludeFile, return IncludeFile.endswith(".h") ? IncludeSorter::IK_CSystemInclude : IncludeSorter::IK_CXXSystemInclude; } - StringRef CanonicalInclude = MakeCanonicalName(IncludeFile, Style); + StringRef CanonicalInclude = makeCanonicalName(IncludeFile, Style); if (CanonicalFile.endswith(CanonicalInclude) || CanonicalInclude.endswith(CanonicalFile)) { return IncludeSorter::IK_MainTUInclude; @@ -127,12 +127,12 @@ IncludeSorter::IncludeSorter(const SourceManager *SourceMgr, const FileID FileID, StringRef FileName, IncludeStyle Style) : SourceMgr(SourceMgr), Style(Style), CurrentFileID(FileID), - CanonicalFile(MakeCanonicalName(FileName, Style)) {} + CanonicalFile(makeCanonicalName(FileName, Style)) {} void IncludeSorter::AddInclude(StringRef FileName, bool IsAngled, SourceLocation HashLocation, SourceLocation EndLocation) { - int Offset = FindNextLine(SourceMgr->getCharacterData(EndLocation)); + int Offset = findNextLine(SourceMgr->getCharacterData(EndLocation)); // Record the relevant location information for this inclusion directive. IncludeLocations[FileName].push_back( @@ -145,7 +145,7 @@ void IncludeSorter::AddInclude(StringRef FileName, bool IsAngled, // Add the included file's name to the appropriate bucket. IncludeKinds Kind = - DetermineIncludeKind(CanonicalFile, FileName, IsAngled, Style); + determineIncludeKind(CanonicalFile, FileName, IsAngled, Style); if (Kind != IK_InvalidInclude) IncludeBucket[Kind].push_back(FileName.str()); } @@ -171,14 +171,15 @@ Optional IncludeSorter::CreateIncludeInsertion(StringRef FileName, } auto IncludeKind = - DetermineIncludeKind(CanonicalFile, FileName, IsAngled, Style); + determineIncludeKind(CanonicalFile, FileName, IsAngled, Style); if (!IncludeBucket[IncludeKind].empty()) { for (const std::string &IncludeEntry : IncludeBucket[IncludeKind]) { if (compareHeaders(FileName, IncludeEntry, Style) < 0) { const auto &Location = IncludeLocations[IncludeEntry][0]; return FixItHint::CreateInsertion(Location.getBegin(), IncludeStmt); - } else if (FileName == IncludeEntry) { + } + if (FileName == IncludeEntry) { return llvm::None; } } @@ -195,9 +196,9 @@ Optional IncludeSorter::CreateIncludeInsertion(StringRef FileName, // include bucket in the file. In that case, we'll want to sort the include // before that bucket. IncludeKinds NonEmptyKind = IK_InvalidInclude; - for (int i = IK_InvalidInclude - 1; i >= 0; --i) { - if (!IncludeBucket[i].empty()) { - NonEmptyKind = static_cast(i); + for (int I = IK_InvalidInclude - 1; I >= 0; --I) { + if (!IncludeBucket[I].empty()) { + NonEmptyKind = static_cast(I); if (NonEmptyKind < IncludeKind) break; } diff --git a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp index e93f3fbf21d7e..9f64c562600bc 100644 --- a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp @@ -104,7 +104,8 @@ void TransformerClangTidyCheck::check( Diag << FixItHint::CreateReplacement(T.Range, T.Replacement); break; case transformer::EditKind::AddInclude: - Diag << Inserter.createMainFileIncludeInsertion(T.Replacement); + Diag << Inserter.createIncludeInsertion( + Result.SourceManager->getFileID(T.Range.getBegin()), T.Replacement); break; } } diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index aecaf7e6b8f7a..abcfc1af848bc 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -283,6 +283,52 @@ std::string printNamespaceScope(const DeclContext &DC) { return ""; } +static llvm::StringRef +getNameOrErrForObjCInterface(const ObjCInterfaceDecl *ID) { + return ID ? ID->getName() : "<>"; +} + +std::string printObjCMethod(const ObjCMethodDecl &Method) { + std::string Name; + llvm::raw_string_ostream OS(Name); + + OS << (Method.isInstanceMethod() ? '-' : '+') << '['; + + // Should always be true. + if (const ObjCContainerDecl *C = + dyn_cast(Method.getDeclContext())) + OS << printObjCContainer(*C); + + Method.getSelector().print(OS << ' '); + if (Method.isVariadic()) + OS << ", ..."; + + OS << ']'; + OS.flush(); + return Name; +} + +std::string printObjCContainer(const ObjCContainerDecl &C) { + if (const ObjCCategoryDecl *Category = dyn_cast(&C)) { + std::string Name; + llvm::raw_string_ostream OS(Name); + const ObjCInterfaceDecl *Class = Category->getClassInterface(); + OS << getNameOrErrForObjCInterface(Class) << '(' << Category->getName() + << ')'; + OS.flush(); + return Name; + } + if (const ObjCCategoryImplDecl *CID = dyn_cast(&C)) { + std::string Name; + llvm::raw_string_ostream OS(Name); + const ObjCInterfaceDecl *Class = CID->getClassInterface(); + OS << getNameOrErrForObjCInterface(Class) << '(' << CID->getName() << ')'; + OS.flush(); + return Name; + } + return C.getNameAsString(); +} + SymbolID getSymbolID(const Decl *D) { llvm::SmallString<128> USR; if (index::generateUSRForDecl(D, USR)) diff --git a/clang-tools-extra/clangd/AST.h b/clang-tools-extra/clangd/AST.h index b603964189e8a..94984a915422e 100644 --- a/clang-tools-extra/clangd/AST.h +++ b/clang-tools-extra/clangd/AST.h @@ -15,6 +15,7 @@ #include "index/SymbolID.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/MacroInfo.h" @@ -64,6 +65,14 @@ std::string printName(const ASTContext &Ctx, const NamedDecl &ND); /// string if decl is not a template specialization. std::string printTemplateSpecializationArgs(const NamedDecl &ND); +/// Print the Objective-C method name, including the full container name, e.g. +/// `-[MyClass(Category) method:]` +std::string printObjCMethod(const ObjCMethodDecl &Method); + +/// Print the Objective-C container name including categories, e.g. `MyClass`, +// `MyClass()`, `MyClass(Category)`, and `MyProtocol`. +std::string printObjCContainer(const ObjCContainerDecl &C); + /// Gets the symbol ID for a declaration. Returned SymbolID might be null. SymbolID getSymbolID(const Decl *D); diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index 35aed2166f038..1d8efe6d84b74 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -51,7 +51,6 @@ namespace clang { namespace clangd { namespace { - // Tracks end-to-end latency of high level lsp calls. Measurements are in // seconds. constexpr trace::Metric LSPLatency("lsp_latency", trace::Metric::Distribution, @@ -71,6 +70,9 @@ llvm::Optional decodeVersion(llvm::StringRef Encoded) { return llvm::None; } +const llvm::StringLiteral APPLY_FIX_COMMAND = "clangd.applyFix"; +const llvm::StringLiteral APPLY_TWEAK_COMMAND = "clangd.applyTweak"; + /// Transforms a tweak into a code action that would apply it if executed. /// EXPECTS: T.prepare() was called and returned true. CodeAction toCodeAction(const ClangdServer::TweakRef &T, const URIForFile &File, @@ -85,11 +87,12 @@ CodeAction toCodeAction(const ClangdServer::TweakRef &T, const URIForFile &File, // directly. CA.command.emplace(); CA.command->title = T.Title; - CA.command->command = std::string(Command::CLANGD_APPLY_TWEAK); - CA.command->tweakArgs.emplace(); - CA.command->tweakArgs->file = File; - CA.command->tweakArgs->tweakID = T.ID; - CA.command->tweakArgs->selection = Selection; + CA.command->command = std::string(APPLY_TWEAK_COMMAND); + TweakArgs Args; + Args.file = File; + Args.tweakID = T.ID; + Args.selection = Selection; + CA.command->argument = std::move(Args); return CA; } @@ -117,18 +120,6 @@ CompletionItemKindBitset defaultCompletionItemKinds() { return Defaults; } -// Build a lookup table (HighlightingKind => {TextMate Scopes}), which is sent -// to the LSP client. -std::vector> buildHighlightScopeLookupTable() { - std::vector> LookupTable; - // HighlightingKind is using as the index. - for (int KindValue = 0; KindValue <= (int)HighlightingKind::LastKind; - ++KindValue) - LookupTable.push_back( - {std::string(toTextMateScope((HighlightingKind)(KindValue)))}); - return LookupTable; -} - // Makes sure edits in \p FE are applicable to latest file contents reported by // editor. If not generates an error message containing information about files // that needs to be saved. @@ -490,6 +481,15 @@ static std::vector semanticTokenTypes() { return Types; } +static std::vector semanticTokenModifiers() { + std::vector Modifiers; + for (unsigned I = 0; + I <= static_cast(HighlightingModifier::LastModifier); ++I) + Modifiers.push_back( + toSemanticTokenModifier(static_cast(I))); + return Modifiers; +} + void ClangdLSPServer::onInitialize(const InitializeParams &Params, Callback Reply) { // Determine character encoding first as it affects constructed ClangdServer. @@ -502,18 +502,10 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, } } - Opts.TheiaSemanticHighlighting = - Params.capabilities.TheiaSemanticHighlighting; if (Params.capabilities.TheiaSemanticHighlighting && - Params.capabilities.SemanticTokens) { - log("Client supports legacy semanticHighlights notification and standard " - "semanticTokens request, choosing the latter (no notifications)."); - Opts.TheiaSemanticHighlighting = false; - } - if (Opts.TheiaSemanticHighlighting) { - log("Using legacy semanticHighlights notification, which will be removed " - "in clangd 13. Clients should use the standard semanticTokens " - "request instead."); + !Params.capabilities.SemanticTokens) { + elog("Client requested legacy semanticHighlights notification, which is " + "no longer supported. Migrate to standard semanticTokens request"); } if (Params.rootUri && *Params.rootUri) @@ -593,6 +585,11 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, {CodeAction::QUICKFIX_KIND, CodeAction::REFACTOR_KIND, CodeAction::INFO_KIND}}}; + std::vector Commands; + for (llvm::StringRef Command : CommandHandlers.keys()) + Commands.push_back(Command); + llvm::sort(Commands); + llvm::json::Object Result{ {{"serverInfo", llvm::json::Object{{"name", "clangd"}, @@ -628,8 +625,9 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, {"full", llvm::json::Object{{"delta", true}}}, {"range", false}, {"legend", - llvm::json::Object{{"tokenTypes", semanticTokenTypes()}, - {"tokenModifiers", llvm::json::Array()}}}, + llvm::json::Object{ + {"tokenTypes", semanticTokenTypes()}, + {"tokenModifiers", semanticTokenModifiers()}}}, }}, {"signatureHelpProvider", llvm::json::Object{ @@ -651,11 +649,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, {"referencesProvider", true}, {"astProvider", true}, // clangd extension {"executeCommandProvider", - llvm::json::Object{ - {"commands", - {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND, - ExecuteCommandParams::CLANGD_APPLY_TWEAK}}, - }}, + llvm::json::Object{{"commands", Commands}}}, {"typeHierarchyProvider", true}, {"memoryUsageProvider", true}, // clangd extension {"compilationDatabase", // clangd extension @@ -664,11 +658,6 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, }}}}; if (Opts.Encoding) Result["offsetEncoding"] = *Opts.Encoding; - if (Opts.TheiaSemanticHighlighting) - Result.getObject("capabilities") - ->insert( - {"semanticHighlighting", - llvm::json::Object{{"scopes", buildHighlightScopeLookupTable()}}}); if (Opts.FoldingRanges) Result.getObject("capabilities")->insert({"foldingRangeProvider", true}); Reply(std::move(Result)); @@ -745,85 +734,86 @@ void ClangdLSPServer::onFileEvent(const DidChangeWatchedFilesParams &Params) { void ClangdLSPServer::onCommand(const ExecuteCommandParams &Params, Callback Reply) { - auto ApplyEdit = [this](WorkspaceEdit WE, std::string SuccessMessage, - decltype(Reply) Reply) { - ApplyWorkspaceEditParams Edit; - Edit.edit = std::move(WE); - call( - "workspace/applyEdit", std::move(Edit), - [Reply = std::move(Reply), SuccessMessage = std::move(SuccessMessage)]( - llvm::Expected Response) mutable { - if (!Response) - return Reply(Response.takeError()); - if (!Response->applied) { - std::string Reason = Response->failureReason - ? *Response->failureReason - : "unknown reason"; - return Reply(error("edits were not applied: {0}", Reason)); - } - return Reply(SuccessMessage); - }); - }; - - if (Params.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND && - Params.workspaceEdit) { - // The flow for "apply-fix" : - // 1. We publish a diagnostic, including fixits - // 2. The user clicks on the diagnostic, the editor asks us for code actions - // 3. We send code actions, with the fixit embedded as context - // 4. The user selects the fixit, the editor asks us to apply it - // 5. We unwrap the changes and send them back to the editor - // 6. The editor applies the changes (applyEdit), and sends us a reply - // 7. We unwrap the reply and send a reply to the editor. - ApplyEdit(*Params.workspaceEdit, "Fix applied.", std::move(Reply)); - } else if (Params.command == ExecuteCommandParams::CLANGD_APPLY_TWEAK && - Params.tweakArgs) { - auto Code = DraftMgr.getDraft(Params.tweakArgs->file.file()); - if (!Code) - return Reply(error("trying to apply a code action for a non-added file")); - - auto Action = [this, ApplyEdit, Reply = std::move(Reply), - File = Params.tweakArgs->file, Code = std::move(*Code)]( - llvm::Expected R) mutable { - if (!R) - return Reply(R.takeError()); - - assert(R->ShowMessage || - (!R->ApplyEdits.empty() && "tweak has no effect")); - - if (R->ShowMessage) { - ShowMessageParams Msg; - Msg.message = *R->ShowMessage; - Msg.type = MessageType::Info; - notify("window/showMessage", Msg); - } - // When no edit is specified, make sure we Reply(). - if (R->ApplyEdits.empty()) - return Reply("Tweak applied."); - - if (auto Err = validateEdits(DraftMgr, R->ApplyEdits)) - return Reply(std::move(Err)); - - WorkspaceEdit WE; - WE.changes.emplace(); - for (const auto &It : R->ApplyEdits) { - (*WE.changes)[URI::createFile(It.first()).toString()] = - It.second.asTextEdits(); - } - // ApplyEdit will take care of calling Reply(). - return ApplyEdit(std::move(WE), "Tweak applied.", std::move(Reply)); - }; - Server->applyTweak(Params.tweakArgs->file.file(), - Params.tweakArgs->selection, Params.tweakArgs->tweakID, - std::move(Action)); - } else { - // We should not get here because ExecuteCommandParams would not have - // parsed in the first place and this handler should not be called. But if - // more commands are added, this will be here has a safe guard. - Reply(llvm::make_error( + auto It = CommandHandlers.find(Params.command); + if (It == CommandHandlers.end()) { + return Reply(llvm::make_error( llvm::formatv("Unsupported command \"{0}\".", Params.command).str(), ErrorCode::InvalidParams)); } + It->second(Params.argument, std::move(Reply)); +} + +void ClangdLSPServer::onCommandApplyEdit(const WorkspaceEdit &WE, + Callback Reply) { + // The flow for "apply-fix" : + // 1. We publish a diagnostic, including fixits + // 2. The user clicks on the diagnostic, the editor asks us for code actions + // 3. We send code actions, with the fixit embedded as context + // 4. The user selects the fixit, the editor asks us to apply it + // 5. We unwrap the changes and send them back to the editor + // 6. The editor applies the changes (applyEdit), and sends us a reply + // 7. We unwrap the reply and send a reply to the editor. + applyEdit(WE, "Fix applied.", std::move(Reply)); +} + +void ClangdLSPServer::onCommandApplyTweak(const TweakArgs &Args, + Callback Reply) { + auto Code = DraftMgr.getDraft(Args.file.file()); + if (!Code) + return Reply(error("trying to apply a code action for a non-added file")); + + auto Action = [this, Reply = std::move(Reply), File = Args.file, + Code = std::move(*Code)]( + llvm::Expected R) mutable { + if (!R) + return Reply(R.takeError()); + + assert(R->ShowMessage || (!R->ApplyEdits.empty() && "tweak has no effect")); + + if (R->ShowMessage) { + ShowMessageParams Msg; + Msg.message = *R->ShowMessage; + Msg.type = MessageType::Info; + notify("window/showMessage", Msg); + } + // When no edit is specified, make sure we Reply(). + if (R->ApplyEdits.empty()) + return Reply("Tweak applied."); + + if (auto Err = validateEdits(DraftMgr, R->ApplyEdits)) + return Reply(std::move(Err)); + + WorkspaceEdit WE; + WE.changes.emplace(); + for (const auto &It : R->ApplyEdits) { + (*WE.changes)[URI::createFile(It.first()).toString()] = + It.second.asTextEdits(); + } + // ApplyEdit will take care of calling Reply(). + return applyEdit(std::move(WE), "Tweak applied.", std::move(Reply)); + }; + Server->applyTweak(Args.file.file(), Args.selection, Args.tweakID, + std::move(Action)); +} + +void ClangdLSPServer::applyEdit(WorkspaceEdit WE, llvm::json::Value Success, + Callback Reply) { + ApplyWorkspaceEditParams Edit; + Edit.edit = std::move(WE); + call( + "workspace/applyEdit", std::move(Edit), + [Reply = std::move(Reply), SuccessMessage = std::move(Success)]( + llvm::Expected Response) mutable { + if (!Response) + return Reply(Response.takeError()); + if (!Response->applied) { + std::string Reason = Response->failureReason + ? *Response->failureReason + : "unknown reason"; + return Reply(error("edits were not applied: {0}", Reason)); + } + return Reply(SuccessMessage); + }); } void ClangdLSPServer::onWorkspaceSymbol( @@ -888,10 +878,6 @@ void ClangdLSPServer::onDocumentDidClose( std::lock_guard Lock(FixItsMutex); FixItsMap.erase(File); } - { - std::lock_guard HLock(HighlightingsMutex); - FileToHighlightings.erase(File); - } { std::lock_guard HLock(SemanticTokensMutex); LastSemanticTokens.erase(File); @@ -1017,8 +1003,8 @@ static llvm::Optional asCommand(const CodeAction &Action) { if (Action.command) { Cmd = *Action.command; } else if (Action.edit) { - Cmd.command = std::string(Command::CLANGD_APPLY_FIX_COMMAND); - Cmd.workspaceEdit = *Action.edit; + Cmd.command = std::string(APPLY_FIX_COMMAND); + Cmd.argument = *Action.edit; } else { return None; } @@ -1303,11 +1289,6 @@ void ClangdLSPServer::applyConfiguration( [&](llvm::StringRef File) { return ModifiedFiles.count(File) != 0; }); } -void ClangdLSPServer::publishTheiaSemanticHighlighting( - const TheiaSemanticHighlightingParams &Params) { - notify("textDocument/semanticHighlighting", Params); -} - void ClangdLSPServer::publishDiagnostics( const PublishDiagnosticsParams &Params) { notify("textDocument/publishDiagnostics", Params); @@ -1339,14 +1320,23 @@ void ClangdLSPServer::onChangeConfiguration( void ClangdLSPServer::onReference(const ReferenceParams &Params, Callback> Reply) { - Server->findReferences(Params.textDocument.uri.file(), Params.position, - Opts.CodeComplete.Limit, - [Reply = std::move(Reply)]( - llvm::Expected Refs) mutable { - if (!Refs) - return Reply(Refs.takeError()); - return Reply(std::move(Refs->References)); - }); + Server->findReferences( + Params.textDocument.uri.file(), Params.position, Opts.CodeComplete.Limit, + [Reply = std::move(Reply), + IncludeDecl(Params.context.includeDeclaration)]( + llvm::Expected Refs) mutable { + if (!Refs) + return Reply(Refs.takeError()); + // Filter out declarations if the client asked. + std::vector Result; + Result.reserve(Refs->References.size()); + for (auto &Ref : Refs->References) { + bool IsDecl = Ref.Attributes & ReferencesResult::Declaration; + if (IncludeDecl || !IsDecl) + Result.push_back(std::move(Ref.Loc)); + } + return Reply(std::move(Result)); + }); } void ClangdLSPServer::onGoToImplementation( @@ -1545,6 +1535,8 @@ ClangdLSPServer::ClangdLSPServer(class Transport &Transp, MsgHandler->bind("$/memoryUsage", &ClangdLSPServer::onMemoryUsage); if (Opts.FoldingRanges) MsgHandler->bind("textDocument/foldingRange", &ClangdLSPServer::onFoldingRange); + bindCommand(APPLY_FIX_COMMAND, &ClangdLSPServer::onCommandApplyEdit); + bindCommand(APPLY_TWEAK_COMMAND, &ClangdLSPServer::onCommandApplyTweak); // clang-format on } @@ -1609,27 +1601,6 @@ bool ClangdLSPServer::shouldRunCompletion( return allowImplicitCompletion(Code->Contents, *Offset); } -void ClangdLSPServer::onHighlightingsReady( - PathRef File, llvm::StringRef Version, - std::vector Highlightings) { - std::vector Old; - std::vector HighlightingsCopy = Highlightings; - { - std::lock_guard Lock(HighlightingsMutex); - Old = std::move(FileToHighlightings[File]); - FileToHighlightings[File] = std::move(HighlightingsCopy); - } - // LSP allows us to send incremental edits of highlightings. Also need to diff - // to remove highlightings from tokens that should no longer have them. - std::vector Diffed = diffHighlightings(Highlightings, Old); - TheiaSemanticHighlightingParams Notification; - Notification.TextDocument.uri = - URIForFile::canonicalize(File, /*TUPath=*/File); - Notification.TextDocument.version = decodeVersion(Version); - Notification.Lines = toTheiaSemanticHighlightingInformation(Diffed); - publishTheiaSemanticHighlighting(Notification); -} - void ClangdLSPServer::onDiagnosticsReady(PathRef File, llvm::StringRef Version, std::vector Diagnostics) { PublishDiagnosticsParams Notification; diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h index d8ce2dbe53db7..ef99acc028664 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.h +++ b/clang-tools-extra/clangd/ClangdLSPServer.h @@ -84,9 +84,6 @@ class ClangdLSPServer : private ClangdServer::Callbacks { void onDiagnosticsReady(PathRef File, llvm::StringRef Version, std::vector Diagnostics) override; void onFileUpdated(PathRef File, const TUStatus &Status) override; - void - onHighlightingsReady(PathRef File, llvm::StringRef Version, - std::vector Highlightings) override; void onBackgroundIndexProgress(const BackgroundQueue::Stats &Stats) override; // LSP methods. Notifications have signature void(const Params&). @@ -129,7 +126,6 @@ class ClangdLSPServer : private ClangdServer::Callbacks { void onDocumentHighlight(const TextDocumentPositionParams &, Callback>); void onFileEvent(const DidChangeWatchedFilesParams &); - void onCommand(const ExecuteCommandParams &, Callback); void onWorkspaceSymbol(const WorkspaceSymbolParams &, Callback>); void onPrepareRename(const TextDocumentPositionParams &, @@ -163,6 +159,18 @@ class ClangdLSPServer : private ClangdServer::Callbacks { /// hierarchy. void onMemoryUsage(Callback); + llvm::StringMap)>> + CommandHandlers; + void onCommand(const ExecuteCommandParams &, Callback); + + /// Implement commands. + void onCommandApplyEdit(const WorkspaceEdit &, Callback); + void onCommandApplyTweak(const TweakArgs &, Callback); + + void applyEdit(WorkspaceEdit WE, llvm::json::Value Success, + Callback Reply); + std::vector getFixes(StringRef File, const clangd::Diagnostic &D); /// Checks if completion request should be ignored. We need this due to the @@ -179,10 +187,6 @@ class ClangdLSPServer : private ClangdServer::Callbacks { llvm::function_ref Filter); void applyConfiguration(const ConfigurationSettings &Settings); - /// Sends a "publishSemanticHighlighting" notification to the LSP client. - void - publishTheiaSemanticHighlighting(const TheiaSemanticHighlightingParams &); - /// Sends a "publishDiagnostics" notification to the LSP client. void publishDiagnostics(const PublishDiagnosticsParams &); @@ -214,8 +218,6 @@ class ClangdLSPServer : private ClangdServer::Callbacks { DiagnosticToReplacementMap; /// Caches FixIts per file and diagnostics llvm::StringMap FixItsMap; - std::mutex HighlightingsMutex; - llvm::StringMap> FileToHighlightings; // Last semantic-tokens response, for incremental requests. std::mutex SemanticTokensMutex; llvm::StringMap LastSemanticTokens; @@ -272,6 +274,19 @@ class ClangdLSPServer : private ClangdServer::Callbacks { Params.value = std::move(Value); notify("$/progress", Params); } + template + void bindCommand(llvm::StringLiteral Method, + void (ClangdLSPServer::*Handler)(const Param &, + Callback)) { + CommandHandlers[Method] = [Method, Handler, + this](llvm::json::Value RawParams, + Callback Reply) { + auto P = parse(RawParams, Method, "command"); + if (!P) + return Reply(P.takeError()); + (this->*Handler)(*P, std::move(Reply)); + }; + } const ThreadsafeFS &TFS; /// Options used for diagnostics. diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index ab9903197d086..b39e582d84a1c 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -65,10 +65,8 @@ namespace { // Update the FileIndex with new ASTs and plumb the diagnostics responses. struct UpdateIndexCallbacks : public ParsingCallbacks { UpdateIndexCallbacks(FileIndex *FIndex, - ClangdServer::Callbacks *ServerCallbacks, - bool TheiaSemanticHighlighting) - : FIndex(FIndex), ServerCallbacks(ServerCallbacks), - TheiaSemanticHighlighting(TheiaSemanticHighlighting) {} + ClangdServer::Callbacks *ServerCallbacks) + : FIndex(FIndex), ServerCallbacks(ServerCallbacks) {} void onPreambleAST(PathRef Path, llvm::StringRef Version, ASTContext &Ctx, std::shared_ptr PP, @@ -82,17 +80,10 @@ struct UpdateIndexCallbacks : public ParsingCallbacks { FIndex->updateMain(Path, AST); std::vector Diagnostics = AST.getDiagnostics(); - std::vector Highlightings; - if (TheiaSemanticHighlighting) - Highlightings = getSemanticHighlightings(AST); - if (ServerCallbacks) Publish([&]() { ServerCallbacks->onDiagnosticsReady(Path, AST.version(), std::move(Diagnostics)); - if (TheiaSemanticHighlighting) - ServerCallbacks->onHighlightingsReady(Path, AST.version(), - std::move(Highlightings)); }); } @@ -111,7 +102,6 @@ struct UpdateIndexCallbacks : public ParsingCallbacks { private: FileIndex *FIndex; ClangdServer::Callbacks *ServerCallbacks; - bool TheiaSemanticHighlighting; }; } // namespace @@ -121,8 +111,6 @@ ClangdServer::Options ClangdServer::optsForTest() { Opts.UpdateDebounce = DebouncePolicy::fixed(/*zero*/ {}); Opts.StorePreamblesInMemory = true; Opts.AsyncThreadsCount = 4; // Consistent! - Opts.TheiaSemanticHighlighting = true; - Opts.AsyncPreambleBuilds = true; return Opts; } @@ -132,7 +120,6 @@ ClangdServer::Options::operator TUScheduler::Options() const { Opts.RetentionPolicy = RetentionPolicy; Opts.StorePreamblesInMemory = StorePreamblesInMemory; Opts.UpdateDebounce = UpdateDebounce; - Opts.AsyncPreambleBuilds = AsyncPreambleBuilds; Opts.ContextProvider = ContextProvider; return Opts; } @@ -141,10 +128,7 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, const ThreadsafeFS &TFS, const Options &Opts, Callbacks *Callbacks) : CDB(CDB), TFS(TFS), - DynamicIdx(Opts.BuildDynamicSymbolIndex - ? new FileIndex(Opts.HeavyweightDynamicSymbolIndex, - Opts.CollectMainFileRefs) - : nullptr), + DynamicIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex() : nullptr), ClangTidyProvider(Opts.ClangTidyProvider), WorkspaceRoot(Opts.WorkspaceRoot), // Pass a callback into `WorkScheduler` to extract symbols from a newly @@ -154,8 +138,7 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, // critical paths. WorkScheduler( CDB, TUScheduler::Options(Opts), - std::make_unique( - DynamicIdx.get(), Callbacks, Opts.TheiaSemanticHighlighting)) { + std::make_unique(DynamicIdx.get(), Callbacks)) { // Adds an index to the stack, at higher priority than existing indexes. auto AddIndex = [&](SymbolIndex *Idx) { if (this->Index != nullptr) { @@ -175,7 +158,6 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, Callbacks->onBackgroundIndexProgress(S); }; BGOpts.ContextProvider = Opts.ContextProvider; - BGOpts.CollectMainFileRefs = Opts.CollectMainFileRefs; BackgroundIdx = std::make_unique( TFS, CDB, BackgroundIndexStorage::createDiskBackedStorageFactory( @@ -415,20 +397,15 @@ void ClangdServer::prepareRename(PathRef File, Position Pos, const RenameOptions &RenameOpts, Callback CB) { auto Action = [Pos, File = File.str(), CB = std::move(CB), - NewName = std::move(NewName), RenameOpts, - this](llvm::Expected InpAST) mutable { + NewName = std::move(NewName), + RenameOpts](llvm::Expected InpAST) mutable { if (!InpAST) return CB(InpAST.takeError()); - // prepareRename is latency-sensitive: - // - for single-file rename, performing rename isn't substantially more - // expensive than doing an AST-based check (the index is used to see if - // the rename is complete); - // - for cross-file rename, we deliberately pass a nullptr index to save - // the cost, thus the result may be incomplete as it only contains - // main-file occurrences; + // prepareRename is latency-sensitive: we don't query the index, as we + // only need main-file references auto Results = clangd::rename( {Pos, NewName.getValueOr("__clangd_rename_dummy"), InpAST->AST, File, - RenameOpts.AllowCrossFile ? nullptr : Index, RenameOpts}); + /*Index=*/nullptr, RenameOpts}); if (!Results) { // LSP says to return null on failure, but that will result in a generic // failure message. If we send an LSP error response, clients can surface diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h index 0a452daa79ed3..83c8567461ec9 100644 --- a/clang-tools-extra/clangd/ClangdServer.h +++ b/clang-tools-extra/clangd/ClangdServer.h @@ -14,6 +14,7 @@ #include "ConfigProvider.h" #include "GlobalCompilationDatabase.h" #include "Hover.h" +#include "Module.h" #include "Protocol.h" #include "SemanticHighlighting.h" #include "TUScheduler.h" @@ -34,7 +35,6 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include -#include #include #include #include @@ -69,12 +69,6 @@ class ClangdServer { /// May be called concurrently for separate files, not for a single file. virtual void onFileUpdated(PathRef File, const TUStatus &Status) {} - /// Called by ClangdServer when some \p Highlightings for \p File are ready. - /// May be called concurrently for separate files, not for a single file. - virtual void - onHighlightingsReady(PathRef File, llvm::StringRef Version, - std::vector Highlightings) {} - /// Called when background indexing tasks are enqueued/started/completed. /// Not called concurrently. virtual void @@ -98,22 +92,14 @@ class ClangdServer { /// Cached preambles are potentially large. If false, store them on disk. bool StorePreamblesInMemory = true; - /// Reuse even stale preambles, and rebuild them in the background. - /// This improves latency at the cost of accuracy. - bool AsyncPreambleBuilds = true; /// If true, ClangdServer builds a dynamic in-memory index for symbols in /// opened files and uses the index to augment code completion results. bool BuildDynamicSymbolIndex = false; - /// Use a heavier and faster in-memory index implementation. - bool HeavyweightDynamicSymbolIndex = true; /// If true, ClangdServer automatically indexes files in the current project /// on background threads. The index is stored in the project root. bool BackgroundIndex = false; - /// Store refs to main-file symbols in the index. - bool CollectMainFileRefs = true; - /// If set, use this index to augment code completion results. SymbolIndex *StaticIndex = nullptr; @@ -154,12 +140,11 @@ class ClangdServer { /// fetch system include path. std::vector QueryDriverGlobs; - /// Enable notification-based semantic highlighting. - bool TheiaSemanticHighlighting = false; - /// Enable preview of FoldingRanges feature. bool FoldingRanges = false; + ModuleSet *Modules = nullptr; + explicit operator TUScheduler::Options() const; }; // Sensible default options for use in tests. @@ -194,13 +179,8 @@ class ClangdServer { void removeDocument(PathRef File); /// Run code completion for \p File at \p Pos. - /// Request is processed asynchronously. /// - /// This method should only be called for currently tracked files. However, it - /// is safe to call removeDocument for \p File after this method returns, even - /// while returned future is not yet ready. - /// A version of `codeComplete` that runs \p Callback on the processing thread - /// when codeComplete results become available. + /// This method should only be called for currently tracked files. void codeComplete(PathRef File, Position Pos, const clangd::CodeCompleteOptions &Opts, Callback CB); diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index 96cbd8806ff62..b55d1b03dee64 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -503,5 +503,32 @@ void ArgStripper::process(std::vector &Args) const { Args.resize(Write); } + +std::string printArgv(llvm::ArrayRef Args) { + std::string Buf; + llvm::raw_string_ostream OS(Buf); + bool Sep = false; + for (llvm::StringRef Arg : Args) { + if (Sep) + OS << ' '; + Sep = true; + if (llvm::all_of(Arg, llvm::isPrint) && + Arg.find_first_of(" \t\n\"\\") == llvm::StringRef::npos) { + OS << Arg; + continue; + } + OS << '"'; + OS.write_escaped(Arg, /*UseHexEscapes=*/true); + OS << '"'; + } + return std::move(OS.str()); +} + +std::string printArgv(llvm::ArrayRef Args) { + std::vector Refs(Args.size()); + llvm::copy(Args, Refs.begin()); + return printArgv(Refs); +} + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/CompileCommands.h b/clang-tools-extra/clangd/CompileCommands.h index 2ba17a0e6c0dc..6e958d271c87b 100644 --- a/clang-tools-extra/clangd/CompileCommands.h +++ b/clang-tools-extra/clangd/CompileCommands.h @@ -96,6 +96,11 @@ class ArgStripper { std::deque Storage; // Store strings not found in option table. }; +// Renders an argv list, with arguments separated by spaces. +// Where needed, arguments are "quoted" and escaped. +std::string printArgv(llvm::ArrayRef Args); +std::string printArgv(llvm::ArrayRef Args); + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index 1a5379acfe7d7..a38c8a57d1613 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -395,20 +396,6 @@ DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const { return None; } -// For platforms where paths are case-insensitive (but case-preserving), -// we need to do case-insensitive comparisons and use lowercase keys. -// FIXME: Make Path a real class with desired semantics instead. -// This class is not the only place this problem exists. -// FIXME: Mac filesystems default to case-insensitive, but may be sensitive. - -static std::string maybeCaseFoldPath(PathRef Path) { -#if defined(_WIN32) || defined(__APPLE__) - return Path.lower(); -#else - return std::string(Path); -#endif -} - std::vector DirectoryBasedGlobalCompilationDatabase::getDirectoryCaches( llvm::ArrayRef Dirs) const { @@ -567,7 +554,10 @@ class DirectoryBasedGlobalCompilationDatabase::BroadcastThread { } ~BroadcastThread() { - ShouldStop.store(true, std::memory_order_release); + { + std::lock_guard Lock(Mu); + ShouldStop.store(true, std::memory_order_release); + } CV.notify_all(); Thread.join(); } diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp index 876645cd6a503..111b05849b81b 100644 --- a/clang-tools-extra/clangd/Headers.cpp +++ b/clang-tools-extra/clangd/Headers.cpp @@ -36,7 +36,7 @@ class RecordHeaders : public PPCallbacks { CharSourceRange /*FilenameRange*/, const FileEntry *File, llvm::StringRef /*SearchPath*/, llvm::StringRef /*RelativePath*/, - const Module * /*Imported*/, + const clang::Module * /*Imported*/, SrcMgr::CharacteristicKind FileKind) override { auto MainFID = SM.getMainFileID(); // If an include is part of the preamble patch, translate #line directives. diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 6d707c8d15212..42acebd7f2939 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -22,6 +22,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -64,6 +65,15 @@ PrintingPolicy getPrintingPolicy(PrintingPolicy Base) { std::string getLocalScope(const Decl *D) { std::vector Scopes; const DeclContext *DC = D->getDeclContext(); + + // ObjC scopes won't have multiple components for us to join, instead: + // - Methods: "-[Class methodParam1:methodParam2]" + // - Classes, categories, and protocols: "MyClass(Category)" + if (const ObjCMethodDecl *MD = dyn_cast(DC)) + return printObjCMethod(*MD); + else if (const ObjCContainerDecl *CD = dyn_cast(DC)) + return printObjCContainer(*CD); + auto GetName = [](const TypeDecl *D) { if (!D->getDeclName().isEmpty()) { PrintingPolicy Policy = D->getASTContext().getPrintingPolicy(); @@ -90,6 +100,11 @@ std::string getLocalScope(const Decl *D) { std::string getNamespaceScope(const Decl *D) { const DeclContext *DC = D->getDeclContext(); + // ObjC does not have the concept of namespaces, so instead we support + // local scopes. + if (isa(DC)) + return ""; + if (const TagDecl *TD = dyn_cast(DC)) return getNamespaceScope(TD); if (const FunctionDecl *FD = dyn_cast(DC)) diff --git a/clang-tools-extra/clangd/IncludeFixer.cpp b/clang-tools-extra/clangd/IncludeFixer.cpp index 690ad4e9363ee..babc3426b868f 100644 --- a/clang-tools-extra/clangd/IncludeFixer.cpp +++ b/clang-tools-extra/clangd/IncludeFixer.cpp @@ -40,31 +40,14 @@ #include "llvm/ADT/StringSet.h" #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" +#include +#include +#include #include namespace clang { namespace clangd { -namespace { - -// Collects contexts visited during a Sema name lookup. -class VisitedContextCollector : public VisibleDeclConsumer { -public: - void EnteredContext(DeclContext *Ctx) override { Visited.push_back(Ctx); } - - void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, - bool InBaseClass) override {} - - std::vector takeVisitedContexts() { - return std::move(Visited); - } - -private: - std::vector Visited; -}; - -} // namespace - std::vector IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) const { switch (Info.getID()) { @@ -78,6 +61,7 @@ std::vector IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel, case diag::err_sizeof_alignof_incomplete_or_sizeless_type: case diag::err_for_range_incomplete_type: case diag::err_func_def_incomplete_result: + case diag::err_field_incomplete_or_sizeless: // Incomplete type diagnostics should have a QualType argument for the // incomplete type. for (unsigned Idx = 0; Idx < Info.getNumArgs(); ++Idx) { @@ -312,17 +296,26 @@ llvm::Optional extractUnresolvedNameCheaply( std::vector collectAccessibleScopes(Sema &Sem, const DeclarationNameInfo &Typo, Scope *S, Sema::LookupNameKind LookupKind) { + // Collects contexts visited during a Sema name lookup. + struct VisitedContextCollector : public VisibleDeclConsumer { + VisitedContextCollector(std::vector &Out) : Out(Out) {} + void EnteredContext(DeclContext *Ctx) override { + if (llvm::isa(Ctx)) + Out.push_back(printNamespaceScope(*Ctx)); + } + void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, + bool InBaseClass) override {} + std::vector &Out; + }; + std::vector Scopes; - VisitedContextCollector Collector; + Scopes.push_back(""); + VisitedContextCollector Collector(Scopes); Sem.LookupVisibleDecls(S, LookupKind, Collector, /*IncludeGlobalScope=*/false, /*LoadExternal=*/false); - - Scopes.push_back(""); - for (const auto *Ctx : Collector.takeVisitedContexts()) { - if (isa(Ctx)) - Scopes.push_back(printNamespaceScope(*Ctx)); - } + std::sort(Scopes.begin(), Scopes.end()); + Scopes.erase(std::unique(Scopes.begin(), Scopes.end()), Scopes.end()); return Scopes; } diff --git a/clang-tools-extra/clangd/Module.h b/clang-tools-extra/clangd/Module.h new file mode 100644 index 0000000000000..d326182388673 --- /dev/null +++ b/clang-tools-extra/clangd/Module.h @@ -0,0 +1,52 @@ +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULE_H + +#include "llvm/ADT/StringRef.h" +#include +#include + +namespace clang { +namespace clangd { + +/// A Module contributes a vertical feature to clangd. +/// +/// FIXME: Extend this with LSP bindings to support reading/updating +/// capabilities and implementing LSP endpoints. +/// +/// The lifetime of a module is roughly: +/// - modules are created before the LSP server, in ClangdMain.cpp +/// - these modules are then passed to ClangdLSPServer and ClangdServer +/// FIXME: LSP bindings should be registered at ClangdLSPServer +/// initialization. +/// - module hooks can be called at this point. +/// FIXME: We should make some server facilities like TUScheduler and index +/// available to those modules after ClangdServer is initalized. +/// - ClangdServer will not be destroyed until all the requests are done. +/// FIXME: Block server shutdown until all the modules are idle. +/// - modules will be destroyed after ClangdLSPServer is destroyed. +/// +/// Conventionally, standard modules live in the `clangd` namespace, and other +/// exposed details live in a sub-namespace. +class Module { +public: + virtual ~Module() = default; +}; + +class ModuleSet { + std::vector> Modules; + +public: + explicit ModuleSet(std::vector> Modules) + : Modules(std::move(Modules)) {} + + using iterator = llvm::pointee_iterator; + using const_iterator = + llvm::pointee_iterator; + iterator begin() { return iterator(Modules.begin()); } + iterator end() { return iterator(Modules.end()); } + const_iterator begin() const { return const_iterator(Modules.begin()); } + const_iterator end() const { return const_iterator(Modules.end()); } +}; +} // namespace clangd +} // namespace clang +#endif diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index 76cf813e68083..74e6b8c72a1c1 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -655,27 +655,27 @@ bool fromJSON(const llvm::json::Value &Params, WorkspaceEdit &R, return O && O.map("changes", R.changes); } -const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND = - "clangd.applyFix"; -const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_TWEAK = - "clangd.applyTweak"; - bool fromJSON(const llvm::json::Value &Params, ExecuteCommandParams &R, llvm::json::Path P) { llvm::json::ObjectMapper O(Params, P); if (!O || !O.map("command", R.command)) return false; - const auto *Args = Params.getAsObject()->getArray("arguments"); - if (R.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND) { - return Args && Args->size() == 1 && - fromJSON(Args->front(), R.workspaceEdit, - P.field("arguments").index(0)); + const auto *Args = Params.getAsObject()->get("arguments"); + if (!Args) + return true; // Missing args is ok, argument is null. + const auto *ArgsArray = Args->getAsArray(); + if (!ArgsArray) { + P.field("arguments").report("expected array"); + return false; } - if (R.command == ExecuteCommandParams::CLANGD_APPLY_TWEAK) - return Args && Args->size() == 1 && - fromJSON(Args->front(), R.tweakArgs, P.field("arguments").index(0)); - return false; // Unrecognized command. + if (ArgsArray->size() > 1) { + P.field("arguments").report("Command should have 0 or 1 argument"); + return false; + } else if (ArgsArray->size() == 1) { + R.argument = ArgsArray->front(); + } + return true; } llvm::json::Value toJSON(const SymbolInformation &P) { @@ -743,10 +743,8 @@ bool fromJSON(const llvm::json::Value &Params, WorkspaceSymbolParams &R, llvm::json::Value toJSON(const Command &C) { auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}}; - if (C.workspaceEdit) - Cmd["arguments"] = {*C.workspaceEdit}; - if (C.tweakArgs) - Cmd["arguments"] = {*C.tweakArgs}; + if (!C.argument.getAsNull()) + Cmd["arguments"] = llvm::json::Array{C.argument}; return std::move(Cmd); } @@ -1219,10 +1217,17 @@ bool fromJSON(const llvm::json::Value &Params, O.map("direction", R.direction); } +bool fromJSON(const llvm::json::Value &Params, ReferenceContext &R, + llvm::json::Path P) { + llvm::json::ObjectMapper O(Params, P); + return O && O.mapOptional("includeDeclaration", R.includeDeclaration); +} + bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R, llvm::json::Path P) { TextDocumentPositionParams &Base = R; - return fromJSON(Params, Base, P); + llvm::json::ObjectMapper O(Params, P); + return fromJSON(Params, Base, P) && O && O.mapOptional("context", R.context); } llvm::json::Value toJSON(SymbolTag Tag) { @@ -1307,25 +1312,6 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, OffsetEncoding Enc) { return OS << toString(Enc); } -bool operator==(const TheiaSemanticHighlightingInformation &Lhs, - const TheiaSemanticHighlightingInformation &Rhs) { - return Lhs.Line == Rhs.Line && Lhs.Tokens == Rhs.Tokens; -} - -llvm::json::Value -toJSON(const TheiaSemanticHighlightingInformation &Highlighting) { - return llvm::json::Object{{"line", Highlighting.Line}, - {"tokens", Highlighting.Tokens}, - {"isInactive", Highlighting.IsInactive}}; -} - -llvm::json::Value toJSON(const TheiaSemanticHighlightingParams &Highlighting) { - return llvm::json::Object{ - {"textDocument", Highlighting.TextDocument}, - {"lines", std::move(Highlighting.Lines)}, - }; -} - bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &S, llvm::json::Path P) { llvm::json::ObjectMapper O(Params, P); diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index 43c95686868b4..922e701d77ef5 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -449,9 +449,8 @@ struct ClientCapabilities { bool SemanticTokens = false; /// Client supports Theia semantic highlighting extension. /// https://github.com/microsoft/vscode-languageserver-node/pull/367 - /// This will be ignored if the client also supports semanticTokens. + /// clangd no longer supports this, we detect it just to log a warning. /// textDocument.semanticHighlightingCapabilities.semanticHighlighting - /// FIXME: drop this support once clients support LSP 3.16 Semantic Tokens. bool TheiaSemanticHighlighting = false; /// Supported encodings for LSP character offsets. (clangd extension). @@ -914,26 +913,13 @@ struct TweakArgs { bool fromJSON(const llvm::json::Value &, TweakArgs &, llvm::json::Path); llvm::json::Value toJSON(const TweakArgs &A); -/// Exact commands are not specified in the protocol so we define the -/// ones supported by Clangd here. The protocol specifies the command arguments -/// to be "any[]" but to make this safer and more manageable, each command we -/// handle maps to a certain llvm::Optional of some struct to contain its -/// arguments. Different commands could reuse the same llvm::Optional as -/// arguments but a command that needs different arguments would simply add a -/// new llvm::Optional and not use any other ones. In practice this means only -/// one argument type will be parsed and set. struct ExecuteCommandParams { - // Command to apply fix-its. Uses WorkspaceEdit as argument. - const static llvm::StringLiteral CLANGD_APPLY_FIX_COMMAND; - // Command to apply the code action. Uses TweakArgs as argument. - const static llvm::StringLiteral CLANGD_APPLY_TWEAK; - - /// The command identifier, e.g. CLANGD_APPLY_FIX_COMMAND + /// The identifier of the actual command handler. std::string command; - // Arguments - llvm::Optional workspaceEdit; - llvm::Optional tweakArgs; + // This is `arguments?: []any` in LSP. + // All clangd's commands accept a single argument (or none => null). + llvm::json::Value argument = nullptr; }; bool fromJSON(const llvm::json::Value &, ExecuteCommandParams &, llvm::json::Path); @@ -1472,8 +1458,13 @@ struct CallHierarchyOutgoingCall { }; llvm::json::Value toJSON(const CallHierarchyOutgoingCall &); +struct ReferenceContext { + /// Include the declaration of the current symbol. + bool includeDeclaration = false; +}; + struct ReferenceParams : public TextDocumentPositionParams { - // For now, no options like context.includeDeclaration are supported. + ReferenceContext context; }; bool fromJSON(const llvm::json::Value &, ReferenceParams &, llvm::json::Path); @@ -1561,33 +1552,6 @@ struct SemanticTokensOrDelta { }; llvm::json::Value toJSON(const SemanticTokensOrDelta &); -/// Represents a semantic highlighting information that has to be applied on a -/// specific line of the text document. -struct TheiaSemanticHighlightingInformation { - /// The line these highlightings belong to. - int Line = 0; - /// The base64 encoded string of highlighting tokens. - std::string Tokens; - /// Is the line in an inactive preprocessor branch? - /// This is a clangd extension. - /// An inactive line can still contain highlighting tokens as well; - /// clients should combine line style and token style if possible. - bool IsInactive = false; -}; -bool operator==(const TheiaSemanticHighlightingInformation &Lhs, - const TheiaSemanticHighlightingInformation &Rhs); -llvm::json::Value -toJSON(const TheiaSemanticHighlightingInformation &Highlighting); - -/// Parameters for the semantic highlighting (server-side) push notification. -struct TheiaSemanticHighlightingParams { - /// The textdocument these highlightings belong to. - VersionedTextDocumentIdentifier TextDocument; - /// The lines of highlightings that should be sent. - std::vector Lines; -}; -llvm::json::Value toJSON(const TheiaSemanticHighlightingParams &Highlighting); - struct SelectionRangeParams { /// The text document. TextDocumentIdentifier textDocument; diff --git a/clang-tools-extra/clangd/QueryDriverDatabase.cpp b/clang-tools-extra/clangd/QueryDriverDatabase.cpp index 0bb2c46189b25..94faec9f3ed97 100644 --- a/clang-tools-extra/clangd/QueryDriverDatabase.cpp +++ b/clang-tools-extra/clangd/QueryDriverDatabase.cpp @@ -222,8 +222,8 @@ extractSystemIncludesAndTarget(llvm::SmallString<128> Driver, if (int RC = llvm::sys::ExecuteAndWait(Driver, Args, /*Env=*/llvm::None, Redirects)) { elog("System include extraction: driver execution failed with return code: " - "{0}. Args: ['{1}']", - llvm::to_string(RC), llvm::join(Args, "', '")); + "{0}. Args: [{1}]", + llvm::to_string(RC), printArgv(Args)); return llvm::None; } diff --git a/clang-tools-extra/clangd/README.md b/clang-tools-extra/clangd/README.md index 3ef9174c95293..c5ed071950609 100644 --- a/clang-tools-extra/clangd/README.md +++ b/clang-tools-extra/clangd/README.md @@ -5,7 +5,7 @@ This is not its documentation. - the **website** is https://clangd.llvm.org/. - the **bug tracker** is https://github.com/clangd/clangd/issues -- the **source code** is hosted at https://github.com/llvm/llvm-project/tree/master/clang-tools-extra/clangd. +- the **source code** is hosted at https://github.com/llvm/llvm-project/tree/main/clang-tools-extra/clangd. - the **website source code** is at https://github.com/llvm/clangd-www/ ### Communication channels diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 5e70baf73310b..23a58b68ce320 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -15,6 +15,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/RecursiveASTVisitor.h" @@ -118,17 +120,83 @@ llvm::Optional kindForType(const Type *TP) { return llvm::None; } -llvm::Optional kindForReference(const ReferenceLoc &R) { - llvm::Optional Result; - for (const NamedDecl *Decl : R.Targets) { - if (!canHighlightName(Decl->getDeclName())) - return llvm::None; - auto Kind = kindForDecl(Decl); - if (!Kind || (Result && Kind != Result)) - return llvm::None; - Result = Kind; +// Whether T is const in a loose sense - is a variable with this type readonly? +bool isConst(QualType T) { + if (T.isNull() || T->isDependentType()) + return false; + T = T.getNonReferenceType(); + if (T.isConstQualified()) + return true; + if (const auto *AT = T->getAsArrayTypeUnsafe()) + return isConst(AT->getElementType()); + if (isConst(T->getPointeeType())) + return true; + return false; +} + +// Whether D is const in a loose sense (should it be highlighted as such?) +// FIXME: This is separate from whether *a particular usage* can mutate D. +// We may want V in V.size() to be readonly even if V is mutable. +bool isConst(const Decl *D) { + if (llvm::isa(D) || llvm::isa(D)) + return true; + if (llvm::isa(D) || llvm::isa(D) || + llvm::isa(D) || llvm::isa(D)) { + if (isConst(llvm::cast(D)->getType())) + return true; } - return Result; + if (const auto *OCPD = llvm::dyn_cast(D)) { + if (OCPD->isReadOnly()) + return true; + } + if (const auto *MPD = llvm::dyn_cast(D)) { + if (!MPD->hasSetter()) + return true; + } + if (const auto *CMD = llvm::dyn_cast(D)) { + if (CMD->isConst()) + return true; + } + return false; +} + +// "Static" means many things in C++, only some get the "static" modifier. +// +// Meanings that do: +// - Members associated with the class rather than the instance. +// This is what 'static' most often means across languages. +// - static local variables +// These are similarly "detached from their context" by the static keyword. +// In practice, these are rarely used inside classes, reducing confusion. +// +// Meanings that don't: +// - Namespace-scoped variables, which have static storage class. +// This is implicit, so the keyword "static" isn't so strongly associated. +// If we want a modifier for these, "global scope" is probably the concept. +// - Namespace-scoped variables/functions explicitly marked "static". +// There the keyword changes *linkage* , which is a totally different concept. +// If we want to model this, "file scope" would be a nice modifier. +// +// This is confusing, and maybe we should use another name, but because "static" +// is a standard LSP modifier, having one with that name has advantages. +bool isStatic(const Decl *D) { + if (const auto *CMD = llvm::dyn_cast(D)) + return CMD->isStatic(); + if (const VarDecl *VD = llvm::dyn_cast(D)) + return VD->isStaticDataMember() || VD->isStaticLocal(); + if (const auto *OPD = llvm::dyn_cast(D)) + return OPD->isClassProperty(); + if (const auto *OMD = llvm::dyn_cast(D)) + return OMD->isClassMethod(); + return false; +} + +bool isAbstract(const Decl *D) { + if (const auto *CMD = llvm::dyn_cast(D)) + return CMD->isPure(); + if (const auto *CRD = llvm::dyn_cast(D)) + return CRD->hasDefinition() && CRD->isAbstract(); + return false; } // For a macro usage `DUMP(foo)`, we want: @@ -145,21 +213,31 @@ SourceLocation getHighlightableSpellingToken(SourceLocation L, return getHighlightableSpellingToken(SM.getImmediateSpellingLoc(L), SM); } -unsigned evaluateHighlightPriority(HighlightingKind Kind) { +unsigned evaluateHighlightPriority(const HighlightingToken &Tok) { enum HighlightPriority { Dependent = 0, Resolved = 1 }; - return Kind == HighlightingKind::DependentType || - Kind == HighlightingKind::DependentName + return (Tok.Modifiers & (1 << uint32_t(HighlightingModifier::DependentName))) ? Dependent : Resolved; } -// Sometimes we get conflicts between findExplicitReferences() returning -// a heuristic result for a dependent name (e.g. Method) and -// CollectExtraHighlighting returning a fallback dependent highlighting (e.g. -// DependentName). In such cases, resolve the conflict in favour of the -// resolved (non-dependent) highlighting. -// With macros we can get other conflicts (if a spelled token has multiple -// expansions with different token types) which we can't usefully resolve. +// Sometimes we get multiple tokens at the same location: +// +// - findExplicitReferences() returns a heuristic result for a dependent name +// (e.g. Method) and CollectExtraHighlighting returning a fallback dependent +// highlighting (e.g. Unknown+Dependent). +// - macro arguments are expanded multiple times and have different roles +// - broken code recovery produces several AST nodes at the same location +// +// We should either resolve these to a single token, or drop them all. +// Our heuristics are: +// +// - token kinds that come with "dependent-name" modifiers are less reliable +// (these tend to be vague, like Type or Unknown) +// - if we have multiple equally reliable kinds, drop token rather than guess +// - take the union of modifiers from all tokens +// +// In particular, heuristically resolved dependent names get their heuristic +// kind, plus the dependent modifier. llvm::Optional resolveConflict(ArrayRef Tokens) { if (Tokens.size() == 1) @@ -168,11 +246,13 @@ resolveConflict(ArrayRef Tokens) { if (Tokens.size() != 2) return llvm::None; - unsigned Priority1 = evaluateHighlightPriority(Tokens[0].Kind); - unsigned Priority2 = evaluateHighlightPriority(Tokens[1].Kind); - if (Priority1 == Priority2) + unsigned Priority1 = evaluateHighlightPriority(Tokens[0]); + unsigned Priority2 = evaluateHighlightPriority(Tokens[1]); + if (Priority1 == Priority2 && Tokens[0].Kind != Tokens[1].Kind) return llvm::None; - return Priority1 > Priority2 ? Tokens[0] : Tokens[1]; + auto Result = Priority1 > Priority2 ? Tokens[0] : Tokens[1]; + Result.Modifiers = Tokens[0].Modifiers | Tokens[1].Modifiers; + return Result; } /// Consumes source locations and maps them to text ranges for highlightings. @@ -182,18 +262,24 @@ class HighlightingsBuilder { : TB(AST.getTokens()), SourceMgr(AST.getSourceManager()), LangOpts(AST.getLangOpts()) {} - void addToken(HighlightingToken T) { Tokens.push_back(T); } - - void addToken(SourceLocation Loc, HighlightingKind Kind) { + HighlightingToken &addToken(SourceLocation Loc, HighlightingKind Kind) { Loc = getHighlightableSpellingToken(Loc, SourceMgr); if (Loc.isInvalid()) - return; + return Dummy; const auto *Tok = TB.spelledTokenAt(Loc); assert(Tok); + return addToken( + halfOpenToRange(SourceMgr, + Tok->range(SourceMgr).toCharRange(SourceMgr)), + Kind); + } - auto Range = halfOpenToRange(SourceMgr, - Tok->range(SourceMgr).toCharRange(SourceMgr)); - Tokens.push_back(HighlightingToken{Kind, std::move(Range)}); + HighlightingToken &addToken(Range R, HighlightingKind Kind) { + HighlightingToken HT; + HT.R = std::move(R); + HT.Kind = Kind; + Tokens.push_back(std::move(HT)); + return Tokens.back(); } std::vector collect(ParsedAST &AST) && { @@ -248,10 +334,13 @@ class HighlightingsBuilder { MainCode.drop_front(*StartOfLine).take_until([](char C) { return C == '\n'; }); - WithInactiveLines.push_back( - {HighlightingKind::InactiveCode, - {Position{Line, 0}, - Position{Line, static_cast(lspLength(LineText))}}}); + HighlightingToken HT; + WithInactiveLines.emplace_back(); + WithInactiveLines.back().Kind = HighlightingKind::InactiveCode; + WithInactiveLines.back().R.start.line = Line; + WithInactiveLines.back().R.end.line = Line; + WithInactiveLines.back().R.end.character = + static_cast(lspLength(LineText)); } else { elog("Failed to convert position to offset: {0}", StartOfLine.takeError()); @@ -277,8 +366,49 @@ class HighlightingsBuilder { const SourceManager &SourceMgr; const LangOptions &LangOpts; std::vector Tokens; + HighlightingToken Dummy; // returned from addToken(InvalidLoc) }; +llvm::Optional scopeModifier(const NamedDecl *D) { + const DeclContext *DC = D->getDeclContext(); + // Injected "Foo" within the class "Foo" has file scope, not class scope. + if (auto *R = dyn_cast_or_null(D)) + if (R->isInjectedClassName()) + DC = DC->getParent(); + // Lambda captures are considered function scope, not class scope. + if (llvm::isa(D)) + if (const auto *RD = llvm::dyn_cast(DC)) + if (RD->isLambda()) + return HighlightingModifier::FunctionScope; + // Walk up the DeclContext hierarchy until we find something interesting. + for (; !DC->isFileContext(); DC = DC->getParent()) { + if (DC->isFunctionOrMethod()) + return HighlightingModifier::FunctionScope; + if (DC->isRecord()) + return HighlightingModifier::ClassScope; + } + // Some template parameters (e.g. those for variable templates) don't have + // meaningful DeclContexts. That doesn't mean they're global! + if (DC->isTranslationUnit() && D->isTemplateParameter()) + return llvm::None; + // ExternalLinkage threshold could be tweaked, e.g. module-visible as global. + if (D->getLinkageInternal() < ExternalLinkage) + return HighlightingModifier::FileScope; + return HighlightingModifier::GlobalScope; +} + +llvm::Optional scopeModifier(const Type *T) { + if (!T) + return llvm::None; + if (T->isBuiltinType()) + return HighlightingModifier::GlobalScope; + if (auto *TD = dyn_cast(T)) + return scopeModifier(TD->getDecl()); + if (auto *TD = T->getAsTagDecl()) + return scopeModifier(TD); + return llvm::None; +} + /// Produces highlightings, which are not captured by findExplicitReferences, /// e.g. highlights dependent names and 'auto' as the underlying type. class CollectExtraHighlightings @@ -287,8 +417,12 @@ class CollectExtraHighlightings CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {} bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) { - if (auto K = kindForType(L.getTypePtr())) - H.addToken(L.getBeginLoc(), *K); + if (auto K = kindForType(L.getTypePtr())) { + auto &Tok = H.addToken(L.getBeginLoc(), *K) + .addModifier(HighlightingModifier::Deduced); + if (auto Mod = scopeModifier(L.getTypePtr())) + Tok.addModifier(*Mod); + } return true; } @@ -296,47 +430,79 @@ class CollectExtraHighlightings auto *AT = D->getType()->getContainedAutoType(); if (!AT) return true; - if (auto K = kindForType(AT->getDeducedType().getTypePtrOrNull())) - H.addToken(D->getTypeSpecStartLoc(), *K); + if (auto K = kindForType(AT->getDeducedType().getTypePtrOrNull())) { + auto &Tok = H.addToken(D->getTypeSpecStartLoc(), *K) + .addModifier(HighlightingModifier::Deduced); + if (auto Mod = scopeModifier(AT->getDeducedType().getTypePtrOrNull())) + Tok.addModifier(*Mod); + } return true; } bool VisitOverloadExpr(OverloadExpr *E) { if (!E->decls().empty()) return true; // handled by findExplicitReferences. - H.addToken(E->getNameLoc(), HighlightingKind::DependentName); + auto &Tok = H.addToken(E->getNameLoc(), HighlightingKind::Unknown) + .addModifier(HighlightingModifier::DependentName); + if (llvm::isa(E)) + Tok.addModifier(HighlightingModifier::ClassScope); + // other case is UnresolvedLookupExpr, scope is unknown. return true; } bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { - H.addToken(E->getMemberNameInfo().getLoc(), - HighlightingKind::DependentName); + H.addToken(E->getMemberNameInfo().getLoc(), HighlightingKind::Unknown) + .addModifier(HighlightingModifier::DependentName) + .addModifier(HighlightingModifier::ClassScope); return true; } bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { - H.addToken(E->getNameInfo().getLoc(), HighlightingKind::DependentName); + H.addToken(E->getNameInfo().getLoc(), HighlightingKind::Unknown) + .addModifier(HighlightingModifier::DependentName) + .addModifier(HighlightingModifier::ClassScope); return true; } bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) { - H.addToken(L.getNameLoc(), HighlightingKind::DependentType); + H.addToken(L.getNameLoc(), HighlightingKind::Type) + .addModifier(HighlightingModifier::DependentName) + .addModifier(HighlightingModifier::ClassScope); return true; } bool VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc L) { - H.addToken(L.getTemplateNameLoc(), HighlightingKind::DependentType); + H.addToken(L.getTemplateNameLoc(), HighlightingKind::Type) + .addModifier(HighlightingModifier::DependentName) + .addModifier(HighlightingModifier::ClassScope); return true; } bool TraverseTemplateArgumentLoc(TemplateArgumentLoc L) { - switch (L.getArgument().getKind()) { - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - H.addToken(L.getTemplateNameLoc(), HighlightingKind::DependentType); + // Handle template template arguments only (other arguments are handled by + // their Expr, TypeLoc etc values). + if (L.getArgument().getKind() != TemplateArgument::Template && + L.getArgument().getKind() != TemplateArgument::TemplateExpansion) + return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L); + + TemplateName N = L.getArgument().getAsTemplateOrTemplatePattern(); + switch (N.getKind()) { + case TemplateName::OverloadedTemplate: + // Template template params must always be class templates. + // Don't bother to try to work out the scope here. + H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class); + break; + case TemplateName::DependentTemplate: + case TemplateName::AssumedTemplate: + H.addToken(L.getTemplateNameLoc(), HighlightingKind::Class) + .addModifier(HighlightingModifier::DependentName); break; - default: + case TemplateName::Template: + case TemplateName::QualifiedTemplate: + case TemplateName::SubstTemplateTemplateParm: + case TemplateName::SubstTemplateTemplateParmPack: + // Names that could be resolved to a TemplateDecl are handled elsewhere. break; } return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L); @@ -350,7 +516,9 @@ class CollectExtraHighlightings bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Q) { if (NestedNameSpecifier *NNS = Q.getNestedNameSpecifier()) { if (NNS->getKind() == NestedNameSpecifier::Identifier) - H.addToken(Q.getLocalBeginLoc(), HighlightingKind::DependentType); + H.addToken(Q.getLocalBeginLoc(), HighlightingKind::Type) + .addModifier(HighlightingModifier::DependentName) + .addModifier(HighlightingModifier::ClassScope); } return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(Q); } @@ -358,29 +526,6 @@ class CollectExtraHighlightings private: HighlightingsBuilder &H; }; - -void write32be(uint32_t I, llvm::raw_ostream &OS) { - std::array Buf; - llvm::support::endian::write32be(Buf.data(), I); - OS.write(Buf.data(), Buf.size()); -} - -void write16be(uint16_t I, llvm::raw_ostream &OS) { - std::array Buf; - llvm::support::endian::write16be(Buf.data(), I); - OS.write(Buf.data(), Buf.size()); -} - -// Get the highlightings on \c Line where the first entry of line is at \c -// StartLineIt. If it is not at \c StartLineIt an empty vector is returned. -ArrayRef -takeLine(ArrayRef AllTokens, - ArrayRef::iterator StartLineIt, int Line) { - return ArrayRef(StartLineIt, AllTokens.end()) - .take_while([Line](const HighlightingToken &Token) { - return Token.R.start.line == Line; - }); -} } // namespace std::vector getSemanticHighlightings(ParsedAST &AST) { @@ -391,16 +536,45 @@ std::vector getSemanticHighlightings(ParsedAST &AST) { CollectExtraHighlightings(Builder).TraverseAST(C); // Highlight all decls and references coming from the AST. findExplicitReferences(C, [&](ReferenceLoc R) { - if (auto Kind = kindForReference(R)) - Builder.addToken(R.NameLoc, *Kind); + for (const NamedDecl *Decl : R.Targets) { + if (!canHighlightName(Decl->getDeclName())) + continue; + auto Kind = kindForDecl(Decl); + if (!Kind) + continue; + auto &Tok = Builder.addToken(R.NameLoc, *Kind); + + // The attribute tests don't want to look at the template. + if (auto *TD = dyn_cast(Decl)) { + if (auto *Templated = TD->getTemplatedDecl()) + Decl = Templated; + } + if (auto Mod = scopeModifier(Decl)) + Tok.addModifier(*Mod); + if (isConst(Decl)) + Tok.addModifier(HighlightingModifier::Readonly); + if (isStatic(Decl)) + Tok.addModifier(HighlightingModifier::Static); + if (isAbstract(Decl)) + Tok.addModifier(HighlightingModifier::Abstract); + if (Decl->isDeprecated()) + Tok.addModifier(HighlightingModifier::Deprecated); + if (R.IsDecl) + Tok.addModifier(HighlightingModifier::Declaration); + } }); // Add highlightings for macro references. - for (const auto &SIDToRefs : AST.getMacros().MacroRefs) { + auto AddMacro = [&](const MacroOccurrence &M) { + auto &T = Builder.addToken(M.Rng, HighlightingKind::Macro); + T.addModifier(HighlightingModifier::GlobalScope); + if (M.IsDefinition) + T.addModifier(HighlightingModifier::Declaration); + }; + for (const auto &SIDToRefs : AST.getMacros().MacroRefs) for (const auto &M : SIDToRefs.second) - Builder.addToken({HighlightingKind::Macro, M.Rng}); - } + AddMacro(M); for (const auto &M : AST.getMacros().UnknownMacros) - Builder.addToken({HighlightingKind::Macro, M.Rng}); + AddMacro(M); return std::move(Builder).collect(AST); } @@ -431,10 +605,10 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) { return OS << "EnumConstant"; case HighlightingKind::Typedef: return OS << "Typedef"; - case HighlightingKind::DependentType: - return OS << "DependentType"; - case HighlightingKind::DependentName: - return OS << "DependentName"; + case HighlightingKind::Type: + return OS << "Type"; + case HighlightingKind::Unknown: + return OS << "Unknown"; case HighlightingKind::Namespace: return OS << "Namespace"; case HighlightingKind::TemplateParameter: @@ -450,73 +624,22 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) { } llvm_unreachable("invalid HighlightingKind"); } - -std::vector -diffHighlightings(ArrayRef New, - ArrayRef Old) { - assert(std::is_sorted(New.begin(), New.end()) && - "New must be a sorted vector"); - assert(std::is_sorted(Old.begin(), Old.end()) && - "Old must be a sorted vector"); - - // FIXME: There's an edge case when tokens span multiple lines. If the first - // token on the line started on a line above the current one and the rest of - // the line is the equal to the previous one than we will remove all - // highlights but the ones for the token spanning multiple lines. This means - // that when we get into the LSP layer the only highlights that will be - // visible are the ones for the token spanning multiple lines. - // Example: - // EndOfMultilineToken Token Token Token - // If "Token Token Token" don't differ from previously the line is - // incorrectly removed. Suggestion to fix is to separate any multiline tokens - // into one token for every line it covers. This requires reading from the - // file buffer to figure out the length of each line though. - std::vector DiffedLines; - // ArrayRefs to the current line in the highlightings. - ArrayRef NewLine(New.begin(), - /*length*/ static_cast(0)); - ArrayRef OldLine(Old.begin(), - /*length*/ static_cast(0)); - auto NewEnd = New.end(); - auto OldEnd = Old.end(); - auto NextLineNumber = [&]() { - int NextNew = NewLine.end() != NewEnd ? NewLine.end()->R.start.line - : std::numeric_limits::max(); - int NextOld = OldLine.end() != OldEnd ? OldLine.end()->R.start.line - : std::numeric_limits::max(); - return std::min(NextNew, NextOld); - }; - - for (int LineNumber = 0; NewLine.end() < NewEnd || OldLine.end() < OldEnd; - LineNumber = NextLineNumber()) { - NewLine = takeLine(New, NewLine.end(), LineNumber); - OldLine = takeLine(Old, OldLine.end(), LineNumber); - if (NewLine != OldLine) { - DiffedLines.push_back({LineNumber, NewLine, /*IsInactive=*/false}); - - // Turn a HighlightingKind::InactiveCode token into the IsInactive flag. - auto &AddedLine = DiffedLines.back(); - llvm::erase_if(AddedLine.Tokens, [&](const HighlightingToken &T) { - if (T.Kind == HighlightingKind::InactiveCode) { - AddedLine.IsInactive = true; - return true; - } - return false; - }); - } +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingModifier K) { + switch (K) { + case HighlightingModifier::Declaration: + return OS << "decl"; // abbrevation for common case + default: + return OS << toSemanticTokenModifier(K); } - - return DiffedLines; } bool operator==(const HighlightingToken &L, const HighlightingToken &R) { - return std::tie(L.R, L.Kind) == std::tie(R.R, R.Kind); + return std::tie(L.R, L.Kind, L.Modifiers) == + std::tie(R.R, R.Kind, R.Modifiers); } bool operator<(const HighlightingToken &L, const HighlightingToken &R) { - return std::tie(L.R, L.Kind) < std::tie(R.R, R.Kind); -} -bool operator==(const LineHighlightings &L, const LineHighlightings &R) { - return std::tie(L.Line, L.Tokens) == std::tie(R.Line, R.Tokens); + return std::tie(L.R, L.Kind, R.Modifiers) < + std::tie(R.R, R.Kind, R.Modifiers); } std::vector @@ -544,6 +667,7 @@ toSemanticTokens(llvm::ArrayRef Tokens) { assert(Tok.R.end.line == Tok.R.start.line); Out.length = Tok.R.end.character - Tok.R.start.character; Out.tokenType = static_cast(Tok.Kind); + Out.tokenModifiers = Tok.Modifiers; Last = &Tok; } @@ -573,11 +697,10 @@ llvm::StringRef toSemanticTokenType(HighlightingKind Kind) { case HighlightingKind::EnumConstant: return "enumMember"; case HighlightingKind::Typedef: + case HighlightingKind::Type: return "type"; - case HighlightingKind::DependentType: - return "dependent"; // nonstandard - case HighlightingKind::DependentName: - return "dependent"; // nonstandard + case HighlightingKind::Unknown: + return "unknown"; // nonstandard case HighlightingKind::Namespace: return "namespace"; case HighlightingKind::TemplateParameter: @@ -594,81 +717,32 @@ llvm::StringRef toSemanticTokenType(HighlightingKind Kind) { llvm_unreachable("unhandled HighlightingKind"); } -std::vector -toTheiaSemanticHighlightingInformation( - llvm::ArrayRef Tokens) { - if (Tokens.size() == 0) - return {}; - - // FIXME: Tokens might be multiple lines long (block comments) in this case - // this needs to add multiple lines for those tokens. - std::vector Lines; - Lines.reserve(Tokens.size()); - for (const auto &Line : Tokens) { - llvm::SmallVector LineByteTokens; - llvm::raw_svector_ostream OS(LineByteTokens); - for (const auto &Token : Line.Tokens) { - // Writes the token to LineByteTokens in the byte format specified by the - // LSP proposal. Described below. - // |<---- 4 bytes ---->|<-- 2 bytes -->|<--- 2 bytes -->| - // | character | length | index | - - write32be(Token.R.start.character, OS); - write16be(Token.R.end.character - Token.R.start.character, OS); - write16be(static_cast(Token.Kind), OS); - } - - Lines.push_back({Line.Line, encodeBase64(LineByteTokens), Line.IsInactive}); +llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier) { + switch (Modifier) { + case HighlightingModifier::Declaration: + return "declaration"; + case HighlightingModifier::Deprecated: + return "deprecated"; + case HighlightingModifier::Readonly: + return "readonly"; + case HighlightingModifier::Static: + return "static"; + case HighlightingModifier::Deduced: + return "deduced"; // nonstandard + case HighlightingModifier::Abstract: + return "abstract"; + case HighlightingModifier::DependentName: + return "dependentName"; // nonstandard + case HighlightingModifier::FunctionScope: + return "functionScope"; // nonstandard + case HighlightingModifier::ClassScope: + return "classScope"; // nonstandard + case HighlightingModifier::FileScope: + return "fileScope"; // nonstandard + case HighlightingModifier::GlobalScope: + return "globalScope"; // nonstandard } - - return Lines; -} - -llvm::StringRef toTextMateScope(HighlightingKind Kind) { - // FIXME: Add scopes for C and Objective C. - switch (Kind) { - case HighlightingKind::Function: - return "entity.name.function.cpp"; - case HighlightingKind::Method: - return "entity.name.function.method.cpp"; - case HighlightingKind::StaticMethod: - return "entity.name.function.method.static.cpp"; - case HighlightingKind::Variable: - return "variable.other.cpp"; - case HighlightingKind::LocalVariable: - return "variable.other.local.cpp"; - case HighlightingKind::Parameter: - return "variable.parameter.cpp"; - case HighlightingKind::Field: - return "variable.other.field.cpp"; - case HighlightingKind::StaticField: - return "variable.other.field.static.cpp"; - case HighlightingKind::Class: - return "entity.name.type.class.cpp"; - case HighlightingKind::Enum: - return "entity.name.type.enum.cpp"; - case HighlightingKind::EnumConstant: - return "variable.other.enummember.cpp"; - case HighlightingKind::Typedef: - return "entity.name.type.typedef.cpp"; - case HighlightingKind::DependentType: - return "entity.name.type.dependent.cpp"; - case HighlightingKind::DependentName: - return "entity.name.other.dependent.cpp"; - case HighlightingKind::Namespace: - return "entity.name.namespace.cpp"; - case HighlightingKind::TemplateParameter: - return "entity.name.type.template.cpp"; - case HighlightingKind::Concept: - return "entity.name.type.concept.cpp"; - case HighlightingKind::Primitive: - return "storage.type.primitive.cpp"; - case HighlightingKind::Macro: - return "entity.name.function.preprocessor.cpp"; - case HighlightingKind::InactiveCode: - return "meta.disabled"; - } - llvm_unreachable("unhandled HighlightingKind"); + llvm_unreachable("unhandled HighlightingModifier"); } std::vector diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h index 9a96cc28c4f5e..e4c36ab5261ef 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -8,19 +8,9 @@ // // This file supports semantic highlighting: categorizing tokens in the file so // that the editor can color/style them differently. -// // This is particularly valuable for C++: its complex and context-dependent // grammar is a challenge for simple syntax-highlighting techniques. // -// We support two protocols for providing highlights to the client: -// - the `textDocument/semanticTokens` request from LSP 3.16 -// https://github.com/microsoft/vscode-languageserver-node/blob/release/protocol/3.16.0-next.1/protocol/src/protocol.semanticTokens.proposed.ts -// - the earlier proposed `textDocument/semanticHighlighting` notification -// https://github.com/microsoft/vscode-languageserver-node/pull/367 -// This is referred to as "Theia" semantic highlighting in the code. -// It was supported from clangd 9 but should be considered deprecated as of -// clangd 11 and eventually removed. -// // Semantic highlightings are calculated for an AST by visiting every AST node // and classifying nodes that are interesting to highlight (variables/function // calls etc.). @@ -50,8 +40,8 @@ enum class HighlightingKind { Enum, EnumConstant, Typedef, - DependentType, - DependentName, + Type, + Unknown, Namespace, TemplateParameter, Concept, @@ -64,57 +54,55 @@ enum class HighlightingKind { LastKind = InactiveCode }; + llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K); +enum class HighlightingModifier { + Declaration, + // FIXME: Definition (needs findExplicitReferences support) + Deprecated, + Deduced, + Readonly, + Static, + Abstract, + DependentName, + + FunctionScope, + ClassScope, + FileScope, + GlobalScope, + + LastModifier = GlobalScope +}; +static_assert(static_cast(HighlightingModifier::LastModifier) < 32, + "Increase width of modifiers bitfield!"); +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingModifier K); + // Contains all information needed for the highlighting a token. struct HighlightingToken { HighlightingKind Kind; + uint32_t Modifiers = 0; Range R; + + HighlightingToken &addModifier(HighlightingModifier M) { + Modifiers |= 1 << static_cast(M); + return *this; + } }; bool operator==(const HighlightingToken &L, const HighlightingToken &R); bool operator<(const HighlightingToken &L, const HighlightingToken &R); -/// Contains all information about highlightings on a single line. -struct LineHighlightings { - int Line; - std::vector Tokens; - bool IsInactive; -}; - -bool operator==(const LineHighlightings &L, const LineHighlightings &R); - // Returns all HighlightingTokens from an AST. Only generates highlights for the // main AST. std::vector getSemanticHighlightings(ParsedAST &AST); std::vector toSemanticTokens(llvm::ArrayRef); llvm::StringRef toSemanticTokenType(HighlightingKind Kind); +llvm::StringRef toSemanticTokenModifier(HighlightingModifier Modifier); std::vector diffTokens(llvm::ArrayRef Before, llvm::ArrayRef After); -/// Converts a HighlightingKind to a corresponding TextMate scope -/// (https://manual.macromates.com/en/language_grammars). -llvm::StringRef toTextMateScope(HighlightingKind Kind); - -/// Convert to LSP's semantic highlighting information. -std::vector -toTheiaSemanticHighlightingInformation( - llvm::ArrayRef Tokens); - -/// Return a line-by-line diff between two highlightings. -/// - if the tokens on a line are the same in both highlightings, this line is -/// omitted. -/// - if a line exists in New but not in Old, the tokens on this line are -/// emitted. -/// - if a line does not exist in New but exists in Old, an empty line is -/// emitted (to tell client to clear the previous highlightings on this line). -/// -/// REQUIRED: Old and New are sorted. -std::vector -diffHighlightings(ArrayRef New, - ArrayRef Old); - } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp index 1d0ca1fee29db..01b583fe64f31 100644 --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -465,6 +465,7 @@ class ASTWorker { std::string Name; steady_clock::time_point AddTime; Context Ctx; + llvm::Optional QueueCtx; llvm::Optional Update; TUScheduler::ASTActionInvalidation InvalidationPolicy; Canceler Invalidate; @@ -507,12 +508,12 @@ class ASTWorker { /// None means no builds yet, null means there was an error while building. /// Only written by ASTWorker's thread. llvm::Optional> LatestPreamble; - std::queue PreambleRequests; /* GUARDED_BY(Mutex) */ + std::deque PreambleRequests; /* GUARDED_BY(Mutex) */ /// Signaled whenever LatestPreamble changes state or there's a new /// PreambleRequest. mutable std::condition_variable PreambleCV; /// Guards the callback that publishes results of AST-related computations - /// (diagnostics, highlightings) and file statuses. + /// (diagnostics) and file statuses. std::mutex PublishMu; // Used to prevent remove document + add document races that lead to // out-of-order callbacks for publishing results of onMainAST callback. @@ -596,8 +597,8 @@ ASTWorker::ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB, FileName(FileName), ContextProvider(Opts.ContextProvider), CDB(CDB), Callbacks(Callbacks), Barrier(Barrier), Done(false), Status(FileName, Callbacks), - PreamblePeer(FileName, Callbacks, Opts.StorePreamblesInMemory, - RunSync || !Opts.AsyncPreambleBuilds, Status, *this) { + PreamblePeer(FileName, Callbacks, Opts.StorePreamblesInMemory, RunSync, + Status, *this) { // Set a fallback command because compile command can be accessed before // `Inputs` is initialized. Other fields are only used after initialization // from client inputs. @@ -648,7 +649,7 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags, log("ASTWorker building file {0} version {1} with command {2}\n[{3}]\n{4}", FileName, Inputs.Version, Inputs.CompileCommand.Heuristic, Inputs.CompileCommand.Directory, - llvm::join(Inputs.CompileCommand.CommandLine, " ")); + printArgv(Inputs.CompileCommand.CommandLine)); StoreDiags CompilerInvocationDiagConsumer; std::vector CC1Args; @@ -656,7 +657,7 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags, Inputs, CompilerInvocationDiagConsumer, &CC1Args); // Log cc1 args even (especially!) if creating invocation failed. if (!CC1Args.empty()) - vlog("Driver produced command: cc1 {0}", llvm::join(CC1Args, " ")); + vlog("Driver produced command: cc1 {0}", printArgv(CC1Args)); std::vector CompilerInvocationDiags = CompilerInvocationDiagConsumer.take(); if (!Invocation) { @@ -826,9 +827,10 @@ void ASTWorker::updatePreamble(std::unique_ptr CI, } { std::lock_guard Lock(Mutex); - PreambleRequests.push({std::move(Task), std::move(TaskName), - steady_clock::now(), Context::current().clone(), - llvm::None, TUScheduler::NoInvalidation, nullptr}); + PreambleRequests.push_back({std::move(Task), std::move(TaskName), + steady_clock::now(), Context::current().clone(), + llvm::None, llvm::None, + TUScheduler::NoInvalidation, nullptr}); } PreambleCV.notify_all(); RequestsCV.notify_all(); @@ -1023,9 +1025,34 @@ void ASTWorker::startTask(llvm::StringRef Name, std::tie(Ctx, Invalidate) = cancelableTask( /*Reason=*/static_cast(ErrorCode::ContentModified)); } + // Trace the time the request spends in the queue, and the requests that + // it's going to wait for. + llvm::Optional QueueCtx; + if (trace::enabled()) { + // Tracers that follow threads and need strict nesting will see a tiny + // instantaneous event "we're enqueueing", and sometime later it runs. + WithContext WC(Ctx.clone()); + trace::Span Tracer("Queued:" + Name); + if (Tracer.Args) { + if (CurrentRequest) + SPAN_ATTACH(Tracer, "CurrentRequest", CurrentRequest->Name); + llvm::json::Array PreambleRequestsNames; + for (const auto &Req : PreambleRequests) + PreambleRequestsNames.push_back(Req.Name); + SPAN_ATTACH(Tracer, "PreambleRequestsNames", + std::move(PreambleRequestsNames)); + llvm::json::Array RequestsNames; + for (const auto &Req : Requests) + RequestsNames.push_back(Req.Name); + SPAN_ATTACH(Tracer, "RequestsNames", std::move(RequestsNames)); + } + // For tracers that follow contexts, keep the trace span's context alive + // until we dequeue the request, so they see the full duration. + QueueCtx = Context::current().clone(); + } Requests.push_back({std::move(Task), std::string(Name), steady_clock::now(), - std::move(Ctx), Update, Invalidation, - std::move(Invalidate)}); + std::move(Ctx), std::move(QueueCtx), Update, + Invalidation, std::move(Invalidate)}); } RequestsCV.notify_all(); } @@ -1071,13 +1098,16 @@ void ASTWorker::run() { // Requests.front(), so prefer them first to preserve LSP order. if (!PreambleRequests.empty()) { CurrentRequest = std::move(PreambleRequests.front()); - PreambleRequests.pop(); + PreambleRequests.pop_front(); } else { CurrentRequest = std::move(Requests.front()); Requests.pop_front(); } } // unlock Mutex + // Inform tracing that the request was dequeued. + CurrentRequest->QueueCtx.reset(); + // It is safe to perform reads to CurrentRequest without holding the lock as // only writer is also this thread. { diff --git a/clang-tools-extra/clangd/TUScheduler.h b/clang-tools-extra/clangd/TUScheduler.h index c8b75b3f4127c..2c381923a37e4 100644 --- a/clang-tools-extra/clangd/TUScheduler.h +++ b/clang-tools-extra/clangd/TUScheduler.h @@ -151,11 +151,11 @@ class ParsingCallbacks { /// in this callback (obtained via ParsedAST::getLocalTopLevelDecls) to obtain /// optimal performance. /// - /// When information about the file (diagnostics, syntax highlighting) is + /// When information about the file (e.g. diagnostics) is /// published to clients, this should be wrapped in Publish, e.g. /// void onMainAST(...) { - /// Highlights = computeHighlights(); - /// Publish([&] { notifyHighlights(Path, Highlights); }); + /// Diags = renderDiagnostics(); + /// Publish([&] { notifyDiagnostics(Path, Diags); }); /// } /// This guarantees that clients will see results in the correct sequence if /// the file is concurrently closed and/or reopened. (The lambda passed to @@ -196,10 +196,6 @@ class TUScheduler { /// Determines when to keep idle ASTs in memory for future use. ASTRetentionPolicy RetentionPolicy; - /// Whether to run PreamblePeer asynchronously. - /// No-op if AsyncThreadsCount is 0. - bool AsyncPreambleBuilds = true; - /// Used to create a context that wraps each single operation. /// Typically to inject per-file configuration. /// If the path is empty, context sholud be "generic". diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp index c26c59fd347da..bcf1cd5a6183a 100644 --- a/clang-tools-extra/clangd/TidyProvider.cpp +++ b/clang-tools-extra/clangd/TidyProvider.cpp @@ -106,7 +106,7 @@ class DotClangTidyTree { llvm::SmallVector Caches; { std::lock_guard Lock(Mu); - for (auto I = path::begin(Parent), E = path::end(Parent); I != E; ++I) { + for (auto I = path::rbegin(Parent), E = path::rend(Parent); I != E; ++I) { assert(I->end() >= Parent.begin() && I->end() <= Parent.end() && "Canonical path components should be substrings"); llvm::StringRef Ancestor(Parent.begin(), I->end() - Parent.begin()); diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index d4dc6212553fb..c4a73ebad3e82 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -872,6 +872,7 @@ class ReferenceFinder : public index::IndexDataConsumer { struct Reference { syntax::Token SpelledTok; index::SymbolRoleSet Role; + SymbolID Target; Range range(const SourceManager &SM) const { return halfOpenToRange(SM, SpelledTok.range(SM).toCharRange(SM)); @@ -906,13 +907,15 @@ class ReferenceFinder : public index::IndexDataConsumer { SourceLocation Loc, index::IndexDataConsumer::ASTNodeInfo ASTNode) override { const SourceManager &SM = AST.getSourceManager(); - if (!isInsideMainFile(Loc, SM) || - TargetIDs.find(getSymbolID(D)) == TargetIDs.end()) + if (!isInsideMainFile(Loc, SM)) + return true; + SymbolID ID = getSymbolID(D); + if (!TargetIDs.contains(ID)) return true; const auto &TB = AST.getTokens(); Loc = SM.getFileLoc(Loc); if (const auto *Tok = TB.spelledTokenAt(Loc)) - References.push_back({*Tok, Roles}); + References.push_back({*Tok, Roles, ID}); return true; } @@ -1278,6 +1281,21 @@ std::vector findImplementations(ParsedAST &AST, Position Pos, return findImplementors(std::move(IDs), QueryKind, Index, *MainFilePath); } +namespace { +// Recursively finds all the overridden methods of `CMD` in complete type +// hierarchy. +void getOverriddenMethods(const CXXMethodDecl *CMD, + llvm::DenseSet &OverriddenMethods) { + if (!CMD) + return; + for (const CXXMethodDecl *Base : CMD->overridden_methods()) { + if (auto ID = getSymbolID(Base)) + OverriddenMethods.insert(ID); + getOverriddenMethods(Base, OverriddenMethods); + } +} +} // namespace + ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index) { if (!Limit) @@ -1297,7 +1315,7 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, return {}; } - RefsRequest Req; + llvm::DenseSet IDs, OverriddenMethods; const auto *IdentifierAtCursor = syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens()); @@ -1312,13 +1330,17 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, auto Refs = IDToRefs.find(MacroSID); if (Refs != IDToRefs.end()) { for (const auto &Ref : Refs->second) { - Location Result; - Result.range = Ref.Rng; - Result.uri = URIMainFile; + ReferencesResult::Reference Result; + Result.Loc.range = Ref.Rng; + Result.Loc.uri = URIMainFile; + if (Ref.IsDefinition) { + Result.Attributes |= ReferencesResult::Declaration; + Result.Attributes |= ReferencesResult::Definition; + } Results.References.push_back(std::move(Result)); } } - Req.IDs.insert(MacroSID); + IDs.insert(MacroSID); } } else { // Handle references to Decls. @@ -1332,26 +1354,22 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, if (auto ID = getSymbolID(D)) Targets.insert(ID); - llvm::DenseSet Overrides; + RelationsRequest OverriddenBy; if (Index) { - RelationsRequest FindOverrides; - FindOverrides.Predicate = RelationKind::OverriddenBy; + OverriddenBy.Predicate = RelationKind::OverriddenBy; for (const NamedDecl *ND : Decls) { - // Special case: virtual void meth^od() = 0 includes refs of overrides. + // Special case: For virtual methods, report decl/def of overrides and + // references to all overridden methods in complete type hierarchy. if (const auto *CMD = llvm::dyn_cast(ND)) { - if (CMD->isPure()) + if (CMD->isVirtual()) if (IdentifierAtCursor && SM.getSpellingLoc(CMD->getLocation()) == - IdentifierAtCursor->location()) + IdentifierAtCursor->location()) { if (auto ID = getSymbolID(CMD)) - FindOverrides.Subjects.insert(ID); + OverriddenBy.Subjects.insert(ID); + getOverriddenMethods(CMD, OverriddenMethods); + } } } - if (!FindOverrides.Subjects.empty()) - Index->relations(FindOverrides, - [&](const SymbolID &Subject, const Symbol &Object) { - Overrides.insert(Object.ID); - }); - Targets.insert(Overrides.begin(), Overrides.end()); } // We traverse the AST to find references in the main file. @@ -1367,13 +1385,41 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, }), MainFileRefs.end()); for (const auto &Ref : MainFileRefs) { - Location Result; - Result.range = Ref.range(SM); - Result.uri = URIMainFile; + ReferencesResult::Reference Result; + Result.Loc.range = Ref.range(SM); + Result.Loc.uri = URIMainFile; + if (Ref.Role & static_cast(index::SymbolRole::Declaration)) + Result.Attributes |= ReferencesResult::Declaration; + // clang-index doesn't report definitions as declarations, but they are. + if (Ref.Role & static_cast(index::SymbolRole::Definition)) + Result.Attributes |= + ReferencesResult::Definition | ReferencesResult::Declaration; Results.References.push_back(std::move(Result)); } + // Add decl/def of overridding methods. + if (Index && Results.References.size() <= Limit && + !OverriddenBy.Subjects.empty()) + Index->relations( + OverriddenBy, [&](const SymbolID &Subject, const Symbol &Object) { + if (auto LSPLoc = + toLSPLocation(Object.CanonicalDeclaration, *MainFilePath)) { + ReferencesResult::Reference Result; + Result.Loc = std::move(*LSPLoc); + Result.Attributes = + ReferencesResult::Declaration | ReferencesResult::Override; + Results.References.push_back(std::move(Result)); + } + if (auto LSPLoc = toLSPLocation(Object.Definition, *MainFilePath)) { + ReferencesResult::Reference Result; + Result.Loc = std::move(*LSPLoc); + Result.Attributes = ReferencesResult::Declaration | + ReferencesResult::Definition | + ReferencesResult::Override; + Results.References.push_back(std::move(Result)); + } + }); + if (Index && Results.References.size() <= Limit) { - Req.IDs = std::move(Overrides); for (const Decl *D : Decls) { // Not all symbols can be referenced from outside (e.g. // function-locals). @@ -1382,25 +1428,47 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, if (D->getParentFunctionOrMethod()) continue; if (auto ID = getSymbolID(D)) - Req.IDs.insert(ID); + IDs.insert(ID); } } } // Now query the index for references from other files. - if (!Req.IDs.empty() && Index && Results.References.size() <= Limit) { + auto QueryIndex = [&](llvm::DenseSet IDs, bool AllowAttributes, + bool AllowMainFileSymbols) { + RefsRequest Req; + Req.IDs = std::move(IDs); Req.Limit = Limit; + if (Req.IDs.empty() || !Index || Results.References.size() > Limit) + return; Results.HasMore |= Index->refs(Req, [&](const Ref &R) { // No need to continue process if we reach the limit. if (Results.References.size() > Limit) return; auto LSPLoc = toLSPLocation(R.Location, *MainFilePath); // Avoid indexed results for the main file - the AST is authoritative. - if (!LSPLoc || LSPLoc->uri.file() == *MainFilePath) + if (!LSPLoc || + (!AllowMainFileSymbols && LSPLoc->uri.file() == *MainFilePath)) return; - - Results.References.push_back(std::move(*LSPLoc)); + ReferencesResult::Reference Result; + Result.Loc = std::move(*LSPLoc); + if (AllowAttributes) { + if ((R.Kind & RefKind::Declaration) == RefKind::Declaration) + Result.Attributes |= ReferencesResult::Declaration; + // FIXME: our index should definitely store def | decl separately! + if ((R.Kind & RefKind::Definition) == RefKind::Definition) + Result.Attributes |= + ReferencesResult::Declaration | ReferencesResult::Definition; + } + Results.References.push_back(std::move(Result)); }); - } + }; + QueryIndex(std::move(IDs), /*AllowAttributes=*/true, + /*AllowMainFileSymbols=*/false); + // For a virtual method: Occurrences of BaseMethod should be treated as refs + // and not as decl/def. Allow symbols from main file since AST does not report + // these. + QueryIndex(std::move(OverriddenMethods), /*AllowAttributes=*/false, + /*AllowMainFileSymbols=*/true); if (Results.References.size() > Limit) { Results.HasMore = true; Results.References.resize(Limit); @@ -1469,6 +1537,18 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LocatedSymbol &S) { return OS; } +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const ReferencesResult::Reference &R) { + OS << R.Loc; + if (R.Attributes & ReferencesResult::Declaration) + OS << " [decl]"; + if (R.Attributes & ReferencesResult::Definition) + OS << " [def]"; + if (R.Attributes & ReferencesResult::Override) + OS << " [override]"; + return OS; +} + template static llvm::Optional declToHierarchyItem(const NamedDecl &ND) { ASTContext &Ctx = ND.getASTContext(); diff --git a/clang-tools-extra/clangd/XRefs.h b/clang-tools-extra/clangd/XRefs.h index 4c745eb9bc514..3f69106611dc6 100644 --- a/clang-tools-extra/clangd/XRefs.h +++ b/clang-tools-extra/clangd/XRefs.h @@ -79,9 +79,22 @@ std::vector findDocumentHighlights(ParsedAST &AST, Position Pos); struct ReferencesResult { - std::vector References; + // Bitmask describing whether the occurrence is a declaration, definition etc. + enum ReferenceAttributes : unsigned { + Declaration = 1 << 0, + Definition = 1 << 1, + // The occurrence is an override of the target base method. + Override = 1 << 2, + }; + struct Reference { + Location Loc; + unsigned Attributes = 0; + }; + std::vector References; bool HasMore = false; }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &, + const ReferencesResult::Reference &); /// Returns implementations at a specified \p Pos: /// - overrides for a virtual method; diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp index e4ce1f57ff2f0..f97f13d8dabe5 100644 --- a/clang-tools-extra/clangd/index/Background.cpp +++ b/clang-tools-extra/clangd/index/Background.cpp @@ -97,7 +97,7 @@ BackgroundIndex::BackgroundIndex( BackgroundIndexStorage::Factory IndexStorageFactory, Options Opts) : SwapIndex(std::make_unique()), TFS(TFS), CDB(CDB), ContextProvider(std::move(Opts.ContextProvider)), - CollectMainFileRefs(Opts.CollectMainFileRefs), + IndexedSymbols(IndexContents::All), Rebuilder(this, &IndexedSymbols, Opts.ThreadPoolSize), IndexStorageFactory(std::move(IndexStorageFactory)), Queue(std::move(Opts.OnProgress)), @@ -304,7 +304,7 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) { return false; // Skip files that haven't changed, without errors. return true; }; - IndexOpts.CollectMainFileRefs = CollectMainFileRefs; + IndexOpts.CollectMainFileRefs = true; IndexFileIn Index; auto Action = createStaticIndexingAction( diff --git a/clang-tools-extra/clangd/index/Background.h b/clang-tools-extra/clangd/index/Background.h index fbcec70149574..808061b17dffe 100644 --- a/clang-tools-extra/clangd/index/Background.h +++ b/clang-tools-extra/clangd/index/Background.h @@ -143,8 +143,6 @@ class BackgroundIndex : public SwapIndex { // file. Called with the empty string for other tasks. // (When called, the context from BackgroundIndex construction is active). std::function ContextProvider = nullptr; - // Whether to collect references to main-file-only symbols. - bool CollectMainFileRefs = false; }; /// Creates a new background index and starts its threads. @@ -198,7 +196,6 @@ class BackgroundIndex : public SwapIndex { const ThreadsafeFS &TFS; const GlobalCompilationDatabase &CDB; std::function ContextProvider; - bool CollectMainFileRefs; llvm::Error index(tooling::CompileCommand); diff --git a/clang-tools-extra/clangd/index/FileIndex.cpp b/clang-tools-extra/clangd/index/FileIndex.cpp index 26084c2886749..f497f845b42d9 100644 --- a/clang-tools-extra/clangd/index/FileIndex.cpp +++ b/clang-tools-extra/clangd/index/FileIndex.cpp @@ -217,11 +217,11 @@ FileShardedIndex::getShard(llvm::StringRef Uri) const { return std::move(IF); } -SlabTuple indexMainDecls(ParsedAST &AST, bool CollectMainFileRefs) { +SlabTuple indexMainDecls(ParsedAST &AST) { return indexSymbols( AST.getASTContext(), AST.getPreprocessorPtr(), AST.getLocalTopLevelDecls(), &AST.getMacros(), AST.getCanonicalIncludes(), - /*IsIndexMainAST=*/true, AST.version(), CollectMainFileRefs); + /*IsIndexMainAST=*/true, AST.version(), /*CollectMainFileRefs=*/true); } SlabTuple indexHeaderSymbols(llvm::StringRef Version, ASTContext &AST, @@ -236,6 +236,9 @@ SlabTuple indexHeaderSymbols(llvm::StringRef Version, ASTContext &AST, /*CollectMainFileRefs=*/false); } +FileSymbols::FileSymbols(IndexContents IdxContents) + : IdxContents(IdxContents) {} + void FileSymbols::update(llvm::StringRef Key, std::unique_ptr Symbols, std::unique_ptr Refs, @@ -376,14 +379,14 @@ FileSymbols::buildIndex(IndexType Type, DuplicateHandling DuplicateHandle, case IndexType::Light: return std::make_unique( llvm::make_pointee_range(AllSymbols), std::move(AllRefs), - std::move(AllRelations), std::move(Files), + std::move(AllRelations), std::move(Files), IdxContents, std::make_tuple(std::move(SymbolSlabs), std::move(RefSlabs), std::move(RefsStorage), std::move(SymsStorage)), StorageSize); case IndexType::Heavy: return std::make_unique( llvm::make_pointee_range(AllSymbols), std::move(AllRefs), - std::move(AllRelations), std::move(Files), + std::move(AllRelations), std::move(Files), IdxContents, std::make_tuple(std::move(SymbolSlabs), std::move(RefSlabs), std::move(RefsStorage), std::move(SymsStorage)), StorageSize); @@ -410,10 +413,11 @@ void FileSymbols::profile(MemoryTree &MT) const { } } -FileIndex::FileIndex(bool UseDex, bool CollectMainFileRefs) - : MergedIndex(&MainFileIndex, &PreambleIndex), UseDex(UseDex), - CollectMainFileRefs(CollectMainFileRefs), +FileIndex::FileIndex() + : MergedIndex(&MainFileIndex, &PreambleIndex), + PreambleSymbols(IndexContents::Symbols | IndexContents::Relations), PreambleIndex(std::make_unique()), + MainFileSymbols(IndexContents::All), MainFileIndex(std::make_unique()) {} void FileIndex::updatePreamble(PathRef Path, llvm::StringRef Version, @@ -436,9 +440,8 @@ void FileIndex::updatePreamble(PathRef Path, llvm::StringRef Version, /*CountReferences=*/false); } size_t IndexVersion = 0; - auto NewIndex = - PreambleSymbols.buildIndex(UseDex ? IndexType::Heavy : IndexType::Light, - DuplicateHandling::PickOne, &IndexVersion); + auto NewIndex = PreambleSymbols.buildIndex( + IndexType::Heavy, DuplicateHandling::PickOne, &IndexVersion); { std::lock_guard Lock(UpdateIndexMu); if (IndexVersion <= PreambleIndexVersion) { @@ -455,7 +458,7 @@ void FileIndex::updatePreamble(PathRef Path, llvm::StringRef Version, } void FileIndex::updateMain(PathRef Path, ParsedAST &AST) { - auto Contents = indexMainDecls(AST, CollectMainFileRefs); + auto Contents = indexMainDecls(AST); MainFileSymbols.update( Path, std::make_unique(std::move(std::get<0>(Contents))), std::make_unique(std::move(std::get<1>(Contents))), diff --git a/clang-tools-extra/clangd/index/FileIndex.h b/clang-tools-extra/clangd/index/FileIndex.h index 8ecae66373a5e..d46a874645689 100644 --- a/clang-tools-extra/clangd/index/FileIndex.h +++ b/clang-tools-extra/clangd/index/FileIndex.h @@ -71,6 +71,7 @@ enum class DuplicateHandling { /// locking when we swap or obtain references to snapshots. class FileSymbols { public: + FileSymbols(IndexContents IdxContents); /// Updates all slabs associated with the \p Key. /// If either is nullptr, corresponding data for \p Key will be removed. /// If CountReferences is true, \p Refs will be used for counting references @@ -91,6 +92,8 @@ class FileSymbols { void profile(MemoryTree &MT) const; private: + IndexContents IdxContents; + struct RefSlabAndCountReferences { std::shared_ptr Slab; bool CountReferences = false; @@ -107,7 +110,7 @@ class FileSymbols { /// FIXME: Expose an interface to remove files that are closed. class FileIndex : public MergedIndex { public: - FileIndex(bool UseDex = true, bool CollectMainFileRefs = false); + FileIndex(); /// Update preamble symbols of file \p Path with all declarations in \p AST /// and macros in \p PP. @@ -122,9 +125,6 @@ class FileIndex : public MergedIndex { void profile(MemoryTree &MT) const; private: - bool UseDex; // FIXME: this should be always on. - bool CollectMainFileRefs; - // Contains information from each file's preamble only. Symbols and relations // are sharded per declaration file to deduplicate multiple symbols and reduce // memory usage. @@ -158,7 +158,7 @@ using SlabTuple = std::tuple; /// Retrieves symbols and refs of local top level decls in \p AST (i.e. /// `AST.getLocalTopLevelDecls()`). /// Exposed to assist in unit tests. -SlabTuple indexMainDecls(ParsedAST &AST, bool CollectMainFileRefs = false); +SlabTuple indexMainDecls(ParsedAST &AST); /// Index declarations from \p AST and macros from \p PP that are declared in /// included headers. diff --git a/clang-tools-extra/clangd/index/Index.cpp b/clang-tools-extra/clangd/index/Index.cpp index 1b085140b4ffa..dbb42bafa1f84 100644 --- a/clang-tools-extra/clangd/index/Index.cpp +++ b/clang-tools-extra/clangd/index/Index.cpp @@ -76,7 +76,7 @@ void SwapIndex::relations( return snapshot()->relations(R, CB); } -llvm::unique_function +llvm::unique_function SwapIndex::indexedFiles() const { // The index snapshot should outlive this method return value. auto SnapShot = snapshot(); diff --git a/clang-tools-extra/clangd/index/Index.h b/clang-tools-extra/clangd/index/Index.h index c961aa9d8bd95..91f7990312c76 100644 --- a/clang-tools-extra/clangd/index/Index.h +++ b/clang-tools-extra/clangd/index/Index.h @@ -82,6 +82,30 @@ struct RelationsRequest { llvm::Optional Limit; }; +/// Describes what data is covered by an index. +/// +/// Indexes may contain symbols but not references from a file, etc. +/// This affects merging: if a staler index contains a reference but a fresher +/// one does not, we want to trust the fresher index *only* if it actually +/// includes references in general. +enum class IndexContents : uint8_t { + None = 0, + Symbols = 1 << 1, + References = 1 << 2, + Relations = 1 << 3, + All = Symbols | References | Relations +}; + +inline constexpr IndexContents operator&(IndexContents L, IndexContents R) { + return static_cast(static_cast(L) & + static_cast(R)); +} + +inline constexpr IndexContents operator|(IndexContents L, IndexContents R) { + return static_cast(static_cast(L) | + static_cast(R)); +} + /// Interface for symbol indexes that can be used for searching or /// matching symbols among a set of symbols based on names or unique IDs. class SymbolIndex { @@ -104,11 +128,12 @@ class SymbolIndex { lookup(const LookupRequest &Req, llvm::function_ref Callback) const = 0; - /// Finds all occurrences (e.g. references, declarations, definitions) of a - /// symbol and applies \p Callback on each result. + /// Finds all occurrences (e.g. references, declarations, definitions) of + /// symbols and applies \p Callback on each result. /// /// Results should be returned in arbitrary order. /// The returned result must be deep-copied if it's used outside Callback. + /// FIXME: there's no indication which result references which symbol. /// /// Returns true if there will be more results (limited by Req.Limit); virtual bool refs(const RefsRequest &Req, @@ -124,7 +149,7 @@ class SymbolIndex { /// Returns function which checks if the specified file was used to build this /// index or not. The function must only be called while the index is alive. - virtual llvm::unique_function + virtual llvm::unique_function indexedFiles() const = 0; /// Returns estimated size of index (in bytes). @@ -151,7 +176,7 @@ class SwapIndex : public SymbolIndex { llvm::function_ref) const override; - llvm::unique_function + llvm::unique_function indexedFiles() const override; size_t estimateMemoryUsage() const override; diff --git a/clang-tools-extra/clangd/index/MemIndex.cpp b/clang-tools-extra/clangd/index/MemIndex.cpp index 2352e801d1fcf..a578ed2da140a 100644 --- a/clang-tools-extra/clangd/index/MemIndex.cpp +++ b/clang-tools-extra/clangd/index/MemIndex.cpp @@ -109,15 +109,15 @@ void MemIndex::relations( } } -llvm::unique_function +llvm::unique_function MemIndex::indexedFiles() const { return [this](llvm::StringRef FileURI) { auto Path = URI::resolve(FileURI); if (!Path) { llvm::consumeError(Path.takeError()); - return false; + return IndexContents::None; } - return Files.contains(*Path); + return Files.contains(*Path) ? IdxContents : IndexContents::None; }; } diff --git a/clang-tools-extra/clangd/index/MemIndex.h b/clang-tools-extra/clangd/index/MemIndex.h index 7855630fda024..27e26c6eb17bb 100644 --- a/clang-tools-extra/clangd/index/MemIndex.h +++ b/clang-tools-extra/clangd/index/MemIndex.h @@ -48,12 +48,14 @@ class MemIndex : public SymbolIndex { template MemIndex(SymbolRange &&Symbols, RefRange &&Refs, RelationRange &&Relations, - FileRange &&Files, Payload &&BackingData, size_t BackingDataSize) + FileRange &&Files, IndexContents IdxContents, Payload &&BackingData, + size_t BackingDataSize) : MemIndex(std::forward(Symbols), std::forward(Refs), std::forward(Relations), std::forward(BackingData), BackingDataSize) { this->Files = std::forward(Files); + this->IdxContents = IdxContents; } /// Builds an index from slabs. The index takes ownership of the data. @@ -74,7 +76,7 @@ class MemIndex : public SymbolIndex { llvm::function_ref Callback) const override; - llvm::unique_function + llvm::unique_function indexedFiles() const override; size_t estimateMemoryUsage() const override; @@ -90,6 +92,8 @@ class MemIndex : public SymbolIndex { llvm::DenseMap, std::vector> Relations; // Set of files which were used during this index build. llvm::StringSet<> Files; + // Contents of the index (symbols, references, etc.) + IndexContents IdxContents; std::shared_ptr KeepAlive; // poor man's move-only std::any // Size of memory retained by KeepAlive. size_t BackingDataSize = 0; diff --git a/clang-tools-extra/clangd/index/Merge.cpp b/clang-tools-extra/clangd/index/Merge.cpp index 6f369ed2edcf5..54793cf566e88 100644 --- a/clang-tools-extra/clangd/index/Merge.cpp +++ b/clang-tools-extra/clangd/index/Merge.cpp @@ -49,8 +49,9 @@ bool MergedIndex::fuzzyFind( More |= Static->fuzzyFind(Req, [&](const Symbol &S) { // We expect the definition to see the canonical declaration, so it seems // to be enough to check only the definition if it exists. - if (DynamicContainsFile(S.Definition ? S.Definition.FileURI - : S.CanonicalDeclaration.FileURI)) + if ((DynamicContainsFile(S.Definition ? S.Definition.FileURI + : S.CanonicalDeclaration.FileURI) & + IndexContents::Symbols) != IndexContents::None) return; auto DynS = Dyn.find(S.ID); ++StaticCount; @@ -84,8 +85,9 @@ void MergedIndex::lookup( Static->lookup(Req, [&](const Symbol &S) { // We expect the definition to see the canonical declaration, so it seems // to be enough to check only the definition if it exists. - if (DynamicContainsFile(S.Definition ? S.Definition.FileURI - : S.CanonicalDeclaration.FileURI)) + if ((DynamicContainsFile(S.Definition ? S.Definition.FileURI + : S.CanonicalDeclaration.FileURI) & + IndexContents::Symbols) != IndexContents::None) return; const Symbol *Sym = B.find(S.ID); RemainingIDs.erase(S.ID); @@ -121,7 +123,8 @@ bool MergedIndex::refs(const RefsRequest &Req, // We return less than Req.Limit if static index returns more refs for dirty // files. bool StaticHadMore = Static->refs(Req, [&](const Ref &O) { - if (DynamicContainsFile(O.Location.FileURI)) + if ((DynamicContainsFile(O.Location.FileURI) & IndexContents::References) != + IndexContents::None) return; // ignore refs that have been seen from dynamic index. if (Remaining == 0) { More = true; @@ -133,11 +136,11 @@ bool MergedIndex::refs(const RefsRequest &Req, return More || StaticHadMore; } -llvm::unique_function +llvm::unique_function MergedIndex::indexedFiles() const { return [DynamicContainsFile{Dynamic->indexedFiles()}, StaticContainsFile{Static->indexedFiles()}](llvm::StringRef FileURI) { - return DynamicContainsFile(FileURI) || StaticContainsFile(FileURI); + return DynamicContainsFile(FileURI) | StaticContainsFile(FileURI); }; } diff --git a/clang-tools-extra/clangd/index/Merge.h b/clang-tools-extra/clangd/index/Merge.h index f8696b460c90c..88125fdbe1ebe 100644 --- a/clang-tools-extra/clangd/index/Merge.h +++ b/clang-tools-extra/clangd/index/Merge.h @@ -41,7 +41,7 @@ class MergedIndex : public SymbolIndex { void relations(const RelationsRequest &, llvm::function_ref) const override; - llvm::unique_function + llvm::unique_function indexedFiles() const override; size_t estimateMemoryUsage() const override { return Dynamic->estimateMemoryUsage() + Static->estimateMemoryUsage(); diff --git a/clang-tools-extra/clangd/index/ProjectAware.cpp b/clang-tools-extra/clangd/index/ProjectAware.cpp index bafe5550f605e..80ebaf903b4cb 100644 --- a/clang-tools-extra/clangd/index/ProjectAware.cpp +++ b/clang-tools-extra/clangd/index/ProjectAware.cpp @@ -54,7 +54,7 @@ class ProjectAwareIndex : public SymbolIndex { llvm::function_ref Callback) const override; - llvm::unique_function + llvm::unique_function indexedFiles() const override; ProjectAwareIndex(IndexFactory Gen) : Gen(std::move(Gen)) {} @@ -115,12 +115,12 @@ void ProjectAwareIndex::relations( return Idx->relations(Req, Callback); } -llvm::unique_function +llvm::unique_function ProjectAwareIndex::indexedFiles() const { trace::Span Tracer("ProjectAwareIndex::indexedFiles"); if (auto *Idx = getIndex()) return Idx->indexedFiles(); - return [](llvm::StringRef) { return false; }; + return [](llvm::StringRef) { return IndexContents::None; }; } SymbolIndex *ProjectAwareIndex::getIndex() const { diff --git a/clang-tools-extra/clangd/index/dex/Dex.cpp b/clang-tools-extra/clangd/index/dex/Dex.cpp index dc072accb05b7..8552fa3b5174f 100644 --- a/clang-tools-extra/clangd/index/dex/Dex.cpp +++ b/clang-tools-extra/clangd/index/dex/Dex.cpp @@ -313,14 +313,15 @@ void Dex::relations( } } -llvm::unique_function Dex::indexedFiles() const { +llvm::unique_function +Dex::indexedFiles() const { return [this](llvm::StringRef FileURI) { auto Path = URI::resolve(FileURI); if (!Path) { llvm::consumeError(Path.takeError()); - return false; + return IndexContents::None; } - return Files.contains(*Path); + return Files.contains(*Path) ? IdxContents : IndexContents::None; }; } diff --git a/clang-tools-extra/clangd/index/dex/Dex.h b/clang-tools-extra/clangd/index/dex/Dex.h index 318a74951379c..abfad98fab3d9 100644 --- a/clang-tools-extra/clangd/index/dex/Dex.h +++ b/clang-tools-extra/clangd/index/dex/Dex.h @@ -70,11 +70,13 @@ class Dex : public SymbolIndex { template Dex(SymbolRange &&Symbols, RefsRange &&Refs, RelationsRange &&Relations, - FileRange &&Files, Payload &&BackingData, size_t BackingDataSize) + FileRange &&Files, IndexContents IdxContents, Payload &&BackingData, + size_t BackingDataSize) : Dex(std::forward(Symbols), std::forward(Refs), std::forward(Relations), std::forward(BackingData), BackingDataSize) { this->Files = std::forward(Files); + this->IdxContents = IdxContents; } /// Builds an index from slabs. The index takes ownership of the slab. @@ -94,7 +96,7 @@ class Dex : public SymbolIndex { llvm::function_ref Callback) const override; - llvm::unique_function + llvm::unique_function indexedFiles() const override; size_t estimateMemoryUsage() const override; @@ -127,6 +129,8 @@ class Dex : public SymbolIndex { std::shared_ptr KeepAlive; // poor man's move-only std::any // Set of files which were used during this index build. llvm::StringSet<> Files; + // Contents of the index (symbols, references, etc.) + IndexContents IdxContents; // Size of memory retained by KeepAlive. size_t BackingDataSize = 0; }; diff --git a/clang-tools-extra/clangd/index/remote/Client.cpp b/clang-tools-extra/clangd/index/remote/Client.cpp index a153a8812baff..84eb2de259b9c 100644 --- a/clang-tools-extra/clangd/index/remote/Client.cpp +++ b/clang-tools-extra/clangd/index/remote/Client.cpp @@ -152,13 +152,13 @@ class IndexClient : public clangd::SymbolIndex { }); } - llvm::unique_function + llvm::unique_function indexedFiles() const override { - // FIXME: For now we always return "false" regardless of whether the file - // was indexed or not. A possible implementation could be based on - // the idea that we do not want to send a request at every + // FIXME: For now we always return IndexContents::None regardless of whether + // the file was indexed or not. A possible implementation could be + // based on the idea that we do not want to send a request at every // call of a function returned by IndexClient::indexedFiles(). - return [](llvm::StringRef) { return false; }; + return [](llvm::StringRef) { return IndexContents::None; }; } // IndexClient does not take any space since the data is stored on the diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index d3c7da96a441f..96cd79bcea35d 100644 --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -15,8 +15,14 @@ #include "index/SymbolCollector.h" #include "support/Logger.h" #include "support/Trace.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ParentMapContext.h" +#include "clang/AST/Stmt.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Tooling/Syntax/Tokens.h" #include "llvm/ADT/None.h" @@ -54,27 +60,6 @@ bool isInMacroBody(const SourceManager &SM, SourceLocation Loc) { return false; } -// Query the index to find some other files where the Decl is referenced. -llvm::Optional getOtherRefFile(const Decl &D, StringRef MainFile, - const SymbolIndex &Index) { - RefsRequest Req; - // We limit the number of results, this is a correctness/performance - // tradeoff. We expect the number of symbol references in the current file - // is smaller than the limit. - Req.Limit = 100; - Req.IDs.insert(getSymbolID(&D)); - llvm::Optional OtherFile; - Index.refs(Req, [&](const Ref &R) { - if (OtherFile) - return; - if (auto RefFilePath = filePath(R.Location, /*HintFilePath=*/MainFile)) { - if (*RefFilePath != MainFile) - OtherFile = *RefFilePath; - } - }); - return OtherFile; -} - // Canonical declarations help simplify the process of renaming. Examples: // - Template's canonical decl is the templated declaration (i.e. // ClassTemplateDecl is canonicalized to its child CXXRecordDecl, @@ -189,7 +174,6 @@ enum class ReasonToReject { NoSymbolFound, NoIndexProvided, NonIndexable, - UsedOutsideFile, // for within-file rename only. UnsupportedSymbol, AmbiguousSymbol, @@ -200,8 +184,7 @@ enum class ReasonToReject { llvm::Optional renameable(const NamedDecl &RenameDecl, StringRef MainFilePath, - const SymbolIndex *Index, - bool CrossFile) { + const SymbolIndex *Index) { trace::Span Tracer("Renameable"); // Filter out symbols that are unsupported in both rename modes. if (llvm::isa(&RenameDecl)) @@ -234,34 +217,9 @@ llvm::Optional renameable(const NamedDecl &RenameDecl, IsMainFileOnly)) return ReasonToReject::NonIndexable; - if (!CrossFile) { - if (!DeclaredInMainFile) - // We are sure the symbol is used externally, bail out early. - return ReasonToReject::UsedOutsideFile; - - // If the symbol is declared in the main file (which is not a header), we - // rename it. - if (!MainFileIsHeader) - return None; - - if (!Index) - return ReasonToReject::NoIndexProvided; - - auto OtherFile = getOtherRefFile(RenameDecl, MainFilePath, *Index); - // If the symbol is indexable and has no refs from other files in the index, - // we rename it. - if (!OtherFile) - return None; - // If the symbol is indexable and has refs from other files in the index, - // we disallow rename. - return ReasonToReject::UsedOutsideFile; - } - - assert(CrossFile); // FIXME: Renaming virtual methods requires to rename all overridens in // subclasses, our index doesn't have this information. - // Note: Within-file rename does support this through the AST. if (const auto *S = llvm::dyn_cast(&RenameDecl)) { if (S->isVirtual()) return ReasonToReject::UnsupportedSymbol; @@ -276,8 +234,6 @@ llvm::Error makeError(ReasonToReject Reason) { return "there is no symbol at the given location"; case ReasonToReject::NoIndexProvided: return "no index provided"; - case ReasonToReject::UsedOutsideFile: - return "the symbol is used outside main file"; case ReasonToReject::NonIndexable: return "symbol may be used in other files (not eligible for indexing)"; case ReasonToReject::UnsupportedSymbol: @@ -318,13 +274,120 @@ std::vector findOccurrencesWithinFile(ParsedAST &AST, return Results; } +// Detect name conflict with othter DeclStmts in the same enclosing scope. +const NamedDecl *lookupSiblingWithinEnclosingScope(ASTContext &Ctx, + const NamedDecl &RenamedDecl, + StringRef NewName) { + // Store Parents list outside of GetSingleParent, so that returned pointer is + // not invalidated. + DynTypedNodeList Storage(DynTypedNode::create(RenamedDecl)); + auto GetSingleParent = [&](const DynTypedNode &Node) -> const DynTypedNode * { + Storage = Ctx.getParents(Node); + return (Storage.size() == 1) ? Storage.begin() : nullptr; + }; + + // We need to get to the enclosing scope: NamedDecl's parent is typically + // DeclStmt (or FunctionProtoTypeLoc in case of function arguments), so + // enclosing scope would be the second order parent. + const auto *Parent = GetSingleParent(DynTypedNode::create(RenamedDecl)); + if (!Parent || !(Parent->get() || Parent->get())) + return nullptr; + Parent = GetSingleParent(*Parent); + + // The following helpers check corresponding AST nodes for variable + // declarations with the name collision. + auto CheckDeclStmt = [&](const DeclStmt *DS, + StringRef Name) -> const NamedDecl * { + if (!DS) + return nullptr; + for (const auto &Child : DS->getDeclGroup()) + if (const auto *ND = dyn_cast(Child)) + if (ND != &RenamedDecl && ND->getName() == Name) + return ND; + return nullptr; + }; + auto CheckCompoundStmt = [&](const Stmt *S, + StringRef Name) -> const NamedDecl * { + if (const auto *CS = dyn_cast_or_null(S)) + for (const auto *Node : CS->children()) + if (const auto *Result = CheckDeclStmt(dyn_cast(Node), Name)) + return Result; + return nullptr; + }; + auto CheckConditionVariable = [&](const auto *Scope, + StringRef Name) -> const NamedDecl * { + if (!Scope) + return nullptr; + return CheckDeclStmt(Scope->getConditionVariableDeclStmt(), Name); + }; + + // CompoundStmt is the most common enclosing scope for function-local symbols + // In the simplest case we just iterate through sibling DeclStmts and check + // for collisions. + if (const auto *EnclosingCS = Parent->get()) { + if (const auto *Result = CheckCompoundStmt(EnclosingCS, NewName)) + return Result; + const auto *ScopeParent = GetSingleParent(*Parent); + // CompoundStmt may be found within if/while/for. In these cases, rename can + // collide with the init-statement variable decalaration, they should be + // checked. + if (const auto *Result = + CheckConditionVariable(ScopeParent->get(), NewName)) + return Result; + if (const auto *Result = + CheckConditionVariable(ScopeParent->get(), NewName)) + return Result; + if (const auto *For = ScopeParent->get()) + if (const auto *Result = CheckDeclStmt( + dyn_cast_or_null(For->getInit()), NewName)) + return Result; + // Also check if there is a name collision with function arguments. + if (const auto *Function = ScopeParent->get()) + for (const auto *Parameter : Function->parameters()) + if (Parameter->getName() == NewName) + return Parameter; + return nullptr; + } + + // When renaming a variable within init-statement within if/while/for + // condition, also check the CompoundStmt in the body. + if (const auto *EnclosingIf = Parent->get()) { + if (const auto *Result = CheckCompoundStmt(EnclosingIf->getElse(), NewName)) + return Result; + return CheckCompoundStmt(EnclosingIf->getThen(), NewName); + } + if (const auto *EnclosingWhile = Parent->get()) + return CheckCompoundStmt(EnclosingWhile->getBody(), NewName); + if (const auto *EnclosingFor = Parent->get()) { + // Check for conflicts with other declarations within initialization + // statement. + if (const auto *Result = CheckDeclStmt( + dyn_cast_or_null(EnclosingFor->getInit()), NewName)) + return Result; + return CheckCompoundStmt(EnclosingFor->getBody(), NewName); + } + if (const auto *EnclosingFunction = Parent->get()) { + // Check for conflicts with other arguments. + for (const auto *Parameter : EnclosingFunction->parameters()) + if (Parameter != &RenamedDecl && Parameter->getName() == NewName) + return Parameter; + // FIXME: We don't modify all references to function parameters when + // renaming from forward declaration now, so using a name colliding with + // something in the definition's body is a valid transformation. + if (!EnclosingFunction->doesThisDeclarationHaveABody()) + return nullptr; + return CheckCompoundStmt(EnclosingFunction->getBody(), NewName); + } + + return nullptr; +} + // Lookup the declarations (if any) with the given Name in the context of // RenameDecl. -const NamedDecl *lookupSiblingWithName(const ASTContext &Ctx, - const NamedDecl &RenamedDecl, - llvm::StringRef Name) { - trace::Span Tracer("LookupSiblingWithName"); - const auto &II = Ctx.Idents.get(Name); +const NamedDecl *lookupSiblingsWithinContext(ASTContext &Ctx, + const NamedDecl &RenamedDecl, + llvm::StringRef NewName) { + const auto &II = Ctx.Idents.get(NewName); DeclarationName LookupName(&II); DeclContextLookupResult LookupResult; const auto *DC = RenamedDecl.getDeclContext(); @@ -356,6 +419,16 @@ const NamedDecl *lookupSiblingWithName(const ASTContext &Ctx, return nullptr; } +const NamedDecl *lookupSiblingWithName(ASTContext &Ctx, + const NamedDecl &RenamedDecl, + llvm::StringRef NewName) { + trace::Span Tracer("LookupSiblingWithName"); + if (const auto *Result = + lookupSiblingsWithinContext(Ctx, RenamedDecl, NewName)) + return Result; + return lookupSiblingWithinEnclosingScope(Ctx, RenamedDecl, NewName); +} + struct InvalidName { enum Kind { Keywords, @@ -474,7 +547,7 @@ findOccurrencesOutsideFile(const NamedDecl &RenameDecl, if ((R.Kind & RefKind::Spelled) == RefKind::Unknown) return; if (auto RefFilePath = filePath(R.Location, /*HintFilePath=*/MainFile)) { - if (*RefFilePath != MainFile) + if (!pathEqual(*RefFilePath, MainFile)) AffectedFiles[*RefFilePath].push_back(toRange(R.Location)); } }); @@ -646,8 +719,7 @@ llvm::Expected rename(const RenameInputs &RInputs) { if (Invalid) return makeError(*Invalid); - auto Reject = renameable(RenameDecl, RInputs.MainFilePath, RInputs.Index, - Opts.AllowCrossFile); + auto Reject = renameable(RenameDecl, RInputs.MainFilePath, RInputs.Index); if (Reject) return makeError(*Reject); @@ -672,7 +744,7 @@ llvm::Expected rename(const RenameInputs &RInputs) { // return the main file edit if this is a within-file rename or the symbol // being renamed is function local. - if (!Opts.AllowCrossFile || RenameDecl.getParentFunctionOrMethod()) { + if (RenameDecl.getParentFunctionOrMethod()) { Result.GlobalChanges = FileEdits( {std::make_pair(RInputs.MainFilePath, std::move(MainFileEdits))}); return Result; @@ -681,7 +753,7 @@ llvm::Expected rename(const RenameInputs &RInputs) { // If the index is nullptr, we don't know the completeness of the result, so // we don't populate the field GlobalChanges. if (!RInputs.Index) { - assert(Result.GlobalChanges.empty() && Opts.AllowCrossFile); + assert(Result.GlobalChanges.empty()); return Result; } diff --git a/clang-tools-extra/clangd/refactor/Rename.h b/clang-tools-extra/clangd/refactor/Rename.h index ff23a67cfc461..7eca4610eacac 100644 --- a/clang-tools-extra/clangd/refactor/Rename.h +++ b/clang-tools-extra/clangd/refactor/Rename.h @@ -27,9 +27,6 @@ using DirtyBufferGetter = llvm::function_ref(PathRef AbsPath)>; struct RenameOptions { - /// If true, enable cross-file rename; otherwise, only allows to rename a - /// symbol that's only used in the current file. - bool AllowCrossFile = false; /// The maximum number of affected files (0 means no limit), only meaningful /// when AllowCrossFile = true. /// If the actual number exceeds the limit, rename is forbidden. diff --git a/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp b/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp index b243f24eb3696..cb53b3bedf9d0 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/AnnotateHighlightings.cpp @@ -8,6 +8,7 @@ #include "SemanticHighlighting.h" #include "refactor/Tweak.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ScopedPrinter.h" namespace clang { namespace clangd { @@ -67,9 +68,19 @@ Expected AnnotateHighlightings::apply(const Selection &Inputs) { if (!InsertOffset) return InsertOffset.takeError(); - auto InsertReplacement = tooling::Replacement( - FilePath, *InsertOffset, 0, - ("/* " + toTextMateScope(Token.Kind) + " */").str()); + std::string Comment = "/* "; + Comment.append(llvm::to_string(Token.Kind)); + for (unsigned I = 0; + I <= static_cast(HighlightingModifier::LastModifier); ++I) { + if (Token.Modifiers & (1 << I)) { + Comment.append(" ["); + Comment.append(llvm::to_string(static_cast(I))); + Comment.push_back(']'); + } + } + Comment.append(" */"); + auto InsertReplacement = + tooling::Replacement(FilePath, *InsertOffset, 0, Comment); if (auto Err = Result.add(InsertReplacement)) return std::move(Err); } diff --git a/clang-tools-extra/clangd/support/CMakeLists.txt b/clang-tools-extra/clangd/support/CMakeLists.txt index f0fe073eb1361..fc7d7a28117b1 100644 --- a/clang-tools-extra/clangd/support/CMakeLists.txt +++ b/clang-tools-extra/clangd/support/CMakeLists.txt @@ -23,6 +23,7 @@ add_clang_library(clangdSupport Logger.cpp Markup.cpp MemoryTree.cpp + Path.cpp Shutdown.cpp Threading.cpp ThreadsafeFS.cpp diff --git a/clang-tools-extra/clangd/support/Context.h b/clang-tools-extra/clangd/support/Context.h index 894032bdd8838..815962b523d62 100644 --- a/clang-tools-extra/clangd/support/Context.h +++ b/clang-tools-extra/clangd/support/Context.h @@ -82,8 +82,6 @@ class Context { public: /// Same as Context::empty(), please use Context::empty() instead. - /// Constructor is defined to workaround a bug in MSVC's version of STL. - /// (arguments of std::future<> must be default-constructible in MSVC). Context() = default; /// Copy operations for this class are deleted, use an explicit clone() method diff --git a/clang-tools-extra/clangd/support/Function.h b/clang-tools-extra/clangd/support/Function.h index 2cac1b1e7f67e..936800d569857 100644 --- a/clang-tools-extra/clangd/support/Function.h +++ b/clang-tools-extra/clangd/support/Function.h @@ -51,7 +51,7 @@ template class Event { Subscription &operator=(Subscription &&Other) { // If *this is active, unsubscribe. if (Parent) { - std::lock_guard(Parent->ListenersMu); + std::lock_guard Lock(Parent->ListenersMu); llvm::erase_if(Parent->Listeners, [&](const std::pair &P) { return P.second == ListenerID; diff --git a/clang-tools-extra/clangd/support/Path.cpp b/clang-tools-extra/clangd/support/Path.cpp new file mode 100644 index 0000000000000..f72d00070f34c --- /dev/null +++ b/clang-tools-extra/clangd/support/Path.cpp @@ -0,0 +1,30 @@ +//===--- Path.cpp -------------------------------------------*- C++-*------===// +// +// 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 "support/Path.h" +namespace clang { +namespace clangd { + +std::string maybeCaseFoldPath(PathRef Path) { +#if defined(_WIN32) || defined(__APPLE__) + return Path.lower(); +#else + return std::string(Path); +#endif +} + +bool pathEqual(PathRef A, PathRef B) { +#if defined(_WIN32) || defined(__APPLE__) + return A.equals_lower(B); +#else + return A == B; +#endif +} + +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/support/Path.h b/clang-tools-extra/clangd/support/Path.h index 4d4ad7f490473..402903130f01a 100644 --- a/clang-tools-extra/clangd/support/Path.h +++ b/clang-tools-extra/clangd/support/Path.h @@ -22,6 +22,12 @@ using Path = std::string; /// signatures. using PathRef = llvm::StringRef; +// For platforms where paths are case-insensitive (but case-preserving), +// we need to do case-insensitive comparisons and use lowercase keys. +// FIXME: Make Path a real class with desired semantics instead. +std::string maybeCaseFoldPath(PathRef Path); +bool pathEqual(PathRef, PathRef); + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/test/document-link.test b/clang-tools-extra/clangd/test/document-link.test index 63f8ca0993228..36977753478a0 100644 --- a/clang-tools-extra/clangd/test/document-link.test +++ b/clang-tools-extra/clangd/test/document-link.test @@ -1,9 +1,10 @@ -# for %resource_dir: REQUIRES: clang -# %resource_dir actually points at builtin_include_dir, go up one directory. -# RUN: clangd -lit-test -resource-dir=%resource_dir/.. < %s | FileCheck -strict-whitespace %s +# Create a fake resource_dir so that the test can find the headers. +# RUN: rm -rf %/t +# RUN: mkdir -p %t/include/ && touch %t/include/foo.h +# RUN: clangd -lit-test -resource-dir=%t < %s | FileCheck -strict-whitespace %s {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} --- -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"#include \n#include "}}} +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"#include "}}} --- {"jsonrpc":"2.0","id":2,"method":"textDocument/documentLink","params":{"textDocument":{"uri":"test:///main.cpp"}}} # CHECK: "id": 2, @@ -12,7 +13,7 @@ # CHECK-NEXT: { # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 19, +# CHECK-NEXT: "character": 16, # CHECK-NEXT: "line": 0 # CHECK-NEXT: }, # CHECK-NEXT: "start": { @@ -20,20 +21,7 @@ # CHECK-NEXT: "line": 0 # CHECK-NEXT: } # CHECK-NEXT: }, -# CHECK-NEXT: "target": "file://{{.*}}/stdint.h" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 19, -# CHECK-NEXT: "line": 1 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 9, -# CHECK-NEXT: "line": 1 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "target": "file://{{.*}}/stddef.h" +# CHECK-NEXT: "target": "file://{{.*}}/foo.h" # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT:} diff --git a/clang-tools-extra/clangd/test/initialize-params.test b/clang-tools-extra/clangd/test/initialize-params.test index 907ab0ade4206..4b40b17b2d64e 100644 --- a/clang-tools-extra/clangd/test/initialize-params.test +++ b/clang-tools-extra/clangd/test/initialize-params.test @@ -81,7 +81,19 @@ # CHECK-NEXT: "delta": true # CHECK-NEXT: }, # CHECK-NEXT: "legend": { -# CHECK-NEXT: "tokenModifiers": [], +# CHECK-NEXT: "tokenModifiers": [ +# CHECK-NEXT: "declaration", +# CHECK-NEXT: "deprecated", +# CHECK-NEXT: "deduced", +# CHECK-NEXT: "readonly", +# CHECK-NEXT: "static", +# CHECK-NEXT: "abstract", +# CHECK-NEXT: "dependentName", +# CHECK-NEXT: "functionScope", +# CHECK-NEXT: "classScope", +# CHECK-NEXT: "fileScope", +# CHECK-NEXT: "globalScope" +# CHECK-NEXT: ], # CHECK-NEXT: "tokenTypes": [ # CHECK-NEXT: "variable", # CHECK: ] diff --git a/clang-tools-extra/clangd/test/references.test b/clang-tools-extra/clangd/test/references.test index 964f5e7f9526c..70e52f4c61535 100644 --- a/clang-tools-extra/clangd/test/references.test +++ b/clang-tools-extra/clangd/test/references.test @@ -1,28 +1,24 @@ # RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} --- -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int x; int y = x;"}}} +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{ + "uri":"test:///main.cpp", + "languageId":"cpp", + "version":1, + "text":"int x; int y = x;" +}}} --- -{"jsonrpc":"2.0","id":1,"method":"textDocument/references","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":0,"character":4}}} +{"jsonrpc":"2.0","id":1,"method":"textDocument/references","params":{ + "textDocument":{"uri":"test:///main.cpp"}, + "position":{"line":0,"character":4}, + "context":{"includeDeclaration": false} +}} # CHECK: "id": 1 # CHECK-NEXT: "jsonrpc": "2.0", # CHECK-NEXT: "result": [ # CHECK-NEXT: { # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 5, -# CHECK-NEXT: "line": 0 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 4, -# CHECK-NEXT: "line": 0 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "uri": "{{.*}}/main.cpp" -# CHECK-NEXT: }, -# CHECK-NEXT: { -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { # CHECK-NEXT: "character": 16, # CHECK-NEXT: "line": 0 # CHECK-NEXT: }, diff --git a/clang-tools-extra/clangd/test/semantic-highlighting.test b/clang-tools-extra/clangd/test/semantic-highlighting.test deleted file mode 100644 index bca6b373aa225..0000000000000 --- a/clang-tools-extra/clangd/test/semantic-highlighting.test +++ /dev/null @@ -1,145 +0,0 @@ -# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s -{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"semanticHighlightingCapabilities":{"semanticHighlighting":true}}},"trace":"off"}} ---- -# CHECK: "id": 0, -# CHECK: "semanticHighlighting": { -# CHECK-NEXT: "scopes": [ -# CHECK-NEXT: [ -# CHECK-NEXT: "variable.other.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "variable.other.local.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "variable.parameter.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.function.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.function.method.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.function.method.static.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "variable.other.field.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "variable.other.field.static.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.type.class.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.type.enum.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "variable.other.enummember.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.type.typedef.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.type.dependent.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.other.dependent.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.namespace.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.type.template.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.type.concept.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "storage.type.primitive.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "entity.name.function.preprocessor.cpp" -# CHECK-NEXT: ], -# CHECK-NEXT: [ -# CHECK-NEXT: "meta.disabled" -# CHECK-NEXT: ] -# CHECK-NEXT: ] -# CHECK-NEXT: }, ---- -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.cpp","languageId":"cpp","text":"int x = 2;"}}} -# CHECK: "method": "textDocument/semanticHighlighting", -# CHECK-NEXT: "params": { -# CHECK-NEXT: "lines": [ -# CHECK-NEXT: { -# CHECK-NEXT: "isInactive": false, -# CHECK-NEXT: "line": 0, -# CHECK-NEXT: "tokens": "AAAABAABAAA=" -# CHECK-NEXT: } -# CHECK-NEXT: ], -# CHECK-NEXT: "textDocument": { -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/foo.cpp", -# CHECK-NEXT: "version": 0 -# CHECK-NEXT: } -# CHECK-NEXT: } -# CHECK-NEXT:} ---- -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo2.cpp","languageId":"cpp","text":"int x = 2;\nint y = 2;"}}} -# CHECK: "method": "textDocument/semanticHighlighting", -# CHECK-NEXT: "params": { -# CHECK-NEXT: "lines": [ -# CHECK-NEXT: { -# CHECK-NEXT: "isInactive": false, -# CHECK-NEXT: "line": 0, -# CHECK-NEXT: "tokens": "AAAABAABAAA=" -# CHECK-NEXT: } -# CHECK-NEXT: { -# CHECK-NEXT: "isInactive": false, -# CHECK-NEXT: "line": 1, -# CHECK-NEXT: "tokens": "AAAABAABAAA=" -# CHECK-NEXT: } -# CHECK-NEXT: ], -# CHECK-NEXT: "textDocument": { -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/foo2.cpp", -# CHECK-NEXT: "version": 0 -# CHECK-NEXT: } -# CHECK-NEXT: } -# CHECK-NEXT:} ---- -{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///foo.cpp"},"contentChanges": [{"range":{"start": {"line": 0,"character": 10},"end": {"line": 0,"character": 10}},"rangeLength": 0,"text": "\nint y = 2;"}]}} -# CHECK: "method": "textDocument/semanticHighlighting", -# CHECK-NEXT: "params": { -# CHECK-NEXT: "lines": [ -# CHECK-NEXT: { -# CHECK-NEXT: "isInactive": false, -# CHECK-NEXT: "line": 1, -# CHECK-NEXT: "tokens": "AAAABAABAAA=" -# CHECK-NEXT: } -# CHECK-NEXT: ], -# CHECK-NEXT: "textDocument": { -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/foo.cpp", -# CHECK-NEXT: "version": 1 -# CHECK-NEXT: } -# CHECK-NEXT: } -# CHECK-NEXT:} ---- -{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///foo.cpp"},"contentChanges": [{"range":{"start": {"line": 0,"character": 10},"end": {"line": 1,"character": 10}},"rangeLength": 11,"text": ""}]}} -# CHECK: "method": "textDocument/semanticHighlighting", -# CHECK-NEXT: "params": { -# CHECK-NEXT: "lines": [ -# CHECK-NEXT: { -# CHECK-NEXT: "isInactive": false, -# CHECK-NEXT: "line": 1, -# CHECK-NEXT: "tokens": "" -# CHECK-NEXT: } -# CHECK-NEXT: ], -# CHECK-NEXT: "textDocument": { -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/foo.cpp", -# CHECK-NEXT: "version": 2 -# CHECK-NEXT: } -# CHECK-NEXT: } -# CHECK-NEXT:} ---- -{"jsonrpc":"2.0","id":3,"method":"shutdown"} ---- -{"jsonrpc":"2.0","method":"exit"} diff --git a/clang-tools-extra/clangd/test/semantic-tokens.test b/clang-tools-extra/clangd/test/semantic-tokens.test index ed0c0d09a13ed..5cfe6489b0c4b 100644 --- a/clang-tools-extra/clangd/test/semantic-tokens.test +++ b/clang-tools-extra/clangd/test/semantic-tokens.test @@ -1,6 +1,6 @@ # RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s -implicit-check-not=semanticHighlight # Send capabilities for both Theia semanticHighlight & standard semanticTokens. -# clangd should not use/acknowledge the Theia protocol in this case. +# clangd should not use/acknowledge the Theia protocol. {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"capabilities":{"textDocument":{ "semanticHighlightingCapabilities":{"semanticHighlighting":true}, "semanticTokens":{"dynamicRegistration":true} @@ -18,12 +18,12 @@ # CHECK-NEXT: "jsonrpc": "2.0", # CHECK-NEXT: "result": { # CHECK-NEXT: "data": [ -# First line, char 5, variable, no modifiers. +# First line, char 5, variable, declaration+globalScope # CHECK-NEXT: 0, # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 0 +# CHECK-NEXT: 1025 # CHECK-NEXT: ], # CHECK-NEXT: "resultId": "1" # CHECK-NEXT: } @@ -44,12 +44,12 @@ # CHECK-NEXT: "edits": [ # CHECK-NEXT: { # CHECK-NEXT: "data": [ -# Next line, char 5, variable, no modifiers +# Next line, char 5, variable, declaration+globalScope # CHECK-NEXT: 1, # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 0 +# CHECK-NEXT: 1025 # CHECK-NEXT: ], # Inserted at position 1 # CHECK-NEXT: "deleteCount": 0, @@ -72,12 +72,12 @@ # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 0, +# CHECK-NEXT: 1025, # CHECK-NEXT: 1, # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 0 +# CHECK-NEXT: 1025 # CHECK-NEXT: ], # CHECK-NEXT: "resultId": "3" # CHECK-NEXT: } diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp index e42596bb4bf4b..9e3e439ae70df 100644 --- a/clang-tools-extra/clangd/tool/Check.cpp +++ b/clang-tools-extra/clangd/tool/Check.cpp @@ -107,10 +107,10 @@ class Checker { if (auto TrueCmd = CDB->getCompileCommand(File)) { Cmd = std::move(*TrueCmd); - log("Compile command from CDB is: {0}", llvm::join(Cmd.CommandLine, " ")); + log("Compile command from CDB is: {0}", printArgv(Cmd.CommandLine)); } else { Cmd = CDB->getFallbackCommand(File); - log("Generic fallback command is: {0}", llvm::join(Cmd.CommandLine, " ")); + log("Generic fallback command is: {0}", printArgv(Cmd.CommandLine)); } return true; @@ -140,7 +140,7 @@ class Checker { buildCompilerInvocation(Inputs, CaptureInvocationDiags, &CC1Args); auto InvocationDiags = CaptureInvocationDiags.take(); ErrCount += showErrors(InvocationDiags); - log("internal (cc1) args are: {0}", llvm::join(CC1Args, " ")); + log("internal (cc1) args are: {0}", printArgv(CC1Args)); if (!Invocation) { elog("Failed to parse command line"); return false; diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index fe69079bfe67c..51280b73afac6 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -172,14 +172,6 @@ opt EnableClangTidy{ init(true), }; -opt ClangTidyChecks{ - "clang-tidy-checks", - cat(Features), - desc("List of clang-tidy checks to run (this will override " - ".clang-tidy files). Only meaningful when -clang-tidy flag is on"), - init(""), -}; - opt CodeCompletionParse{ "completion-parse", cat(Features), @@ -281,6 +273,13 @@ opt IncludeIneligibleResults{ }; RetiredFlag EnableIndex("index"); +RetiredFlag SuggestMissingIncludes("suggest-missing-includes"); +RetiredFlag RecoveryAST("recovery-ast"); +RetiredFlag RecoveryASTType("recovery-ast-type"); +RetiredFlag AsyncPreamble("async-preamble"); +RetiredFlag CollectMainFileRefs("collect-main-file-refs"); +RetiredFlag CrossFileRename("cross-file-rename"); +RetiredFlag ClangTidyChecks("clang-tidy-checks"); opt LimitResults{ "limit-results", @@ -290,8 +289,6 @@ opt LimitResults{ init(100), }; -RetiredFlag SuggestMissingIncludes("suggest-missing-includes"); - list TweakList{ "tweaks", cat(Features), @@ -300,16 +297,6 @@ list TweakList{ CommaSeparated, }; -opt CrossFileRename{ - "cross-file-rename", - cat(Features), - desc("Enable cross-file rename feature."), - init(true), -}; - -RetiredFlag RecoveryAST("recovery-ast"); -RetiredFlag RecoveryASTType("recovery-ast-type"); - opt FoldingRanges{ "folding-ranges", cat(Features), @@ -450,16 +437,6 @@ opt PrettyPrint{ init(false), }; -// FIXME: retire this flag in llvm 13 release cycle. -opt AsyncPreamble{ - "async-preamble", - cat(Misc), - desc("Reuse even stale preambles, and rebuild them in the background. This " - "improves latency at the cost of accuracy."), - init(ClangdServer::Options().AsyncPreambleBuilds), - Hidden, -}; - opt EnableConfig{ "enable-config", cat(Misc), @@ -474,15 +451,6 @@ opt EnableConfig{ init(true), }; -// FIXME: retire this flag in llvm 13 release cycle. -opt CollectMainFileRefs{ - "collect-main-file-refs", - cat(Misc), - desc("Store references to main-file-only symbols in the index"), - init(ClangdServer::Options().CollectMainFileRefs), - Hidden, -}; - #if defined(__GLIBC__) && CLANGD_MALLOC_TRIM opt EnableMallocTrim{ "malloc-trim", @@ -760,7 +728,6 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var if (!ResourceDir.empty()) Opts.ResourceDir = ResourceDir; Opts.BuildDynamicSymbolIndex = true; - Opts.CollectMainFileRefs = CollectMainFileRefs; std::vector> IdxStack; std::unique_ptr StaticIdx; std::future AsyncIndexLoad; // Block exit while loading the index. @@ -852,15 +819,11 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var Providers.push_back(provideClangTidyFiles(TFS)); if (EnableConfig) Providers.push_back(provideClangdConfig()); - if (!ClangTidyChecks.empty()) - Providers.push_back(addTidyChecks(ClangTidyChecks)); - else - Providers.push_back(provideDefaultChecks()); + Providers.push_back(provideDefaultChecks()); Providers.push_back(disableUnusableChecks()); ClangTidyOptProvider = combine(std::move(Providers)); Opts.ClangTidyProvider = ClangTidyOptProvider; } - Opts.AsyncPreambleBuilds = AsyncPreamble; Opts.QueryDriverGlobs = std::move(QueryDriverGlobs); Opts.TweakFilter = [&](const Tweak &T) { if (T.hidden() && !HiddenFeatures) @@ -872,9 +835,6 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding) Opts.Encoding = ForceOffsetEncoding; - // Shall we allow to customize the file limit? - Opts.Rename.AllowCrossFile = CrossFileRename; - if (CheckFile.getNumOccurrences()) { llvm::SmallString<256> Path; llvm::sys::fs::real_path(CheckFile, Path, /*expand_tilde=*/true); diff --git a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp index bcbedd2500ce8..de8ff2b4a14e1 100644 --- a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp +++ b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp @@ -190,7 +190,6 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) { MemoryShardStorage MSS(Storage, CacheHits); OverlayCDB CDB(/*Base=*/nullptr); BackgroundIndex::Options Opts; - Opts.CollectMainFileRefs = true; BackgroundIndex Idx( FS, CDB, [&](llvm::StringRef) { return &MSS; }, Opts); @@ -241,52 +240,25 @@ TEST_F(BackgroundIndexTest, MainFileRefs) { FS.Files[testPath("root/A.cc")] = "#include \"A.h\"\nstatic void main_sym() { (void)header_sym; }"; - // Check the behaviour with CollectMainFileRefs = false (the default - // at the SymbolCollector level). - { - llvm::StringMap Storage; - size_t CacheHits = 0; - MemoryShardStorage MSS(Storage, CacheHits); - OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; }, - /*Opts=*/{}); - - tooling::CompileCommand Cmd; - Cmd.Filename = testPath("root/A.cc"); - Cmd.Directory = testPath("root"); - Cmd.CommandLine = {"clang++", testPath("root/A.cc")}; - CDB.setCompileCommand(testPath("root/A.cc"), Cmd); - - ASSERT_TRUE(Idx.blockUntilIdleForTest()); - EXPECT_THAT( - runFuzzyFind(Idx, ""), - UnorderedElementsAre(AllOf(Named("header_sym"), NumReferences(1U)), - AllOf(Named("main_sym"), NumReferences(0U)))); - } - - // Check the behaviour with CollectMainFileRefs = true. - { - llvm::StringMap Storage; - size_t CacheHits = 0; - MemoryShardStorage MSS(Storage, CacheHits); - OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex::Options Opts; - Opts.CollectMainFileRefs = true; - BackgroundIndex Idx( - FS, CDB, [&](llvm::StringRef) { return &MSS; }, Opts); + llvm::StringMap Storage; + size_t CacheHits = 0; + MemoryShardStorage MSS(Storage, CacheHits); + OverlayCDB CDB(/*Base=*/nullptr); + BackgroundIndex::Options Opts; + BackgroundIndex Idx( + FS, CDB, [&](llvm::StringRef) { return &MSS; }, Opts); - tooling::CompileCommand Cmd; - Cmd.Filename = testPath("root/A.cc"); - Cmd.Directory = testPath("root"); - Cmd.CommandLine = {"clang++", testPath("root/A.cc")}; - CDB.setCompileCommand(testPath("root/A.cc"), Cmd); + tooling::CompileCommand Cmd; + Cmd.Filename = testPath("root/A.cc"); + Cmd.Directory = testPath("root"); + Cmd.CommandLine = {"clang++", testPath("root/A.cc")}; + CDB.setCompileCommand(testPath("root/A.cc"), Cmd); - ASSERT_TRUE(Idx.blockUntilIdleForTest()); - EXPECT_THAT( - runFuzzyFind(Idx, ""), - UnorderedElementsAre(AllOf(Named("header_sym"), NumReferences(1U)), - AllOf(Named("main_sym"), NumReferences(1U)))); - } + ASSERT_TRUE(Idx.blockUntilIdleForTest()); + EXPECT_THAT( + runFuzzyFind(Idx, ""), + UnorderedElementsAre(AllOf(Named("header_sym"), NumReferences(1U)), + AllOf(Named("main_sym"), NumReferences(1U)))); } TEST_F(BackgroundIndexTest, ShardStorageTest) { @@ -711,7 +683,7 @@ TEST_F(BackgroundIndexTest, Reindex) { class BackgroundIndexRebuilderTest : public testing::Test { protected: BackgroundIndexRebuilderTest() - : Target(std::make_unique()), + : Source(IndexContents::All), Target(std::make_unique()), Rebuilder(&Target, &Source, /*Threads=*/10) { // Prepare FileSymbols with TestSymbol in it, for checkRebuild. TestSymbol.ID = SymbolID("foo"); diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index adf4ac827cce3..f4d364720eafd 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -93,6 +93,7 @@ add_unittest(ClangdUnitTests ClangdTests TestIndex.cpp TestTU.cpp TestWorkspace.cpp + TidyProviderTests.cpp TypeHierarchyTests.cpp URITests.cpp XRefsTests.cpp diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 8d6ac8cd22e4a..9403cda57cfea 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1098,6 +1098,20 @@ template