diff --git a/.arcconfig b/.arcconfig index 9cb88800d30d7a26adde7d03fc61c5c3610ca3ea..412ead903384380cc81dd614805a2190ec6d8e5d 100644 --- a/.arcconfig +++ b/.arcconfig @@ -2,5 +2,6 @@ "phabricator.uri" : "https://reviews.llvm.org/", "repository.callsign" : "G", "conduit_uri" : "https://reviews.llvm.org/", - "base": "git:HEAD^" + "base": "git:HEAD^", + "arc.land.onto.default": "main" } diff --git a/.github/workflows/main-branch-sync.yml b/.github/workflows/main-branch-sync.yml index c8cd4773858b7e4c6458a054f5512d9726e5450c..5ea360e281d6154b32ec5b86d361935b546430d3 100644 --- a/.github/workflows/main-branch-sync.yml +++ b/.github/workflows/main-branch-sync.yml @@ -3,7 +3,7 @@ name: main branch sync on: push: branches: - - 'master' + - 'main' jobs: branch_sync: @@ -12,10 +12,14 @@ jobs: - 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:temp-test-main + git push https://$LLVMBOT_TOKEN@github.com/${{ github.repository }} HEAD:master diff --git a/clang-tools-extra/clang-query/Query.h b/clang-tools-extra/clang-query/Query.h index 223644fe2e515b44289856a5b3033ea9ae2b7047..4c95195d96c1ad800f3da7b54b512eff78139563 100644 --- a/clang-tools-extra/clang-query/Query.h +++ b/clang-tools-extra/clang-query/Query.h @@ -120,7 +120,7 @@ template <> struct SetQueryKind { static const QueryKind value = QK_SetOutputKind; }; -template <> struct SetQueryKind { +template <> struct SetQueryKind { static const QueryKind value = QK_SetTraversalKind; }; diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index 45a0d425b7c2b4bcabc61b5de35be967f1fb7618..b01d8001b66960b9be11c4b624a2087fe6e3649a 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -128,20 +128,17 @@ template QueryRef QueryParser::parseSetOutputKind() { llvm_unreachable("Invalid output kind"); } -QueryRef QueryParser::parseSetTraversalKind( - ast_type_traits::TraversalKind QuerySession::*Var) { +QueryRef QueryParser::parseSetTraversalKind(TraversalKind QuerySession::*Var) { StringRef ValStr; unsigned Value = LexOrCompleteWord(this, ValStr) - .Case("AsIs", ast_type_traits::TK_AsIs) - .Case("IgnoreUnlessSpelledInSource", - ast_type_traits::TK_IgnoreUnlessSpelledInSource) + .Case("AsIs", TK_AsIs) + .Case("IgnoreUnlessSpelledInSource", TK_IgnoreUnlessSpelledInSource) .Default(~0u); if (Value == ~0u) { return new InvalidQuery("expected traversal kind, got '" + ValStr + "'"); } - return new SetQuery( - Var, static_cast(Value)); + return new SetQuery(Var, static_cast(Value)); } QueryRef QueryParser::endQuery(QueryRef Q) { diff --git a/clang-tools-extra/clang-query/QueryParser.h b/clang-tools-extra/clang-query/QueryParser.h index 68f420dc0994ef948eee2e9235aa1123efd51b71..ece646024265e43837b172e02d3ec1c39933ac33 100644 --- a/clang-tools-extra/clang-query/QueryParser.h +++ b/clang-tools-extra/clang-query/QueryParser.h @@ -43,8 +43,7 @@ private: template struct LexOrCompleteWord; QueryRef parseSetBool(bool QuerySession::*Var); - QueryRef - parseSetTraversalKind(ast_type_traits::TraversalKind QuerySession::*Var); + QueryRef parseSetTraversalKind(TraversalKind QuerySession::*Var); template QueryRef parseSetOutputKind(); QueryRef completeMatcherExpression(); diff --git a/clang-tools-extra/clang-query/QuerySession.h b/clang-tools-extra/clang-query/QuerySession.h index 20c788b206a0a659db356f9ad05553aeb000f971..31a4900e26190b13354c5101ef8ddb0fecd61e36 100644 --- a/clang-tools-extra/clang-query/QuerySession.h +++ b/clang-tools-extra/clang-query/QuerySession.h @@ -26,7 +26,7 @@ public: QuerySession(llvm::ArrayRef> ASTs) : ASTs(ASTs), PrintOutput(false), DiagOutput(true), DetailedASTOutput(false), BindRoot(true), PrintMatcher(false), - Terminate(false), TK(ast_type_traits::TK_AsIs) {} + Terminate(false), TK(TK_AsIs) {} llvm::ArrayRef> ASTs; @@ -38,7 +38,7 @@ public: bool PrintMatcher; bool Terminate; - ast_type_traits::TraversalKind TK; + TraversalKind TK; llvm::StringMap NamedValues; }; diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp index c99931e0aa3a27f6f41d7f8f5c41bf3658b2610e..af19da2419ab21ffc874d4ab2757dc3772332f60 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp @@ -21,34 +21,28 @@ char UnparseableEnumOptionError::ID; char UnparseableIntegerOptionError::ID; std::string MissingOptionError::message() const { - llvm::SmallString<128> Buffer; - llvm::raw_svector_ostream Output(Buffer); - Output << "option not found '" << OptionName << '\''; + llvm::SmallString<128> Buffer({"option not found '", OptionName, "'"}); return std::string(Buffer); } std::string UnparseableEnumOptionError::message() const { - llvm::SmallString<128> Buffer; - llvm::raw_svector_ostream Output(Buffer); - Output << "invalid configuration value '" << LookupValue << "' for option '" - << LookupName << '\''; + llvm::SmallString<256> Buffer({"invalid configuration value '", LookupValue, + "' for option '", LookupName, "'"}); if (SuggestedValue) - Output << "; did you mean '" << *SuggestedValue << "'?"; + Buffer.append({"; did you mean '", *SuggestedValue, "'?"}); return std::string(Buffer); } std::string UnparseableIntegerOptionError::message() const { - llvm::SmallString<128> Buffer; - llvm::raw_svector_ostream Output(Buffer); - Output << "invalid configuration value '" << LookupValue << "' for option '" - << LookupName << "'; expected " - << (IsBoolean ? "a bool" : "an integer value"); + llvm::SmallString<256> Buffer({"invalid configuration value '", LookupValue, + "' for option '", LookupName, "'; expected ", + (IsBoolean ? "a bool" : "an integer value")}); return std::string(Buffer); } ClangTidyCheck::ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context) : CheckName(CheckName), Context(Context), - Options(CheckName, Context->getOptions().CheckOptions) { + Options(CheckName, Context->getOptions().CheckOptions, Context) { assert(Context != nullptr); assert(!CheckName.empty()); } @@ -58,6 +52,17 @@ DiagnosticBuilder ClangTidyCheck::diag(SourceLocation Loc, StringRef Message, return Context->diag(CheckName, Loc, Message, Level); } +DiagnosticBuilder ClangTidyCheck::diag(StringRef Message, + DiagnosticIDs::Level Level) { + return Context->diag(CheckName, Message, Level); +} + +DiagnosticBuilder +ClangTidyCheck::configurationDiag(StringRef Description, + DiagnosticIDs::Level Level) { + return Context->configurationDiag(Description, Level); +} + void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) { // For historical reasons, checks don't implement the MatchFinder run() // callback directly. We keep the run()/check() distinction to avoid interface @@ -65,9 +70,11 @@ void ClangTidyCheck::run(const ast_matchers::MatchFinder::MatchResult &Result) { check(Result); } -ClangTidyCheck::OptionsView::OptionsView(StringRef CheckName, - const ClangTidyOptions::OptionMap &CheckOptions) - : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {} +ClangTidyCheck::OptionsView::OptionsView( + StringRef CheckName, const ClangTidyOptions::OptionMap &CheckOptions, + ClangTidyContext *Context) + : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions), + Context(Context) {} llvm::Expected ClangTidyCheck::OptionsView::get(StringRef LocalName) const { @@ -127,7 +134,7 @@ bool ClangTidyCheck::OptionsView::get(StringRef LocalName, llvm::Expected ValueOr = get(LocalName); if (ValueOr) return *ValueOr; - logIfOptionParsingError(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } @@ -146,7 +153,7 @@ bool ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName, llvm::Expected ValueOr = getLocalOrGlobal(LocalName); if (ValueOr) return *ValueOr; - logIfOptionParsingError(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } @@ -205,11 +212,11 @@ llvm::Expected ClangTidyCheck::OptionsView::getEnumInt( Iter->getValue().Value); } -void ClangTidyCheck::OptionsView::logIfOptionParsingError(llvm::Error &&Err) { +void ClangTidyCheck::OptionsView::reportOptionParsingError( + llvm::Error &&Err) const { if (auto RemainingErrors = llvm::handleErrors(std::move(Err), [](const MissingOptionError &) {})) - llvm::logAllUnhandledErrors(std::move(RemainingErrors), - llvm::WithColor::warning()); + Context->configurationDiag(llvm::toString(std::move(RemainingErrors))); } template <> diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.h b/clang-tools-extra/clang-tidy/ClangTidyCheck.h index 6237e216656beea93dfb81a3328db014f7145853..9fa0d63286409102bfa22f3c8c8986790e4ac010 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.h +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.h @@ -176,6 +176,15 @@ public: DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + /// Add a diagnostic with the check's name. + DiagnosticBuilder diag(StringRef Description, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + + /// Adds a diagnostic to report errors in the check's configuration. + DiagnosticBuilder + configurationDiag(StringRef Description, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + /// Should store all options supported by this check with their /// current values or default values for options that haven't been overridden. /// @@ -192,7 +201,8 @@ public: public: /// Initializes the instance using \p CheckName + "." as a prefix. OptionsView(StringRef CheckName, - const ClangTidyOptions::OptionMap &CheckOptions); + const ClangTidyOptions::OptionMap &CheckOptions, + ClangTidyContext *Context); /// Read a named option from the ``Context``. /// @@ -268,7 +278,7 @@ public: if (llvm::Expected ValueOr = get(LocalName)) return *ValueOr; else - logIfOptionParsingError(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } @@ -314,7 +324,7 @@ public: if (llvm::Expected ValueOr = getLocalOrGlobal(LocalName)) return *ValueOr; else - logIfOptionParsingError(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } @@ -353,7 +363,7 @@ public: if (auto ValueOr = get(LocalName, IgnoreCase)) return *ValueOr; else - logIfOptionParsingError(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } @@ -395,7 +405,7 @@ public: if (auto ValueOr = getLocalOrGlobal(LocalName, IgnoreCase)) return *ValueOr; else - logIfOptionParsingError(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return Default; } @@ -407,7 +417,7 @@ public: if (auto ValueOr = get(LocalName)) return *ValueOr; else - logIfOptionParsingError(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return llvm::None; } @@ -420,7 +430,7 @@ public: if (auto ValueOr = getLocalOrGlobal(LocalName)) return *ValueOr; else - logIfOptionParsingError(ValueOr.takeError()); + reportOptionParsingError(ValueOr.takeError()); return llvm::None; } @@ -481,11 +491,12 @@ public: void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName, int64_t Value) const; - /// Logs an Error to stderr if a \p Err is not a MissingOptionError. - static void logIfOptionParsingError(llvm::Error &&Err); + /// Emits a diagnostic if \p Err is not a MissingOptionError. + void reportOptionParsingError(llvm::Error &&Err) const; std::string NamePrefix; const ClangTidyOptions::OptionMap &CheckOptions; + ClangTidyContext *Context; }; private: diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp index e7b5b1db08ebb79a846b8a083471270560548847..2c3f51a4034eb7c531d8a2e80e2ed1bfbf281bea 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -177,6 +177,21 @@ DiagnosticBuilder ClangTidyContext::diag( return DiagEngine->Report(Loc, ID); } +DiagnosticBuilder ClangTidyContext::diag( + StringRef CheckName, StringRef Description, + DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) { + unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID( + Level, (Description + " [" + CheckName + "]").str()); + CheckNamesByDiagnosticID.try_emplace(ID, CheckName); + return DiagEngine->Report(ID); +} + +DiagnosticBuilder ClangTidyContext::configurationDiag( + StringRef Message, + DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) { + return diag("clang-tidy-config", Message, Level); +} + void ClangTidyContext::setSourceManager(SourceManager *SourceMgr) { DiagEngine->setSourceManager(SourceMgr); } @@ -256,8 +271,10 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer( void ClangTidyDiagnosticConsumer::finalizeLastError() { if (!Errors.empty()) { ClangTidyError &Error = Errors.back(); - if (!Context.isCheckEnabled(Error.DiagnosticName) && - Error.DiagLevel != ClangTidyError::Error) { + if (Error.DiagnosticName == "clang-tidy-config") { + // Never ignore these. + } else if (!Context.isCheckEnabled(Error.DiagnosticName) && + Error.DiagLevel != ClangTidyError::Error) { ++Context.Stats.ErrorsIgnoredCheckFilter; Errors.pop_back(); } else if (!LastErrorRelatesToUserCode) { diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h index eaa7f1851ce323380295bfb61210048c99a95189..079293149e90ffdfde186f5af42ed48e0db1c429 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h @@ -96,6 +96,14 @@ public: StringRef Message, DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + DiagnosticBuilder diag(StringRef CheckName, StringRef Message, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + + /// Report any errors to do with reading the configuration using this method. + DiagnosticBuilder + configurationDiag(StringRef Message, + DiagnosticIDs::Level Level = DiagnosticIDs::Warning); + /// Sets the \c SourceManager of the used \c DiagnosticsEngine. /// /// This is called from the \c ClangTidyCheck base class. diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp index 950a64f4c274929183d74d0d05e783068d07f16b..f17ef716d60f6b58f9d15ba13891caf349f5af1f 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -195,14 +195,13 @@ DefaultOptionsProvider::getRawOptions(llvm::StringRef FileName) { } ConfigOptionsProvider::ConfigOptionsProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &ConfigOptions, - const ClangTidyOptions &OverrideOptions, + ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, + ClangTidyOptions ConfigOptions, ClangTidyOptions OverrideOptions, llvm::IntrusiveRefCntPtr FS) - : FileOptionsBaseProvider(GlobalOptions, DefaultOptions, OverrideOptions, - FS), - ConfigOptions(ConfigOptions) {} + : FileOptionsBaseProvider(std::move(GlobalOptions), + std::move(DefaultOptions), + std::move(OverrideOptions), std::move(FS)), + ConfigOptions(std::move(ConfigOptions)) {} std::vector ConfigOptionsProvider::getRawOptions(llvm::StringRef FileName) { @@ -227,24 +226,25 @@ ConfigOptionsProvider::getRawOptions(llvm::StringRef FileName) { } FileOptionsBaseProvider::FileOptionsBaseProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, + ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, llvm::IntrusiveRefCntPtr VFS) - : DefaultOptionsProvider(GlobalOptions, DefaultOptions), - OverrideOptions(OverrideOptions), FS(std::move(VFS)) { + : DefaultOptionsProvider(std::move(GlobalOptions), + std::move(DefaultOptions)), + OverrideOptions(std::move(OverrideOptions)), FS(std::move(VFS)) { if (!FS) FS = llvm::vfs::getRealFileSystem(); ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration); } FileOptionsBaseProvider::FileOptionsBaseProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, - const FileOptionsBaseProvider::ConfigFileHandlers &ConfigHandlers) - : DefaultOptionsProvider(GlobalOptions, DefaultOptions), - OverrideOptions(OverrideOptions), ConfigHandlers(ConfigHandlers) {} + ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, + FileOptionsBaseProvider::ConfigFileHandlers ConfigHandlers) + : DefaultOptionsProvider(std::move(GlobalOptions), + std::move(DefaultOptions)), + OverrideOptions(std::move(OverrideOptions)), + ConfigHandlers(std::move(ConfigHandlers)) {} void FileOptionsBaseProvider::addRawFileOptions( llvm::StringRef AbsolutePath, std::vector &CurOptions) { @@ -286,20 +286,20 @@ void FileOptionsBaseProvider::addRawFileOptions( } FileOptionsProvider::FileOptionsProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, + ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, llvm::IntrusiveRefCntPtr VFS) - : FileOptionsBaseProvider(GlobalOptions, DefaultOptions, OverrideOptions, - VFS){} + : FileOptionsBaseProvider(std::move(GlobalOptions), + std::move(DefaultOptions), + std::move(OverrideOptions), std::move(VFS)) {} FileOptionsProvider::FileOptionsProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, - const FileOptionsBaseProvider::ConfigFileHandlers &ConfigHandlers) - : FileOptionsBaseProvider(GlobalOptions, DefaultOptions, OverrideOptions, - ConfigHandlers) {} + ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, + FileOptionsBaseProvider::ConfigFileHandlers ConfigHandlers) + : FileOptionsBaseProvider( + std::move(GlobalOptions), std::move(DefaultOptions), + std::move(OverrideOptions), std::move(ConfigHandlers)) {} // FIXME: This method has some common logic with clang::format::getStyle(). // Consider pulling out common bits to a findParentFileWithName function or @@ -360,7 +360,7 @@ FileOptionsBaseProvider::tryReadConfigFile(StringRef Directory) { if ((*Text)->getBuffer().empty()) continue; llvm::ErrorOr ParsedOptions = - ConfigHandler.second((*Text)->getBuffer()); + ConfigHandler.second({(*Text)->getBuffer(), ConfigFile}); if (!ParsedOptions) { if (ParsedOptions.getError()) llvm::errs() << "Error parsing " << ConfigFile << ": " @@ -380,7 +380,8 @@ std::error_code parseLineFilter(StringRef LineFilter, return Input.error(); } -llvm::ErrorOr parseConfiguration(StringRef Config) { +llvm::ErrorOr +parseConfiguration(llvm::MemoryBufferRef Config) { llvm::yaml::Input Input(Config); ClangTidyOptions Options; Input >> Options; diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h index 11c2e652a4d704f7993655ac7e576b5b2c87ff25..e7cd89951ff93118147eb5b215398dc0eb1dbc37 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h @@ -173,9 +173,10 @@ public: /// returns the same options for all files. class DefaultOptionsProvider : public ClangTidyOptionsProvider { public: - DefaultOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &Options) - : GlobalOptions(GlobalOptions), DefaultOptions(Options) {} + DefaultOptionsProvider(ClangTidyGlobalOptions GlobalOptions, + ClangTidyOptions Options) + : GlobalOptions(std::move(GlobalOptions)), + DefaultOptions(std::move(Options)) {} const ClangTidyGlobalOptions &getGlobalOptions() override { return GlobalOptions; } @@ -187,11 +188,11 @@ private: }; class FileOptionsBaseProvider : public DefaultOptionsProvider { -public: +protected: // A pair of configuration file base name and a function parsing // configuration from text in the corresponding format. typedef std::pair( - llvm::StringRef)>> + llvm::MemoryBufferRef)>> ConfigFileHandler; /// Configuration file handlers listed in the order of priority. @@ -213,16 +214,15 @@ public: /// take precedence over ".clang-tidy" if both reside in the same directory. typedef std::vector ConfigFileHandlers; - FileOptionsBaseProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, - llvm::IntrusiveRefCntPtr FS = nullptr); + FileOptionsBaseProvider(ClangTidyGlobalOptions GlobalOptions, + ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, + llvm::IntrusiveRefCntPtr FS); - FileOptionsBaseProvider(const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, - const ConfigFileHandlers &ConfigHandlers); + FileOptionsBaseProvider(ClangTidyGlobalOptions GlobalOptions, + ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, + ConfigFileHandlers ConfigHandlers); protected: void addRawFileOptions(llvm::StringRef AbsolutePath, @@ -243,10 +243,8 @@ protected: class ConfigOptionsProvider : public FileOptionsBaseProvider { public: ConfigOptionsProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &ConfigOptions, - const ClangTidyOptions &OverrideOptions, + ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, + ClangTidyOptions ConfigOptions, ClangTidyOptions OverrideOptions, llvm::IntrusiveRefCntPtr FS = nullptr); std::vector getRawOptions(llvm::StringRef FileName) override; @@ -275,9 +273,8 @@ public: /// If any of the \param OverrideOptions fields are set, they will override /// whatever options are read from the configuration file. FileOptionsProvider( - const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, + ClangTidyGlobalOptions GlobalOptions, ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, llvm::IntrusiveRefCntPtr FS = nullptr); /// Initializes the \c FileOptionsProvider instance with a custom set @@ -297,10 +294,10 @@ public: /// that can parse configuration from this file type. The configuration files /// in each directory are searched for in the order of appearance in /// \p ConfigHandlers. - FileOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions, - const ClangTidyOptions &DefaultOptions, - const ClangTidyOptions &OverrideOptions, - const ConfigFileHandlers &ConfigHandlers); + FileOptionsProvider(ClangTidyGlobalOptions GlobalOptions, + ClangTidyOptions DefaultOptions, + ClangTidyOptions OverrideOptions, + ConfigFileHandlers ConfigHandlers); std::vector getRawOptions(llvm::StringRef FileName) override; }; @@ -311,7 +308,8 @@ std::error_code parseLineFilter(llvm::StringRef LineFilter, /// Parses configuration from JSON and returns \c ClangTidyOptions or an /// error. -llvm::ErrorOr parseConfiguration(llvm::StringRef Config); +llvm::ErrorOr +parseConfiguration(llvm::MemoryBufferRef Config); /// Serializes configuration to a YAML-encoded string. std::string configurationAsText(const ClangTidyOptions &Options); diff --git a/clang-tools-extra/clang-tidy/GlobList.cpp b/clang-tools-extra/clang-tidy/GlobList.cpp index 88e6ea22d675c72ab05308fa60a7681779207c5b..5b70b8d8c57718017ceebededcf77adc23859f83 100644 --- a/clang-tools-extra/clang-tidy/GlobList.cpp +++ b/clang-tools-extra/clang-tidy/GlobList.cpp @@ -52,7 +52,7 @@ GlobList::GlobList(StringRef Globs) { } while (!Globs.empty()); } -bool GlobList::contains(StringRef S) { +bool GlobList::contains(StringRef S) const { // Iterating the container backwards as the last match determins if S is in // the list. for (const GlobListItem &Item : llvm::reverse(Items)) { diff --git a/clang-tools-extra/clang-tidy/GlobList.h b/clang-tools-extra/clang-tidy/GlobList.h index 5acb6a5b878cbbb585cfc7be98423f51cfa5033e..fe68a3497c92ab3905350349ebe092c17f5d36fd 100644 --- a/clang-tools-extra/clang-tidy/GlobList.h +++ b/clang-tools-extra/clang-tidy/GlobList.h @@ -33,7 +33,7 @@ public: /// Returns \c true if the pattern matches \p S. The result is the last /// matching glob's Positive flag. - bool contains(StringRef S); + bool contains(StringRef S) const; private: diff --git a/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp b/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp index ab55dd7f9019e72676a329abd498be74214b3041..5ded02a2097b4d4df8ad74f662ba6f93e589f5ad 100644 --- a/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp @@ -21,7 +21,7 @@ void DurationDivisionCheck::registerMatchers(MatchFinder *finder) { const auto DurationExpr = expr(hasType(cxxRecordDecl(hasName("::absl::Duration")))); finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, implicitCastExpr( hasSourceExpression(ignoringParenCasts( cxxOperatorCallExpr(hasOverloadedOperatorName("/"), diff --git a/clang-tools-extra/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp b/clang-tools-extra/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp index ef260d9b1f6b8ba1a5c26eaf2a5f7bb6b06e49a6..efb3faa7cff87d0cf1e0b1de56b559f89cc7cc0d 100644 --- a/clang-tools-extra/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp @@ -79,7 +79,7 @@ void FasterStrsplitDelimiterCheck::registerMatchers(MatchFinder *Finder) { // Find uses of absl::StrSplit(..., "x") and absl::StrSplit(..., // absl::ByAnyChar("x")) to transform them into absl::StrSplit(..., 'x'). Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, callExpr(callee(functionDecl(hasName("::absl::StrSplit"))), hasArgument(1, anyOf(ByAnyCharArg, SingleChar)), unless(isInTemplateInstantiation())) @@ -90,7 +90,7 @@ void FasterStrsplitDelimiterCheck::registerMatchers(MatchFinder *Finder) { // absl::MaxSplits(absl::ByAnyChar("x"), N) to transform them into // absl::MaxSplits('x', N). Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, callExpr(callee(functionDecl(hasName("::absl::MaxSplits"))), hasArgument(0, anyOf(ByAnyCharArg, ignoringParenCasts(SingleChar))), diff --git a/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp b/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp index be3fa9a5628b4ee71094a7aa048e06218a3e422e..abcf570abc6efd4c2fd677f23af71ac8ada64dc5 100644 --- a/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp @@ -68,7 +68,7 @@ const clang::CallExpr* ProcessArgument(const Expr* Arg, has(callExpr(callee(functionDecl(*Strcat))).bind("StrCat"))); if (const auto *SubStrcatCall = selectFirst( "StrCat", - match(stmt(traverse(ast_type_traits::TK_AsIs, + match(stmt(traverse(TK_AsIs, anyOf(cxxConstructExpr(IsAlphanum, hasArgument(0, IsStrcat)), IsStrcat))), diff --git a/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp index 7aaf976a9c5886c6e03018650273f2552fc4e54c..a2586beac387910f7c17ece4aa26317c72e3cd36 100644 --- a/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp @@ -58,7 +58,7 @@ void StrCatAppendCheck::registerMatchers(MatchFinder *Finder) { // StrCat on the RHS. The first argument of the StrCat call should be the same // as the LHS. Ignore calls from template instantiations. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxOperatorCallExpr( unless(isInTemplateInstantiation()), hasOverloadedOperatorName("="), diff --git a/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp index 87af9ea6cd5ac370ebccae5c92165783db8464ea..977c1919cee3a3c82d7a7d090a94990cf7fd99a3 100644 --- a/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp @@ -29,6 +29,9 @@ using ::clang::transformer::cat; using ::clang::transformer::change; using ::clang::transformer::makeRule; using ::clang::transformer::node; +using ::clang::transformer::RewriteRule; + +AST_MATCHER(Type, isCharType) { return Node.isCharType(); } static const char DefaultStringLikeClasses[] = "::std::basic_string;" "::std::basic_string_view;" @@ -57,19 +60,21 @@ MakeRule(const LangOptions &LangOpts, hasUnqualifiedDesugaredType(recordType(hasDeclaration(StringLikeClass))); auto CharStarType = hasUnqualifiedDesugaredType(pointerType(pointee(isAnyCharacter()))); + auto CharType = hasUnqualifiedDesugaredType(isCharType()); auto StringNpos = declRefExpr( to(varDecl(hasName("npos"), hasDeclContext(StringLikeClass)))); auto StringFind = cxxMemberCallExpr( callee(cxxMethodDecl( hasName("find"), - hasParameter(0, parmVarDecl(anyOf(hasType(StringType), - hasType(CharStarType)))))), + hasParameter( + 0, parmVarDecl(anyOf(hasType(StringType), hasType(CharStarType), + hasType(CharType)))))), on(hasType(StringType)), hasArgument(0, expr().bind("parameter_to_find")), anyOf(hasArgument(1, integerLiteral(equals(0))), hasArgument(1, cxxDefaultArgExpr())), onImplicitObjectArgument(expr().bind("string_being_searched"))); - tooling::RewriteRule rule = applyFirst( + RewriteRule rule = applyFirst( {makeRule(binaryOperator(hasOperatorName("=="), hasOperands(ignoringParenImpCasts(StringNpos), ignoringParenImpCasts(StringFind))), diff --git a/clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp b/clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp index 4d28d1242f25c65fd1d99d277e0bb45f608ab28f..208d1df27763716232af709826f726323519c074 100644 --- a/clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp @@ -100,17 +100,16 @@ void UpgradeDurationConversionsCheck::registerMatchers(MatchFinder *Finder) { // `absl::Hours(x)` // where `x` is not of a built-in type. Finder->addMatcher( - traverse( - ast_type_traits::TK_AsIs, - implicitCastExpr(anyOf(hasCastKind(CK_UserDefinedConversion), - has(implicitCastExpr( - hasCastKind(CK_UserDefinedConversion)))), - hasParent(callExpr( - callee(functionDecl( - DurationFactoryFunction(), - unless(hasParent(functionTemplateDecl())))), - hasArgument(0, expr().bind("arg"))))) - .bind("OuterExpr")), + traverse(TK_AsIs, implicitCastExpr( + anyOf(hasCastKind(CK_UserDefinedConversion), + has(implicitCastExpr( + hasCastKind(CK_UserDefinedConversion)))), + hasParent(callExpr( + callee(functionDecl( + DurationFactoryFunction(), + unless(hasParent(functionTemplateDecl())))), + hasArgument(0, expr().bind("arg"))))) + .bind("OuterExpr")), this); } @@ -120,7 +119,7 @@ void UpgradeDurationConversionsCheck::check( "implicit conversion to 'int64_t' is deprecated in this context; use an " "explicit cast instead"; - TraversalKindScope RAII(*Result.Context, ast_type_traits::TK_AsIs); + TraversalKindScope RAII(*Result.Context, TK_AsIs); const auto *ArgExpr = Result.Nodes.getNodeAs("arg"); SourceLocation Loc = ArgExpr->getBeginLoc(); diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp index 5cb55639db7852c4ce9487788559455a86326111..8f7d1d1237e9235040055089424365e6160a07ea 100644 --- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp @@ -84,8 +84,7 @@ void AssertSideEffectCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void AssertSideEffectCheck::registerMatchers(MatchFinder *Finder) { auto DescendantWithSideEffect = - traverse(ast_type_traits::TK_AsIs, - hasDescendant(expr(hasSideEffect(CheckFunctionCalls)))); + traverse(TK_AsIs, hasDescendant(expr(hasSideEffect(CheckFunctionCalls)))); auto ConditionWithSideEffect = hasCondition(DescendantWithSideEffect); Finder->addMatcher( stmt( diff --git a/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp index 17dab1b0f73e3a90a8654ddf5209a14b9729966f..8aae92e40558336c4ccf9a8fa5abe9b5a1a196b3 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp @@ -19,7 +19,7 @@ void BoolPointerImplicitConversionCheck::registerMatchers(MatchFinder *Finder) { // condition. Filter negations. Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, ifStmt( hasCondition(findAll(implicitCastExpr( unless(hasParent(unaryOperator(hasOperatorName("!")))), diff --git a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp index 5f771e49f808ca8625e91c71fbe29040aef44f78..ae91533a7c9e2cab85ea2ce3403385e405e6ca58 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp @@ -117,7 +117,7 @@ void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) { // Find 'Handle foo = ReturnsAValue();' Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, varDecl(hasType(hasUnqualifiedDesugaredType(recordType( hasDeclaration(cxxRecordDecl(IsAHandle))))), unless(parmVarDecl()), @@ -128,7 +128,7 @@ void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) { this); // Find 'foo = ReturnsAValue(); // foo is Handle' Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxOperatorCallExpr(callee(cxxMethodDecl(ofClass(IsAHandle))), hasOverloadedOperatorName("="), hasArgument(1, ConvertedHandle)) @@ -136,16 +136,16 @@ void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) { this); // Container insertions that will dangle. - Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, - makeContainerMatcher(IsAHandle).bind("bad_stmt")), - this); + Finder->addMatcher( + traverse(TK_AsIs, makeContainerMatcher(IsAHandle).bind("bad_stmt")), + this); } void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) { // Return a local. Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, returnStmt( // The AST contains two constructor calls: // 1. Value to Handle conversion. @@ -170,7 +170,7 @@ void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) { // Return a temporary. Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, returnStmt(has(exprWithCleanups(has(ignoringParenImpCasts(handleFrom( IsAHandle, handleFromTemporaryValue(IsAHandle))))))) .bind("bad_stmt")), diff --git a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp index 2d3f1755d9880733a3da652bd682929e7ab19146..30842486975743c8598f87ff950c26860bdbe251 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp @@ -34,8 +34,8 @@ DynamicStaticInitializersCheck::DynamicStaticInitializersCheck(StringRef Name, if (!utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions, utils::defaultFileExtensionDelimiters())) { - llvm::errs() << "Invalid header file extension: " - << RawStringHeaderFileExtensions << "\n"; + this->configurationDiag("Invalid header file extension: '%0'") + << RawStringHeaderFileExtensions; } } diff --git a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp index 19e91b44b41afdc339d0a16e576895919c217146..8e5a532801839ae773aa9b64704ba156b9df947b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp @@ -33,7 +33,7 @@ void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) { tagType(hasDeclaration(decl(isInStdNamespace()))))); Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxMemberCallExpr( on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))), callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1), diff --git a/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp index 7b0682b31eb795882ec71190176cfb5dc9ab047d..500210748f52b6b45bc8028fb06de424cfe95297 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp @@ -51,7 +51,7 @@ void IncorrectRoundingsCheck::registerMatchers(MatchFinder *MatchFinder) { // Find expressions of cast to int of the sum of a floating point expression // and 0.5. MatchFinder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, implicitCastExpr(hasImplicitDestinationType(isInteger()), ignoringParenCasts(binaryOperator( hasOperatorName("+"), OneSideHalf))) diff --git a/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp index 9214a7da2729725c6fb06ac29ebaa58c9b66ae4b..f68c2f823ba8e874811190b02786c3ca17c13911 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp @@ -30,7 +30,7 @@ void IntegerDivisionCheck::registerMatchers(MatchFinder *Finder) { callExpr(IntType), explicitCastExpr(IntType), UnaryOperators); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, binaryOperator( hasOperatorName("/"), hasLHS(expr(IntType)), hasRHS(expr(IntType)), diff --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp index 7c8c26370118fb2730fba794b02bf7be90a712df..beecfa6be99a0274d933a8959d1a3b095c21b6fa 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp @@ -55,19 +55,17 @@ void MisplacedOperatorInStrlenInAllocCheck::registerMatchers( declRefExpr(hasDeclaration(Alloc1Func))))); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, - callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))), - hasArgument(0, BadArg)) - .bind("Alloc")), + traverse(TK_AsIs, callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))), + hasArgument(0, BadArg)) + .bind("Alloc")), this); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, - callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))), - hasArgument(1, BadArg)) - .bind("Alloc")), + traverse(TK_AsIs, callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))), + hasArgument(1, BadArg)) + .bind("Alloc")), this); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc")), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp index 13f0e41a7a3e4981f236ada69e7fc5f93b2a80e9..65fa31e580ff8d2e3bf7414ff11ddaa3432c53f8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp @@ -40,8 +40,7 @@ void MisplacedWideningCastCheck::registerMatchers(MatchFinder *Finder) { implicitCastExpr(hasImplicitDestinationType(isInteger()), has(ignoringParenImpCasts(Calc))); const auto Cast = - traverse(ast_type_traits::TK_AsIs, - expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast")); + traverse(TK_AsIs, expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast")); Finder->addMatcher(varDecl(hasInitializer(Cast)), this); Finder->addMatcher(returnStmt(hasReturnValue(Cast)), this); diff --git a/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp index cfe556e5561077a4b6e1cc005b844dc6d4a96bb6..6b8b7fc7ffc54e009e6ab11e076bd5a8d4648a54 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp @@ -84,7 +84,7 @@ static std::string getExprAsString(const clang::Expr &E, void ParentVirtualCallCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxMemberCallExpr( callee(memberExpr(hasDescendant(implicitCastExpr( hasImplicitDestinationType(pointsTo( diff --git a/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp index abb8e8be9b2f850f0cd799a0e2b154f7cf4750c1..2b0d9630527b4526da2711b538cfffb95169208d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp @@ -23,15 +23,21 @@ namespace bugprone { static const char CondVarStr[] = "cond_var"; static const char OuterIfStr[] = "outer_if"; static const char InnerIfStr[] = "inner_if"; +static const char OuterIfVar1Str[] = "outer_if_var1"; +static const char OuterIfVar2Str[] = "outer_if_var2"; +static const char InnerIfVar1Str[] = "inner_if_var1"; +static const char InnerIfVar2Str[] = "inner_if_var2"; static const char FuncStr[] = "func"; -/// Returns whether `Var` is changed in `S` before `NextS`. -static bool isChangedBefore(const Stmt *S, const Stmt *NextS, +/// Returns whether `Var` is changed in range (`PrevS`..`NextS`). +static bool isChangedBefore(const Stmt *S, const Stmt *NextS, const Stmt *PrevS, const VarDecl *Var, ASTContext *Context) { ExprMutationAnalyzer MutAn(*S, *Context); const auto &SM = Context->getSourceManager(); const Stmt *MutS = MutAn.findMutation(Var); return MutS && + SM.isBeforeInTranslationUnit(PrevS->getEndLoc(), + MutS->getBeginLoc()) && SM.isBeforeInTranslationUnit(MutS->getEndLoc(), NextS->getBeginLoc()); } @@ -43,19 +49,22 @@ void RedundantBranchConditionCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( ifStmt( hasCondition(ignoringParenImpCasts(anyOf( - declRefExpr(hasDeclaration(ImmutableVar)), + declRefExpr(hasDeclaration(ImmutableVar)).bind(OuterIfVar1Str), binaryOperator(hasOperatorName("&&"), - hasEitherOperand(ignoringParenImpCasts(declRefExpr( - hasDeclaration(ImmutableVar)))))))), + hasEitherOperand(ignoringParenImpCasts( + declRefExpr(hasDeclaration(ImmutableVar)) + .bind(OuterIfVar2Str))))))), hasThen(hasDescendant( ifStmt(hasCondition(ignoringParenImpCasts( - anyOf(declRefExpr(hasDeclaration( - varDecl(equalsBoundNode(CondVarStr)))), + anyOf(declRefExpr(hasDeclaration(varDecl( + equalsBoundNode(CondVarStr)))) + .bind(InnerIfVar1Str), binaryOperator( hasAnyOperatorName("&&", "||"), hasEitherOperand(ignoringParenImpCasts( declRefExpr(hasDeclaration(varDecl( - equalsBoundNode(CondVarStr))))))))))) + equalsBoundNode(CondVarStr)))) + .bind(InnerIfVar2Str)))))))) .bind(InnerIfStr))), forFunction(functionDecl().bind(FuncStr))) .bind(OuterIfStr), @@ -69,15 +78,32 @@ void RedundantBranchConditionCheck::check(const MatchFinder::MatchResult &Result const auto *CondVar = Result.Nodes.getNodeAs(CondVarStr); const auto *Func = Result.Nodes.getNodeAs(FuncStr); + const DeclRefExpr *OuterIfVar, *InnerIfVar; + if (const auto *Inner = Result.Nodes.getNodeAs(InnerIfVar1Str)) + InnerIfVar = Inner; + else + InnerIfVar = Result.Nodes.getNodeAs(InnerIfVar2Str); + if (const auto *Outer = Result.Nodes.getNodeAs(OuterIfVar1Str)) + OuterIfVar = Outer; + else + OuterIfVar = Result.Nodes.getNodeAs(OuterIfVar2Str); + + if (OuterIfVar && InnerIfVar) { + if (isChangedBefore(OuterIf->getThen(), InnerIfVar, OuterIfVar, CondVar, + Result.Context)) + return; + + if (isChangedBefore(OuterIf->getCond(), InnerIfVar, OuterIfVar, CondVar, + Result.Context)) + return; + } + // If the variable has an alias then it can be changed by that alias as well. // FIXME: could potentially support tracking pointers and references in the // future to improve catching true positives through aliases. if (hasPtrOrReferenceInFunc(Func, CondVar)) return; - if (isChangedBefore(OuterIf->getThen(), InnerIf, CondVar, Result.Context)) - return; - auto Diag = diag(InnerIf->getBeginLoc(), "redundant condition %0") << CondVar; // For standalone condition variables and for "or" binary operations we simply @@ -123,7 +149,7 @@ void RedundantBranchConditionCheck::check(const MatchFinder::MatchResult &Result CharSourceRange::getTokenRange(IfBegin, IfEnd)); } - // For comound statements also remove the right brace at the end. + // For compound statements also remove the right brace at the end. if (isa(Body)) Diag << FixItHint::CreateRemoval( CharSourceRange::getTokenRange(Body->getEndLoc(), Body->getEndLoc())); diff --git a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp index 555f8e11dff94b97c105112e8bf2c5ad7dcf1aac..e9d97383cd61e0d137ff2b8f98048043f9da975b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp @@ -70,9 +70,8 @@ BindableMatcher SignedCharMisuseCheck::charCastExpression( // We catch any type of casts to an integer. We need to have these cast // expressions explicitly to catch only those casts which are direct children // of the checked expressions. (e.g. assignment, declaration). - return traverse(ast_type_traits::TK_AsIs, - expr(anyOf(ImplicitCastExpr, CStyleCastExpr, StaticCastExpr, - FunctionalCastExpr))); + return traverse(TK_AsIs, expr(anyOf(ImplicitCastExpr, CStyleCastExpr, + StaticCastExpr, FunctionalCastExpr))); } void SignedCharMisuseCheck::registerMatchers(MatchFinder *Finder) { @@ -84,14 +83,14 @@ void SignedCharMisuseCheck::registerMatchers(MatchFinder *Finder) { const auto UnSignedCharCastExpr = charCastExpression(false, IntegerType, "unsignedCastExpression"); - // Catch assignments with singed char -> integer conversion. + // Catch assignments with signed char -> integer conversion. const auto AssignmentOperatorExpr = expr(binaryOperator(hasOperatorName("="), hasLHS(hasType(IntegerType)), hasRHS(SignedCharCastExpr))); Finder->addMatcher(AssignmentOperatorExpr, this); - // Catch declarations with singed char -> integer conversion. + // Catch declarations with signed char -> integer conversion. const auto Declaration = varDecl(isDefinition(), hasType(IntegerType), hasInitializer(SignedCharCastExpr)); diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp index 80004f91c0692d7ca10cb4eb9ac9c734b42b7911..a3e5c0e26d1727825406f8c76a7f2be0d525f98a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp @@ -46,15 +46,15 @@ SuspiciousIncludeCheck::SuspiciousIncludeCheck(StringRef Name, if (!utils::parseFileExtensions(RawStringImplementationFileExtensions, ImplementationFileExtensions, utils::defaultFileExtensionDelimiters())) { - llvm::errs() << "Invalid implementation file extension: " - << RawStringImplementationFileExtensions << "\n"; + this->configurationDiag("Invalid implementation file extension: '%0'") + << RawStringImplementationFileExtensions; } if (!utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions, utils::defaultFileExtensionDelimiters())) { - llvm::errs() << "Invalid header file extension: " - << RawStringHeaderFileExtensions << "\n"; + this->configurationDiag("Invalid header file extension: '%0'") + << RawStringHeaderFileExtensions; } } diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp index 3de6dfed6356a34c581a3570b6274b5eafcff355..8fd1abe03646e4a342df1236832a2799347efe36 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp @@ -23,7 +23,7 @@ bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx, // String literals surrounded by parentheses are assumed to be on purpose. // i.e.: const char* Array[] = { ("a" "b" "c"), "d", [...] }; - TraversalKindScope RAII(*Ctx, ast_type_traits::TK_AsIs); + TraversalKindScope RAII(*Ctx, TK_AsIs); auto Parents = Ctx->getParents(*Lit); if (Parents.size() == 1 && Parents[0].get() != nullptr) return true; diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp index b4def0f9aa9dbe7dea0998da6e9d20a5f230ac3d..b234c3d128edc9a9edb42f281e45b15843867dd4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp @@ -135,7 +135,7 @@ void SuspiciousStringCompareCheck::registerMatchers(MatchFinder *Finder) { // Detect suspicious cast to an inconsistant type (i.e. not integer type). Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, implicitCastExpr(unless(hasType(isInteger())), hasSourceExpression(StringCompareCallExpr)) .bind("invalid-conversion")), diff --git a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp index 06332af92e3780ef7133db407d3c466c18d84991..f5821fe3b616412d160ebfea7d24fd6341ee9b12 100644 --- a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp @@ -57,9 +57,8 @@ void TooSmallLoopVariableCheck::registerMatchers(MatchFinder *Finder) { .bind(LoopVarName); // We need to catch only those comparisons which contain any integer cast. - StatementMatcher LoopVarConversionMatcher = - traverse(ast_type_traits::TK_AsIs, - implicitCastExpr(hasImplicitDestinationType(isInteger()), + StatementMatcher LoopVarConversionMatcher = traverse( + TK_AsIs, implicitCastExpr(hasImplicitDestinationType(isInteger()), has(ignoringParenImpCasts(LoopVarMatcher))) .bind(LoopVarCastName)); diff --git a/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp index 839bc71fa59499718907a980512a6467b4b32b56..76a7a5d0e6593ec0e733bfe2dadd352d6ff88c0d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp @@ -56,7 +56,7 @@ void UndelegatedConstructorCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, compoundStmt(hasParent(cxxConstructorDecl( ofClass(cxxRecordDecl().bind("parent")))), forEach(ignoringTemporaryExpr( diff --git a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp index 1f1158f0479f87854ed70a18c795792774bfc459..7539b51ebd12fa7fb2f1d6c64aa60401f42645a3 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp @@ -52,7 +52,7 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) { // In the non-template case, we can search for the copy constructor call. const auto HasNonTemplateSelfCopy = cxxMethodDecl( ofClass(cxxRecordDecl(unless(hasAncestor(classTemplateDecl())))), - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, hasDescendant(cxxConstructExpr(hasDeclaration(cxxConstructorDecl( isCopyConstructor(), ofClass(equalsBoundNode("class")))))))); diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp index 5e4a0ba6d56983bd1c053d108cae3f9c782af179..3a52180cf04d1ed19dd139a653e33dd1577b27ec 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp @@ -32,7 +32,7 @@ void UnusedRaiiCheck::registerMatchers(MatchFinder *Finder) { unless(has(ignoringParenImpCasts(objcMessageExpr())))) .bind("temp"); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, exprWithCleanups( unless(isInTemplateInstantiation()), hasParent(compoundStmt().bind("compound")), diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp index f65c02853a7369c440c2b0fb4ae68ffa5db1a814..9d08dbe1ead7bb4a465031d88808f1fb1f625efc 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -275,9 +275,8 @@ void UseAfterMoveFinder::getDeclRefs( unless(inDecltypeOrTemplateArg())) .bind("declref"); - addDeclRefs( - match(traverse(ast_type_traits::TK_AsIs, findAll(DeclRefMatcher)), - *S->getStmt(), *Context)); + addDeclRefs(match(traverse(TK_AsIs, findAll(DeclRefMatcher)), *S->getStmt(), + *Context)); addDeclRefs(match(findAll(cxxOperatorCallExpr( hasAnyOverloadedOperatorName("*", "->", "[]"), hasArgument(0, DeclRefMatcher)) @@ -342,7 +341,7 @@ void UseAfterMoveFinder::getReinits( // Passing variable to a function as a non-const lvalue reference // (unless that function is std::move()). callExpr(forEachArgumentWithParam( - traverse(ast_type_traits::TK_AsIs, DeclRefMatcher), + traverse(TK_AsIs, DeclRefMatcher), unless(parmVarDecl(hasType( references(qualType(isConstQualified())))))), unless(callee(functionDecl(hasName("::std::move"))))))) @@ -406,7 +405,7 @@ void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, // To find the Stmt that we assume performs the actual move, we look // for the direct ancestor of the std::move() that isn't one of the // node types ignored by ignoringParenImpCasts(). diff --git a/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp b/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp index 678e7408bf452098fd9b420d55f25ae28ed1a350..fa6e82c1c12b33a8e9a4e598ef221d21b95687df 100644 --- a/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp @@ -30,7 +30,7 @@ void MutatingCopyCheck::registerMatchers(MatchFinder *Finder) { MemberExprOrSourceObject); const auto IsSourceMutatingAssignment = traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, expr(anyOf(binaryOperator(isAssignmentOperator(), hasLHS(IsPartOfSource)) .bind(MutatingOperatorName), cxxOperatorCallExpr(isAssignmentOperator(), diff --git a/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp b/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp index 3fddbffeb1edf122bd9a20c9a160b3f5225a5ccb..1165eb9a38a56a8e861a71465af912132d5c10c0 100644 --- a/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp @@ -62,7 +62,7 @@ void ProperlySeededRandomGeneratorCheck::registerMatchers(MatchFinder *Finder) { // std::mt19937 engine(x); // ^ Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxConstructExpr(RandomGeneratorEngineTypeMatcher).bind("ctor")), this); diff --git a/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp b/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp index 9e255659bee7fc1fc4c73eecd2d4dd26dfc51b57..61ef166b66c2e1ea1d4e9f10daa451aa39685600 100644 --- a/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp @@ -22,7 +22,7 @@ void StaticObjectExceptionCheck::registerMatchers(MatchFinder *Finder) { // initializer that can throw. Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, varDecl( anyOf(hasThreadStorageDuration(), hasStaticStorageDuration()), unless(anyOf(isConstexpr(), hasType(cxxRecordDecl(isLambda())), diff --git a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp b/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp index 6a6aab7eaf6fda236e16ad53a2d6534a41fc0f48..6b2579bdfdb7dfc34f401ee0ae273e503dad40b2 100644 --- a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp @@ -20,7 +20,7 @@ namespace cert { void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxThrowExpr(has(ignoringParenImpCasts( cxxConstructExpr(hasDeclaration(cxxConstructorDecl( isCopyConstructor(), unless(isNoThrow())))) diff --git a/clang-tools-extra/clang-tidy/concurrency/CMakeLists.txt b/clang-tools-extra/clang-tidy/concurrency/CMakeLists.txt index df329662b0df52fdea59746b2a3be194072ab085..b757d6a60b782f5974e4c033cc6fec04c1aaa5e7 100644 --- a/clang-tools-extra/clang-tidy/concurrency/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/concurrency/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + FrontendOpenMP Support ) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp index fb19daf34172b2a93b5eda5e46e0ba9ba2f1b0a9..30a40cdd0370fbe7d74a714e16c9694e692eb3a8 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp @@ -27,12 +27,12 @@ void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) { const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration( varDecl(GlobalVarDecl, unless(isDefinition())).bind("referencee"))); - Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, - varDecl(GlobalVarDecl, isDefinition(), - hasInitializer(expr(hasDescendant( - ReferencesUndefinedGlobalVar)))) - .bind("var")), - this); + Finder->addMatcher( + traverse(TK_AsIs, varDecl(GlobalVarDecl, isDefinition(), + hasInitializer(expr(hasDescendant( + ReferencesUndefinedGlobalVar)))) + .bind("var")), + this); } void InterfacesGlobalInitCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp index 1837ccb6002f956efbdf905bca876b222f895b46..6819d6a4174f8547babda598d6d27f33a95913ee 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp @@ -46,28 +46,31 @@ void NarrowingConversionsCheck::registerMatchers(MatchFinder *Finder) { // i = 0.5; // void f(int); f(0.5); Finder->addMatcher( - traverse( - ast_type_traits::TK_AsIs, - implicitCastExpr(hasImplicitDestinationType(builtinType()), - hasSourceExpression(hasType(builtinType())), - unless(hasSourceExpression(IsCeilFloorCallExpr)), - unless(hasParent(castExpr())), - unless(isInTemplateInstantiation())) - .bind("cast")), + traverse(TK_AsIs, implicitCastExpr( + hasImplicitDestinationType( + hasUnqualifiedDesugaredType(builtinType())), + hasSourceExpression(hasType( + hasUnqualifiedDesugaredType(builtinType()))), + unless(hasSourceExpression(IsCeilFloorCallExpr)), + unless(hasParent(castExpr())), + unless(isInTemplateInstantiation())) + .bind("cast")), this); // Binary operators: // i += 0.5; - Finder->addMatcher(binaryOperator(isAssignmentOperator(), - hasLHS(expr(hasType(builtinType()))), - hasRHS(expr(hasType(builtinType()))), - unless(hasRHS(IsCeilFloorCallExpr)), - unless(isInTemplateInstantiation()), - // The `=` case generates an implicit cast - // which is covered by the previous matcher. - unless(hasOperatorName("="))) - .bind("binary_op"), - this); + Finder->addMatcher( + binaryOperator( + isAssignmentOperator(), + hasLHS(expr(hasType(hasUnqualifiedDesugaredType(builtinType())))), + hasRHS(expr(hasType(hasUnqualifiedDesugaredType(builtinType())))), + unless(hasRHS(IsCeilFloorCallExpr)), + unless(isInTemplateInstantiation()), + // The `=` case generates an implicit cast + // which is covered by the previous matcher. + unless(hasOperatorName("="))) + .bind("binary_op"), + this); } static const BuiltinType *getBuiltinType(const Expr &E) { diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp index 79c1b6ccd6152b55ffe8e2506570583484113f35..9e3f0883ccd9a00c06d3c112131a66e2344cda1a 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp @@ -69,7 +69,7 @@ void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) { // Find delete expressions that delete non-owners. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxDeleteExpr(hasDescendant(declRefExpr(unless(ConsideredOwner)) .bind("deleted_variable"))) .bind("delete_expr")), @@ -83,18 +83,17 @@ void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) { // resources. This check assumes that all pointer arguments of a legacy // functions shall be 'gsl::owner<>'. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, - callExpr(callee(LegacyOwnerConsumers), - hasAnyArgument( - expr(unless(ignoringImpCasts(ConsideredOwner)), - hasType(pointerType())))) - .bind("legacy_consumer")), + traverse(TK_AsIs, callExpr(callee(LegacyOwnerConsumers), + hasAnyArgument(expr( + unless(ignoringImpCasts(ConsideredOwner)), + hasType(pointerType())))) + .bind("legacy_consumer")), this); // Matching assignment to owners, with the rhs not being an owner nor creating // one. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, binaryOperator(isAssignmentOperator(), hasLHS(IsOwnerType), hasRHS(unless(ConsideredOwner))) .bind("owner_assignment")), @@ -102,7 +101,7 @@ void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) { // Matching initialization of owners with non-owners, nor creating owners. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, namedDecl( varDecl(hasInitializer(unless(ConsideredOwner)), IsOwnerType) .bind("owner_initialization"))), @@ -120,9 +119,9 @@ void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) { // Match class member initialization that expects owners, but does not get // them. - Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, - cxxRecordDecl(HasConstructorInitializerForOwner)), - this); + Finder->addMatcher( + traverse(TK_AsIs, cxxRecordDecl(HasConstructorInitializerForOwner)), + this); // Matching on assignment operations where the RHS is a newly created owner, // but the LHS is not an owner. @@ -136,7 +135,7 @@ void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) { // created owner, but the LHS is not an owner. Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, namedDecl( varDecl(eachOf(allOf(hasInitializer(CreatesOwner), unless(IsOwnerType)), diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp index bc0a3b98ac7a4c3b46452215fc768f7f4448a21e..2d7500943860176c48d8f54ffea1e25b73a8a065 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp @@ -97,7 +97,7 @@ PreferMemberInitializerCheck::PreferMemberInitializerCheck( IsUseDefaultMemberInitEnabled( Context->isCheckEnabled("modernize-use-default-member-init")), UseAssignment(OptionsView("modernize-use-default-member-init", - Context->getOptions().CheckOptions) + Context->getOptions().CheckOptions, Context) .get("UseAssignment", false)) {} void PreferMemberInitializerCheck::storeOptions( diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp index 2b80c0ba25d6888a4cc8c3e1304a7ecbb28357ca..160d15e6c0e1f364e1fb9d92345caf03ee6a830e 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp @@ -54,7 +54,7 @@ void ProBoundsArrayToPointerDecayCheck::registerMatchers(MatchFinder *Finder) { // 2) inside a range-for over an array // 3) if it converts a string literal to a pointer Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, implicitCastExpr( unless(hasParent(arraySubscriptExpr())), unless(hasParentIgnoringImpCasts(explicitCastExpr())), diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp index 62d752f299d35dd0fbb037f9c7f1fa7ca06ab242..93081133190f1eb6dc1f00659f735cb566d14515 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp @@ -62,11 +62,10 @@ void SlicingCheck::registerMatchers(MatchFinder *Finder) { // constructor in DerivedDecl's constructors. unless(IsWithinDerivedCtor)); - Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, - expr(anyOf(SlicesObjectInAssignment, SlicesObjectInCtor)) - .bind("Call")), - this); + Finder->addMatcher(traverse(TK_AsIs, expr(anyOf(SlicesObjectInAssignment, + SlicesObjectInCtor)) + .bind("Call")), + this); } /// Warns on methods overridden in DerivedDecl with respect to BaseDecl. diff --git a/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp index b76c9f5fb6b60867faf86c743d10f0d884fa791f..2ec53746fbab18b4fc1e57ae96a02b9eaaf624f0 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp @@ -26,10 +26,10 @@ AST_MATCHER(VarDecl, isGlobalStatic) { void StaticallyConstructedObjectsCheck::registerMatchers(MatchFinder *Finder) { // Constructing global, non-trivial objects with static storage is - // disallowed, unless the object is statically initialized with a constexpr + // disallowed, unless the object is statically initialized with a constexpr // constructor or has no explicit constructor. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, varDecl( // Match global, statically stored objects... isGlobalStatic(), diff --git a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp index 968adb882391c09950492a37b8fcbb7e11d41531..ae3738aa691e440d91a4f84a11d1537195da8c69 100644 --- a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp @@ -27,8 +27,8 @@ GlobalNamesInHeadersCheck::GlobalNamesInHeadersCheck(StringRef Name, if (!utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions, utils::defaultFileExtensionDelimiters())) { - llvm::errs() << "Invalid header file extension: " - << RawStringHeaderFileExtensions << "\n"; + this->configurationDiag("Invalid header file extension: '%0'") + << RawStringHeaderFileExtensions; } } diff --git a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp index fa1df281326c61d5fdf856a08f92a43f560d21e8..5037799a90b4e94a92f9ffe85072d95988b40669 100644 --- a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp @@ -26,8 +26,8 @@ UnnamedNamespaceInHeaderCheck::UnnamedNamespaceInHeaderCheck( if (!utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions, utils::defaultFileExtensionDelimiters())) { - llvm::errs() << "Invalid header file extension: " - << RawStringHeaderFileExtensions << "\n"; + this->configurationDiag("Invalid header file extension: '%0'") + << RawStringHeaderFileExtensions; } } diff --git a/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp b/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp index 13646ccbafa6d399900966e2ec38e4a70710430a..132178f892eaff3abdb2c6cd85b15824a7d2374a 100644 --- a/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp @@ -52,7 +52,7 @@ void PreferIsaOrDynCastInConditionalsCheck::registerMatchers( .bind("rhs"); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, stmt(anyOf( ifStmt(Any), whileStmt(Any), doStmt(Condition), binaryOperator( diff --git a/clang-tools-extra/clang-tidy/llvm/PreferRegisterOverUnsignedCheck.cpp b/clang-tools-extra/clang-tidy/llvm/PreferRegisterOverUnsignedCheck.cpp index 006c8df1b07cf4d5ff49f023ee96ed75812d7a8a..17e75abd724ce5a34ee6863c4c9ed9426ce0e2f4 100644 --- a/clang-tools-extra/clang-tidy/llvm/PreferRegisterOverUnsignedCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/PreferRegisterOverUnsignedCheck.cpp @@ -21,7 +21,7 @@ void PreferRegisterOverUnsignedCheck::registerMatchers(MatchFinder *Finder) { cxxRecordDecl(hasName("::llvm::Register")).bind("registerClassDecl")); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, valueDecl(allOf( hasType(qualType(isUnsignedInteger()).bind("varType")), varDecl(hasInitializer(exprWithCleanups( diff --git a/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp b/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp index 6b4618ea042c1d15c390fe57734018aeee818ba1..820bb3bebd9131e79c287d4a6771bfe49af29929 100644 --- a/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp @@ -36,10 +36,8 @@ DefinitionsInHeadersCheck::DefinitionsInHeadersCheck(StringRef Name, if (!utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions, utils::defaultFileExtensionDelimiters())) { - // FIXME: Find a more suitable way to handle invalid configuration - // options. - llvm::errs() << "Invalid header file extension: " - << RawStringHeaderFileExtensions << "\n"; + this->configurationDiag("Invalid header file extension: '%0'") + << RawStringHeaderFileExtensions; } } diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index 5d3d3c46edb4a6dd4f5cb9374785b7f9a2a292e3..9217c22b07bc51d357227d7a6e4aab7c52e3f1a5 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -366,7 +366,7 @@ static bool hasSameOperatorParent(const Expr *TheExpr, ASTContext &Context) { // IgnoreParenImpCasts logic in reverse: skip surrounding uninteresting nodes const DynTypedNodeList Parents = Context.getParents(*TheExpr); - for (ast_type_traits::DynTypedNode DynParent : Parents) { + for (DynTypedNode DynParent : Parents) { if (const auto *Parent = DynParent.get()) { bool Skip = isa(Parent) || isa(Parent) || isa(Parent) || @@ -420,16 +420,14 @@ markDuplicateOperands(const TExpr *TheExpr, if (areEquivalentExpr(AllOperands[I], AllOperands[J])) { FoundDuplicates = true; Duplicates.set(J); - Builder->setBinding( - SmallString<11>(llvm::formatv("duplicate{0}", J)), - ast_type_traits::DynTypedNode::create(*AllOperands[J])); + Builder->setBinding(SmallString<11>(llvm::formatv("duplicate{0}", J)), + DynTypedNode::create(*AllOperands[J])); } } if (FoundDuplicates) - Builder->setBinding( - SmallString<11>(llvm::formatv("duplicate{0}", I)), - ast_type_traits::DynTypedNode::create(*AllOperands[I])); + Builder->setBinding(SmallString<11>(llvm::formatv("duplicate{0}", I)), + DynTypedNode::create(*AllOperands[I])); } return Duplicates.any(); @@ -837,7 +835,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { // Binary with equivalent operands, like (X != 2 && X != 2). Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, binaryOperator( anyOf(isComparisonOperator(), hasAnyOperatorName("-", "/", "%", "|", "&", "^", "&&", @@ -868,7 +866,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { // Conditional (trenary) operator with equivalent operands, like (Y ? X : X). Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, conditionalOperator(expressionsAreEquivalent(), // Filter noisy false positives. unless(conditionalOperatorIsInMacro()), @@ -878,7 +876,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { // Overloaded operators with equivalent operands. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxOperatorCallExpr( hasAnyOverloadedOperatorName("-", "/", "%", "|", "&", "^", "==", "!=", "<", "<=", ">", @@ -901,7 +899,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { // Match expressions like: !(1 | 2 | 3) Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, implicitCastExpr( hasImplicitDestinationType(isInteger()), has(unaryOperator( @@ -915,20 +913,19 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { .bind("logical-bitwise-confusion")))), this); - // Match expressions like: (X << 8) & 0xFF - Finder->addMatcher( - traverse( - ast_type_traits::TK_AsIs, - binaryOperator( - hasOperatorName("&"), - hasOperands( - ignoringParenImpCasts( - binaryOperator(hasOperatorName("<<"), - hasRHS(ignoringParenImpCasts( - integerLiteral().bind("shift-const"))))), - ignoringParenImpCasts(integerLiteral().bind("and-const")))) - .bind("left-right-shift-confusion")), - this); + // Match expressions like: (X << 8) & 0xFF + Finder->addMatcher( + traverse(TK_AsIs, + binaryOperator( + hasOperatorName("&"), + hasOperands(ignoringParenImpCasts(binaryOperator( + hasOperatorName("<<"), + hasRHS(ignoringParenImpCasts( + integerLiteral().bind("shift-const"))))), + ignoringParenImpCasts( + integerLiteral().bind("and-const")))) + .bind("left-right-shift-confusion")), + this); // Match common expressions and apply more checks to find redundant // sub-expressions. @@ -942,17 +939,16 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { const auto SymRight = matchSymbolicExpr("rhs"); // Match expressions like: x 0xFF == 0xF00. - Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, - binaryOperator(isComparisonOperator(), - hasOperands(BinOpCstLeft, - CstRight)) - .bind("binop-const-compare-to-const")), - this); + Finder->addMatcher( + traverse(TK_AsIs, binaryOperator(isComparisonOperator(), + hasOperands(BinOpCstLeft, CstRight)) + .bind("binop-const-compare-to-const")), + this); // Match expressions like: x 0xFF == x. Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, binaryOperator(isComparisonOperator(), anyOf(allOf(hasLHS(BinOpCstLeft), hasRHS(SymRight)), allOf(hasLHS(SymRight), hasRHS(BinOpCstLeft)))) @@ -961,7 +957,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { // Match expressions like: x 10 == x 12. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, binaryOperator(isComparisonOperator(), hasLHS(BinOpCstLeft), hasRHS(BinOpCstRight), // Already reported as redundant. @@ -977,7 +973,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { const auto ComparisonLeft = matchRelationalIntegerConstantExpr("lhs"); const auto ComparisonRight = matchRelationalIntegerConstantExpr("rhs"); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, binaryOperator(hasAnyOperatorName("||", "&&"), hasLHS(ComparisonLeft), hasRHS(ComparisonRight), // Already reported as redundant. diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp index 20791c60339ad09dc4b1d0f2762ba7cecaaac94c..65384afdf5b84f0ece856d64e96c254a990bf5aa 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -19,7 +19,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -501,10 +500,10 @@ LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context) ReverseHeader(Options.get("MakeReverseRangeHeader", "")) { if (ReverseFunction.empty() && !ReverseHeader.empty()) { - llvm::WithColor::warning() - << "modernize-loop-convert: 'MakeReverseRangeHeader' is set but " - "'MakeReverseRangeFunction' is not, disabling reverse loop " - "transformation\n"; + configurationDiag( + "modernize-loop-convert: 'MakeReverseRangeHeader' is set but " + "'MakeReverseRangeFunction' is not, disabling reverse loop " + "transformation"); UseReverseRanges = false; } else if (ReverseFunction.empty()) { UseReverseRanges = UseCxx20IfAvailable && getLangOpts().CPlusPlus20; @@ -530,16 +529,11 @@ void LoopConvertCheck::registerPPCallbacks(const SourceManager &SM, } void LoopConvertCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, makeArrayLoopMatcher()), - this); - Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, makeIteratorLoopMatcher(false)), this); - Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, makePseudoArrayLoopMatcher()), this); + Finder->addMatcher(traverse(TK_AsIs, makeArrayLoopMatcher()), this); + Finder->addMatcher(traverse(TK_AsIs, makeIteratorLoopMatcher(false)), this); + Finder->addMatcher(traverse(TK_AsIs, makePseudoArrayLoopMatcher()), this); if (UseReverseRanges) - Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, makeIteratorLoopMatcher(true)), - this); + Finder->addMatcher(traverse(TK_AsIs, makeIteratorLoopMatcher(true)), this); } /// Given the range of a single declaration, such as: @@ -966,7 +960,7 @@ void LoopConvertCheck::check(const MatchFinder::MatchResult &Result) { } // Find out which qualifiers we have to use in the loop range. - TraversalKindScope RAII(*Context, ast_type_traits::TK_AsIs); + TraversalKindScope RAII(*Context, TK_AsIs); const UsageResult &Usages = Finder.getUsages(); determineRangeDescriptor(Context, Nodes, Loop, FixerKind, ContainerExpr, Usages, Descriptor); diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp index c00067fa825767de2f6ddb1869fd66f5cd9cd94a..41f38ed00fc8e57f0e5fadbafdf86a0997b65adf 100644 --- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "../utils/TypeTraits.h" #include "MakeSharedCheck.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/Lexer.h" @@ -49,13 +50,17 @@ MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context, Options.get("MakeSmartPtrFunctionHeader", "")), MakeSmartPtrFunctionName( Options.get("MakeSmartPtrFunction", MakeSmartPtrFunctionName)), - IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {} + IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)), + IgnoreDefaultInitialization( + Options.get("IgnoreDefaultInitialization", true)) {} void MakeSmartPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "IncludeStyle", Inserter.getStyle()); Options.store(Opts, "MakeSmartPtrFunctionHeader", MakeSmartPtrFunctionHeader); Options.store(Opts, "MakeSmartPtrFunction", MakeSmartPtrFunctionName); Options.store(Opts, "IgnoreMacros", IgnoreMacros); + Options.store(Opts, "IgnoreDefaultInitialization", + IgnoreDefaultInitialization); } bool MakeSmartPtrCheck::isLanguageVersionSupported( @@ -79,7 +84,7 @@ void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxBindTemporaryExpr(has(ignoringParenImpCasts( cxxConstructExpr( hasType(getSmartPointerTypeMatcher()), argumentCountIs(1), @@ -93,7 +98,7 @@ void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) { this); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxMemberCallExpr( thisPointerType(getSmartPointerTypeMatcher()), callee(cxxMethodDecl(hasName("reset"))), @@ -120,14 +125,18 @@ void MakeSmartPtrCheck::check(const MatchFinder::MatchResult &Result) { if (New->getType()->getPointeeType()->getContainedAutoType()) return; - // Be conservative for cases where we construct an array without any - // initialization. + // Be conservative for cases where we construct and default initialize. + // // For example, + // P.reset(new int) // check fix: P = std::make_unique() // P.reset(new int[5]) // check fix: P = std::make_unique(5) // - // The fix of the check has side effect, it introduces default initialization + // The fix of the check has side effect, it introduces value initialization // which maybe unexpected and cause performance regression. - if (New->isArray() && !New->hasInitializer()) + bool Initializes = New->hasInitializer() || + !utils::type_traits::isTriviallyDefaultConstructible( + New->getAllocatedType(), *Result.Context); + if (!Initializes && IgnoreDefaultInitialization) return; if (Construct) checkConstruct(SM, Result.Context, Construct, Type, New); @@ -252,7 +261,7 @@ bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag, const CXXNewExpr *New, SourceManager &SM, ASTContext *Ctx) { auto SkipParensParents = [&](const Expr *E) { - TraversalKindScope RAII(*Ctx, ast_type_traits::TK_AsIs); + TraversalKindScope RAII(*Ctx, TK_AsIs); for (const Expr *OldE = nullptr; E != OldE;) { OldE = E; diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h index 7a1bba624c539db90ebaab7466d3d0603b9b1e9c..ca12d77341625fc0fe2c257951632941e03ee101 100644 --- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h @@ -50,6 +50,7 @@ private: const std::string MakeSmartPtrFunctionHeader; const std::string MakeSmartPtrFunctionName; const bool IgnoreMacros; + const bool IgnoreDefaultInitialization; void checkConstruct(SourceManager &SM, ASTContext *Ctx, const CXXConstructExpr *Construct, const QualType *Type, diff --git a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp index 557bcce63fa1a1c549d7261819b673024f1504ee..5acbe9971416947b0525812342a1d931c7d32780 100644 --- a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp @@ -132,7 +132,7 @@ void PassByValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void PassByValueCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxConstructorDecl( forEachConstructorInitializer( cxxCtorInitializer( diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp index 2b072172792d30279047133bef02e23787533766..746d2cfed0241e74c8e5fc250eedac2ac8327ed3 100644 --- a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp @@ -88,7 +88,7 @@ void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) { hasArgument(1, MovableArgumentMatcher)), this); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxConstructExpr(hasType(AutoPtrType), argumentCountIs(1), hasArgument(0, MovableArgumentMatcher))), this); diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp index 409d1e931730e93916c4376d266843b0cf64f964..f21482d165f80d13b7435f56827ff6448c846e47 100644 --- a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp @@ -33,7 +33,7 @@ void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) { const auto RandomFunc = hasArgument(2, expr().bind("randomFunc")); Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, callExpr( anyOf(allOf(Begin, End, argumentCountIs(2)), allOf(Begin, End, RandomFunc, argumentCountIs(3))), diff --git a/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp index d94e1cee227acd54c89c57c66479bb1a499ede2c..6dc91e91ffde7cb2fd898d6d95fdbbc55bec9ca6 100644 --- a/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp @@ -31,7 +31,7 @@ void ReturnBracedInitListCheck::registerMatchers(MatchFinder *Finder) { has(ConstructExpr), has(cxxFunctionalCastExpr(has(ConstructExpr))))); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, functionDecl( isDefinition(), // Declarations don't have return statements. returns(unless(anyOf(builtinType(), autoType()))), diff --git a/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp index d967e5283fa00d289f048bec012bc4839ff258bb..7911a56a9a75fa4661b8c36bb2c2b29e53fbbea5 100644 --- a/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp @@ -42,8 +42,8 @@ void ShrinkToFitCheck::registerMatchers(MatchFinder *Finder) { on(hasType(hasCanonicalType(hasDeclaration(namedDecl( hasAnyName("std::basic_string", "std::deque", "std::vector")))))), callee(cxxMethodDecl(hasName("swap"))), - has(ignoringParenImpCasts(memberExpr(traverse( - ast_type_traits::TK_AsIs, hasDescendant(CopyCtorCall))))), + has(ignoringParenImpCasts( + memberExpr(traverse(TK_AsIs, hasDescendant(CopyCtorCall))))), hasArgument(0, SwapParam.bind("ContainerToShrink")), unless(isInTemplateInstantiation())) .bind("CopyAndSwapTrick"), diff --git a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp index f15b734c55d6b4ae247450511502c7700a1a26d4..fab13cdbfe9f46cf41764f219886f70895da8635 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp @@ -281,8 +281,7 @@ void UseAutoCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } void UseAutoCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, makeCombinedMatcher()), - this); + Finder->addMatcher(traverse(TK_AsIs, makeCombinedMatcher()), this); } void UseAutoCheck::replaceIterators(const DeclStmt *D, ASTContext *Context) { diff --git a/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp index 3dab7437021b61a3631b61833d9b3b095b0b3594..ad11e39f1f1bb4ddd60012c93ad5fe0ef1ad6121 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp @@ -29,7 +29,7 @@ void UseBoolLiteralsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, implicitCastExpr( has(ignoringParenImpCasts(integerLiteral().bind("literal"))), hasImplicitDestinationType(qualType(booleanType())), @@ -38,7 +38,7 @@ void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) { this); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, conditionalOperator( hasParent(implicitCastExpr( hasImplicitDestinationType(qualType(booleanType())), diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp index 77d84bd340f602ed82b624fea98a29eaf40654af..8ddcf3ddf694df6fc56663f9b5c920f7adaa5150 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp @@ -110,10 +110,9 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { HasConstructExpr, has(cxxFunctionalCastExpr(HasConstructExpr)))); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, - cxxMemberCallExpr(CallPushBack, has(SoughtParam), - unless(isInTemplateInstantiation())) - .bind("call")), + traverse(TK_AsIs, cxxMemberCallExpr(CallPushBack, has(SoughtParam), + unless(isInTemplateInstantiation())) + .bind("call")), this); } diff --git a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp index 23e48c0a9ab2f1af47089cfe7025e7db1d0f64c9..d1d25825ba93b73efec75f34c9beb254c7719bf9 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp @@ -75,7 +75,7 @@ static bool isCopyConstructorAndCanBeDefaulted(ASTContext *Context, // The initialization of a base class should be a call to a copy // constructor of the base. if (match( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxConstructorDecl( forEachConstructorInitializer(cxxCtorInitializer( isBaseInitializer(), @@ -96,7 +96,7 @@ static bool isCopyConstructorAndCanBeDefaulted(ASTContext *Context, auto AccessToFieldInParam = accessToFieldInVar(Field, Param); // The initialization is a CXXConstructExpr for class types. if (match(traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxConstructorDecl( forEachConstructorInitializer(cxxCtorInitializer( isMemberInitializer(), forField(equalsNode(Field)), @@ -137,7 +137,7 @@ static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context, // return *this; if (Compound->body_empty() || match(traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, returnStmt(has(ignoringParenImpCasts(unaryOperator( hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())))))), *Compound->body_back(), *Context) @@ -153,7 +153,7 @@ static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context, // ((Base*)this)->operator=((Base)Other); // // So we are looking for a member call that fulfills: - if (match(traverse(ast_type_traits::TK_AsIs, + if (match(traverse(TK_AsIs, compoundStmt(has(ignoringParenImpCasts(cxxMemberCallExpr( // - The object is an implicit cast of 'this' to a // pointer to @@ -184,7 +184,7 @@ static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context, member(fieldDecl(equalsNode(Field)))); auto RHS = accessToFieldInVar(Field, Param); if (match( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, compoundStmt(has(ignoringParenImpCasts(stmt(anyOf( binaryOperator(hasOperatorName("="), hasLHS(LHS), hasRHS(RHS)), diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp index 7e30c174a615f35e106e44523a033ebff41e7b46..25a789dd08315c09ccb1ab65c46d03e371ef9ac4 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp @@ -42,7 +42,7 @@ StatementMatcher makeCastSequenceMatcher() { unless(hasSourceExpression(hasType(sugaredNullptrType())))); return traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, castExpr(anyOf(ImplicitCastToNull, explicitCastExpr(hasDescendant(ImplicitCastToNull))), unless(hasAncestor(explicitCastExpr()))) @@ -277,10 +277,9 @@ private: return false; // Step 2: Find the first ancestor that doesn't expand from this macro. - ast_type_traits::DynTypedNode ContainingAncestor; - if (!findContainingAncestor( - ast_type_traits::DynTypedNode::create(*CE), MacroLoc, - ContainingAncestor)) + DynTypedNode ContainingAncestor; + if (!findContainingAncestor(DynTypedNode::create(*CE), MacroLoc, + ContainingAncestor)) return false; // Step 3: @@ -407,9 +406,8 @@ private: /// /// \pre MacroLoc.isFileID() /// \returns true if such an ancestor was found, false otherwise. - bool findContainingAncestor(ast_type_traits::DynTypedNode Start, - SourceLocation MacroLoc, - ast_type_traits::DynTypedNode &Result) { + bool findContainingAncestor(DynTypedNode Start, SourceLocation MacroLoc, + DynTypedNode &Result) { // Below we're only following the first parent back up the AST. This should // be fine since for the statements we care about there should only be one // parent, except for the case specified below. @@ -431,7 +429,7 @@ private: } } - const ast_type_traits::DynTypedNode &Parent = Parents[0]; + const DynTypedNode &Parent = Parents[0]; SourceLocation Loc; if (const auto *D = Parent.get()) diff --git a/clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp b/clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp index 2b9eee2f0f33b3efc51f4d91f4b3dfd04819e84f..793c6021c39818f2d014a99eff4fbb3fdff99008 100644 --- a/clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp +++ b/clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp @@ -101,7 +101,7 @@ fixItHintForVarDecl(const VarDecl *VD, const SourceManager &SM, void NSInvocationArgumentLifetimeCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, objcMessageExpr( hasReceiverType(asString("NSInvocation *")), anyOf(hasSelector("getArgument:atIndex:"), diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt index 0e38e9fc5c0c934af3dc5122eba8fa13a0d755a2..3153646416927d4721094586c246a059e1e661d7 100644 --- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt @@ -13,6 +13,7 @@ add_clang_library(clangTidyPerformanceModule MoveConstArgCheck.cpp MoveConstructorInitCheck.cpp NoAutomaticMoveCheck.cpp + NoIntToPtrCheck.cpp NoexceptMoveConstructorCheck.cpp PerformanceTidyModule.cpp TriviallyDestructibleCheck.cpp diff --git a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp index 84a4ac922fa548966bfa90fb6a754982f9be3cb6..4b7a34f6c40f52f650b67f648f72659054c7ae2e 100644 --- a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp @@ -50,7 +50,7 @@ void ForRangeCopyCheck::registerMatchers(MatchFinder *Finder) { unless(hasInitializer(expr(hasDescendant(expr(anyOf( materializeTemporaryExpr(), IteratorReturnsValueType))))))); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxForRangeStmt(hasLoopVariable(LoopVar.bind("loopVar"))) .bind("forRange")), this); diff --git a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp index 9cddd2b4d31ce31ace5a5e7ac2da23271d29ade3..38ede424be6658329469f8ea5dd65b1a43c3004c 100644 --- a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp @@ -48,7 +48,7 @@ void ImplicitConversionInLoopCheck::registerMatchers(MatchFinder *Finder) { // cxxOperatorCallExpr() matcher. Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxForRangeStmt(hasLoopVariable( varDecl( hasType(qualType(references(qualType(isConstQualified())))), diff --git a/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp b/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp index dfea0104614c99516e21a8ba47a44d96376ec9d2..8381ed0b15539651baedb0a38dbb91632a698f07 100644 --- a/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp @@ -36,7 +36,7 @@ void InefficientAlgorithmCheck::registerMatchers(MatchFinder *Finder) { "::std::unordered_multiset", "::std::unordered_multimap")); const auto Matcher = traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, callExpr( callee(functionDecl(Algorithms)), hasArgument( diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp index 95aa33863d656be7e0ce823acee0d71c6300f49a..0cb1b82782d98f675d6bcf51606e376ee4e78158 100644 --- a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp @@ -52,7 +52,7 @@ void MoveConstArgCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(callExpr(ConstParamMatcher).bind("receiving-expr"), this); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxConstructExpr(ConstParamMatcher).bind("receiving-expr")), this); } diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp index 6b42cd3180d734a5a7cae3c9f92b4949e865839e..35afa31746df310876d6225eb73c11fdedc865b0 100644 --- a/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp @@ -28,7 +28,7 @@ MoveConstructorInitCheck::MoveConstructorInitCheck(StringRef Name, void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxConstructorDecl( unless(isImplicit()), isMoveConstructor(), hasAnyConstructorInitializer( diff --git a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp index 057e10d3c21ebc1519768d926a62e3e823d36193..21eba9af0997d136fff43006a921b00fccae6f30 100644 --- a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp @@ -44,7 +44,7 @@ void NoAutomaticMoveCheck::registerMatchers(MatchFinder *Finder) { pointee(type(equalsBoundNode("SrcT"))))))))))); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, returnStmt(hasReturnValue( ignoringElidableConstructorCall(ignoringParenImpCasts( cxxConstructExpr( diff --git a/clang-tools-extra/clang-tidy/performance/NoIntToPtrCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoIntToPtrCheck.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc82a21bbf5a5684f82ac74b03051c5e28c008d9 --- /dev/null +++ b/clang-tools-extra/clang-tidy/performance/NoIntToPtrCheck.cpp @@ -0,0 +1,34 @@ +//===--- NoIntToPtrCheck.cpp - clang-tidy ---------------------------------===// +// +// 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 "NoIntToPtrCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace performance { + +void NoIntToPtrCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(castExpr(hasCastKind(CK_IntegralToPointer), + unless(hasSourceExpression(integerLiteral()))) + .bind("x"), + this); +} + +void NoIntToPtrCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedCast = Result.Nodes.getNodeAs("x"); + diag(MatchedCast->getBeginLoc(), + "integer to pointer cast pessimizes optimization opportunities"); +} + +} // namespace performance +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/performance/NoIntToPtrCheck.h b/clang-tools-extra/clang-tidy/performance/NoIntToPtrCheck.h new file mode 100644 index 0000000000000000000000000000000000000000..f07343184538c93787bbcc476777abf820ccaf65 --- /dev/null +++ b/clang-tools-extra/clang-tidy/performance/NoIntToPtrCheck.h @@ -0,0 +1,34 @@ +//===--- NoIntToPtrCheck.h - clang-tidy -------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_NOINTTOPTRCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_NOINTTOPTRCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace performance { + +/// Diagnoses every integer to pointer cast. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/performance-no-int-to-ptr.html +class NoIntToPtrCheck : public ClangTidyCheck { +public: + NoIntToPtrCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace performance +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_NOINTTOPTRCHECK_H diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp index 87673a228da44b84d0de3d64fb6d856c2097828e..ba9d7eed55e23ec9df60b5e8af7fd9045bee8ca1 100644 --- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp @@ -18,6 +18,7 @@ #include "MoveConstArgCheck.h" #include "MoveConstructorInitCheck.h" #include "NoAutomaticMoveCheck.h" +#include "NoIntToPtrCheck.h" #include "NoexceptMoveConstructorCheck.h" #include "TriviallyDestructibleCheck.h" #include "TypePromotionInMathFnCheck.h" @@ -49,6 +50,7 @@ public: "performance-move-constructor-init"); CheckFactories.registerCheck( "performance-no-automatic-move"); + CheckFactories.registerCheck("performance-no-int-to-ptr"); CheckFactories.registerCheck( "performance-noexcept-move-constructor"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp index 24847d80657c15492476dd94425aa70f7c4adcf2..06cfb24de1eadecdf5a548336b460866580e253a 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -19,6 +19,14 @@ namespace tidy { namespace performance { namespace { +using namespace ::clang::ast_matchers; +using llvm::StringRef; +using utils::decl_ref_expr::isOnlyUsedAsConst; + +static constexpr StringRef ObjectArgId = "objectArg"; +static constexpr StringRef InitFunctionCallId = "initFunctionCall"; +static constexpr StringRef OldVarDeclId = "oldVarDecl"; + void recordFixes(const VarDecl &Var, ASTContext &Context, DiagnosticBuilder &Diagnostic) { Diagnostic << utils::fixit::changeVarDeclToReference(Var, Context); @@ -29,10 +37,88 @@ void recordFixes(const VarDecl &Var, ASTContext &Context, } } -} // namespace +AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningMethodCall) { + // Match method call expressions where the `this` argument is only used as + // const, this will be checked in `check()` part. This returned const + // reference is highly likely to outlive the local const reference of the + // variable being declared. The assumption is that the const reference being + // returned either points to a global static variable or to a member of the + // called object. + return cxxMemberCallExpr( + callee(cxxMethodDecl(returns(matchers::isReferenceToConst()))), + on(declRefExpr(to(varDecl().bind(ObjectArgId))))); +} -using namespace ::clang::ast_matchers; -using utils::decl_ref_expr::isOnlyUsedAsConst; +AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningFunctionCall) { + // Only allow initialization of a const reference from a free function if it + // has no arguments. Otherwise it could return an alias to one of its + // arguments and the arguments need to be checked for const use as well. + return callExpr(callee(functionDecl(returns(matchers::isReferenceToConst()))), + argumentCountIs(0), unless(callee(cxxMethodDecl()))) + .bind(InitFunctionCallId); +} + +AST_MATCHER_FUNCTION(StatementMatcher, isInitializedFromReferenceToConst) { + auto OldVarDeclRef = + declRefExpr(to(varDecl(hasLocalStorage()).bind(OldVarDeclId))); + return declStmt(has(varDecl(hasInitializer( + anyOf(isConstRefReturningFunctionCall(), isConstRefReturningMethodCall(), + ignoringImpCasts(OldVarDeclRef), + ignoringImpCasts(unaryOperator( + hasOperatorName("&"), hasUnaryOperand(OldVarDeclRef)))))))); +} + +// This checks that the variable itself is only used as const, and also makes +// sure that it does not reference another variable that could be modified in +// the BlockStmt. It does this by checking the following: +// 1. If the variable is neither a reference nor a pointer then the +// isOnlyUsedAsConst() check is sufficient. +// 2. If the (reference or pointer) variable is not initialized in a DeclStmt in +// the BlockStmt. In this case its pointee is likely not modified (unless it +// is passed as an alias into the method as well). +// 3. If the reference is initialized from a reference to const. This is +// the same set of criteria we apply when identifying the unnecessary copied +// variable in this check to begin with. In this case we check whether the +// object arg or variable that is referenced is immutable as well. +static bool isInitializingVariableImmutable(const VarDecl &InitializingVar, + const Stmt &BlockStmt, + ASTContext &Context) { + if (!isOnlyUsedAsConst(InitializingVar, BlockStmt, Context)) + return false; + + QualType T = InitializingVar.getType(); + // The variable is a value type and we know it is only used as const. Safe + // to reference it and avoid the copy. + if (!isa(T)) + return true; + + auto Matches = + match(findAll(declStmt(has(varDecl(equalsNode(&InitializingVar)))) + .bind("declStmt")), + BlockStmt, Context); + // The reference or pointer is not initialized in the BlockStmt. We assume + // its pointee is not modified then. + if (Matches.empty()) + return true; + + const auto *Initialization = selectFirst("declStmt", Matches); + Matches = + match(isInitializedFromReferenceToConst(), *Initialization, Context); + // The reference is initialized from a free function without arguments + // returning a const reference. This is a global immutable object. + if (selectFirst(InitFunctionCallId, Matches) != nullptr) + return true; + // Check that the object argument is immutable as well. + if (const auto *OrigVar = selectFirst(ObjectArgId, Matches)) + return isInitializingVariableImmutable(*OrigVar, BlockStmt, Context); + // Check that the old variable we reference is immutable as well. + if (const auto *OrigVar = selectFirst(OldVarDeclId, Matches)) + return isInitializingVariableImmutable(*OrigVar, BlockStmt, Context); + + return false; +} + +} // namespace UnnecessaryCopyInitialization::UnnecessaryCopyInitialization( StringRef Name, ClangTidyContext *Context) @@ -41,22 +127,6 @@ UnnecessaryCopyInitialization::UnnecessaryCopyInitialization( utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { - auto ConstReference = referenceType(pointee(qualType(isConstQualified()))); - - // Match method call expressions where the `this` argument is only used as - // const, this will be checked in `check()` part. This returned const - // reference is highly likely to outlive the local const reference of the - // variable being declared. The assumption is that the const reference being - // returned either points to a global static variable or to a member of the - // called object. - auto ConstRefReturningMethodCall = - cxxMemberCallExpr(callee(cxxMethodDecl(returns(ConstReference))), - on(declRefExpr(to(varDecl().bind("objectArg"))))); - auto ConstRefReturningFunctionCall = - callExpr(callee(functionDecl(returns(ConstReference))), - unless(callee(cxxMethodDecl()))) - .bind("initFunctionCall"); - auto localVarCopiedFrom = [this](const internal::Matcher &CopyCtorArg) { return compoundStmt( forEachDescendant( @@ -72,7 +142,7 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { AllowedTypes)))))), unless(isImplicit()), hasInitializer(traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxConstructExpr( hasDeclaration(cxxConstructorDecl( isCopyConstructor())), @@ -83,26 +153,24 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { .bind("blockStmt"); }; - Finder->addMatcher(localVarCopiedFrom(anyOf(ConstRefReturningFunctionCall, - ConstRefReturningMethodCall)), + Finder->addMatcher(localVarCopiedFrom(anyOf(isConstRefReturningFunctionCall(), + isConstRefReturningMethodCall())), this); Finder->addMatcher(localVarCopiedFrom(declRefExpr( - to(varDecl(hasLocalStorage()).bind("oldVarDecl")))), + to(varDecl(hasLocalStorage()).bind(OldVarDeclId)))), this); } void UnnecessaryCopyInitialization::check( const MatchFinder::MatchResult &Result) { const auto *NewVar = Result.Nodes.getNodeAs("newVarDecl"); - const auto *OldVar = Result.Nodes.getNodeAs("oldVarDecl"); - const auto *ObjectArg = Result.Nodes.getNodeAs("objectArg"); + const auto *OldVar = Result.Nodes.getNodeAs(OldVarDeclId); + const auto *ObjectArg = Result.Nodes.getNodeAs(ObjectArgId); const auto *BlockStmt = Result.Nodes.getNodeAs("blockStmt"); const auto *CtorCall = Result.Nodes.getNodeAs("ctorCall"); - const auto *InitFunctionCall = - Result.Nodes.getNodeAs("initFunctionCall"); - TraversalKindScope RAII(*Result.Context, ast_type_traits::TK_AsIs); + TraversalKindScope RAII(*Result.Context, TK_AsIs); // Do not propose fixes if the DeclStmt has multiple VarDecls or in macros // since we cannot place them correctly. @@ -118,11 +186,6 @@ void UnnecessaryCopyInitialization::check( return; if (OldVar == nullptr) { - // Only allow initialization of a const reference from a free function if it - // has no arguments. Otherwise it could return an alias to one of its - // arguments and the arguments need to be checked for const use as well. - if (InitFunctionCall != nullptr && InitFunctionCall->getNumArgs() > 0) - return; handleCopyFromMethodReturn(*NewVar, *BlockStmt, IssueFix, ObjectArg, *Result.Context); } else { @@ -138,7 +201,7 @@ void UnnecessaryCopyInitialization::handleCopyFromMethodReturn( if (!IsConstQualified && !isOnlyUsedAsConst(Var, BlockStmt, Context)) return; if (ObjectArg != nullptr && - !isOnlyUsedAsConst(*ObjectArg, BlockStmt, Context)) + !isInitializingVariableImmutable(*ObjectArg, BlockStmt, Context)) return; auto Diagnostic = @@ -158,7 +221,7 @@ void UnnecessaryCopyInitialization::handleCopyFromLocalVar( const VarDecl &NewVar, const VarDecl &OldVar, const Stmt &BlockStmt, bool IssueFix, ASTContext &Context) { if (!isOnlyUsedAsConst(NewVar, BlockStmt, Context) || - !isOnlyUsedAsConst(OldVar, BlockStmt, Context)) + !isInitializingVariableImmutable(OldVar, BlockStmt, Context)) return; auto Diagnostic = diag(NewVar.getLocation(), diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp index 12fb2f588539f7d337bd07763f5887605d659802..e3dae9a135581d2160052987c0152fd99e3fb522 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -42,7 +42,7 @@ bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function, bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl, ASTContext &Context) { auto Matches = match( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, decl(forEachDescendant(declRefExpr( equalsNode(&DeclRef), unless(hasAncestor(stmt(anyOf(forStmt(), cxxForRangeStmt(), @@ -83,7 +83,7 @@ void UnnecessaryValueParamCheck::registerMatchers(MatchFinder *Finder) { decl().bind("param")); Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, functionDecl(hasBody(stmt()), isDefinition(), unless(isImplicit()), unless(cxxMethodDecl(anyOf(isOverride(), isFinal()))), has(typeLoc(forEach(ExpensiveValueParamDecl))), @@ -95,7 +95,7 @@ void UnnecessaryValueParamCheck::check(const MatchFinder::MatchResult &Result) { const auto *Param = Result.Nodes.getNodeAs("param"); const auto *Function = Result.Nodes.getNodeAs("functionDecl"); - TraversalKindScope RAII(*Result.Context, ast_type_traits::TK_AsIs); + TraversalKindScope RAII(*Result.Context, TK_AsIs); FunctionParmMutationAnalyzer &Analyzer = MutationAnalyzers.try_emplace(Function, *Function, *Result.Context) diff --git a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp index bcd3e248df77dd34cd780e8f19fe87437eff25b1..14a38c09ad9b001bdcff6c85d522edf9e1b061d4 100644 --- a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp @@ -40,7 +40,7 @@ void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) { .bind("container"))))))); const auto WrongUse = traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, anyOf( hasParent(binaryOperator(isComparisonOperator(), hasEitherOperand(ignoringImpCasts( diff --git a/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp b/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp index 57b1a0c9e141c63dd9fa34956726cbd938b47f76..16e86c201ff1eddce49d7fc5b59c967a267a588c 100644 --- a/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp @@ -39,7 +39,7 @@ void DeleteNullPointerCheck::registerMatchers(MatchFinder *Finder) { hasOperands(castExpr(hasCastKind(CK_NullToPointer)), PointerExpr)); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, ifStmt(hasCondition( anyOf(PointerCondition, BinaryPointerCheckCondition)), hasThen(anyOf(DeleteExpr, DeleteMemberExpr, diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index ef8f54913ed92d280fc3b602bc3033dd70f476f5..d33040a00e1501a1fc00618fcce5e852e96b3c7f 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -773,7 +773,8 @@ IdentifierNamingCheck::getStyleForFile(StringRef FileName) const { ClangTidyOptions Options = Context->getOptionsForFile(FileName); if (Options.Checks && GlobList(*Options.Checks).contains(CheckName)) { auto It = NamingStylesCache.try_emplace( - Parent, getFileStyleFromOptions({CheckName, Options.CheckOptions})); + Parent, + getFileStyleFromOptions({CheckName, Options.CheckOptions, Context})); assert(It.second); return It.first->getValue(); } diff --git a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp index d7a782bfd18207d662a4dedc70499e63206bd4d8..0ff2c066e4741202c05d33e60e4cf099d76274d5 100644 --- a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp @@ -222,7 +222,7 @@ bool isCastAllowedInCondition(const ImplicitCastExpr *Cast, std::queue Q; Q.push(Cast); - TraversalKindScope RAII(Context, ast_type_traits::TK_AsIs); + TraversalKindScope RAII(Context, TK_AsIs); while (!Q.empty()) { for (const auto &N : Context.getParents(*Q.front())) { @@ -276,7 +276,7 @@ void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) { binaryOperator(hasOperatorName("^"), hasLHS(implicitCastFromBool), hasRHS(implicitCastFromBool)); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, implicitCastExpr( anyOf(hasCastKind(CK_IntegralToBoolean), hasCastKind(CK_FloatingToBoolean), @@ -309,7 +309,7 @@ void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) { forField(hasBitWidth(1))))); Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, implicitCastExpr( implicitCastFromBool, // Exclude comparisons of bools, as they are always cast to diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp index 18165a619adf452c9016f58e731db9e03f9e25c7..3d8a0b7b3970a88325983fb35d5ff1ac64d80b5b 100644 --- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp @@ -19,7 +19,6 @@ #include using namespace clang::ast_matchers; -using namespace clang::ast_type_traits; namespace clang { @@ -127,7 +126,7 @@ void MagicNumbersCheck::registerMatchers(MatchFinder *Finder) { void MagicNumbersCheck::check(const MatchFinder::MatchResult &Result) { - TraversalKindScope RAII(*Result.Context, ast_type_traits::TK_AsIs); + TraversalKindScope RAII(*Result.Context, TK_AsIs); checkBoundMatch(Result, "integer"); checkBoundMatch(Result, "float"); diff --git a/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp index 7a8ad2c3aec62b82c3217dee58f9ca7101476df2..7983436257293e220db9391c70599cd8823d8d0b 100644 --- a/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp @@ -212,7 +212,7 @@ AST_MATCHER(CXXMethodDecl, usesThisAsConst) { void MakeMemberFunctionConstCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxMethodDecl( isDefinition(), isUserProvided(), unless(anyOf( diff --git a/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp b/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp index c5112da413db2cd9a2f6542f760ba9ae74d93a77..5cc4b963b30fba82bd23f6d888815871affaa838 100644 --- a/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp @@ -20,10 +20,9 @@ namespace readability { void MisplacedArrayIndexCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, - arraySubscriptExpr(hasLHS(hasType(isInteger())), - hasRHS(hasType(isAnyPointer()))) - .bind("expr")), + traverse(TK_AsIs, arraySubscriptExpr(hasLHS(hasType(isInteger())), + hasRHS(hasType(isAnyPointer()))) + .bind("expr")), this); } diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp index 688547ca2975300b71557b6ed9a8953cde257dfb..1044df0032d8046bb56693ae3b9f1ecf239ecb77 100644 --- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp @@ -29,7 +29,7 @@ void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) { // Analyse parameter usage in function. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, stmt(anyOf(unaryOperator(hasAnyOperatorName("++", "--")), binaryOperator(), callExpr(), returnStmt(), cxxConstructExpr())) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp index 56565ff2115c0f54d83931d6bc9f92b44a4d60c7..17613785fac067d96c348ed2c7f02b4155acc832 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp @@ -17,12 +17,12 @@ namespace tidy { namespace readability { void RedundantFunctionPtrDereferenceCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, - unaryOperator(hasOperatorName("*"), - has(implicitCastExpr(hasCastKind( - CK_FunctionToPointerDecay)))) - .bind("op")), - this); + Finder->addMatcher( + traverse(TK_AsIs, unaryOperator(hasOperatorName("*"), + has(implicitCastExpr(hasCastKind( + CK_FunctionToPointerDecay)))) + .bind("op")), + this); } void RedundantFunctionPtrDereferenceCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp index 027146f12aad52772ed20bef2d22886b7afe7c37..df6e57bfb9eda2315f473f809a6182966b6363ef 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp @@ -34,7 +34,7 @@ void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxConstructorDecl( unless(isDelegatingConstructor()), ofClass(unless( diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp index 1f371eed2db8028199ad004e6b8be555442cd62d..79211731ff7becf21bffad943e392e800c142aa0 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp @@ -99,7 +99,7 @@ void RedundantStringCStrCheck::registerMatchers( // check that matched ParamDecl of the ancestor CallExpr is not rvalue. Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxConstructExpr( StringConstructorExpr, hasArgument(0, StringCStrCallExpr), unless(anyOf(HasRValueTempParent, hasParent(cxxBindTemporaryExpr( @@ -158,7 +158,7 @@ void RedundantStringCStrCheck::registerMatchers( // Detect redundant 'c_str()' calls through a StringRef constructor. Finder->addMatcher( traverse( - ast_type_traits::TK_AsIs, + TK_AsIs, cxxConstructExpr( // Implicit constructors of these classes are overloaded // wrt. string types and they internally make a StringRef diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp index 24defc80f161d6e9776071ee0db3f810584af962..26c8ae5a324439f7c2f7bafc402c1017aa0f7f20 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp @@ -97,16 +97,16 @@ void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) { const auto StringType = hasType(hasUnqualifiedDesugaredType( recordType(hasDeclaration(cxxRecordDecl(hasStringTypeName))))); - const auto EmptyStringInit = - traverse(ast_type_traits::TK_AsIs, expr(ignoringImplicit( - anyOf(EmptyStringCtorExpr, EmptyStringCtorExprWithTemporaries)))); + const auto EmptyStringInit = traverse( + TK_AsIs, expr(ignoringImplicit(anyOf( + EmptyStringCtorExpr, EmptyStringCtorExprWithTemporaries)))); // Match a variable declaration with an empty string literal as initializer. // Examples: // string foo = ""; // string bar(""); Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, namedDecl(varDecl(StringType, hasInitializer(EmptyStringInit)) .bind("vardecl"), unless(parmVarDecl()))), diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp index 19d40c54f12c718bb4ecb392347f38e1fdf69ee2..d3cf27d1fc3f4a6d3b95ab71732f1e9729868253 100644 --- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp @@ -32,7 +32,7 @@ void StringCompareCheck::registerMatchers(MatchFinder *Finder) { // First and second case: cast str.compare(str) to boolean. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, implicitCastExpr(hasImplicitDestinationType(booleanType()), has(StrCompare)) .bind("match1")), diff --git a/clang-tools-extra/clang-tidy/rename_check.py b/clang-tools-extra/clang-tidy/rename_check.py index 4d5311c9a2934e57541af3d2934360397831b929..2410041fd5d2d8f667f1710733b4050d26ec00f9 100755 --- a/clang-tools-extra/clang-tidy/rename_check.py +++ b/clang-tools-extra/clang-tidy/rename_check.py @@ -120,16 +120,15 @@ def adapt_cmake(module_path, check_name_camel): if (not file_added) and (cpp_line or cpp_found): cpp_found = True if (line.strip() > cpp_file) or (not cpp_line): - f.write(' ' + cpp_file + '\n') + f.write((' ' + cpp_file + '\n').encode()) file_added = True - f.write(line) + f.write(line.encode()) return True # Modifies the module to include the new check. def adapt_module(module_path, module, check_name, check_name_camel): - modulecpp = filter(lambda p: p.lower() == module.lower() + 'tidymodule.cpp', - os.listdir(module_path))[0] + modulecpp = next(filter(lambda p: p.lower() == module.lower() + 'tidymodule.cpp', os.listdir(module_path))) filename = os.path.join(module_path, modulecpp) with open(filename, 'r') as f: lines = f.readlines() @@ -149,21 +148,21 @@ def adapt_module(module_path, module, check_name, check_name_camel): header_found = True if match.group(1) > check_name_camel: header_added = True - f.write('#include "' + check_name_camel + '.h"\n') + f.write(('#include "' + check_name_camel + '.h"\n').encode()) elif header_found: header_added = True - f.write('#include "' + check_name_camel + '.h"\n') + f.write(('#include "' + check_name_camel + '.h"\n').encode()) if not check_added: if line.strip() == '}': check_added = True - f.write(check_decl) + f.write(check_decl.encode()) else: match = re.search('registerCheck<(.*)>', line) if match and match.group(1) > check_name_camel: check_added = True - f.write(check_decl) - f.write(line) + f.write(check_decl.encode()) + f.write(line.encode()) # Adds a release notes entry. @@ -198,22 +197,22 @@ def add_release_notes(clang_tidy_path, old_check_name, new_check_name): if match: header_found = True - f.write(line) + f.write(line.encode()) continue if line.startswith('^^^^'): - f.write(line) + f.write(line.encode()) continue if header_found and add_note_here: if not line.startswith('^^^^'): - f.write("""- The '%s' check was renamed to :doc:`%s + f.write(("""- The '%s' check was renamed to :doc:`%s ` -""" % (old_check_name, new_check_name, new_check_name)) +""" % (old_check_name, new_check_name, new_check_name)).encode()) note_added = True - f.write(line) + f.write(line.encode()) def main(): parser = argparse.ArgumentParser(description='Rename clang-tidy check.') @@ -259,9 +258,9 @@ def main(): (check_name_camel, cmake_lists)) return 1 - modulecpp = filter( + modulecpp = next(filter( lambda p: p.lower() == old_module.lower() + 'tidymodule.cpp', - os.listdir(old_module_path))[0] + os.listdir(old_module_path))) deleteMatchingLines(os.path.join(old_module_path, modulecpp), '\\b' + check_name_camel + '|\\b' + args.old_check_name) diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp index a4069da79ff18c2d6eca5301e437ff3183b6b7a0..2748fd9f74a5d80b45e89bd6e056cda2b18eb96f 100644 --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -312,15 +312,16 @@ static std::unique_ptr createOptionsProvider( if (UseColor.getNumOccurrences() > 0) OverrideOptions.UseColor = UseColor; - auto LoadConfig = [&](StringRef Configuration) - -> std::unique_ptr { + auto LoadConfig = + [&](StringRef Configuration, + StringRef Source) -> std::unique_ptr { llvm::ErrorOr ParsedConfig = - parseConfiguration(Configuration); + parseConfiguration(MemoryBufferRef(Configuration, Source)); if (ParsedConfig) return std::make_unique( - GlobalOptions, + std::move(GlobalOptions), ClangTidyOptions::getDefaults().merge(DefaultOptions, 0), - *ParsedConfig, OverrideOptions, std::move(FS)); + std::move(*ParsedConfig), std::move(OverrideOptions), std::move(FS)); llvm::errs() << "Error: invalid configuration specified.\n" << ParsedConfig.getError().message() << "\n"; return nullptr; @@ -334,21 +335,22 @@ static std::unique_ptr createOptionsProvider( } llvm::ErrorOr> Text = - llvm::MemoryBuffer::getFile(ConfigFile.c_str()); + llvm::MemoryBuffer::getFile(ConfigFile); if (std::error_code EC = Text.getError()) { llvm::errs() << "Error: can't read config-file '" << ConfigFile << "': " << EC.message() << "\n"; return nullptr; } - return LoadConfig((*Text)->getBuffer()); + return LoadConfig((*Text)->getBuffer(), ConfigFile); } if (Config.getNumOccurrences() > 0) - return LoadConfig(Config); + return LoadConfig(Config, ""); - return std::make_unique(GlobalOptions, DefaultOptions, - OverrideOptions, std::move(FS)); + return std::make_unique( + std::move(GlobalOptions), std::move(DefaultOptions), + std::move(OverrideOptions), std::move(FS)); } llvm::IntrusiveRefCntPtr diff --git a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp index d0933f0860c8a00b6a58ff9274aba9e590611ad3..10d2b24a9677ab2b92e8bfcf2a6c7e586da4cc17 100644 --- a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp @@ -58,7 +58,7 @@ constReferenceDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, SmallPtrSet DeclRefs; extractNodesByIdTo(Matches, "declRef", DeclRefs); auto ConstReferenceOrValue = - qualType(anyOf(referenceType(pointee(qualType(isConstQualified()))), + qualType(anyOf(matchers::isReferenceToConst(), unless(anyOf(referenceType(), pointerType(), substTemplateTypeParmType())))); auto ConstReferenceOrValueOrReplaced = qualType(anyOf( @@ -71,6 +71,20 @@ constReferenceDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, Matches = match(findAll(cxxConstructExpr(UsedAsConstRefOrValueArg)), Stmt, Context); extractNodesByIdTo(Matches, "declRef", DeclRefs); + // References and pointers to const assignments. + Matches = + match(findAll(declStmt( + has(varDecl(hasType(qualType(matchers::isReferenceToConst())), + hasInitializer(ignoringImpCasts(DeclRefToVar)))))), + Stmt, Context); + extractNodesByIdTo(Matches, "declRef", DeclRefs); + Matches = + match(findAll(declStmt(has(varDecl( + hasType(qualType(matchers::isPointerToConst())), + hasInitializer(ignoringImpCasts(unaryOperator( + hasOperatorName("&"), hasUnaryOperand(DeclRefToVar)))))))), + Stmt, Context); + extractNodesByIdTo(Matches, "declRef", DeclRefs); return DeclRefs; } diff --git a/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp b/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp index 15c4375a64be7bd486929e38cae5d28ddfe595ab..76e40a3e1d562c83bf0c2816cfdb9b66979fee02 100644 --- a/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp @@ -29,14 +29,13 @@ static SmallVector getParentStmts(const Stmt *S, ASTContext *Context) { SmallVector Result; - TraversalKindScope RAII(*Context, ast_type_traits::TK_AsIs); + TraversalKindScope RAII(*Context, TK_AsIs); DynTypedNodeList Parents = Context->getParents(*S); - SmallVector NodesToProcess(Parents.begin(), - Parents.end()); + SmallVector NodesToProcess(Parents.begin(), Parents.end()); while (!NodesToProcess.empty()) { - ast_type_traits::DynTypedNode Node = NodesToProcess.back(); + DynTypedNode Node = NodesToProcess.back(); NodesToProcess.pop_back(); if (const auto *S = Node.get()) { diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.h b/clang-tools-extra/clang-tidy/utils/Matchers.h index 348ab758f3d4708bad289d8238b0b6423cc8c29d..9b765aedd13afe70f979fdb38368bbe521b77332 100644 --- a/clang-tools-extra/clang-tidy/utils/Matchers.h +++ b/clang-tools-extra/clang-tidy/utils/Matchers.h @@ -43,6 +43,12 @@ AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isReferenceToConst) { return referenceType(pointee(qualType(isConstQualified()))); } +// Returns QualType matcher for pointers to const. +AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isPointerToConst) { + using namespace ast_matchers; + return pointerType(pointee(qualType(isConstQualified()))); +} + AST_MATCHER_P(NamedDecl, matchesAnyListedName, std::vector, NameList) { return llvm::any_of(NameList, [&Node](const std::string &Name) { diff --git a/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp b/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp index d816f0ba1866d6a94040fe0eb92a3e6b2ecdb598..fa822c3dd8b7cf092ee3b705bc670ac721f58123 100644 --- a/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp +++ b/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp @@ -36,7 +36,7 @@ void TemporaryObjectsCheck::registerMatchers(MatchFinder *Finder) { // Matcher for user-defined constructors. Finder->addMatcher( - traverse(ast_type_traits::TK_AsIs, + traverse(TK_AsIs, cxxConstructExpr(hasParent(cxxFunctionalCastExpr()), hasDeclaration(cxxConstructorDecl(hasParent( cxxRecordDecl(matchesAnyName(Names)))))) diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index d1702b2d25b65a72eed7efff0c0d8084f963456c..b0c9ecab1e059e0b69a12882a7bb0f78ac697cf8 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -258,7 +258,7 @@ std::string printTemplateSpecializationArgs(const NamedDecl &ND) { // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we // create a new argument location list from TypeSourceInfo. auto STL = TSI->getTypeLoc().getAs(); - llvm::SmallVector ArgLocs; + llvm::SmallVector ArgLocs; ArgLocs.reserve(STL.getNumArgs()); for (unsigned I = 0; I < STL.getNumArgs(); ++I) ArgLocs.push_back(STL.getArgLoc(I)); @@ -303,8 +303,8 @@ SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI, std::string printType(const QualType QT, const DeclContext &CurContext) { std::string Result; llvm::raw_string_ostream OS(Result); - auto Decls = explicitReferenceTargets( - ast_type_traits::DynTypedNode::create(QT), DeclRelation::Alias); + auto Decls = + explicitReferenceTargets(DynTypedNode::create(QT), DeclRelation::Alias); if (!Decls.empty()) OS << getQualification(CurContext.getParentASTContext(), &CurContext, Decls.front(), diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index aa19a9485e171766e54a62872eb79d7df06b22e6..8b0d0591abe707b9e34f2bc938b029844452032f 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -139,7 +139,7 @@ ClangdServer::Options::operator TUScheduler::Options() const { ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, const ThreadsafeFS &TFS, const Options &Opts, Callbacks *Callbacks) - : ConfigProvider(Opts.ConfigProvider), TFS(TFS), + : ConfigProvider(Opts.ConfigProvider), TFS(TFS), ServerCallbacks(Callbacks), DynamicIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex(Opts.HeavyweightDynamicSymbolIndex, Opts.CollectMainFileRefs) @@ -829,16 +829,44 @@ Context ClangdServer::createProcessingContext(PathRef File) const { Params.Path = PosixPath.str(); } - auto DiagnosticHandler = [](const llvm::SMDiagnostic &Diag) { - if (Diag.getKind() == llvm::SourceMgr::DK_Error) { - elog("config error at {0}:{1}:{2}: {3}", Diag.getFilename(), - Diag.getLineNo(), Diag.getColumnNo(), Diag.getMessage()); - } else { - log("config warning at {0}:{1}:{2}: {3}", Diag.getFilename(), - Diag.getLineNo(), Diag.getColumnNo(), Diag.getMessage()); + llvm::StringMap> ReportableDiagnostics; + auto ConfigDiagnosticHandler = [&](const llvm::SMDiagnostic &D) { + // Ensure we create the map entry even for note diagnostics we don't report. + // This means that when the file is parsed with no warnings, we'll + // publish an empty set of diagnostics, clearing any the client has. + auto *Reportable = D.getFilename().empty() + ? nullptr + : &ReportableDiagnostics[D.getFilename()]; + switch (D.getKind()) { + case llvm::SourceMgr::DK_Error: + elog("config error at {0}:{1}:{2}: {3}", D.getFilename(), D.getLineNo(), + D.getColumnNo(), D.getMessage()); + if (Reportable) + Reportable->push_back(toDiag(D, Diag::ClangdConfig)); + break; + case llvm::SourceMgr::DK_Warning: + log("config warning at {0}:{1}:{2}: {3}", D.getFilename(), D.getLineNo(), + D.getColumnNo(), D.getMessage()); + if (Reportable) + Reportable->push_back(toDiag(D, Diag::ClangdConfig)); + break; + case llvm::SourceMgr::DK_Note: + case llvm::SourceMgr::DK_Remark: + vlog("config note at {0}:{1}:{2}: {3}", D.getFilename(), D.getLineNo(), + D.getColumnNo(), D.getMessage()); + break; } }; - Config C = ConfigProvider->getConfig(Params, DiagnosticHandler); + Config C = ConfigProvider->getConfig(Params, ConfigDiagnosticHandler); + // Blindly publish diagnostics for the (unopened) parsed config files. + // We must avoid reporting diagnostics for *the same file* concurrently. + // Source file diags are published elsewhere, but those are different files. + if (!ReportableDiagnostics.empty()) { + std::lock_guard Lock(ConfigDiagnosticsMu); + for (auto &Entry : ReportableDiagnostics) + ServerCallbacks->onDiagnosticsReady(Entry.first(), /*Version=*/"", + std::move(Entry.second)); + } return Context::current().derive(Config::Key, std::move(C)); } diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h index 35ba4686cc9a5d982d058fab5dc18e5c1bf31003..ff2fc8578103858b1b4a7148bcf6b531805a6a8b 100644 --- a/clang-tools-extra/clangd/ClangdServer.h +++ b/clang-tools-extra/clangd/ClangdServer.h @@ -363,6 +363,8 @@ private: config::Provider *ConfigProvider = nullptr; const ThreadsafeFS &TFS; + Callbacks *ServerCallbacks = nullptr; + mutable std::mutex ConfigDiagnosticsMu; Path ResourceDir; // The index used to look up symbols. This could be: diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 1d85439f53aff25f1afa2a79bd0ebf664a5a8e09..cc6b5dbc9904f20144b8e96dc1274cfdcc425034 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -173,9 +173,22 @@ struct CompletionCandidate { // Returns a token identifying the overload set this is part of. // 0 indicates it's not part of any overload set. - size_t overloadSet(const CodeCompleteOptions &Opts) const { + size_t overloadSet(const CodeCompleteOptions &Opts, llvm::StringRef FileName, + IncludeInserter *Inserter) const { if (!Opts.BundleOverloads.getValueOr(false)) return 0; + + // Depending on the index implementation, we can see different header + // strings (literal or URI) mapping to the same file. We still want to + // bundle those, so we must resolve the header to be included here. + std::string HeaderForHash; + if (Inserter) + if (auto Header = headerToInsertIfAllowed(Opts)) + if (auto HeaderFile = toHeaderFile(*Header, FileName)) + if (auto Spelled = + Inserter->calculateIncludePath(*HeaderFile, FileName)) + HeaderForHash = *Spelled; + llvm::SmallString<256> Scratch; if (IndexResult) { switch (IndexResult->SymInfo.Kind) { @@ -192,7 +205,7 @@ struct CompletionCandidate { // This could break #include insertion. return llvm::hash_combine( (IndexResult->Scope + IndexResult->Name).toStringRef(Scratch), - headerToInsertIfAllowed(Opts).getValueOr("")); + HeaderForHash); default: return 0; } @@ -206,8 +219,7 @@ struct CompletionCandidate { llvm::raw_svector_ostream OS(Scratch); D->printQualifiedName(OS); } - return llvm::hash_combine(Scratch, - headerToInsertIfAllowed(Opts).getValueOr("")); + return llvm::hash_combine(Scratch, HeaderForHash); } assert(IdentifierResult); return 0; @@ -1570,7 +1582,8 @@ private: assert(IdentifierResult); C.Name = IdentifierResult->Name; } - if (auto OverloadSet = C.overloadSet(Opts)) { + if (auto OverloadSet = C.overloadSet( + Opts, FileName, Inserter ? Inserter.getPointer() : nullptr)) { auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size()); if (Ret.second) Bundles.emplace_back(); diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index f6210a43b34eb3fab0f1815b08749f7909be452f..96cbd8806ff621c5c4254374763e54d8738d4330 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -367,7 +367,7 @@ llvm::ArrayRef ArgStripper::rulesFor(llvm::StringRef Arg) { for (unsigned ID = 1 /*Skip INVALID */; ID < DriverID::LastOption; ++ID) { if (PrevAlias[ID] || ID == DriverID::OPT_Xclang) continue; // Not canonical, or specially handled. - llvm::SmallVector Rules; + llvm::SmallVector Rules; // Iterate over each alias, to add rules for parsing it. for (unsigned A = ID; A != DriverID::OPT_INVALID; A = NextAlias[A]) { if (Prefixes[A] == nullptr) // option groups. diff --git a/clang-tools-extra/clangd/CompileCommands.h b/clang-tools-extra/clangd/CompileCommands.h index 3efd80026cf6b5117083eed8a027f06acba8a438..2ba17a0e6c0dc6afa6a1f3c37eda1dee126a4236 100644 --- a/clang-tools-extra/clangd/CompileCommands.h +++ b/clang-tools-extra/clangd/CompileCommands.h @@ -92,7 +92,7 @@ private: static llvm::ArrayRef rulesFor(llvm::StringRef Arg); const Rule *matchingRule(llvm::StringRef Arg, unsigned Mode, unsigned &ArgCount) const; - llvm::SmallVector Rules; + llvm::SmallVector Rules; std::deque Storage; // Store strings not found in option table. }; diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp index 846c6a170b389fc2351f610618bd132b607ccb3d..b1189e2868260c6d13e57ae0c145da217edc9b31 100644 --- a/clang-tools-extra/clangd/ConfigCompile.cpp +++ b/clang-tools-extra/clangd/ConfigCompile.cpp @@ -137,7 +137,7 @@ struct FragmentCompiler { llvm::StringRef EnumName; const Located &Input; llvm::Optional Result; - llvm::SmallVector ValidValues; + llvm::SmallVector ValidValues; public: EnumSwitch(llvm::StringRef EnumName, const Located &In, diff --git a/clang-tools-extra/clangd/ConfigProvider.cpp b/clang-tools-extra/clangd/ConfigProvider.cpp index 8a3991ed1c1ec541772f2d6319908fbb491d6964..05b2ba50566ddc7ae15138e32e08f6e24dfc2ba0 100644 --- a/clang-tools-extra/clangd/ConfigProvider.cpp +++ b/clang-tools-extra/clangd/ConfigProvider.cpp @@ -83,7 +83,7 @@ Provider::fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, const ThreadsafeFS &FS; mutable std::mutex Mu; - // Keys are the ancestor directory, not the actual config path within it. + // Keys are the (posix-style) ancestor directory, not the config within it. // We only insert into this map, so pointers to values are stable forever. // Mutex guards the map itself, not the values (which are threadsafe). mutable llvm::StringMap Cache; @@ -117,6 +117,8 @@ Provider::fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, if (It == Cache.end()) { llvm::SmallString<256> ConfigPath = Ancestor; path::append(ConfigPath, RelPath); + // Use native slashes for reading the file, affects diagnostics. + llvm::sys::path::native(ConfigPath); It = Cache.try_emplace(Ancestor, ConfigPath.str(), Ancestor).first; } Caches.push_back(&It->second); @@ -142,7 +144,7 @@ Provider::fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, std::unique_ptr Provider::combine(std::vector Providers) { - struct CombinedProvider : Provider { + class CombinedProvider : public Provider { std::vector Providers; std::vector @@ -154,14 +156,13 @@ Provider::combine(std::vector Providers) { } return Result; } + + public: + CombinedProvider(std::vector Providers) + : Providers(std::move(Providers)) {} }; - auto Result = std::make_unique(); - Result->Providers = std::move(Providers); - // FIXME: This is a workaround for a bug in older versions of clang (< 3.9) - // The constructor that is supposed to allow for Derived to Base - // conversion does not work. Remove this if we drop support for such - // configurations. - return std::unique_ptr(Result.release()); + + return std::make_unique(std::move(Providers)); } Config Provider::getConfig(const Params &P, DiagnosticCallback DC) const { diff --git a/clang-tools-extra/clangd/ConfigProvider.h b/clang-tools-extra/clangd/ConfigProvider.h index 67ab833ee5519d3b0cfca7748cf54e3e845e7b50..25d9450f28a7214d66d3504f30aa3450fcef28ff 100644 --- a/clang-tools-extra/clangd/ConfigProvider.h +++ b/clang-tools-extra/clangd/ConfigProvider.h @@ -46,6 +46,8 @@ struct Params { /// Used to report problems in parsing or interpreting a config. /// Errors reflect structurally invalid config that should be user-visible. /// Warnings reflect e.g. unknown properties that are recoverable. +/// Notes are used to report files and fragments. +/// (This can be used to track when previous warnings/errors have been "fixed"). using DiagnosticCallback = llvm::function_ref; /// A chunk of configuration that has been fully analyzed and is ready to apply. diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp index a3bb1eb29adb5200f524afe28d435d34000e998a..022d890a9687ea7c830c370c4419c791896c691a 100644 --- a/clang-tools-extra/clangd/ConfigYAML.cpp +++ b/clang-tools-extra/clangd/ConfigYAML.cpp @@ -273,10 +273,16 @@ std::vector Fragment::parseYAML(llvm::StringRef YAML, Fragment Fragment; Fragment.Source.Manager = SM; Fragment.Source.Location = N->getSourceRange().Start; + SM->PrintMessage(Fragment.Source.Location, llvm::SourceMgr::DK_Note, + "Parsing config fragment"); if (Parser(*SM).parse(Fragment, *N)) Result.push_back(std::move(Fragment)); } } + SM->PrintMessage(SM->FindLocForLineAndColumn(SM->getMainFileID(), 0, 0), + llvm::SourceMgr::DK_Note, + "Parsed " + llvm::Twine(Result.size()) + + " fragments from file"); // Hack: stash the buffer in the SourceMgr to keep it alive. // SM has two entries: "main" non-owning buffer, and ignored owning buffer. SM->AddNewSourceBuffer(std::move(Buf), llvm::SMLoc()); diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index a4429a7c945232cb3f41b30ecb1c548aa3edea59..7b59cedb0f67986da0701fdfe15816496f97863f 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -186,7 +186,7 @@ const char *getMainFileRange(const Diag &D, const SourceManager &SM, // Place the diagnostic the main file, rather than the header, if possible: // - for errors in included files, use the #include location -// - for errors in template instantiation, use the instantation location +// - for errors in template instantiation, use the instantiation location // In both cases, add the original header location as a note. bool tryMoveToMainFile(Diag &D, FullSourceLoc DiagLoc) { const SourceManager &SM = DiagLoc.getManager(); @@ -377,6 +377,32 @@ CodeAction toCodeAction(const Fix &F, const URIForFile &File) { return Action; } +Diag toDiag(const llvm::SMDiagnostic &D, Diag::DiagSource Source) { + Diag Result; + Result.Message = D.getMessage().str(); + switch (D.getKind()) { + case llvm::SourceMgr::DK_Error: + Result.Severity = DiagnosticsEngine::Error; + break; + case llvm::SourceMgr::DK_Warning: + Result.Severity = DiagnosticsEngine::Warning; + break; + default: + break; + } + Result.Source = Source; + Result.AbsFile = D.getFilename().str(); + Result.InsideMainFile = D.getSourceMgr()->FindBufferContainingLoc( + D.getLoc()) == D.getSourceMgr()->getMainFileID(); + if (D.getRanges().empty()) + Result.Range = {{D.getLineNo() - 1, D.getColumnNo()}, + {D.getLineNo() - 1, D.getColumnNo()}}; + else + Result.Range = {{D.getLineNo() - 1, (int)D.getRanges().front().first}, + {D.getLineNo() - 1, (int)D.getRanges().front().second}}; + return Result; +} + void toLSPDiags( const Diag &D, const URIForFile &File, const ClangdDiagnosticOptions &Opts, llvm::function_ref)> OutFn) { @@ -404,6 +430,9 @@ void toLSPDiags( case Diag::ClangTidy: Main.source = "clang-tidy"; break; + case Diag::ClangdConfig: + Main.source = "clangd-config"; + break; case Diag::Unknown: break; } diff --git a/clang-tools-extra/clangd/Diagnostics.h b/clang-tools-extra/clangd/Diagnostics.h index 4a00abfc450fc7e41e2a8d4f7110b3ccd51f2ecd..e1c3bcafcbf7f9cac5786fbd97cb65818082a93e 100644 --- a/clang-tools-extra/clangd/Diagnostics.h +++ b/clang-tools-extra/clangd/Diagnostics.h @@ -20,6 +20,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSet.h" +#include "llvm/Support/SourceMgr.h" #include #include @@ -86,10 +87,11 @@ struct Note : DiagBase {}; struct Diag : DiagBase { std::string Name; // if ID was recognized. // The source of this diagnostic. - enum { + enum DiagSource { Unknown, Clang, ClangTidy, + ClangdConfig, } Source = Unknown; /// Elaborate on the problem, usually pointing to a related piece of code. std::vector Notes; @@ -98,6 +100,8 @@ struct Diag : DiagBase { }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diag &D); +Diag toDiag(const llvm::SMDiagnostic &, Diag::DiagSource Source); + /// Conversion to LSP diagnostics. Formats the error message of each diagnostic /// to include all its notes. Notes inside main file are also provided as /// separate diagnostics with their corresponding fixits. Notes outside main diff --git a/clang-tools-extra/clangd/FileDistance.cpp b/clang-tools-extra/clangd/FileDistance.cpp index 584c64d077e17e15f7d5fe7bd7800e8459acf6ec..e1cead329189a2ab36bf0d0fd1e08827fc02b453 100644 --- a/clang-tools-extra/clangd/FileDistance.cpp +++ b/clang-tools-extra/clangd/FileDistance.cpp @@ -58,8 +58,7 @@ const llvm::hash_code FileDistance::RootHash = FileDistance::FileDistance(llvm::StringMap Sources, const FileDistanceOptions &Opts) : Opts(Opts) { - llvm::DenseMap> - DownEdges; + llvm::DenseMap> DownEdges; // Compute the best distance following only up edges. // Keep track of down edges, in case we can use them to improve on this. for (const auto &S : Sources) { @@ -118,7 +117,7 @@ FileDistance::FileDistance(llvm::StringMap Sources, unsigned FileDistance::distance(llvm::StringRef Path) { auto Canonical = canonicalize(Path); unsigned Cost = Unreachable; - llvm::SmallVector Ancestors; + llvm::SmallVector Ancestors; // Walk up ancestors until we find a path we know the distance for. for (llvm::StringRef Rest = Canonical; !Rest.empty(); Rest = parent_path(Rest, llvm::sys::path::Style::posix)) { @@ -177,7 +176,7 @@ FileDistance &URIDistance::forScheme(llvm::StringRef Scheme) { } static std::pair scopeToPath(llvm::StringRef Scope) { - llvm::SmallVector Split; + llvm::SmallVector Split; Scope.split(Split, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false); return {"/" + llvm::join(Split, "/"), Split.size()}; } diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index a9aa25805be4de118956213fd27d7027ad3de6d6..3afd6552268057556e74e5c48999b9cffe67e430 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -44,10 +44,8 @@ namespace clang { namespace clangd { namespace { -using ast_type_traits::DynTypedNode; -LLVM_ATTRIBUTE_UNUSED std::string -nodeToString(const ast_type_traits::DynTypedNode &N) { +LLVM_ATTRIBUTE_UNUSED std::string nodeToString(const DynTypedNode &N) { std::string S = std::string(N.getNodeKind().asStringRef()); { llvm::raw_string_ostream OS(S); @@ -335,13 +333,11 @@ private: RelSet Flags; template void debug(T &Node, RelSet Flags) { - dlog("visit [{0}] {1}", Flags, - nodeToString(ast_type_traits::DynTypedNode::create(Node))); + dlog("visit [{0}] {1}", Flags, nodeToString(DynTypedNode::create(Node))); } void report(const NamedDecl *D, RelSet Flags) { - dlog("--> [{0}] {1}", Flags, - nodeToString(ast_type_traits::DynTypedNode::create(*D))); + dlog("--> [{0}] {1}", Flags, nodeToString(DynTypedNode::create(*D))); auto It = Decls.try_emplace(D, std::make_pair(Flags, Decls.size())); // If already exists, update the flags. if (!It.second) @@ -684,7 +680,7 @@ public: } // namespace llvm::SmallVector, 1> -allTargetDecls(const ast_type_traits::DynTypedNode &N) { +allTargetDecls(const DynTypedNode &N) { dlog("allTargetDecls({0})", nodeToString(N)); TargetFinder Finder; DeclRelationSet Flags; @@ -708,8 +704,8 @@ allTargetDecls(const ast_type_traits::DynTypedNode &N) { return Finder.takeDecls(); } -llvm::SmallVector -targetDecl(const ast_type_traits::DynTypedNode &N, DeclRelationSet Mask) { +llvm::SmallVector targetDecl(const DynTypedNode &N, + DeclRelationSet Mask) { llvm::SmallVector Result; for (const auto &Entry : allTargetDecls(N)) { if (!(Entry.second & ~Mask)) @@ -750,9 +746,9 @@ explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask) { } namespace { -llvm::SmallVector refInDecl(const Decl *D) { +llvm::SmallVector refInDecl(const Decl *D) { struct Visitor : ConstDeclVisitor { - llvm::SmallVector Refs; + llvm::SmallVector Refs; void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { // We want to keep it as non-declaration references, as the @@ -819,10 +815,10 @@ llvm::SmallVector refInDecl(const Decl *D) { return V.Refs; } -llvm::SmallVector refInStmt(const Stmt *S) { +llvm::SmallVector refInStmt(const Stmt *S) { struct Visitor : ConstStmtVisitor { // FIXME: handle more complicated cases: more ObjC, designated initializers. - llvm::SmallVector Refs; + llvm::SmallVector Refs; void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) { Refs.push_back(ReferenceLoc{E->getNestedNameSpecifierLoc(), @@ -920,7 +916,7 @@ llvm::SmallVector refInStmt(const Stmt *S) { return V.Refs; } -llvm::SmallVector refInTypeLoc(TypeLoc L) { +llvm::SmallVector refInTypeLoc(TypeLoc L) { struct Visitor : TypeLocVisitor { llvm::Optional Ref; @@ -1114,7 +1110,7 @@ private: /// be references. However, declarations can have references inside them, /// e.g. 'namespace foo = std' references namespace 'std' and this /// function will return the corresponding reference. - llvm::SmallVector explicitReference(DynTypedNode N) { + llvm::SmallVector explicitReference(DynTypedNode N) { if (auto *D = N.get()) return refInDecl(D); if (auto *S = N.get()) diff --git a/clang-tools-extra/clangd/FindTarget.h b/clang-tools-extra/clangd/FindTarget.h index f328ae358c06559d096c96a49dc28caca1feae5e..435e4f4ac038b1f966a74596cdf4455545805186 100644 --- a/clang-tools-extra/clangd/FindTarget.h +++ b/clang-tools-extra/clangd/FindTarget.h @@ -80,15 +80,15 @@ class DeclRelationSet; /// If callers want to support such decls, they should cast the node directly. /// /// FIXME: some AST nodes cannot be DynTypedNodes, these cannot be specified. -llvm::SmallVector -targetDecl(const ast_type_traits::DynTypedNode &, DeclRelationSet Mask); +llvm::SmallVector targetDecl(const DynTypedNode &, + DeclRelationSet Mask); /// Similar to targetDecl(), however instead of applying a filter, all possible /// decls are returned along with their DeclRelationSets. /// This is suitable for indexing, where everything is recorded and filtering /// is applied later. llvm::SmallVector, 1> -allTargetDecls(const ast_type_traits::DynTypedNode &); +allTargetDecls(const DynTypedNode &); enum class DeclRelation : unsigned { // Template options apply when the declaration is an instantiated template. @@ -162,8 +162,7 @@ void findExplicitReferences(const ASTContext &AST, /// ^~~ there is no Decl for 'Ptr', so we return the template pattern. /// \p Mask should not contain TemplatePattern or TemplateInstantiation. llvm::SmallVector -explicitReferenceTargets(ast_type_traits::DynTypedNode N, - DeclRelationSet Mask); +explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask); // Boring implementation details of bitfield. diff --git a/clang-tools-extra/clangd/Headers.h b/clang-tools-extra/clangd/Headers.h index 164a2005ac91f9bf76f64d1dce8d0353760b6047..d86a4788f0a624c257cb71d4365ef700aebaea86 100644 --- a/clang-tools-extra/clangd/Headers.h +++ b/clang-tools-extra/clangd/Headers.h @@ -136,7 +136,7 @@ private: unsigned fileIndex(llvm::StringRef Name); llvm::StringMap NameToIndex; // Values are file indexes. // Maps a file's index to that of the files it includes. - llvm::DenseMap> IncludeChildren; + llvm::DenseMap> IncludeChildren; }; /// Returns a PPCallback that visits all inclusions in the main file. diff --git a/clang-tools-extra/clangd/QueryDriverDatabase.cpp b/clang-tools-extra/clangd/QueryDriverDatabase.cpp index d59263e739947e7916ecba440fb3cbe10cacf7b4..797771ce144eae074e51e900ea78f4dbb55f1e5c 100644 --- a/clang-tools-extra/clangd/QueryDriverDatabase.cpp +++ b/clang-tools-extra/clangd/QueryDriverDatabase.cpp @@ -79,7 +79,7 @@ llvm::Optional parseDriverOutput(llvm::StringRef Output) { const char SIS[] = "#include <...> search starts here:"; const char SIE[] = "End of search list."; const char TS[] = "Target: "; - llvm::SmallVector Lines; + llvm::SmallVector Lines; Output.split(Lines, '\n', /*MaxSplit=*/-1, /*KeepEmpty=*/false); enum { @@ -171,8 +171,8 @@ extractSystemIncludesAndTarget(PathRef Driver, llvm::StringRef Lang, llvm::Optional Redirects[] = { {""}, {""}, llvm::StringRef(StdErrPath)}; - llvm::SmallVector Args = {Driver, "-E", "-x", - Lang, "-", "-v"}; + llvm::SmallVector Args = {Driver, "-E", "-x", + Lang, "-", "-v"}; // These flags will be preserved const llvm::StringRef FlagsToPreserve[] = { diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp index fbd72be320a798e31920c17ec4eca25f04ada35f..cec6c035db58b1c45b86654806148de8aba6cc34 100644 --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -35,24 +35,26 @@ namespace clang { namespace clangd { namespace { using Node = SelectionTree::Node; -using ast_type_traits::DynTypedNode; // Measure the fraction of selections that were enabled by recovery AST. -void recordMetrics(const SelectionTree &S) { +void recordMetrics(const SelectionTree &S, const LangOptions &Lang) { + if (!trace::enabled()) + return; + const char *LanguageLabel = Lang.CPlusPlus ? "C++" : Lang.ObjC ? "ObjC" : "C"; static constexpr trace::Metric SelectionUsedRecovery( - "selection_recovery", trace::Metric::Distribution); - static constexpr trace::Metric RecoveryType("selection_recovery_type", - trace::Metric::Distribution); + "selection_recovery", trace::Metric::Distribution, "language"); + static constexpr trace::Metric RecoveryType( + "selection_recovery_type", trace::Metric::Distribution, "language"); const auto *Common = S.commonAncestor(); for (const auto *N = Common; N; N = N->Parent) { if (const auto *RE = N->ASTNode.get()) { - SelectionUsedRecovery.record(1); // used recovery ast. - RecoveryType.record(RE->isTypeDependent() ? 0 : 1); + SelectionUsedRecovery.record(1, LanguageLabel); // used recovery ast. + RecoveryType.record(RE->isTypeDependent() ? 0 : 1, LanguageLabel); return; } } if (Common) - SelectionUsedRecovery.record(0); // unused. + SelectionUsedRecovery.record(0, LanguageLabel); // unused. } // An IntervalSet maintains a set of disjoint subranges of an array. @@ -80,8 +82,8 @@ public: // Removes the elements of Claim from the set, modifying or removing ranges // that overlap it. // Returns the continuous subranges of Claim that were actually removed. - llvm::SmallVector, 4> erase(llvm::ArrayRef Claim) { - llvm::SmallVector, 4> Out; + llvm::SmallVector> erase(llvm::ArrayRef Claim) { + llvm::SmallVector> Out; if (Claim.empty()) return Out; @@ -834,7 +836,7 @@ SelectionTree::SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens, .printToString(SM)); Nodes = SelectionVisitor::collect(AST, Tokens, PrintPolicy, Begin, End, FID); Root = Nodes.empty() ? nullptr : &Nodes.front(); - recordMetrics(*this); + recordMetrics(*this, AST.getLangOpts()); dlog("Built selection tree\n{0}", *this); } diff --git a/clang-tools-extra/clangd/Selection.h b/clang-tools-extra/clangd/Selection.h index df7b6ac6ad9db77d8a1d9489979847dd432cc19c..775006f40f6cc661d5619245d25037ee2e0ced29 100644 --- a/clang-tools-extra/clangd/Selection.h +++ b/clang-tools-extra/clangd/Selection.h @@ -123,9 +123,9 @@ public: // The parent within the selection tree. nullptr for TranslationUnitDecl. Node *Parent; // Direct children within the selection tree. - llvm::SmallVector Children; + llvm::SmallVector Children; // The corresponding node from the full AST. - ast_type_traits::DynTypedNode ASTNode; + DynTypedNode ASTNode; // The extent to which this node is covered by the selection. Selection Selected; // Walk up the AST to get the DeclContext of this Node, diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 5397d328b0869127589e3c87827c7ed7d6e8c7ca..be0a5437cde6ed8e7ea0404629a6bdbc2208b4ca 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -571,7 +571,7 @@ llvm::StringRef toSemanticTokenType(HighlightingKind Kind) { case HighlightingKind::Enum: return "enum"; case HighlightingKind::EnumConstant: - return "enumConstant"; // nonstandard + return "enumMember"; case HighlightingKind::Typedef: return "type"; case HighlightingKind::DependentType: @@ -605,7 +605,7 @@ toTheiaSemanticHighlightingInformation( std::vector Lines; Lines.reserve(Tokens.size()); for (const auto &Line : Tokens) { - llvm::SmallVector LineByteTokens; + 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 diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp index bcd5758af44118315ef87b94f92b0462b01dc3e1..c0ccf21527509b8cae33a5b0dff4521b2c42b815 100644 --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -779,8 +779,8 @@ void parseNamespaceEvents(llvm::StringRef Code, const LangOptions &LangOpts, } // Returns the prefix namespaces of NS: {"" ... NS}. -llvm::SmallVector ancestorNamespaces(llvm::StringRef NS) { - llvm::SmallVector Results; +llvm::SmallVector ancestorNamespaces(llvm::StringRef NS) { + llvm::SmallVector Results; Results.push_back(NS.take_front(0)); NS.split(Results, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false); for (llvm::StringRef &R : Results) @@ -975,17 +975,30 @@ llvm::Optional locateMacroAt(const syntax::Token &SpelledTok, if (!IdentifierInfo || !IdentifierInfo->hadMacroDefinition()) return None; - // Get the definition just before the searched location so that a macro - // referenced in a '#undef MACRO' can still be found. Note that we only do - // that if Loc is not pointing at start of file. - if (SM.getLocForStartOfFile(SM.getFileID(Loc)) != Loc) - Loc = Loc.getLocWithOffset(-1); - MacroDefinition MacroDef = PP.getMacroDefinitionAtLoc(IdentifierInfo, Loc); - if (auto *MI = MacroDef.getMacroInfo()) - return DefinedMacro{ - IdentifierInfo->getName(), MI, - translatePreamblePatchLocation(MI->getDefinitionLoc(), SM)}; - return None; + // We need to take special case to handle #define and #undef. + // Preprocessor::getMacroDefinitionAtLoc() only considers a macro + // definition to be in scope *after* the location of the macro name in a + // #define that introduces it, and *before* the location of the macro name + // in an #undef that undefines it. To handle these cases, we check for + // the macro being in scope either just after or just before the location + // of the token. In getting the location before, we also take care to check + // for start-of-file. + FileID FID = SM.getFileID(Loc); + assert(Loc != SM.getLocForEndOfFile(FID)); + SourceLocation JustAfterToken = Loc.getLocWithOffset(1); + auto *MacroInfo = + PP.getMacroDefinitionAtLoc(IdentifierInfo, JustAfterToken).getMacroInfo(); + if (!MacroInfo && SM.getLocForStartOfFile(FID) != Loc) { + SourceLocation JustBeforeToken = Loc.getLocWithOffset(-1); + MacroInfo = PP.getMacroDefinitionAtLoc(IdentifierInfo, JustBeforeToken) + .getMacroInfo(); + } + if (!MacroInfo) { + return None; + } + return DefinedMacro{ + IdentifierInfo->getName(), MacroInfo, + translatePreamblePatchLocation(MacroInfo->getDefinitionLoc(), SM)}; } llvm::Expected Edit::apply() const { diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp index baf3f910b45ee8c95834c338ba1c3fe35a6312b5..443abcfe847ad31f0f29a10b299f489473d6bd81 100644 --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -477,7 +477,7 @@ private: /// thread are not locked, as it's the only writer. ParseInputs FileInputs; /* GUARDED_BY(Mutex) */ /// Times of recent AST rebuilds, used for UpdateDebounce computation. - llvm::SmallVector + llvm::SmallVector RebuildTimes; /* GUARDED_BY(Mutex) */ /// Set to true to signal run() to finish processing. bool Done; /* GUARDED_BY(Mutex) */ diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp index 687ae6501d25fc640dc345e30d9a692c20b99c1b..730a402b5df1a9dacdccded3af1b9ac643ab6c74 100644 --- a/clang-tools-extra/clangd/TidyProvider.cpp +++ b/clang-tools-extra/clangd/TidyProvider.cpp @@ -41,7 +41,8 @@ public: [this](llvm::Optional Data) { Value.reset(); if (Data && !Data->empty()) { - if (auto Parsed = tidy::parseConfiguration(*Data)) + if (auto Parsed = tidy::parseConfiguration( + llvm::MemoryBufferRef(*Data, path()))) Value = std::make_shared( std::move(*Parsed)); else @@ -81,7 +82,7 @@ public: // Compute absolute paths to all ancestors (substrings of P.Path). // Ensure cache entries for each ancestor exist in the map. llvm::StringRef Parent = path::parent_path(AbsPath); - llvm::SmallVector Caches; + llvm::SmallVector Caches; { std::lock_guard Lock(Mu); for (auto I = path::begin(Parent, path::Style::posix), @@ -105,7 +106,7 @@ public: // This will take a (per-file) lock for each file that actually exists. std::chrono::steady_clock::time_point FreshTime = std::chrono::steady_clock::now() - MaxStaleness; - llvm::SmallVector, 4> + llvm::SmallVector> OptionStack; for (const DotClangTidyCache *Cache : Caches) if (auto Config = Cache->get(FS, FreshTime)) { diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 8a85507ff14cfc1678ca8f07f1978237e4e22ded..ac4543026a9f6922c04ab28a9eb11270e4bca026 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -292,6 +292,35 @@ const NamedDecl *getPreferredDecl(const NamedDecl *D) { return D; } +std::vector findOverrides(llvm::DenseSet IDs, + const SymbolIndex *Index, + llvm::StringRef MainFilePath) { + if (IDs.empty()) + return {}; + RelationsRequest Req; + Req.Predicate = RelationKind::OverriddenBy; + Req.Subjects = std::move(IDs); + std::vector Results; + Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) { + auto DeclLoc = + indexToLSPLocation(Object.CanonicalDeclaration, MainFilePath); + if (!DeclLoc) { + elog("Find overrides: {0}", DeclLoc.takeError()); + return; + } + Results.emplace_back(); + Results.back().Name = Object.Name.str(); + Results.back().PreferredDeclaration = *DeclLoc; + auto DefLoc = indexToLSPLocation(Object.Definition, MainFilePath); + if (!DefLoc) { + elog("Failed to convert location: {0}", DefLoc.takeError()); + return; + } + Results.back().Definition = *DefLoc; + }); + return Results; +} + // Decls are more complicated. // The AST contains at least a declaration, maybe a definition. // These are up-to-date, and so generally preferred over index results. @@ -330,10 +359,19 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier, DeclRelation::TemplatePattern | DeclRelation::Alias; auto Candidates = getDeclAtPositionWithRelations(AST, CurLoc, Relations, NodeKind); + llvm::DenseSet VirtualMethods; for (const auto &E : Candidates) { const NamedDecl *D = E.first; - // Special case: void foo() ^override: jump to the overridden method. if (const auto *CMD = llvm::dyn_cast(D)) { + // Special case: virtual void ^method() = 0: jump to all overrides. + // FIXME: extend it to ^virtual, unfortunately, virtual location is not + // saved in the AST. + if (CMD->isPure()) { + if (TouchedIdentifier && SM.getSpellingLoc(CMD->getLocation()) == + TouchedIdentifier->location()) + VirtualMethods.insert(getSymbolID(CMD)); + } + // Special case: void foo() ^override: jump to the overridden method. const InheritableAttr *Attr = D->getAttr(); if (!Attr) Attr = D->getAttr(); @@ -420,6 +458,8 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier, }); } + auto Overrides = findOverrides(VirtualMethods, Index, MainFilePath); + Result.insert(Result.end(), Overrides.begin(), Overrides.end()); return Result; } @@ -1145,36 +1185,14 @@ std::vector findImplementations(ParsedAST &AST, Position Pos, CurLoc.takeError()); return {}; } - std::vector Results; DeclRelationSet Relations = DeclRelation::TemplatePattern | DeclRelation::Alias; - RelationsRequest Req; - Req.Predicate = RelationKind::OverriddenBy; + llvm::DenseSet VirtualMethods; for (const NamedDecl *ND : getDeclAtPosition(AST, *CurLoc, Relations)) if (const CXXMethodDecl *CXXMD = llvm::dyn_cast(ND)) if (CXXMD->isVirtual()) - Req.Subjects.insert(getSymbolID(ND)); - - if (Req.Subjects.empty()) - return Results; - Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) { - auto DeclLoc = - indexToLSPLocation(Object.CanonicalDeclaration, *MainFilePath); - if (!DeclLoc) { - elog("Find implementation: {0}", DeclLoc.takeError()); - return; - } - LocatedSymbol Loc; - Loc.Name = Object.Name.str(); - Loc.PreferredDeclaration = *DeclLoc; - auto DefLoc = indexToLSPLocation(Object.Definition, *MainFilePath); - if (DefLoc) - Loc.Definition = *DefLoc; - else - llvm::consumeError(DefLoc.takeError()); - Results.push_back(Loc); - }); - return Results; + VirtualMethods.insert(getSymbolID(ND)); + return findOverrides(std::move(VirtualMethods), Index, *MainFilePath); } ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, diff --git a/clang-tools-extra/clangd/index/FileIndex.cpp b/clang-tools-extra/clangd/index/FileIndex.cpp index 9a376df8dfecdcc124a8dfec085c442aebfe2511..1ccfb44856383832fec634f6ab89d9d63c9b36d8 100644 --- a/clang-tools-extra/clangd/index/FileIndex.cpp +++ b/clang-tools-extra/clangd/index/FileIndex.cpp @@ -366,8 +366,6 @@ FileSymbols::buildIndex(IndexType Type, DuplicateHandling DuplicateHandle, StorageSize += Slab->bytes(); for (const auto &RefSlab : RefSlabs) StorageSize += RefSlab->bytes(); - for (const auto &RelationSlab : RelationSlabs) - StorageSize += RelationSlab->bytes(); // Index must keep the slabs and contiguous ranges alive. switch (Type) { diff --git a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp index 7652dbb92d020276f70e0caef40b4933f0a9ca80..49f16e72be92abc302828176987b3e0ceed262b8 100644 --- a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp +++ b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp @@ -11,6 +11,8 @@ // //===----------------------------------------------------------------------===// +#include "index/Index.h" +#include "index/Relation.h" #include "index/Serialization.h" #include "index/dex/Dex.h" #include "index/remote/Client.h" @@ -153,7 +155,7 @@ class FuzzyFind : public Command { Request.Limit = Limit; Request.Query = Query; if (Scopes.getNumOccurrences() > 0) { - llvm::SmallVector Scopes; + llvm::SmallVector Scopes; llvm::StringRef(this->Scopes).split(Scopes, ','); Request.Scopes = {Scopes.begin(), Scopes.end()}; } @@ -267,6 +269,43 @@ class Refs : public Command { } }; +class Relations : public Command { + llvm::cl::opt ID{ + "id", + llvm::cl::Positional, + llvm::cl::desc("Symbol ID of the symbol being queried (hex)."), + }; + llvm::cl::opt Relation{ + "relation", + llvm::cl::desc("Relation kind for the predicate."), + values(clEnumValN(RelationKind::BaseOf, "base_of", + "Find subclasses of a class."), + clEnumValN(RelationKind::OverriddenBy, "overridden_by", + "Find methods that overrides a virtual method.")), + }; + + void run() override { + if (ID.getNumOccurrences() == 0 || Relation.getNumOccurrences() == 0) { + llvm::errs() + << "Missing required argument: please provide id and -relation.\n"; + return; + } + RelationsRequest Req; + if (ID.getNumOccurrences()) { + auto SID = SymbolID::fromStr(ID); + if (!SID) { + llvm::errs() << llvm::toString(SID.takeError()) << "\n"; + return; + } + Req.Subjects.insert(*SID); + } + Req.Predicate = Relation.getValue(); + Index->relations(Req, [](const SymbolID &SID, const Symbol &S) { + llvm::outs() << toYAML(S); + }); + } +}; + class Export : public Command { llvm::cl::opt Format{ "format", @@ -326,6 +365,8 @@ struct { {"lookup", "Dump symbol details by ID or qualified name", std::make_unique}, {"refs", "Find references by ID or qualified name", std::make_unique}, + {"relations", "Find relations by ID and relation kind", + std::make_unique}, {"export", "Export index", std::make_unique}, }; @@ -339,7 +380,7 @@ std::unique_ptr openIndex(llvm::StringRef Index) { bool runCommand(std::string Request, const SymbolIndex &Index) { // Split on spaces and add required null-termination. std::replace(Request.begin(), Request.end(), ' ', '\0'); - llvm::SmallVector Args; + llvm::SmallVector Args; llvm::StringRef(Request).split(Args, '\0', /*MaxSplit=*/-1, /*KeepEmpty=*/false); if (Args.empty()) @@ -351,7 +392,7 @@ bool runCommand(std::string Request, const SymbolIndex &Index) { llvm::outs() << "Get detailed command help with e.g. `find -help`.\n"; return true; } - llvm::SmallVector FakeArgv; + llvm::SmallVector FakeArgv; for (llvm::StringRef S : Args) FakeArgv.push_back(S.data()); // Terminated by separator or end of string. diff --git a/clang-tools-extra/clangd/index/remote/Client.cpp b/clang-tools-extra/clangd/index/remote/Client.cpp index 4980a4bee74e36afa7f218ef8fec7c3eda827262..0387e65db7d026fcdcb0dff8e009e2ce221d26d8 100644 --- a/clang-tools-extra/clangd/index/remote/Client.cpp +++ b/clang-tools-extra/clangd/index/remote/Client.cpp @@ -15,6 +15,7 @@ #include "support/Logger.h" #include "support/Trace.h" #include "clang/Basic/Version.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -42,10 +43,13 @@ class IndexClient : public clangd::SymbolIndex { SPAN_ATTACH(Tracer, "Request", RPCRequest.DebugString()); grpc::ClientContext Context; Context.AddMetadata("version", clang::getClangToolFullVersion("clangd")); - std::chrono::system_clock::time_point Deadline = - std::chrono::system_clock::now() + DeadlineWaitingTime; + std::chrono::system_clock::time_point StartTime = + std::chrono::system_clock::now(); + auto Deadline = StartTime + DeadlineWaitingTime; Context.set_deadline(Deadline); auto Reader = (Stub.get()->*RPCCall)(&Context, RPCRequest); + dlog("Sending {0}: {1}", RequestT::descriptor()->name(), + RPCRequest.DebugString()); ReplyT Reply; unsigned Successful = 0; unsigned FailedToParse = 0; @@ -65,6 +69,11 @@ class IndexClient : public clangd::SymbolIndex { Callback(*Response); ++Successful; } + auto Millis = std::chrono::duration_cast( + std::chrono::system_clock::now() - StartTime) + .count(); + vlog("Remote index [{0}]: {1} => {2} results in {3}ms.", ServerAddress, + RequestT::descriptor()->name(), Successful, Millis); SPAN_ATTACH(Tracer, "Status", Reader->Finish().ok()); SPAN_ATTACH(Tracer, "Successful", Successful); SPAN_ATTACH(Tracer, "Failed to parse", FailedToParse); @@ -74,11 +83,12 @@ class IndexClient : public clangd::SymbolIndex { public: IndexClient( std::shared_ptr Channel, llvm::StringRef ProjectRoot, + llvm::StringRef Address, std::chrono::milliseconds DeadlineTime = std::chrono::milliseconds(1000)) : Stub(remote::v1::SymbolIndex::NewStub(Channel)), ProtobufMarshaller(new Marshaller(/*RemoteIndexRoot=*/"", /*LocalIndexRoot=*/ProjectRoot)), - DeadlineWaitingTime(DeadlineTime) { + ServerAddress(Address), DeadlineWaitingTime(DeadlineTime) { assert(!ProjectRoot.empty()); } @@ -119,6 +129,7 @@ public: private: std::unique_ptr Stub; std::unique_ptr ProtobufMarshaller; + llvm::SmallString<256> ServerAddress; // Each request will be terminated if it takes too long. std::chrono::milliseconds DeadlineWaitingTime; }; @@ -131,7 +142,7 @@ std::unique_ptr getClient(llvm::StringRef Address, grpc::CreateChannel(Address.str(), grpc::InsecureChannelCredentials()); Channel->GetState(true); return std::unique_ptr( - new IndexClient(Channel, ProjectRoot)); + new IndexClient(Channel, ProjectRoot, Address)); } } // namespace remote diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index 946daaf6d158da6e25623af265f2b5931dcfb31f..8ed5811c88b292f1b1b85e1a91b264f2daa72c0c 100644 --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -129,7 +129,8 @@ const NamedDecl *canonicalRenameDecl(const NamedDecl *D) { // CXXMethodDecl::getInstantiatedFromMemberFunction for the field because // Clang AST does not store relevant information about the field that is // instantiated. - const auto *FieldParent = dyn_cast(Field->getParent()); + const auto *FieldParent = + dyn_cast_or_null(Field->getParent()); if (!FieldParent) return Field->getCanonicalDecl(); FieldParent = FieldParent->getTemplateInstantiationPattern(); @@ -636,7 +637,10 @@ llvm::Expected rename(const RenameInputs &RInputs) { if (DeclsUnderCursor.size() > 1) return makeError(ReasonToReject::AmbiguousSymbol); const auto &RenameDecl = **DeclsUnderCursor.begin(); - if (RenameDecl.getName() == RInputs.NewName) + const auto *ID = RenameDecl.getIdentifier(); + if (!ID) + return makeError(ReasonToReject::UnsupportedSymbol); + if (ID->getName() == RInputs.NewName) return makeError(ReasonToReject::SameName); auto Invalid = checkName(RenameDecl, RInputs.NewName); if (Invalid) diff --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp index b00c2716005c7ff02e7b199684678b8a8955521b..d6a57efeeef13af16a9297f38f2f1dde6928fdee 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp @@ -274,6 +274,8 @@ bool AddUsing::prepare(const Selection &Inputs) { } else if (auto *T = Node->ASTNode.get()) { if (auto E = T->getAs()) { QualifierToRemove = E.getQualifierLoc(); + if (!QualifierToRemove) + return false; auto SpelledTokens = TB.spelledForExpanded(TB.expandedTokens(E.getSourceRange())); diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp index 02be220e0b6c5d70b8aa166c105af8c7003b5c71..f1c6f666e7d051d9f50e488eb4a70006809b1ee5 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp @@ -84,7 +84,7 @@ llvm::Optional getSemicolonForDecl(const FunctionDecl *FD) { // or the function decl to be selected. Returns null if none of the above // criteria is met. const FunctionDecl *getSelectedFunction(const SelectionTree::Node *SelNode) { - const ast_type_traits::DynTypedNode &AstNode = SelNode->ASTNode; + const DynTypedNode &AstNode = SelNode->ASTNode; if (const FunctionDecl *FD = AstNode.get()) return FD; if (AstNode.get() && @@ -480,7 +480,7 @@ public: const tooling::Replacement DeleteFuncBody(SM, DefRange->getBegin(), SourceLen, ""); - llvm::SmallVector, 2> Edits; + llvm::SmallVector> Edits; // Edit for Target. auto FE = Effect::fileEdit(SM, SM.getFileID(*Semicolon), std::move(TargetFileReplacements)); diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp index 23b0e00d9aa5fd9d88db59940dcd7cf645a6dc65..6f7ad2e2a541cbab3601f35c70280c4be53245a7 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp @@ -51,7 +51,7 @@ namespace { const FunctionDecl *getSelectedFunction(const SelectionTree::Node *SelNode) { if (!SelNode) return nullptr; - const ast_type_traits::DynTypedNode &AstNode = SelNode->ASTNode; + const DynTypedNode &AstNode = SelNode->ASTNode; if (const FunctionDecl *FD = AstNode.get()) return FD; if (AstNode.get() && diff --git a/clang-tools-extra/clangd/refactor/tweaks/DumpAST.cpp b/clang-tools-extra/clangd/refactor/tweaks/DumpAST.cpp index 72e7cd5a252790240559ddda173b6b33139e18fc..d7a7852925db5dece02b38104f35a6951a77f557 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/DumpAST.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/DumpAST.cpp @@ -49,13 +49,13 @@ public: bool hidden() const override { return true; } private: - static bool dumpable(const ast_type_traits::DynTypedNode &N) { + static bool dumpable(const DynTypedNode &N) { // Sadly not all node types can be dumped, and there's no API to check. // See DynTypedNode::dump(). return N.get() || N.get() || N.get(); } - llvm::Optional Node; + llvm::Optional Node; }; REGISTER_TWEAK(DumpAST) diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp index 61f68a68825226f03343fe54b2116ba0ea7267e9..6d38eb1de82a1e57d764eecfa8be5502973d3af0 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp @@ -63,6 +63,25 @@ bool isStructuredBindingType(const SelectionTree::Node *N) { return N && N->ASTNode.get(); } +// Returns true iff Node is a lambda, and thus should not be expanded. Loc is +// the location of the auto type. +bool isDeducedAsLambda(const SelectionTree::Node *Node, SourceLocation Loc) { + // getDeducedType() does a traversal, which we want to avoid in prepare(). + // But at least check this isn't auto x = []{...};, which can't ever be + // expanded. + // (It would be nice if we had an efficient getDeducedType(), instead). + for (const auto *It = Node; It; It = It->Parent) { + if (const auto *DD = It->ASTNode.get()) { + if (DD->getTypeSourceInfo() && + DD->getTypeSourceInfo()->getTypeLoc().getBeginLoc() == Loc) { + if (auto *RD = DD->getType()->getAsRecordDecl()) + return RD->isLambda(); + } + } + } + return false; +} + bool ExpandAutoType::prepare(const Selection& Inputs) { CachedLocation = llvm::None; if (auto *Node = Inputs.ASTSelection.commonAncestor()) { @@ -70,11 +89,13 @@ bool ExpandAutoType::prepare(const Selection& Inputs) { if (const AutoTypeLoc Result = TypeNode->getAs()) { // Code in apply() does handle 'decltype(auto)' yet. if (!Result.getTypePtr()->isDecltypeAuto() && - !isStructuredBindingType(Node)) + !isStructuredBindingType(Node) && + !isDeducedAsLambda(Node, Result.getBeginLoc())) CachedLocation = Result; } } } + return (bool) CachedLocation; } diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp index 18fe7bf3916045c79d4f9bbb8b1de4b91f0331f3..8eec42876d6bd57f35956104df4f9ed732a86b78 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp @@ -708,6 +708,27 @@ tooling::Replacement createFunctionDefinition(const NewFunction &ExtractedFunc, return tooling::Replacement(SM, ExtractedFunc.InsertionPoint, 0, FunctionDef); } +// Returns true if ExtZone contains any ReturnStmts. +bool hasReturnStmt(const ExtractionZone &ExtZone) { + class ReturnStmtVisitor + : public clang::RecursiveASTVisitor { + public: + bool VisitReturnStmt(ReturnStmt *Return) { + Found = true; + return false; // We found the answer, abort the scan. + } + bool Found = false; + }; + + ReturnStmtVisitor V; + for (const Stmt *RootStmt : ExtZone.RootStmts) { + V.TraverseStmt(const_cast(RootStmt)); + if (V.Found) + break; + } + return V.Found; +} + bool ExtractFunction::prepare(const Selection &Inputs) { const LangOptions &LangOpts = Inputs.AST->getLangOpts(); if (!LangOpts.CPlusPlus) @@ -715,8 +736,12 @@ bool ExtractFunction::prepare(const Selection &Inputs) { const Node *CommonAnc = Inputs.ASTSelection.commonAncestor(); const SourceManager &SM = Inputs.AST->getSourceManager(); auto MaybeExtZone = findExtractionZone(CommonAnc, SM, LangOpts); + if (!MaybeExtZone || + (hasReturnStmt(*MaybeExtZone) && !alwaysReturns(*MaybeExtZone))) + return false; + // FIXME: Get rid of this check once we support hoisting. - if (!MaybeExtZone || MaybeExtZone->requiresHoisting(SM)) + if (MaybeExtZone->requiresHoisting(SM)) return false; ExtZone = std::move(*MaybeExtZone); diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp index 8feef4e847222b7efa33d087e9d42015b5006b02..bcf9bbe00f7cbb778dbeae9ee6affbdc74cfe88e 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp @@ -202,7 +202,7 @@ ExtractionContext::insertDeclaration(llvm::StringRef VarName, struct ParsedBinaryOperator { BinaryOperatorKind Kind; SourceLocation ExprLoc; - llvm::SmallVector SelectedOperands; + llvm::SmallVector SelectedOperands; // If N is a binary operator, populate this and return true. bool parse(const SelectionTree::Node &N) { diff --git a/clang-tools-extra/clangd/support/Markup.cpp b/clang-tools-extra/clangd/support/Markup.cpp index 9dffdf675d3ee1bcf217bb824f3bf777dcf31458..60ad9464b2f6598c5de72bb33d4dae7cf448f509 100644 --- a/clang-tools-extra/clangd/support/Markup.cpp +++ b/clang-tools-extra/clangd/support/Markup.cpp @@ -215,7 +215,7 @@ std::string getMarkerForCodeBlock(llvm::StringRef Input) { // Trims the input and concatenates whitespace blocks into a single ` `. std::string canonicalizeSpaces(llvm::StringRef Input) { - llvm::SmallVector Words; + llvm::SmallVector Words; llvm::SplitString(Input, Words); return llvm::join(Words, " "); } diff --git a/clang-tools-extra/clangd/support/ThreadsafeFS.cpp b/clang-tools-extra/clangd/support/ThreadsafeFS.cpp index cadda8efa09525a01c57bd2a38e74f80f90c439e..ae9450f17411a53940b8e9605c254e13e6b8511b 100644 --- a/clang-tools-extra/clangd/support/ThreadsafeFS.cpp +++ b/clang-tools-extra/clangd/support/ThreadsafeFS.cpp @@ -87,8 +87,7 @@ RealThreadsafeFS::viewImpl() const { // Avoid using memory-mapped files. // FIXME: Try to use a similar approach in Sema instead of relying on // propagation of the 'isVolatile' flag through all layers. - return new VolatileFileSystem( - llvm::vfs::createPhysicalFileSystem().release()); + return new VolatileFileSystem(llvm::vfs::createPhysicalFileSystem()); } } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/test/check-fail.test b/clang-tools-extra/clangd/test/check-fail.test index 0ee777f02cc5589da4f741ee6a84da71bcf548bc..dd50b59b2c790055e0b68816988807a356f81f55 100644 --- a/clang-tools-extra/clangd/test/check-fail.test +++ b/clang-tools-extra/clangd/test/check-fail.test @@ -11,4 +11,5 @@ // CHECK: All checks completed, 2 errors #include "missing.h" -auto x = []{}; +void fun(); +auto x = fun; diff --git a/clang-tools-extra/clangd/test/config.test b/clang-tools-extra/clangd/test/config.test new file mode 100644 index 0000000000000000000000000000000000000000..eb556feefd955870da1e40c0fa1555c01dff99e4 --- /dev/null +++ b/clang-tools-extra/clangd/test/config.test @@ -0,0 +1,66 @@ +# We specify a custom path in XDG_CONFIG_HOME, which only works on some systems. +# UNSUPPORTED: system-windows +# UNSUPPORTED: system-darwin + +# RUN: rm -rf %t +# RUN: mkdir -p %t/clangd + +# Create a config file that injects a flag we can observe, and has an error. +# RUN: echo 'Foo: bar' > %t/clangd/config.yaml +# RUN: echo 'CompileFlags: {Add: -DFOO=BAR}' >> %t/clangd/config.yaml + +# RUN: env XDG_CONFIG_HOME=%t clangd -lit-test -enable-config < %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:///foo.c","languageId":"c","text":"int x = FOO;"}}} +# First, the errors from the config file. +# CHECK: "method": "textDocument/publishDiagnostics", +# CHECK-NEXT: "params": { +# CHECK-NEXT: "diagnostics": [ +# CHECK-NEXT: { +# CHECK-NEXT: "message": "Unknown Config key Foo", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 3, +# CHECK-NEXT: "line": 0 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 0, +# CHECK-NEXT: "line": 0 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "severity": 2, +# CHECK-NEXT: "source": "clangd-config" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "uri": "file://{{.*}}/config.yaml" +# CHECK-NEXT: } +# Next, the error from the main file. BAR rather than FOO means we used config. +# CHECK: "method": "textDocument/publishDiagnostics", +# CHECK-NEXT: "params": { +# CHECK-NEXT: "diagnostics": [ +# CHECK-NEXT: { +# CHECK-NEXT: "code": "undeclared_var_use", +# CHECK-NEXT: "message": "Use of undeclared identifier 'BAR'", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 11, +# CHECK-NEXT: "line": 0 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 8, +# CHECK-NEXT: "line": 0 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "severity": 1, +# CHECK-NEXT: "source": "clang" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "uri": "file://{{.*}}/foo.c", +# CHECK-NEXT: "version": 0 +# CHECK-NEXT: } +--- +{"jsonrpc":"2.0","id":4,"method":"shutdown"} +--- +{"jsonrpc":"2.0","method":"exit"} diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index 72ce97ed31b61f2433d87bf8f8d635bf3817e8be..10f10f200471dabb0a21032208ec6ca759b32afe 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -93,8 +93,6 @@ add_unittest(ClangdUnitTests ClangdTests TestTU.cpp TestWorkspace.cpp TypeHierarchyTests.cpp - TweakTests.cpp - TweakTesting.cpp URITests.cpp XRefsTests.cpp ${CMAKE_CURRENT_BINARY_DIR}/DecisionForestRuntimeTest.cpp @@ -108,6 +106,26 @@ add_unittest(ClangdUnitTests ClangdTests support/TestTracer.cpp support/TraceTests.cpp + tweaks/AddUsingTests.cpp + tweaks/AnnotateHighlightingsTests.cpp + tweaks/DefineInlineTests.cpp + tweaks/DefineOutlineTests.cpp + tweaks/DumpASTTests.cpp + tweaks/DumpRecordLayoutTests.cpp + tweaks/DumpSymbolTests.cpp + tweaks/ExpandAutoTypeTests.cpp + tweaks/ExpandMacroTests.cpp + tweaks/ExtractFunctionTests.cpp + tweaks/ExtractVariableTests.cpp + tweaks/ObjCLocalizeStringLiteralTests.cpp + tweaks/PopulateSwitchTests.cpp + tweaks/RawStringLiteralTests.cpp + tweaks/RemoveUsingNamespaceTests.cpp + tweaks/ShowSelectionTreeTests.cpp + tweaks/SwapIfBranchesTests.cpp + tweaks/TweakTesting.cpp + tweaks/TweakTests.cpp + ${REMOTE_TEST_SOURCES} $ diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index a7e1c6c481431bd631913edaaff5f95765ed43aa..a19c6a83e95460b7a8c23c145f35581c32440bbf 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1628,6 +1628,29 @@ TEST(CompletionTest, OverloadBundling) { EXPECT_EQ(A.SnippetSuffix, "($0)"); } +TEST(CompletionTest, OverloadBundlingSameFileDifferentURI) { + clangd::CodeCompleteOptions Opts; + Opts.BundleOverloads = true; + + Symbol SymX = sym("ns::X", index::SymbolKind::Function, "@F@\\0#"); + Symbol SymY = sym("ns::X", index::SymbolKind::Function, "@F@\\0#I#"); + std::string BarHeader = testPath("bar.h"); + auto BarURI = URI::create(BarHeader).toString(); + SymX.CanonicalDeclaration.FileURI = BarURI.c_str(); + SymY.CanonicalDeclaration.FileURI = BarURI.c_str(); + // The include header is different, but really it's the same file. + SymX.IncludeHeaders.emplace_back("\"bar.h\"", 1); + SymY.IncludeHeaders.emplace_back(BarURI.c_str(), 1); + + auto Results = completions("void f() { ::ns::^ }", {SymX, SymY}, Opts); + // Expect both results are bundled, despite the different-but-same + // IncludeHeader. + ASSERT_EQ(1u, Results.Completions.size()); + const auto &R = Results.Completions.front(); + EXPECT_EQ("X", R.Name); + EXPECT_EQ(2u, R.BundleSize); +} + TEST(CompletionTest, DocumentationFromChangedFileCrash) { MockFS FS; auto FooH = testPath("foo.h"); diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp index 1acbcd94ac84ec40139b787182d4bd5822032107..d91117956b095f168f15806319b50ad89b35e3ab 100644 --- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp +++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp @@ -208,7 +208,7 @@ TEST(CommandMangler, ConfigEdits) { } static std::string strip(llvm::StringRef Arg, llvm::StringRef Argv) { - llvm::SmallVector Parts; + llvm::SmallVector Parts; llvm::SplitString(Argv, Parts); std::vector Args = {Parts.begin(), Parts.end()}; ArgStripper S; diff --git a/clang-tools-extra/clangd/unittests/ConfigProviderTests.cpp b/clang-tools-extra/clangd/unittests/ConfigProviderTests.cpp index d6af5856cc49ce78e00e9f1b3c715ea38f884a90..9c45266d1a83d2fa9a20b649fe9cf94966491b67 100644 --- a/clang-tools-extra/clangd/unittests/ConfigProviderTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigProviderTests.cpp @@ -96,21 +96,26 @@ TEST(ProviderTest, FromYAMLFile) { auto Cfg = P->getConfig(Params(), Diags.callback()); EXPECT_THAT(Diags.Diagnostics, ElementsAre(DiagMessage("Unknown CompileFlags key Unknown"))); + EXPECT_THAT(Diags.Files, ElementsAre(testPath("foo.yaml"))); EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo")); - Diags.Diagnostics.clear(); + Diags.clear(); Cfg = P->getConfig(Params(), Diags.callback()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "Cached, not re-parsed"; + EXPECT_THAT(Diags.Files, IsEmpty()); EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo")); FS.Files["foo.yaml"] = AddBarBaz; Cfg = P->getConfig(Params(), Diags.callback()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "New config, no errors"; + EXPECT_THAT(Diags.Files, ElementsAre(testPath("foo.yaml"))); EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("bar", "baz")); + Diags.clear(); FS.Files.erase("foo.yaml"); Cfg = P->getConfig(Params(), Diags.callback()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "Missing file is not an error"; + EXPECT_THAT(Diags.Files, IsEmpty()); EXPECT_THAT(getAddedArgs(Cfg), IsEmpty()); } @@ -133,21 +138,27 @@ TEST(ProviderTest, FromAncestorRelativeYAMLFiles) { auto Cfg = P->getConfig(Params(), Diags.callback()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); + EXPECT_THAT(Diags.Files, IsEmpty()); EXPECT_THAT(getAddedArgs(Cfg), IsEmpty()); Cfg = P->getConfig(ABCParams, Diags.callback()); EXPECT_THAT(Diags.Diagnostics, ElementsAre(DiagMessage("Unknown CompileFlags key Unknown"))); + // FIXME: fails on windows: paths have mixed slashes like C:\a/b\c.yaml + EXPECT_THAT(Diags.Files, + ElementsAre(testPath("a/foo.yaml"), testPath("a/b/c/foo.yaml"))); EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo", "bar", "baz")); - Diags.Diagnostics.clear(); + Diags.clear(); Cfg = P->getConfig(AParams, Diags.callback()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "Cached config"; + EXPECT_THAT(Diags.Files, IsEmpty()); EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo")); FS.Files.erase("a/foo.yaml"); Cfg = P->getConfig(ABCParams, Diags.callback()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); + EXPECT_THAT(Diags.Files, IsEmpty()); EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("bar", "baz")); } @@ -169,7 +180,7 @@ TEST(ProviderTest, Staleness) { EXPECT_THAT(Diags.Diagnostics, ElementsAre(DiagMessage("Unknown CompileFlags key Unknown"))); EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo")); - Diags.Diagnostics.clear(); + Diags.clear(); // Stale value reused by policy. FS.Files["foo.yaml"] = AddBarBaz; @@ -211,14 +222,14 @@ CompileFlags: auto Cfg = P->getConfig(Bar, Diags.callback()); ASSERT_THAT(Diags.Diagnostics, IsEmpty()); EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("bar")); - Diags.Diagnostics.clear(); + Diags.clear(); // This should be a relative match/exclude hence baz/bar.h should be excluded. P = Provider::fromAncestorRelativeYAMLFiles("foo.yaml", FS); Cfg = P->getConfig(Bar, Diags.callback()); ASSERT_THAT(Diags.Diagnostics, IsEmpty()); EXPECT_THAT(getAddedArgs(Cfg), IsEmpty()); - Diags.Diagnostics.clear(); + Diags.clear(); } } // namespace } // namespace config diff --git a/clang-tools-extra/clangd/unittests/ConfigTesting.h b/clang-tools-extra/clangd/unittests/ConfigTesting.h index 5541c6fffe59678063d1f93572b57471c257770f..46c51e80b6bc09b0e6a989a2a8d7482b49c13b63 100644 --- a/clang-tools-extra/clangd/unittests/ConfigTesting.h +++ b/clang-tools-extra/clangd/unittests/ConfigTesting.h @@ -24,6 +24,12 @@ namespace config { struct CapturedDiags { std::function callback() { return [this](const llvm::SMDiagnostic &D) { + if (Files.empty() || Files.back() != D.getFilename()) + Files.push_back(D.getFilename().str()); + + if (D.getKind() > llvm::SourceMgr::DK_Warning) + return; + Diagnostics.emplace_back(); Diag &Out = Diagnostics.back(); Out.Message = D.getMessage().str(); @@ -50,7 +56,13 @@ struct CapturedDiags { << D.Message << "@" << llvm::to_string(D.Pos); } }; - std::vector Diagnostics; + std::vector Diagnostics; // Warning or higher. + std::vector Files; // Filename from diagnostics including notes. + + void clear() { + Diagnostics.clear(); + Files.clear(); + } }; MATCHER_P(DiagMessage, M, "") { return arg.Message == M; } diff --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp index 1da0f3a1cc7166076d607e85eed39a06dfe57c12..54ef7d1d85cdd232378e65b4ef82d9f416f30887 100644 --- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp @@ -67,6 +67,7 @@ ClangTidy: )yaml"; auto Results = Fragment::parseYAML(YAML, "config.yaml", Diags.callback()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); + EXPECT_THAT(Diags.Files, ElementsAre("config.yaml")); ASSERT_EQ(Results.size(), 4u); EXPECT_FALSE(Results[0].If.HasUnrecognizedCondition); EXPECT_THAT(Results[0].If.PathMatch, ElementsAre(Val("abc"))); diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp index 2382dba19659b78ff47244041e57269bec0ddfb1..0aa87c61baebc72c00f85899624e47f13e534842 100644 --- a/clang-tools-extra/clangd/unittests/RenameTests.cpp +++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp @@ -816,6 +816,13 @@ TEST(RenameTest, WithinFileRename) { [[F^oo]] foo = static_cast<[[F^oo]]>(boo); } )cpp", + + // ObjC, should not crash. + R"cpp( + @interface ObjC { + char [[da^ta]]; + } @end + )cpp", }; llvm::StringRef NewName = "NewName"; for (llvm::StringRef T : Tests) { @@ -823,6 +830,7 @@ TEST(RenameTest, WithinFileRename) { Annotations Code(T); auto TU = TestTU::withCode(Code.code()); TU.ExtraArgs.push_back("-fno-delayed-template-parsing"); + TU.ExtraArgs.push_back("-xobjective-c++"); auto AST = TU.build(); for (const auto &RenamePos : Code.points()) { auto RenameResult = @@ -938,6 +946,13 @@ TEST(RenameTest, Renameable) { )cpp", "not a supported kind", !HeaderFile, Index}, + {R"cpp(// disallow rename on non-normal identifiers. + @interface Foo {} + -(int) fo^o:(int)x; // Token is an identifier, but declaration name isn't a simple identifier. + @end + )cpp", + "not a supported kind", HeaderFile, Index}, + {R"cpp( void foo(int); void foo(char); diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp index 55b05ebe11ab502e09c66ccfcb9a06888b72562d..efe06383b04aad8d9415cdb3ffbf45b60f918e81 100644 --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -18,6 +18,7 @@ namespace clang { namespace clangd { namespace { +using ::testing::ElementsAreArray; using ::testing::UnorderedElementsAreArray; // Create a selection tree corresponding to a point or pair of points. @@ -452,7 +453,8 @@ TEST(SelectionTest, CommonAncestor) { if (Test.ranges().empty()) { // If no [[range]] is marked in the example, there should be no selection. EXPECT_FALSE(T.commonAncestor()) << C.Code << "\n" << T; - EXPECT_THAT(Tracer.takeMetric("selection_recovery"), testing::IsEmpty()); + EXPECT_THAT(Tracer.takeMetric("selection_recovery", "C++"), + testing::IsEmpty()); } else { // If there is an expected selection, common ancestor should exist // with the appropriate node type. @@ -468,8 +470,8 @@ TEST(SelectionTest, CommonAncestor) { // and no nodes outside it are selected. EXPECT_TRUE(verifyCommonAncestor(T.root(), T.commonAncestor(), C.Code)) << C.Code; - EXPECT_THAT(Tracer.takeMetric("selection_recovery"), - testing::ElementsAreArray({0})); + EXPECT_THAT(Tracer.takeMetric("selection_recovery", "C++"), + ElementsAreArray({0})); } } } @@ -494,10 +496,10 @@ TEST(SelectionTree, Metrics) { auto AST = TestTU::withCode(Annotations(Code).code()).build(); trace::TestTracer Tracer; auto T = makeSelectionTree(Code, AST); - EXPECT_THAT(Tracer.takeMetric("selection_recovery"), - testing::ElementsAreArray({1})); - EXPECT_THAT(Tracer.takeMetric("selection_recovery_type"), - testing::ElementsAreArray({1})); + EXPECT_THAT(Tracer.takeMetric("selection_recovery", "C++"), + ElementsAreArray({1})); + EXPECT_THAT(Tracer.takeMetric("selection_recovery_type", "C++"), + ElementsAreArray({1})); } // FIXME: Doesn't select the binary operator node in diff --git a/clang-tools-extra/clangd/unittests/TestIndex.cpp b/clang-tools-extra/clangd/unittests/TestIndex.cpp index 11ac4239df1ab068a6d1ec0cd7c35840705f3afc..04fcbb46a89c6e15ce6b5373e4a5b1ea42778350 100644 --- a/clang-tools-extra/clangd/unittests/TestIndex.cpp +++ b/clang-tools-extra/clangd/unittests/TestIndex.cpp @@ -29,7 +29,7 @@ Symbol symbol(llvm::StringRef QName) { static std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle, llvm::StringRef Repl) { - llvm::SmallVector Parts; + llvm::SmallVector Parts; Haystack.split(Parts, Needle); return llvm::join(Parts, Repl); } diff --git a/clang-tools-extra/clangd/unittests/TestTU.cpp b/clang-tools-extra/clangd/unittests/TestTU.cpp index f487cf717f043b5d44431e443d88c3b2b99e8d9c..3b11304446717287231617b322e91ed629af04b1 100644 --- a/clang-tools-extra/clangd/unittests/TestTU.cpp +++ b/clang-tools-extra/clangd/unittests/TestTU.cpp @@ -187,9 +187,6 @@ const Symbol &findSymbol(const SymbolSlab &Slab, llvm::StringRef QName) { } const NamedDecl &findDecl(ParsedAST &AST, llvm::StringRef QName) { - llvm::SmallVector Components; - QName.split(Components, "::"); - auto &Ctx = AST.getASTContext(); auto LookupDecl = [&Ctx](const DeclContext &Scope, llvm::StringRef Name) -> const NamedDecl & { @@ -200,11 +197,13 @@ const NamedDecl &findDecl(ParsedAST &AST, llvm::StringRef QName) { }; const DeclContext *Scope = Ctx.getTranslationUnitDecl(); - for (auto NameIt = Components.begin(), End = Components.end() - 1; - NameIt != End; ++NameIt) { - Scope = &cast(LookupDecl(*Scope, *NameIt)); + + StringRef Cur, Rest; + for (std::tie(Cur, Rest) = QName.split("::"); !Rest.empty(); + std::tie(Cur, Rest) = Rest.split("::")) { + Scope = &cast(LookupDecl(*Scope, Cur)); } - return LookupDecl(*Scope, Components.back()); + return LookupDecl(*Scope, Cur); } const NamedDecl &findDecl(ParsedAST &AST, diff --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp b/clang-tools-extra/clangd/unittests/TweakTests.cpp deleted file mode 100644 index eefc50d754e2a3652d0da588b4143ce70d30c184..0000000000000000000000000000000000000000 --- a/clang-tools-extra/clangd/unittests/TweakTests.cpp +++ /dev/null @@ -1,3114 +0,0 @@ -//===-- TweakTests.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 "Annotations.h" -#include "Config.h" -#include "SourceCode.h" -#include "TestFS.h" -#include "TestTU.h" -#include "TweakTesting.h" -#include "refactor/Tweak.h" -#include "clang/AST/Expr.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticIDs.h" -#include "clang/Basic/DiagnosticOptions.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/FileSystemOptions.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Rewrite/Core/Rewriter.h" -#include "clang/Tooling/Core/Replacement.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/VirtualFileSystem.h" -#include "llvm/Testing/Support/Error.h" -#include "gmock/gmock-matchers.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include -#include -#include -#include - -using ::testing::AllOf; -using ::testing::ElementsAre; -using ::testing::HasSubstr; -using ::testing::StartsWith; - -namespace clang { -namespace clangd { -namespace { - -MATCHER_P2(FileWithContents, FileName, Contents, "") { - return arg.first() == FileName && arg.second == Contents; -} - -TEST(FileEdits, AbsolutePath) { - auto RelPaths = {"a.h", "foo.cpp", "test/test.cpp"}; - - llvm::IntrusiveRefCntPtr MemFS( - new llvm::vfs::InMemoryFileSystem); - MemFS->setCurrentWorkingDirectory(testRoot()); - for (auto Path : RelPaths) - MemFS->addFile(Path, 0, llvm::MemoryBuffer::getMemBuffer("", Path)); - FileManager FM(FileSystemOptions(), MemFS); - DiagnosticsEngine DE(new DiagnosticIDs, new DiagnosticOptions); - SourceManager SM(DE, FM); - - for (auto Path : RelPaths) { - auto FID = SM.createFileID(*FM.getFile(Path), SourceLocation(), - clang::SrcMgr::C_User); - auto Res = Tweak::Effect::fileEdit(SM, FID, tooling::Replacements()); - ASSERT_THAT_EXPECTED(Res, llvm::Succeeded()); - EXPECT_EQ(Res->first, testPath(Path)); - } -} - -TWEAK_TEST(SwapIfBranches); -TEST_F(SwapIfBranchesTest, Test) { - Context = Function; - EXPECT_EQ(apply("^if (true) {return;} else {(void)0;}"), - "if (true) {(void)0;} else {return;}"); - EXPECT_EQ(apply("^if (/*error-ok*/) {return;} else {(void)0;}"), - "if (/*error-ok*/) {(void)0;} else {return;}") - << "broken condition"; - EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return; } ^e^l^s^e^ { return; }"); - EXPECT_UNAVAILABLE("if (true) {^return ^;^ } else { ^return^;^ }"); - // Available in subexpressions of the condition; - EXPECT_THAT("if(2 + [[2]] + 2) { return; } else {return;}", isAvailable()); - // But not as part of the branches. - EXPECT_THAT("if(2 + 2 + 2) { [[return]]; } else { return; }", - Not(isAvailable())); - // Range covers the "else" token, so available. - EXPECT_THAT("if(2 + 2 + 2) { return[[; } else {return;]]}", isAvailable()); - // Not available in compound statements in condition. - EXPECT_THAT("if([]{return [[true]];}()) { return; } else { return; }", - Not(isAvailable())); - // Not available if both sides aren't braced. - EXPECT_THAT("^if (1) return; else { return; }", Not(isAvailable())); - // Only one if statement is supported! - EXPECT_THAT("[[if(1){}else{}if(2){}else{}]]", Not(isAvailable())); -} - -TWEAK_TEST(RawStringLiteral); -TEST_F(RawStringLiteralTest, Test) { - Context = Expression; - EXPECT_AVAILABLE(R"cpp(^"^f^o^o^\^n^")cpp"); - EXPECT_AVAILABLE(R"cpp(R"(multi )" ^"token " "str\ning")cpp"); - EXPECT_UNAVAILABLE(R"cpp(^"f^o^o^o")cpp"); // no chars need escaping - EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii - EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw - EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro - EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char - - const char *Input = R"cpp(R"(multi -token)" "\nst^ring\n" "literal")cpp"; - const char *Output = R"cpp(R"(multi -token -string -literal)")cpp"; - EXPECT_EQ(apply(Input), Output); -} - -TWEAK_TEST(ObjCLocalizeStringLiteral); -TEST_F(ObjCLocalizeStringLiteralTest, Test) { - ExtraArgs.push_back("-x"); - ExtraArgs.push_back("objective-c"); - - // Ensure the action can be initiated in the string literal. - EXPECT_AVAILABLE(R"(id x = ^[[@[[^"^t^est^"]]]];)"); - - // Ensure that the action can't be initiated in other places. - EXPECT_UNAVAILABLE(R"([[i^d ^[[x]] ^= @"test";^]])"); - - // Ensure that the action is not available for regular C strings. - EXPECT_UNAVAILABLE(R"(const char * x= "^test";)"); - - const char *Input = R"(id x = [[@"test"]];)"; - const char *Output = R"(id x = NSLocalizedString(@"test", @"");)"; - EXPECT_EQ(apply(Input), Output); -} - -TWEAK_TEST(DumpAST); -TEST_F(DumpASTTest, Test) { - EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }"); - EXPECT_UNAVAILABLE("/*c^omment*/ int foo() { return 2 ^ + 2; }"); - EXPECT_THAT(apply("int x = 2 ^+ 2;"), - AllOf(StartsWith("message:"), HasSubstr("BinaryOperator"), - HasSubstr("'+'"), HasSubstr("|-IntegerLiteral"), - HasSubstr(" 'int' 2\n`-IntegerLiteral"), - HasSubstr(" 'int' 2"))); -} - -TWEAK_TEST(DumpSymbol); -TEST_F(DumpSymbolTest, Test) { - std::string ID = R"("id":"CA2EBE44A1D76D2A")"; - std::string USR = R"("usr":"c:@F@foo#")"; - EXPECT_THAT(apply("void f^oo();"), - AllOf(StartsWith("message:"), testing::HasSubstr(ID), - testing::HasSubstr(USR))); -} - -TWEAK_TEST(ShowSelectionTree); -TEST_F(ShowSelectionTreeTest, Test) { - EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }"); - EXPECT_AVAILABLE("/*c^omment*/ int foo() { return 2 ^ + 2; }"); - - const char *Output = R"(message: - TranslationUnitDecl - VarDecl int x = fcall(2 + 2) - .CallExpr fcall(2 + 2) - ImplicitCastExpr fcall - .DeclRefExpr fcall - .BinaryOperator 2 + 2 - *IntegerLiteral 2 -)"; - EXPECT_EQ(apply("int fcall(int); int x = fca[[ll(2 +]]2);"), Output); - - Output = R"(message: - TranslationUnitDecl - FunctionDecl void x() - CompoundStmt { … - ForStmt for (;;) … - *BreakStmt break; -)"; - EXPECT_EQ(apply("void x() { for (;;) br^eak; }"), Output); -} - -TWEAK_TEST(DumpRecordLayout); -TEST_F(DumpRecordLayoutTest, Test) { - EXPECT_AVAILABLE("^s^truct ^X ^{ int x; ^};"); - EXPECT_THAT("struct X { int ^a; };", Not(isAvailable())); - EXPECT_THAT("struct ^X;", Not(isAvailable())); - EXPECT_THAT("template struct ^X { T t; };", Not(isAvailable())); - EXPECT_THAT("enum ^X {};", Not(isAvailable())); - - EXPECT_THAT(apply("struct ^X { int x; int y; };"), - AllOf(StartsWith("message:"), HasSubstr("0 | int x"))); -} - -TWEAK_TEST(ExtractVariable); -TEST_F(ExtractVariableTest, Test) { - const char *AvailableCases = R"cpp( - int xyz(int a = 1) { - struct T { - int bar(int a = 1); - int z; - } t; - // return statement - return [[[[t.b[[a]]r]](t.z)]]; - } - void f() { - int a = [[5 +]] [[4 * [[[[xyz]]()]]]]; - // multivariable initialization - if(1) - int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1; - // if without else - if([[1]]) - a = [[1]] + 1; - // if with else - if(a < [[3]]) - if(a == [[4]]) - a = [[5]] + 1; - else - a = [[5]] + 1; - else if (a < [[4]]) - a = [[4]] + 1; - else - a = [[5]] + 1; - // for loop - for(a = [[1]] + 1; a > [[[[3]] + [[4]]]]; a++) - a = [[2]] + 1; - // while - while(a < [[1]]) - a = [[1]] + 1; - // do while - do - a = [[1]] + 1; - while(a < [[3]]); - } - )cpp"; - EXPECT_AVAILABLE(AvailableCases); - - ExtraArgs = {"-xc"}; - const char *AvailableButC = R"cpp( - void foo() { - int x = [[1]]; - })cpp"; - EXPECT_UNAVAILABLE(AvailableButC); - ExtraArgs = {}; - - const char *NoCrashCases = R"cpp( - // error-ok: broken code, but shouldn't crash - template - struct Test { - Test(const T &v) :val[[(^]]) {} - T val; - }; - )cpp"; - EXPECT_UNAVAILABLE(NoCrashCases); - - const char *UnavailableCases = R"cpp( - int xyz(int a = [[1]]) { - struct T { - int bar(int a = [[1]]); - int z = [[1]]; - } t; - return [[t]].bar([[[[t]].z]]); - } - void v() { return; } - // function default argument - void f(int b = [[1]]) { - // empty selection - int a = ^1 ^+ ^2; - // void expressions - auto i = new int, j = new int; - [[[[delete i]], delete j]]; - [[v]](); - // if - if(1) - int x = 1, y = a + 1, a = 1, z = [[a + 1]]; - if(int a = 1) - if([[a + 1]] == 4) - a = [[[[a]] +]] 1; - // for loop - for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]]) - a = [[a + 1]]; - // lambda - auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}; - // assignment - xyz([[a = 5]]); - xyz([[a *= 5]]); - // Variable DeclRefExpr - a = [[b]]; - a = [[xyz()]]; - // statement expression - [[xyz()]]; - while (a) - [[++a]]; - // label statement - goto label; - label: - a = [[1]]; - } - )cpp"; - EXPECT_UNAVAILABLE(UnavailableCases); - - // vector of pairs of input and output strings - const std::vector> InputOutputs = { - // extraction from variable declaration/assignment - {R"cpp(void varDecl() { - int a = 5 * (4 + (3 [[- 1)]]); - })cpp", - R"cpp(void varDecl() { - auto dummy = (3 - 1); int a = 5 * (4 + dummy); - })cpp"}, - // FIXME: extraction from switch case - /*{R"cpp(void f(int a) { - if(1) - while(a < 1) - switch (1) { - case 1: - a = [[1 + 2]]; - break; - default: - break; - } - })cpp", - R"cpp(void f(int a) { - auto dummy = 1 + 2; if(1) - while(a < 1) - switch (1) { - case 1: - a = dummy; - break; - default: - break; - } - })cpp"},*/ - // Macros - {R"cpp(#define PLUS(x) x++ - void f(int a) { - int y = PLUS([[1+a]]); - })cpp", - /*FIXME: It should be extracted like this. - R"cpp(#define PLUS(x) x++ - void f(int a) { - auto dummy = 1+a; int y = PLUS(dummy); - })cpp"},*/ - R"cpp(#define PLUS(x) x++ - void f(int a) { - auto dummy = PLUS(1+a); int y = dummy; - })cpp"}, - // ensure InsertionPoint isn't inside a macro - {R"cpp(#define LOOP(x) while (1) {a = x;} - void f(int a) { - if(1) - LOOP(5 + [[3]]) - })cpp", - R"cpp(#define LOOP(x) while (1) {a = x;} - void f(int a) { - auto dummy = 3; if(1) - LOOP(5 + dummy) - })cpp"}, - {R"cpp(#define LOOP(x) do {x;} while(1); - void f(int a) { - if(1) - LOOP(5 + [[3]]) - })cpp", - R"cpp(#define LOOP(x) do {x;} while(1); - void f(int a) { - auto dummy = 3; if(1) - LOOP(5 + dummy) - })cpp"}, - // attribute testing - {R"cpp(void f(int a) { - [ [gsl::suppress("type")] ] for (;;) a = [[1]] + 1; - })cpp", - R"cpp(void f(int a) { - auto dummy = 1; [ [gsl::suppress("type")] ] for (;;) a = dummy + 1; - })cpp"}, - // MemberExpr - {R"cpp(class T { - T f() { - return [[T().f()]].f(); - } - };)cpp", - R"cpp(class T { - T f() { - auto dummy = T().f(); return dummy.f(); - } - };)cpp"}, - // Function DeclRefExpr - {R"cpp(int f() { - return [[f]](); - })cpp", - R"cpp(int f() { - auto dummy = f(); return dummy; - })cpp"}, - // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = [[1]]; - // since the attr is inside the DeclStmt and the bounds of - // DeclStmt don't cover the attribute. - - // Binary subexpressions - {R"cpp(void f() { - int x = 1 + [[2 + 3 + 4]] + 5; - })cpp", - R"cpp(void f() { - auto dummy = 2 + 3 + 4; int x = 1 + dummy + 5; - })cpp"}, - {R"cpp(void f() { - int x = [[1 + 2 + 3]] + 4 + 5; - })cpp", - R"cpp(void f() { - auto dummy = 1 + 2 + 3; int x = dummy + 4 + 5; - })cpp"}, - {R"cpp(void f() { - int x = 1 + 2 + [[3 + 4 + 5]]; - })cpp", - R"cpp(void f() { - auto dummy = 3 + 4 + 5; int x = 1 + 2 + dummy; - })cpp"}, - // Non-associative operations have no special support - {R"cpp(void f() { - int x = 1 - [[2 - 3 - 4]] - 5; - })cpp", - R"cpp(void f() { - auto dummy = 1 - 2 - 3 - 4; int x = dummy - 5; - })cpp"}, - // A mix of associative operators isn't associative. - {R"cpp(void f() { - int x = 0 + 1 * [[2 + 3]] * 4 + 5; - })cpp", - R"cpp(void f() { - auto dummy = 1 * 2 + 3 * 4; int x = 0 + dummy + 5; - })cpp"}, - // Overloaded operators are supported, we assume associativity - // as if they were built-in. - {R"cpp(struct S { - S(int); - }; - S operator+(S, S); - - void f() { - S x = S(1) + [[S(2) + S(3) + S(4)]] + S(5); - })cpp", - R"cpp(struct S { - S(int); - }; - S operator+(S, S); - - void f() { - auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5); - })cpp"}, - // Don't try to analyze across macro boundaries - // FIXME: it'd be nice to do this someday (in a safe way) - {R"cpp(#define ECHO(X) X - void f() { - int x = 1 + [[ECHO(2 + 3) + 4]] + 5; - })cpp", - R"cpp(#define ECHO(X) X - void f() { - auto dummy = 1 + ECHO(2 + 3) + 4; int x = dummy + 5; - })cpp"}, - {R"cpp(#define ECHO(X) X - void f() { - int x = 1 + [[ECHO(2) + ECHO(3) + 4]] + 5; - })cpp", - R"cpp(#define ECHO(X) X - void f() { - auto dummy = 1 + ECHO(2) + ECHO(3) + 4; int x = dummy + 5; - })cpp"}, - }; - for (const auto &IO : InputOutputs) { - EXPECT_EQ(IO.second, apply(IO.first)) << IO.first; - } -} - -TWEAK_TEST(AnnotateHighlightings); -TEST_F(AnnotateHighlightingsTest, Test) { - EXPECT_AVAILABLE("^vo^id^ ^f(^) {^}^"); // available everywhere. - EXPECT_AVAILABLE("[[int a; int b;]]"); - EXPECT_EQ("void /* entity.name.function.cpp */f() {}", apply("void ^f() {}")); - - EXPECT_EQ(apply("[[void f1(); void f2();]]"), - "void /* entity.name.function.cpp */f1(); " - "void /* entity.name.function.cpp */f2();"); - - EXPECT_EQ(apply("void f1(); void f2() {^}"), - "void f1(); " - "void /* entity.name.function.cpp */f2() {}"); -} - -TWEAK_TEST(ExpandMacro); -TEST_F(ExpandMacroTest, Test) { - Header = R"cpp( - // error-ok: not real c++, just token manipulation - #define FOO 1 2 3 - #define FUNC(X) X+X+X - #define EMPTY - #define EMPTY_FN(X) - )cpp"; - - // Available on macro names, not available anywhere else. - EXPECT_AVAILABLE("^F^O^O^ BAR ^F^O^O^"); - EXPECT_AVAILABLE("^F^U^N^C^(1)"); - EXPECT_UNAVAILABLE("^#^d^efine^ ^XY^Z 1 ^2 ^3^"); - EXPECT_UNAVAILABLE("FOO ^B^A^R^ FOO ^"); - EXPECT_UNAVAILABLE("FUNC(^1^)^"); - - // Works as expected on object-like macros. - EXPECT_EQ(apply("^FOO BAR FOO"), "1 2 3 BAR FOO"); - EXPECT_EQ(apply("FOO BAR ^FOO"), "FOO BAR 1 2 3"); - // And function-like macros. - EXPECT_EQ(apply("F^UNC(2)"), "2 + 2 + 2"); - - // Works on empty macros. - EXPECT_EQ(apply("int a ^EMPTY;"), "int a ;"); - EXPECT_EQ(apply("int a ^EMPTY_FN(1 2 3);"), "int a ;"); - EXPECT_EQ(apply("int a = 123 ^EMPTY EMPTY_FN(1);"), - "int a = 123 EMPTY_FN(1);"); - EXPECT_EQ(apply("int a = 123 ^EMPTY_FN(1) EMPTY;"), "int a = 123 EMPTY;"); - EXPECT_EQ(apply("int a = 123 EMPTY_FN(1) ^EMPTY;"), - "int a = 123 EMPTY_FN(1) ;"); -} - -TWEAK_TEST(ExpandAutoType); -TEST_F(ExpandAutoTypeTest, Test) { - - Header = R"cpp( - namespace ns { - struct Class { - struct Nested {}; - }; - void Func(); - } - inline namespace inl_ns { - namespace { - struct Visible {}; - } - } - )cpp"; - - EXPECT_AVAILABLE("^a^u^t^o^ i = 0;"); - EXPECT_UNAVAILABLE("auto ^i^ ^=^ ^0^;^"); - - // check primitive type - EXPECT_EQ(apply("[[auto]] i = 0;"), "int i = 0;"); - EXPECT_EQ(apply("au^to i = 0;"), "int i = 0;"); - // check classes and namespaces - EXPECT_EQ(apply("^auto C = ns::Class::Nested();"), - "ns::Class::Nested C = ns::Class::Nested();"); - // check that namespaces are shortened - EXPECT_EQ(apply("namespace ns { void f() { ^auto C = Class(); } }"), - "namespace ns { void f() { Class C = Class(); } }"); - // undefined functions should not be replaced - EXPECT_THAT(apply("au^to x = doesnt_exist(); // error-ok"), - StartsWith("fail: Could not deduce type for 'auto' type")); - // function pointers should not be replaced - EXPECT_THAT(apply("au^to x = &ns::Func;"), - StartsWith("fail: Could not expand type of function pointer")); - // lambda types are not replaced - EXPECT_THAT(apply("au^to x = []{};"), - StartsWith("fail: Could not expand type of lambda expression")); - // inline namespaces - EXPECT_EQ(apply("au^to x = inl_ns::Visible();"), - "Visible x = inl_ns::Visible();"); - // local class - EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"), - "namespace x { void y() { struct S{}; S z = S(); } }"); - // replace array types - EXPECT_EQ(apply(R"cpp(au^to x = "test";)cpp"), - R"cpp(const char * x = "test";)cpp"); - - EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;"); - // expanding types in structured bindings is syntactically invalid. - EXPECT_UNAVAILABLE("const ^auto &[x,y] = (int[]){1,2};"); - - // FIXME: Auto-completion in a template requires disabling delayed template - // parsing. - ExtraArgs.push_back("-fno-delayed-template-parsing"); - // unknown types in a template should not be replaced - EXPECT_THAT(apply("template void x() { ^auto y = T::z(); }"), - StartsWith("fail: Could not deduce type for 'auto' type")); -} - -TWEAK_TEST(ExtractFunction); -TEST_F(ExtractFunctionTest, FunctionTest) { - Context = Function; - - // Root statements should have common parent. - EXPECT_EQ(apply("for(;;) [[1+2; 1+2;]]"), "unavailable"); - // Expressions aren't extracted. - EXPECT_EQ(apply("int x = 0; [[x++;]]"), "unavailable"); - // We don't support extraction from lambdas. - EXPECT_EQ(apply("auto lam = [](){ [[int x;]] }; "), "unavailable"); - // Partial statements aren't extracted. - EXPECT_THAT(apply("int [[x = 0]];"), "unavailable"); - // FIXME: Support hoisting. - EXPECT_THAT(apply(" [[int a = 5;]] a++; "), "unavailable"); - - // Ensure that end of Zone and Beginning of PostZone being adjacent doesn't - // lead to break being included in the extraction zone. - EXPECT_THAT(apply("for(;;) { [[int x;]]break; }"), HasSubstr("extracted")); - // FIXME: ExtractFunction should be unavailable inside loop construct - // initializer/condition. - EXPECT_THAT(apply(" for([[int i = 0;]];);"), HasSubstr("extracted")); - // Extract certain return - EXPECT_THAT(apply(" if(true) [[{ return; }]] "), HasSubstr("extracted")); - // Don't extract uncertain return - EXPECT_THAT(apply(" if(true) [[if (false) return;]] "), StartsWith("fail")); - - FileName = "a.c"; - EXPECT_THAT(apply(" for([[int i = 0;]];);"), HasSubstr("unavailable")); -} - -TEST_F(ExtractFunctionTest, FileTest) { - // Check all parameters are in order - std::string ParameterCheckInput = R"cpp( -struct Foo { - int x; -}; -void f(int a) { - int b; - int *ptr = &a; - Foo foo; - [[a += foo.x + b; - *ptr++;]] -})cpp"; - std::string ParameterCheckOutput = R"cpp( -struct Foo { - int x; -}; -void extracted(int &a, int &b, int * &ptr, Foo &foo) { -a += foo.x + b; - *ptr++; -} -void f(int a) { - int b; - int *ptr = &a; - Foo foo; - extracted(a, b, ptr, foo); -})cpp"; - EXPECT_EQ(apply(ParameterCheckInput), ParameterCheckOutput); - - // Check const qualifier - std::string ConstCheckInput = R"cpp( -void f(const int c) { - [[while(c) {}]] -})cpp"; - std::string ConstCheckOutput = R"cpp( -void extracted(const int &c) { -while(c) {} -} -void f(const int c) { - extracted(c); -})cpp"; - EXPECT_EQ(apply(ConstCheckInput), ConstCheckOutput); - - // Don't extract when we need to make a function as a parameter. - EXPECT_THAT(apply("void f() { [[int a; f();]] }"), StartsWith("fail")); - - // We don't extract from methods for now since they may involve multi-file - // edits - std::string MethodFailInput = R"cpp( - class T { - void f() { - [[int x;]] - } - }; - )cpp"; - EXPECT_EQ(apply(MethodFailInput), "unavailable"); - - // We don't extract from templated functions for now as templates are hard - // to deal with. - std::string TemplateFailInput = R"cpp( - template - void f() { - [[int x;]] - } - )cpp"; - EXPECT_EQ(apply(TemplateFailInput), "unavailable"); - - std::string MacroInput = R"cpp( - #define F(BODY) void f() { BODY } - F ([[int x = 0;]]) - )cpp"; - std::string MacroOutput = R"cpp( - #define F(BODY) void f() { BODY } - void extracted() { -int x = 0; -} -F (extracted();) - )cpp"; - EXPECT_EQ(apply(MacroInput), MacroOutput); - - // Shouldn't crash. - EXPECT_EQ(apply("void f([[int a]]);"), "unavailable"); - // Don't extract if we select the entire function body (CompoundStmt). - std::string CompoundFailInput = R"cpp( - void f() [[{ - int a; - }]] - )cpp"; - EXPECT_EQ(apply(CompoundFailInput), "unavailable"); -} - -TEST_F(ExtractFunctionTest, ControlFlow) { - Context = Function; - // We should be able to extract break/continue with a parent loop/switch. - EXPECT_THAT(apply(" [[for(;;) if(1) break;]] "), HasSubstr("extracted")); - EXPECT_THAT(apply(" for(;;) [[while(1) break;]] "), HasSubstr("extracted")); - EXPECT_THAT(apply(" [[switch(1) { break; }]]"), HasSubstr("extracted")); - EXPECT_THAT(apply(" [[while(1) switch(1) { continue; }]]"), - HasSubstr("extracted")); - // Don't extract break and continue without a loop/switch parent. - EXPECT_THAT(apply(" for(;;) [[if(1) continue;]] "), StartsWith("fail")); - EXPECT_THAT(apply(" while(1) [[if(1) break;]] "), StartsWith("fail")); - EXPECT_THAT(apply(" switch(1) { [[break;]] }"), StartsWith("fail")); - EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"), - StartsWith("fail")); -} - -TEST_F(ExtractFunctionTest, ExistingReturnStatement) { - Context = File; - const char *Before = R"cpp( - bool lucky(int N); - int getNum(bool Superstitious, int Min, int Max) { - if (Superstitious) [[{ - for (int I = Min; I <= Max; ++I) - if (lucky(I)) - return I; - return -1; - }]] else { - return (Min + Max) / 2; - } - } - )cpp"; - // FIXME: min/max should be by value. - // FIXME: avoid emitting redundant braces - const char *After = R"cpp( - bool lucky(int N); - int extracted(int &Min, int &Max) { -{ - for (int I = Min; I <= Max; ++I) - if (lucky(I)) - return I; - return -1; - } -} -int getNum(bool Superstitious, int Min, int Max) { - if (Superstitious) return extracted(Min, Max); else { - return (Min + Max) / 2; - } - } - )cpp"; - EXPECT_EQ(apply(Before), After); -} - -TWEAK_TEST(RemoveUsingNamespace); -TEST_F(RemoveUsingNamespaceTest, All) { - std::pair Cases[] = { - {// Remove all occurrences of ns. Qualify only unqualified. - R"cpp( - namespace ns1 { struct vector {}; } - namespace ns2 { struct map {}; } - using namespace n^s1; - using namespace ns2; - using namespace ns1; - int main() { - ns1::vector v1; - vector v2; - map m1; - } - )cpp", - R"cpp( - namespace ns1 { struct vector {}; } - namespace ns2 { struct map {}; } - - using namespace ns2; - - int main() { - ns1::vector v1; - ns1::vector v2; - map m1; - } - )cpp"}, - {// Ident to be qualified is a macro arg. - R"cpp( - #define DECLARE(x, y) x y - namespace ns { struct vector {}; } - using namespace n^s; - int main() { - DECLARE(ns::vector, v1); - DECLARE(vector, v2); - } - )cpp", - R"cpp( - #define DECLARE(x, y) x y - namespace ns { struct vector {}; } - - int main() { - DECLARE(ns::vector, v1); - DECLARE(ns::vector, v2); - } - )cpp"}, - {// Nested namespace: Fully qualify ident from inner ns. - R"cpp( - namespace aa { namespace bb { struct map {}; }} - using namespace aa::b^b; - int main() { - map m; - } - )cpp", - R"cpp( - namespace aa { namespace bb { struct map {}; }} - - int main() { - aa::bb::map m; - } - )cpp"}, - {// Nested namespace: Fully qualify ident from inner ns. - R"cpp( - namespace aa { namespace bb { struct map {}; }} - using namespace a^a; - int main() { - bb::map m; - } - )cpp", - R"cpp( - namespace aa { namespace bb { struct map {}; }} - - int main() { - aa::bb::map m; - } - )cpp"}, - {// Typedef. - R"cpp( - namespace aa { namespace bb { struct map {}; }} - using namespace a^a; - typedef bb::map map; - int main() { map M; } - )cpp", - R"cpp( - namespace aa { namespace bb { struct map {}; }} - - typedef aa::bb::map map; - int main() { map M; } - )cpp"}, - {// FIXME: Nested namespaces: Not aware of using ns decl of outer ns. - R"cpp( - namespace aa { namespace bb { struct map {}; }} - using name[[space aa::b]]b; - using namespace aa; - int main() { - map m; - } - )cpp", - R"cpp( - namespace aa { namespace bb { struct map {}; }} - - using namespace aa; - int main() { - aa::bb::map m; - } - )cpp"}, - {// Does not qualify ident from inner namespace. - R"cpp( - namespace aa { namespace bb { struct map {}; }} - using namespace aa::bb; - using namespace a^a; - int main() { - map m; - } - )cpp", - R"cpp( - namespace aa { namespace bb { struct map {}; }} - using namespace aa::bb; - - int main() { - map m; - } - )cpp"}, - {// Available only for top level namespace decl. - R"cpp( - namespace aa { - namespace bb { struct map {}; } - using namespace b^b; - } - int main() { aa::map m; } - )cpp", - "unavailable"}, - {// FIXME: Unavailable for namespaces containing using-namespace decl. - R"cpp( - namespace aa { - namespace bb { struct map {}; } - using namespace bb; - } - using namespace a^a; - int main() { - map m; - } - )cpp", - "unavailable"}, - {R"cpp( - namespace a::b { struct Foo {}; } - using namespace a; - using namespace a::[[b]]; - using namespace b; - int main() { Foo F;} - )cpp", - R"cpp( - namespace a::b { struct Foo {}; } - using namespace a; - - - int main() { a::b::Foo F;} - )cpp"}, - {R"cpp( - namespace a::b { struct Foo {}; } - using namespace a; - using namespace a::b; - using namespace [[b]]; - int main() { Foo F;} - )cpp", - R"cpp( - namespace a::b { struct Foo {}; } - using namespace a; - - - int main() { b::Foo F;} - )cpp"}, - {// Enumerators. - R"cpp( - namespace tokens { - enum Token { - comma, identifier, numeric - }; - } - using namespace tok^ens; - int main() { - auto x = comma; - } - )cpp", - R"cpp( - namespace tokens { - enum Token { - comma, identifier, numeric - }; - } - - int main() { - auto x = tokens::comma; - } - )cpp"}, - {// inline namespaces. - R"cpp( - namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}} - using namespace st^d; - int main() { - vector V; - } - )cpp", - R"cpp( - namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}} - - int main() { - std::vector V; - } - )cpp"}}; - for (auto C : Cases) - EXPECT_EQ(C.second, apply(C.first)) << C.first; -} - -TWEAK_TEST(DefineInline); -TEST_F(DefineInlineTest, TriggersOnFunctionDecl) { - // Basic check for function body and signature. - EXPECT_AVAILABLE(R"cpp( - class Bar { - void baz(); - }; - - [[void [[Bar::[[b^a^z]]]]() [[{ - return; - }]]]] - - void foo(); - [[void [[f^o^o]]() [[{ - return; - }]]]] - )cpp"); - - EXPECT_UNAVAILABLE(R"cpp( - // Not a definition - vo^i[[d^ ^f]]^oo(); - - [[vo^id ]]foo[[()]] {[[ - [[(void)(5+3); - return;]] - }]] - - // Definition with no body. - class Bar { Bar() = def^ault; }; - )cpp"); -} - -TEST_F(DefineInlineTest, NoForwardDecl) { - Header = "void bar();"; - EXPECT_UNAVAILABLE(R"cpp( - void bar() { - return; - } - // FIXME: Generate a decl in the header. - void fo^o() { - return; - })cpp"); -} - -TEST_F(DefineInlineTest, ReferencedDecls) { - EXPECT_AVAILABLE(R"cpp( - void bar(); - void foo(int test); - - void fo^o(int baz) { - int x = 10; - bar(); - })cpp"); - - // Internal symbol usage. - Header = "void foo(int test);"; - EXPECT_UNAVAILABLE(R"cpp( - void bar(); - void fo^o(int baz) { - int x = 10; - bar(); - })cpp"); - - // Becomes available after making symbol visible. - Header = "void bar();" + Header; - EXPECT_AVAILABLE(R"cpp( - void fo^o(int baz) { - int x = 10; - bar(); - })cpp"); - - // FIXME: Move declaration below bar to make it visible. - Header.clear(); - EXPECT_UNAVAILABLE(R"cpp( - void foo(); - void bar(); - - void fo^o() { - bar(); - })cpp"); - - // Order doesn't matter within a class. - EXPECT_AVAILABLE(R"cpp( - class Bar { - void foo(); - void bar(); - }; - - void Bar::fo^o() { - bar(); - })cpp"); - - // FIXME: Perform include insertion to make symbol visible. - ExtraFiles["a.h"] = "void bar();"; - Header = "void foo(int test);"; - EXPECT_UNAVAILABLE(R"cpp( - #include "a.h" - void fo^o(int baz) { - int x = 10; - bar(); - })cpp"); -} - -TEST_F(DefineInlineTest, TemplateSpec) { - EXPECT_UNAVAILABLE(R"cpp( - template void foo(); - template<> void foo(); - - template<> void f^oo() { - })cpp"); - EXPECT_UNAVAILABLE(R"cpp( - template void foo(); - - template<> void f^oo() { - })cpp"); - EXPECT_UNAVAILABLE(R"cpp( - template struct Foo { void foo(); }; - - template void Foo::f^oo() { - })cpp"); - EXPECT_AVAILABLE(R"cpp( - template void foo(); - void bar(); - template <> void foo(); - - template<> void f^oo() { - bar(); - })cpp"); - EXPECT_UNAVAILABLE(R"cpp( - namespace bar { - template void f^oo() {} - template void foo(); - })cpp"); -} - -TEST_F(DefineInlineTest, CheckForCanonDecl) { - EXPECT_UNAVAILABLE(R"cpp( - void foo(); - - void bar() {} - void f^oo() { - // This bar normally refers to the definition just above, but it is not - // visible from the forward declaration of foo. - bar(); - })cpp"); - // Make it available with a forward decl. - EXPECT_AVAILABLE(R"cpp( - void bar(); - void foo(); - - void bar() {} - void f^oo() { - bar(); - })cpp"); -} - -TEST_F(DefineInlineTest, UsingShadowDecls) { - // Template body is not parsed until instantiation time on windows, which - // results in arbitrary failures as function body becomes NULL. - ExtraArgs.push_back("-fno-delayed-template-parsing"); - EXPECT_UNAVAILABLE(R"cpp( - namespace ns1 { void foo(int); } - namespace ns2 { void foo(int*); } - template - void bar(); - - using ns1::foo; - using ns2::foo; - - template - void b^ar() { - foo(T()); - })cpp"); -} - -TEST_F(DefineInlineTest, TransformNestedNamespaces) { - auto Test = R"cpp( - namespace a { - void bar(); - namespace b { - void baz(); - namespace c { - void aux(); - } - } - } - - void foo(); - using namespace a; - using namespace b; - using namespace c; - void f^oo() { - bar(); - a::bar(); - - baz(); - b::baz(); - a::b::baz(); - - aux(); - c::aux(); - b::c::aux(); - a::b::c::aux(); - })cpp"; - auto Expected = R"cpp( - namespace a { - void bar(); - namespace b { - void baz(); - namespace c { - void aux(); - } - } - } - - void foo(){ - a::bar(); - a::bar(); - - a::b::baz(); - a::b::baz(); - a::b::baz(); - - a::b::c::aux(); - a::b::c::aux(); - a::b::c::aux(); - a::b::c::aux(); - } - using namespace a; - using namespace b; - using namespace c; - )cpp"; - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, TransformUsings) { - auto Test = R"cpp( - namespace a { namespace b { namespace c { void aux(); } } } - - void foo(); - void f^oo() { - using namespace a; - using namespace b; - using namespace c; - using c::aux; - namespace d = c; - })cpp"; - auto Expected = R"cpp( - namespace a { namespace b { namespace c { void aux(); } } } - - void foo(){ - using namespace a; - using namespace a::b; - using namespace a::b::c; - using a::b::c::aux; - namespace d = a::b::c; - } - )cpp"; - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, TransformDecls) { - auto Test = R"cpp( - void foo(); - void f^oo() { - class Foo { - public: - void foo(); - int x; - }; - - enum En { Zero, One }; - En x = Zero; - - enum class EnClass { Zero, One }; - EnClass y = EnClass::Zero; - })cpp"; - auto Expected = R"cpp( - void foo(){ - class Foo { - public: - void foo(); - int x; - }; - - enum En { Zero, One }; - En x = Zero; - - enum class EnClass { Zero, One }; - EnClass y = EnClass::Zero; - } - )cpp"; - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, TransformTemplDecls) { - auto Test = R"cpp( - namespace a { - template class Bar { - public: - void bar(); - }; - template T bar; - template void aux() {} - } - - void foo(); - - using namespace a; - void f^oo() { - bar>.bar(); - aux>(); - })cpp"; - auto Expected = R"cpp( - namespace a { - template class Bar { - public: - void bar(); - }; - template T bar; - template void aux() {} - } - - void foo(){ - a::bar>.bar(); - a::aux>(); - } - - using namespace a; - )cpp"; - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, TransformMembers) { - auto Test = R"cpp( - class Foo { - void foo(); - }; - - void Foo::f^oo() { - return; - })cpp"; - auto Expected = R"cpp( - class Foo { - void foo(){ - return; - } - }; - - )cpp"; - EXPECT_EQ(apply(Test), Expected); - - ExtraFiles["a.h"] = R"cpp( - class Foo { - void foo(); - };)cpp"; - - llvm::StringMap EditedFiles; - Test = R"cpp( - #include "a.h" - void Foo::f^oo() { - return; - })cpp"; - Expected = R"cpp( - #include "a.h" - )cpp"; - EXPECT_EQ(apply(Test, &EditedFiles), Expected); - - Expected = R"cpp( - class Foo { - void foo(){ - return; - } - };)cpp"; - EXPECT_THAT(EditedFiles, - ElementsAre(FileWithContents(testPath("a.h"), Expected))); -} - -TEST_F(DefineInlineTest, TransformDependentTypes) { - auto Test = R"cpp( - namespace a { - template class Bar {}; - } - - template - void foo(); - - using namespace a; - template - void f^oo() { - Bar B; - Bar> q; - })cpp"; - auto Expected = R"cpp( - namespace a { - template class Bar {}; - } - - template - void foo(){ - a::Bar B; - a::Bar> q; - } - - using namespace a; - )cpp"; - - // Template body is not parsed until instantiation time on windows, which - // results in arbitrary failures as function body becomes NULL. - ExtraArgs.push_back("-fno-delayed-template-parsing"); - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, TransformFunctionTempls) { - // Check we select correct specialization decl. - std::pair Cases[] = { - {R"cpp( - template - void foo(T p); - - template <> - void foo(int p); - - template <> - void foo(char p); - - template <> - void fo^o(int p) { - return; - })cpp", - R"cpp( - template - void foo(T p); - - template <> - void foo(int p){ - return; - } - - template <> - void foo(char p); - - )cpp"}, - {// Make sure we are not selecting the first specialization all the time. - R"cpp( - template - void foo(T p); - - template <> - void foo(int p); - - template <> - void foo(char p); - - template <> - void fo^o(char p) { - return; - })cpp", - R"cpp( - template - void foo(T p); - - template <> - void foo(int p); - - template <> - void foo(char p){ - return; - } - - )cpp"}, - {R"cpp( - template - void foo(T p); - - template <> - void foo(int p); - - template - void fo^o(T p) { - return; - })cpp", - R"cpp( - template - void foo(T p){ - return; - } - - template <> - void foo(int p); - - )cpp"}, - }; - // Template body is not parsed until instantiation time on windows, which - // results in arbitrary failures as function body becomes NULL. - ExtraArgs.push_back("-fno-delayed-template-parsing"); - for (const auto &Case : Cases) - EXPECT_EQ(apply(Case.first), Case.second) << Case.first; -} - -TEST_F(DefineInlineTest, TransformTypeLocs) { - auto Test = R"cpp( - namespace a { - template class Bar { - public: - template class Baz {}; - }; - class Foo{}; - } - - void foo(); - - using namespace a; - void f^oo() { - Bar B; - Foo foo; - a::Bar>::Baz> q; - })cpp"; - auto Expected = R"cpp( - namespace a { - template class Bar { - public: - template class Baz {}; - }; - class Foo{}; - } - - void foo(){ - a::Bar B; - a::Foo foo; - a::Bar>::Baz> q; - } - - using namespace a; - )cpp"; - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, TransformDeclRefs) { - auto Test = R"cpp( - namespace a { - template class Bar { - public: - void foo(); - static void bar(); - int x; - static int y; - }; - void bar(); - void test(); - } - - void foo(); - using namespace a; - void f^oo() { - a::Bar B; - B.foo(); - a::bar(); - Bar>::bar(); - a::Bar::bar(); - B.x = Bar::y; - Bar::y = 3; - bar(); - a::test(); - })cpp"; - auto Expected = R"cpp( - namespace a { - template class Bar { - public: - void foo(); - static void bar(); - int x; - static int y; - }; - void bar(); - void test(); - } - - void foo(){ - a::Bar B; - B.foo(); - a::bar(); - a::Bar>::bar(); - a::Bar::bar(); - B.x = a::Bar::y; - a::Bar::y = 3; - a::bar(); - a::test(); - } - using namespace a; - )cpp"; - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, StaticMembers) { - auto Test = R"cpp( - namespace ns { class X { static void foo(); void bar(); }; } - void ns::X::b^ar() { - foo(); - })cpp"; - auto Expected = R"cpp( - namespace ns { class X { static void foo(); void bar(){ - foo(); - } }; } - )cpp"; - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, TransformParamNames) { - std::pair Cases[] = { - {R"cpp( - void foo(int, bool b, int T\ -est); - void ^foo(int f, bool x, int z) {})cpp", - R"cpp( - void foo(int f, bool x, int z){} - )cpp"}, - {R"cpp( - #define PARAM int Z - void foo(PARAM); - - void ^foo(int X) {})cpp", - "fail: Cant rename parameter inside macro body."}, - {R"cpp( - #define TYPE int - #define PARAM TYPE Z - #define BODY(x) 5 * (x) + 2 - template - void foo(PARAM, TYPE Q, TYPE, TYPE W = BODY(P)); - template - void ^foo(int Z, int b, int c, int d) {})cpp", - R"cpp( - #define TYPE int - #define PARAM TYPE Z - #define BODY(x) 5 * (x) + 2 - template - void foo(PARAM, TYPE b, TYPE c, TYPE d = BODY(x)){} - )cpp"}, - }; - ExtraArgs.push_back("-fno-delayed-template-parsing"); - for (const auto &Case : Cases) - EXPECT_EQ(apply(Case.first), Case.second) << Case.first; -} - -TEST_F(DefineInlineTest, TransformTemplParamNames) { - auto Test = R"cpp( - struct Foo { - struct Bar { - template class, template class Y, - int, int Z> - void foo(X, Y, int W = 5 * Z + 2); - }; - }; - - template class V, template class W, - int X, int Y> - void Foo::Bar::f^oo(U, W, int Q) {})cpp"; - auto Expected = R"cpp( - struct Foo { - struct Bar { - template class V, template class W, - int X, int Y> - void foo(U, W, int Q = 5 * Y + 2){} - }; - }; - - )cpp"; - ExtraArgs.push_back("-fno-delayed-template-parsing"); - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, TransformInlineNamespaces) { - auto Test = R"cpp( - namespace a { inline namespace b { namespace { struct Foo{}; } } } - void foo(); - - using namespace a; - void ^foo() {Foo foo;})cpp"; - auto Expected = R"cpp( - namespace a { inline namespace b { namespace { struct Foo{}; } } } - void foo(){a::Foo foo;} - - using namespace a; - )cpp"; - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineInlineTest, TokensBeforeSemicolon) { - std::pair Cases[] = { - {R"cpp( - void foo() /*Comment -_-*/ /*Com 2*/ ; - void fo^o() { return ; })cpp", - R"cpp( - void foo() /*Comment -_-*/ /*Com 2*/ { return ; } - )cpp"}, - - {R"cpp( - void foo(); - void fo^o() { return ; })cpp", - R"cpp( - void foo(){ return ; } - )cpp"}, - - {R"cpp( - #define SEMI ; - void foo() SEMI - void fo^o() { return ; })cpp", - "fail: Couldn't find semicolon for target declaration."}, - }; - for (const auto &Case : Cases) - EXPECT_EQ(apply(Case.first), Case.second) << Case.first; -} - -TEST_F(DefineInlineTest, HandleMacros) { - EXPECT_UNAVAILABLE(R"cpp( - #define BODY { return; } - void foo(); - void f^oo()BODY)cpp"); - - EXPECT_UNAVAILABLE(R"cpp( - #define BODY void foo(){ return; } - void foo(); - [[BODY]])cpp"); - - std::pair Cases[] = { - // We don't qualify declarations coming from macros. - {R"cpp( - #define BODY Foo - namespace a { class Foo{}; } - void foo(); - using namespace a; - void f^oo(){BODY();})cpp", - R"cpp( - #define BODY Foo - namespace a { class Foo{}; } - void foo(){BODY();} - using namespace a; - )cpp"}, - - // Macro is not visible at declaration location, but we proceed. - {R"cpp( - void foo(); - #define BODY return; - void f^oo(){BODY})cpp", - R"cpp( - void foo(){BODY} - #define BODY return; - )cpp"}, - - {R"cpp( - #define TARGET void foo() - TARGET; - void f^oo(){ return; })cpp", - R"cpp( - #define TARGET void foo() - TARGET{ return; } - )cpp"}, - - {R"cpp( - #define TARGET foo - void TARGET(); - void f^oo(){ return; })cpp", - R"cpp( - #define TARGET foo - void TARGET(){ return; } - )cpp"}, - }; - for (const auto &Case : Cases) - EXPECT_EQ(apply(Case.first), Case.second) << Case.first; -} - -TEST_F(DefineInlineTest, DropCommonNameSpecifiers) { - struct { - llvm::StringRef Test; - llvm::StringRef Expected; - } Cases[] = { - {R"cpp( - namespace a { namespace b { void aux(); } } - namespace ns1 { - void foo(); - namespace qq { void test(); } - namespace ns2 { - void bar(); - namespace ns3 { void baz(); } - } - } - - using namespace a; - using namespace a::b; - using namespace ns1::qq; - void ns1::ns2::ns3::b^az() { - foo(); - bar(); - baz(); - ns1::ns2::ns3::baz(); - aux(); - test(); - })cpp", - R"cpp( - namespace a { namespace b { void aux(); } } - namespace ns1 { - void foo(); - namespace qq { void test(); } - namespace ns2 { - void bar(); - namespace ns3 { void baz(){ - foo(); - bar(); - baz(); - ns1::ns2::ns3::baz(); - a::b::aux(); - qq::test(); - } } - } - } - - using namespace a; - using namespace a::b; - using namespace ns1::qq; - )cpp"}, - {R"cpp( - namespace ns1 { - namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; } - namespace ns2 { void baz(); } - } - - using namespace ns1::qq; - void ns1::ns2::b^az() { Foo f; B b; })cpp", - R"cpp( - namespace ns1 { - namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; } - namespace ns2 { void baz(){ qq::Foo f; qq::B b; } } - } - - using namespace ns1::qq; - )cpp"}, - {R"cpp( - namespace ns1 { - namespace qq { - template struct Foo { template struct Bar {}; }; - template - using B = typename Foo::template Bar; - } - namespace ns2 { void baz(); } - } - - using namespace ns1::qq; - void ns1::ns2::b^az() { B b; })cpp", - R"cpp( - namespace ns1 { - namespace qq { - template struct Foo { template struct Bar {}; }; - template - using B = typename Foo::template Bar; - } - namespace ns2 { void baz(){ qq::B b; } } - } - - using namespace ns1::qq; - )cpp"}, - }; - for (const auto &Case : Cases) - EXPECT_EQ(apply(Case.Test), Case.Expected) << Case.Test; -} - -TEST_F(DefineInlineTest, QualifyWithUsingDirectives) { - llvm::StringRef Test = R"cpp( - namespace a { - void bar(); - namespace b { struct Foo{}; void aux(); } - namespace c { void cux(); } - } - using namespace a; - using X = b::Foo; - void foo(); - - using namespace b; - using namespace c; - void ^foo() { - cux(); - bar(); - X x; - aux(); - using namespace c; - // FIXME: The last reference to cux() in body of foo should not be - // qualified, since there is a using directive inside the function body. - cux(); - })cpp"; - llvm::StringRef Expected = R"cpp( - namespace a { - void bar(); - namespace b { struct Foo{}; void aux(); } - namespace c { void cux(); } - } - using namespace a; - using X = b::Foo; - void foo(){ - c::cux(); - bar(); - X x; - b::aux(); - using namespace c; - // FIXME: The last reference to cux() in body of foo should not be - // qualified, since there is a using directive inside the function body. - c::cux(); - } - - using namespace b; - using namespace c; - )cpp"; - EXPECT_EQ(apply(Test), Expected) << Test; -} - -TEST_F(DefineInlineTest, AddInline) { - ExtraArgs.push_back("-fno-delayed-template-parsing"); - llvm::StringMap EditedFiles; - ExtraFiles["a.h"] = "void foo();"; - apply(R"cpp(#include "a.h" - void fo^o() {})cpp", - &EditedFiles); - EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( - testPath("a.h"), "inline void foo(){}"))); - - // Check we put inline before cv-qualifiers. - ExtraFiles["a.h"] = "const int foo();"; - apply(R"cpp(#include "a.h" - const int fo^o() {})cpp", - &EditedFiles); - EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( - testPath("a.h"), "inline const int foo(){}"))); - - // No double inline. - ExtraFiles["a.h"] = "inline void foo();"; - apply(R"cpp(#include "a.h" - inline void fo^o() {})cpp", - &EditedFiles); - EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( - testPath("a.h"), "inline void foo(){}"))); - - // Constexprs don't need "inline". - ExtraFiles["a.h"] = "constexpr void foo();"; - apply(R"cpp(#include "a.h" - constexpr void fo^o() {})cpp", - &EditedFiles); - EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( - testPath("a.h"), "constexpr void foo(){}"))); - - // Class members don't need "inline". - ExtraFiles["a.h"] = "struct Foo { void foo(); };"; - apply(R"cpp(#include "a.h" - void Foo::fo^o() {})cpp", - &EditedFiles); - EXPECT_THAT(EditedFiles, - testing::ElementsAre(FileWithContents( - testPath("a.h"), "struct Foo { void foo(){} };"))); - - // Function template doesn't need to be "inline"d. - ExtraFiles["a.h"] = "template void foo();"; - apply(R"cpp(#include "a.h" - template - void fo^o() {})cpp", - &EditedFiles); - EXPECT_THAT(EditedFiles, - testing::ElementsAre(FileWithContents( - testPath("a.h"), "template void foo(){}"))); - - // Specializations needs to be marked "inline". - ExtraFiles["a.h"] = R"cpp( - template void foo(); - template <> void foo();)cpp"; - apply(R"cpp(#include "a.h" - template <> - void fo^o() {})cpp", - &EditedFiles); - EXPECT_THAT(EditedFiles, - testing::ElementsAre(FileWithContents(testPath("a.h"), - R"cpp( - template void foo(); - template <> inline void foo(){})cpp"))); -} - -TWEAK_TEST(DefineOutline); -TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) { - FileName = "Test.cpp"; - // Not available unless in a header file. - EXPECT_UNAVAILABLE(R"cpp( - [[void [[f^o^o]]() [[{ - return; - }]]]])cpp"); - - FileName = "Test.hpp"; - // Not available unless function name or fully body is selected. - EXPECT_UNAVAILABLE(R"cpp( - // Not a definition - vo^i[[d^ ^f]]^oo(); - - [[vo^id ]]foo[[()]] {[[ - [[(void)(5+3); - return;]] - }]])cpp"); - - // Available even if there are no implementation files. - EXPECT_AVAILABLE(R"cpp( - [[void [[f^o^o]]() [[{ - return; - }]]]])cpp"); - - // Not available for out-of-line methods. - EXPECT_UNAVAILABLE(R"cpp( - class Bar { - void baz(); - }; - - [[void [[Bar::[[b^a^z]]]]() [[{ - return; - }]]]])cpp"); - - // Basic check for function body and signature. - EXPECT_AVAILABLE(R"cpp( - class Bar { - [[void [[f^o^o^]]() [[{ return; }]]]] - }; - - void foo(); - [[void [[f^o^o]]() [[{ - return; - }]]]])cpp"); - - // Not available on defaulted/deleted members. - EXPECT_UNAVAILABLE(R"cpp( - class Foo { - Fo^o() = default; - F^oo(const Foo&) = delete; - };)cpp"); - - // Not available within templated classes, as it is hard to spell class name - // out-of-line in such cases. - EXPECT_UNAVAILABLE(R"cpp( - template struct Foo { void fo^o(){} }; - )cpp"); - - // Not available on function templates and specializations, as definition must - // be visible to all translation units. - EXPECT_UNAVAILABLE(R"cpp( - template void fo^o() {}; - template <> void fo^o() {}; - )cpp"); -} - -TEST_F(DefineOutlineTest, FailsWithoutSource) { - FileName = "Test.hpp"; - llvm::StringRef Test = "void fo^o() { return; }"; - llvm::StringRef Expected = - "fail: Couldn't find a suitable implementation file."; - EXPECT_EQ(apply(Test), Expected); -} - -TEST_F(DefineOutlineTest, ApplyTest) { - llvm::StringMap EditedFiles; - ExtraFiles["Test.cpp"] = ""; - FileName = "Test.hpp"; - // Template body is not parsed until instantiation time on windows, which - // results in arbitrary failures as function body becomes NULL. - ExtraArgs.push_back("-fno-delayed-template-parsing"); - - struct { - llvm::StringRef Test; - llvm::StringRef ExpectedHeader; - llvm::StringRef ExpectedSource; - } Cases[] = { - // Simple check - { - "void fo^o() { return; }", - "void foo() ;", - "void foo() { return; }", - }, - // Default args. - { - "void fo^o(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) {}", - "void foo(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) ;", - "void foo(int x, int y , int , int (*foo)(int) ) {}", - }, - // Constructors - { - R"cpp( - class Foo {public: Foo(); Foo(int);}; - class Bar { - Ba^r() {} - Bar(int x) : f1(x) {} - Foo f1; - Foo f2 = 2; - };)cpp", - R"cpp( - class Foo {public: Foo(); Foo(int);}; - class Bar { - Bar() ; - Bar(int x) : f1(x) {} - Foo f1; - Foo f2 = 2; - };)cpp", - "Bar::Bar() {}\n", - }, - // Ctor with initializer. - { - R"cpp( - class Foo {public: Foo(); Foo(int);}; - class Bar { - Bar() {} - B^ar(int x) : f1(x), f2(3) {} - Foo f1; - Foo f2 = 2; - };)cpp", - R"cpp( - class Foo {public: Foo(); Foo(int);}; - class Bar { - Bar() {} - Bar(int x) ; - Foo f1; - Foo f2 = 2; - };)cpp", - "Bar::Bar(int x) : f1(x), f2(3) {}\n", - }, - // Ctor initializer with attribute. - { - R"cpp( - class Foo { - F^oo(int z) __attribute__((weak)) : bar(2){} - int bar; - };)cpp", - R"cpp( - class Foo { - Foo(int z) __attribute__((weak)) ; - int bar; - };)cpp", - "Foo::Foo(int z) __attribute__((weak)) : bar(2){}\n", - }, - // Virt specifiers. - { - R"cpp( - struct A { - virtual void f^oo() {} - };)cpp", - R"cpp( - struct A { - virtual void foo() ; - };)cpp", - " void A::foo() {}\n", - }, - { - R"cpp( - struct A { - virtual virtual void virtual f^oo() {} - };)cpp", - R"cpp( - struct A { - virtual virtual void virtual foo() ; - };)cpp", - " void A::foo() {}\n", - }, - { - R"cpp( - struct A { - virtual void foo() = 0; - }; - struct B : A { - void fo^o() override {} - };)cpp", - R"cpp( - struct A { - virtual void foo() = 0; - }; - struct B : A { - void foo() override ; - };)cpp", - "void B::foo() {}\n", - }, - { - R"cpp( - struct A { - virtual void foo() = 0; - }; - struct B : A { - void fo^o() final {} - };)cpp", - R"cpp( - struct A { - virtual void foo() = 0; - }; - struct B : A { - void foo() final ; - };)cpp", - "void B::foo() {}\n", - }, - { - R"cpp( - struct A { - virtual void foo() = 0; - }; - struct B : A { - void fo^o() final override {} - };)cpp", - R"cpp( - struct A { - virtual void foo() = 0; - }; - struct B : A { - void foo() final override ; - };)cpp", - "void B::foo() {}\n", - }, - { - R"cpp( - struct A { - static void fo^o() {} - };)cpp", - R"cpp( - struct A { - static void foo() ; - };)cpp", - " void A::foo() {}\n", - }, - { - R"cpp( - struct A { - static static void fo^o() {} - };)cpp", - R"cpp( - struct A { - static static void foo() ; - };)cpp", - " void A::foo() {}\n", - }, - }; - for (const auto &Case : Cases) { - SCOPED_TRACE(Case.Test); - EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader); - EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( - testPath("Test.cpp"), Case.ExpectedSource))); - } -} - -TEST_F(DefineOutlineTest, HandleMacros) { - llvm::StringMap EditedFiles; - ExtraFiles["Test.cpp"] = ""; - FileName = "Test.hpp"; - ExtraArgs.push_back("-DVIRTUAL=virtual"); - ExtraArgs.push_back("-DOVER=override"); - - struct { - llvm::StringRef Test; - llvm::StringRef ExpectedHeader; - llvm::StringRef ExpectedSource; - } Cases[] = { - {R"cpp( - #define BODY { return; } - void f^oo()BODY)cpp", - R"cpp( - #define BODY { return; } - void foo();)cpp", - "void foo()BODY"}, - - {R"cpp( - #define BODY return; - void f^oo(){BODY})cpp", - R"cpp( - #define BODY return; - void foo();)cpp", - "void foo(){BODY}"}, - - {R"cpp( - #define TARGET void foo() - [[TARGET]]{ return; })cpp", - R"cpp( - #define TARGET void foo() - TARGET;)cpp", - "TARGET{ return; }"}, - - {R"cpp( - #define TARGET foo - void [[TARGET]](){ return; })cpp", - R"cpp( - #define TARGET foo - void TARGET();)cpp", - "void TARGET(){ return; }"}, - {R"cpp(#define VIRT virtual - struct A { - VIRT void f^oo() {} - };)cpp", - R"cpp(#define VIRT virtual - struct A { - VIRT void foo() ; - };)cpp", - " void A::foo() {}\n"}, - {R"cpp( - struct A { - VIRTUAL void f^oo() {} - };)cpp", - R"cpp( - struct A { - VIRTUAL void foo() ; - };)cpp", - " void A::foo() {}\n"}, - {R"cpp( - struct A { - virtual void foo() = 0; - }; - struct B : A { - void fo^o() OVER {} - };)cpp", - R"cpp( - struct A { - virtual void foo() = 0; - }; - struct B : A { - void foo() OVER ; - };)cpp", - "void B::foo() {}\n"}, - {R"cpp(#define STUPID_MACRO(X) virtual - struct A { - STUPID_MACRO(sizeof sizeof int) void f^oo() {} - };)cpp", - R"cpp(#define STUPID_MACRO(X) virtual - struct A { - STUPID_MACRO(sizeof sizeof int) void foo() ; - };)cpp", - " void A::foo() {}\n"}, - {R"cpp(#define STAT static - struct A { - STAT void f^oo() {} - };)cpp", - R"cpp(#define STAT static - struct A { - STAT void foo() ; - };)cpp", - " void A::foo() {}\n"}, - {R"cpp(#define STUPID_MACRO(X) static - struct A { - STUPID_MACRO(sizeof sizeof int) void f^oo() {} - };)cpp", - R"cpp(#define STUPID_MACRO(X) static - struct A { - STUPID_MACRO(sizeof sizeof int) void foo() ; - };)cpp", - " void A::foo() {}\n"}, - }; - for (const auto &Case : Cases) { - SCOPED_TRACE(Case.Test); - EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader); - EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( - testPath("Test.cpp"), Case.ExpectedSource))); - } -} - -TEST_F(DefineOutlineTest, QualifyReturnValue) { - FileName = "Test.hpp"; - ExtraFiles["Test.cpp"] = ""; - - struct { - llvm::StringRef Test; - llvm::StringRef ExpectedHeader; - llvm::StringRef ExpectedSource; - } Cases[] = { - {R"cpp( - namespace a { class Foo{}; } - using namespace a; - Foo fo^o() { return {}; })cpp", - R"cpp( - namespace a { class Foo{}; } - using namespace a; - Foo foo() ;)cpp", - "a::Foo foo() { return {}; }"}, - {R"cpp( - namespace a { - class Foo { - class Bar {}; - Bar fo^o() { return {}; } - }; - })cpp", - R"cpp( - namespace a { - class Foo { - class Bar {}; - Bar foo() ; - }; - })cpp", - "a::Foo::Bar a::Foo::foo() { return {}; }\n"}, - {R"cpp( - class Foo {}; - Foo fo^o() { return {}; })cpp", - R"cpp( - class Foo {}; - Foo foo() ;)cpp", - "Foo foo() { return {}; }"}, - }; - llvm::StringMap EditedFiles; - for (auto &Case : Cases) { - apply(Case.Test, &EditedFiles); - EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader); - EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( - testPath("Test.cpp"), Case.ExpectedSource))); - } -} - -TEST_F(DefineOutlineTest, QualifyFunctionName) { - FileName = "Test.hpp"; - struct { - llvm::StringRef TestHeader; - llvm::StringRef TestSource; - llvm::StringRef ExpectedHeader; - llvm::StringRef ExpectedSource; - } Cases[] = { - { - R"cpp( - namespace a { - namespace b { - class Foo { - void fo^o() {} - }; - } - })cpp", - "", - R"cpp( - namespace a { - namespace b { - class Foo { - void foo() ; - }; - } - })cpp", - "void a::b::Foo::foo() {}\n", - }, - { - "namespace a { namespace b { void f^oo() {} } }", - "namespace a{}", - "namespace a { namespace b { void foo() ; } }", - "namespace a{void b::foo() {} }", - }, - { - "namespace a { namespace b { void f^oo() {} } }", - "using namespace a;", - "namespace a { namespace b { void foo() ; } }", - // FIXME: Take using namespace directives in the source file into - // account. This can be spelled as b::foo instead. - "using namespace a;void a::b::foo() {} ", - }, - }; - llvm::StringMap EditedFiles; - for (auto &Case : Cases) { - ExtraFiles["Test.cpp"] = std::string(Case.TestSource); - EXPECT_EQ(apply(Case.TestHeader, &EditedFiles), Case.ExpectedHeader); - EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( - testPath("Test.cpp"), Case.ExpectedSource))) - << Case.TestHeader; - } -} - -TEST_F(DefineOutlineTest, FailsMacroSpecifier) { - FileName = "Test.hpp"; - ExtraFiles["Test.cpp"] = ""; - ExtraArgs.push_back("-DFINALOVER=final override"); - - std::pair Cases[] = { - { - R"cpp( - #define VIRT virtual void - struct A { - VIRT fo^o() {} - };)cpp", - "fail: define outline: couldn't remove `virtual` keyword."}, - { - R"cpp( - #define OVERFINAL final override - struct A { - virtual void foo() {} - }; - struct B : A { - void fo^o() OVERFINAL {} - };)cpp", - "fail: define outline: Can't move out of line as function has a " - "macro `override` specifier.\ndefine outline: Can't move out of line " - "as function has a macro `final` specifier."}, - { - R"cpp( - struct A { - virtual void foo() {} - }; - struct B : A { - void fo^o() FINALOVER {} - };)cpp", - "fail: define outline: Can't move out of line as function has a " - "macro `override` specifier.\ndefine outline: Can't move out of line " - "as function has a macro `final` specifier."}, - }; - for (const auto &Case : Cases) { - EXPECT_EQ(apply(Case.first), Case.second); - } -} - -TWEAK_TEST(AddUsing); -TEST_F(AddUsingTest, Prepare) { - Config Cfg; - Cfg.Style.FullyQualifiedNamespaces.push_back("ban"); - WithContextValue WithConfig(Config::Key, std::move(Cfg)); - - const std::string Header = R"cpp( -#define NS(name) one::two::name -namespace ban { void foo() {} } -namespace banana { void foo() {} } -namespace one { -void oo() {} -template class tt {}; -namespace two { -enum ee {}; -void ff() {} -class cc { -public: - struct st {}; - static void mm() {} - cc operator|(const cc& x) const { return x; } -}; -} -})cpp"; - - EXPECT_AVAILABLE(Header + "void fun() { o^n^e^:^:^t^w^o^:^:^f^f(); }"); - EXPECT_AVAILABLE(Header + "void fun() { o^n^e^::^o^o(); }"); - EXPECT_AVAILABLE(Header + "void fun() { o^n^e^:^:^t^w^o^:^:^e^e E; }"); - EXPECT_AVAILABLE(Header + "void fun() { o^n^e^:^:^t^w^o:^:^c^c C; }"); - EXPECT_UNAVAILABLE(Header + - "void fun() { o^n^e^:^:^t^w^o^:^:^c^c^:^:^m^m(); }"); - EXPECT_UNAVAILABLE(Header + - "void fun() { o^n^e^:^:^t^w^o^:^:^c^c^:^:^s^t inst; }"); - EXPECT_UNAVAILABLE(Header + - "void fun() { o^n^e^:^:^t^w^o^:^:^c^c^:^:^s^t inst; }"); - EXPECT_UNAVAILABLE(Header + "void fun() { N^S(c^c) inst; }"); - // This used to crash. Ideally we would support this case, but for now we just - // test that we don't crash. - EXPECT_UNAVAILABLE(Header + - "template using foo = one::tt;"); - // Test that we don't crash or misbehave on unnamed DeclRefExpr. - EXPECT_UNAVAILABLE(Header + - "void fun() { one::two::cc() ^| one::two::cc(); }"); - // Do not offer code action when operating on a banned namespace. - EXPECT_UNAVAILABLE(Header + "void fun() { ban::fo^o(); }"); - EXPECT_UNAVAILABLE(Header + "void fun() { ::ban::fo^o(); }"); - EXPECT_AVAILABLE(Header + "void fun() { banana::fo^o(); }"); - - // Do not offer code action on typo-corrections. - EXPECT_UNAVAILABLE(Header + "/*error-ok*/c^c C;"); - - // Check that we do not trigger in header files. - FileName = "test.h"; - ExtraArgs.push_back("-xc++-header"); // .h file is treated a C by default. - EXPECT_UNAVAILABLE(Header + "void fun() { one::two::f^f(); }"); - FileName = "test.hpp"; - EXPECT_UNAVAILABLE(Header + "void fun() { one::two::f^f(); }"); -} - -TEST_F(AddUsingTest, Apply) { - FileName = "test.cpp"; - struct { - llvm::StringRef TestSource; - llvm::StringRef ExpectedSource; - } Cases[]{{ - // Function, no other using, namespace. - R"cpp( -#include "test.hpp" -namespace { -void fun() { - ^o^n^e^:^:^t^w^o^:^:^f^f(); -} -})cpp", - R"cpp( -#include "test.hpp" -namespace {using one::two::ff; - -void fun() { - ff(); -} -})cpp", - }, - // Type, no other using, namespace. - { - R"cpp( -#include "test.hpp" -namespace { -void fun() { - ::on^e::t^wo::c^c inst; -} -})cpp", - R"cpp( -#include "test.hpp" -namespace {using ::one::two::cc; - -void fun() { - cc inst; -} -})cpp", - }, - // Type, no other using, no namespace. - { - R"cpp( -#include "test.hpp" - -void fun() { - on^e::t^wo::e^e inst; -})cpp", - R"cpp( -#include "test.hpp" - -using one::two::ee; - -void fun() { - ee inst; -})cpp"}, - // Function, other usings. - { - R"cpp( -#include "test.hpp" - -using one::two::cc; -using one::two::ee; - -namespace { -void fun() { - one::two::f^f(); -} -})cpp", - R"cpp( -#include "test.hpp" - -using one::two::cc; -using one::two::ff;using one::two::ee; - -namespace { -void fun() { - ff(); -} -})cpp", - }, - // Function, other usings inside namespace. - { - R"cpp( -#include "test.hpp" - -using one::two::cc; - -namespace { - -using one::two::ff; - -void fun() { - o^ne::o^o(); -} -})cpp", - R"cpp( -#include "test.hpp" - -using one::two::cc; - -namespace { - -using one::oo;using one::two::ff; - -void fun() { - oo(); -} -})cpp"}, - // Using comes after cursor. - { - R"cpp( -#include "test.hpp" - -namespace { - -void fun() { - one::t^wo::ff(); -} - -using one::two::cc; - -})cpp", - R"cpp( -#include "test.hpp" - -namespace {using one::two::ff; - - -void fun() { - ff(); -} - -using one::two::cc; - -})cpp"}, - // Pointer type. - {R"cpp( -#include "test.hpp" - -void fun() { - one::two::c^c *p; -})cpp", - R"cpp( -#include "test.hpp" - -using one::two::cc; - -void fun() { - cc *p; -})cpp"}, - // Namespace declared via macro. - {R"cpp( -#include "test.hpp" -#define NS_BEGIN(name) namespace name { - -NS_BEGIN(foo) - -void fun() { - one::two::f^f(); -} -})cpp", - R"cpp( -#include "test.hpp" -#define NS_BEGIN(name) namespace name { - -using one::two::ff; - -NS_BEGIN(foo) - -void fun() { - ff(); -} -})cpp"}, - // Inside macro argument. - {R"cpp( -#include "test.hpp" -#define CALL(name) name() - -void fun() { - CALL(one::t^wo::ff); -})cpp", - R"cpp( -#include "test.hpp" -#define CALL(name) name() - -using one::two::ff; - -void fun() { - CALL(ff); -})cpp"}, - // Parent namespace != lexical parent namespace - {R"cpp( -#include "test.hpp" -namespace foo { void fun(); } - -void foo::fun() { - one::two::f^f(); -})cpp", - R"cpp( -#include "test.hpp" -using one::two::ff; - -namespace foo { void fun(); } - -void foo::fun() { - ff(); -})cpp"}, - // If all other using are fully qualified, add :: - {R"cpp( -#include "test.hpp" - -using ::one::two::cc; -using ::one::two::ee; - -void fun() { - one::two::f^f(); -})cpp", - R"cpp( -#include "test.hpp" - -using ::one::two::cc; -using ::one::two::ff;using ::one::two::ee; - -void fun() { - ff(); -})cpp"}, - // Make sure we don't add :: if it's already there - {R"cpp( -#include "test.hpp" - -using ::one::two::cc; -using ::one::two::ee; - -void fun() { - ::one::two::f^f(); -})cpp", - R"cpp( -#include "test.hpp" - -using ::one::two::cc; -using ::one::two::ff;using ::one::two::ee; - -void fun() { - ff(); -})cpp"}, - // If even one using doesn't start with ::, do not add it - {R"cpp( -#include "test.hpp" - -using ::one::two::cc; -using one::two::ee; - -void fun() { - one::two::f^f(); -})cpp", - R"cpp( -#include "test.hpp" - -using ::one::two::cc; -using one::two::ff;using one::two::ee; - -void fun() { - ff(); -})cpp"}, - // using alias; insert using for the spelled name. - {R"cpp( -#include "test.hpp" - -void fun() { - one::u^u u; -})cpp", - R"cpp( -#include "test.hpp" - -using one::uu; - -void fun() { - uu u; -})cpp"}, - // using namespace. - {R"cpp( -#include "test.hpp" -using namespace one; -namespace { -two::c^c C; -})cpp", - R"cpp( -#include "test.hpp" -using namespace one; -namespace {using two::cc; - -cc C; -})cpp"}, - // Type defined in main file, make sure using is after that. - {R"cpp( -namespace xx { - struct yy {}; -} - -x^x::yy X; -)cpp", - R"cpp( -namespace xx { - struct yy {}; -} - -using xx::yy; - -yy X; -)cpp"}, - // Type defined in main file via "using", insert after that. - {R"cpp( -#include "test.hpp" - -namespace xx { - using yy = one::two::cc; -} - -x^x::yy X; -)cpp", - R"cpp( -#include "test.hpp" - -namespace xx { - using yy = one::two::cc; -} - -using xx::yy; - -yy X; -)cpp"}, - // Using must come after function definition. - {R"cpp( -namespace xx { - void yy(); -} - -void fun() { - x^x::yy(); -} -)cpp", - R"cpp( -namespace xx { - void yy(); -} - -using xx::yy; - -void fun() { - yy(); -} -)cpp"}, - // Existing using with non-namespace part. - {R"cpp( -#include "test.hpp" -using one::two::ee::ee_one; -one::t^wo::cc c; -)cpp", - R"cpp( -#include "test.hpp" -using one::two::cc;using one::two::ee::ee_one; -cc c; -)cpp"}}; - llvm::StringMap EditedFiles; - for (const auto &Case : Cases) { - for (const auto &SubCase : expandCases(Case.TestSource)) { - ExtraFiles["test.hpp"] = R"cpp( -namespace one { -void oo() {} -namespace two { -enum ee {ee_one}; -void ff() {} -class cc { -public: - struct st { struct nested {}; }; - static void mm() {} -}; -} -using uu = two::cc; -})cpp"; - EXPECT_EQ(apply(SubCase, &EditedFiles), Case.ExpectedSource); - } - } -} - -TWEAK_TEST(PopulateSwitch); -TEST_F(PopulateSwitchTest, Test) { - struct Case { - CodeContext Context; - llvm::StringRef TestSource; - llvm::StringRef ExpectedSource; - }; - - Case Cases[]{ - { - // No enumerators - Function, - R""(enum Enum {}; ^switch ((Enum)0) {})"", - "unavailable", - }, - { - // All enumerators already in switch (unscoped) - Function, - R""(enum Enum {A,B}; ^switch (A) {case A:break;case B:break;})"", - "unavailable", - }, - { - // All enumerators already in switch (scoped) - Function, - R""( - enum class Enum {A,B}; - ^switch (Enum::A) {case Enum::A:break;case Enum::B:break;} - )"", - "unavailable", - }, - { - // Default case in switch - Function, - R""( - enum class Enum {A,B}; - ^switch (Enum::A) {default:break;} - )"", - "unavailable", - }, - { - // GNU range in switch - Function, - R""( - enum class Enum {A,B}; - ^switch (Enum::A) {case Enum::A ... Enum::B:break;} - )"", - "unavailable", - }, - { - // Value dependent case expression - File, - R""( - enum class Enum {A,B}; - template - void function() { - ^switch (Enum::A) {case Value:break;} - } - )"", - "unavailable", - }, - { - // Body not CompoundStmt - Function, - R""(enum Enum {A}; ^switch (A);)"", - "unavailable", - }, - { - // Selection on switch token - Function, - R""(enum Enum {A}; ^switch (A) {})"", - R""(enum Enum {A}; switch (A) {case A:break;})"", - }, - { - // Selection on switch condition - Function, - R""(enum Enum {A}; switch (^A) {})"", - R""(enum Enum {A}; switch (A) {case A:break;})"", - }, - { - // Selection in switch body - Function, - R""(enum Enum {A}; switch (A) {^})"", - R""(enum Enum {A}; switch (A) {case A:break;})"", - }, - { - // Scoped enumeration - Function, - R""(enum class Enum {A}; ^switch (Enum::A) {})"", - R""(enum class Enum {A}; switch (Enum::A) {case Enum::A:break;})"", - }, - { - // Scoped enumeration with multiple enumerators - Function, - R""( - enum class Enum {A,B}; - ^switch (Enum::A) {} - )"", - R""( - enum class Enum {A,B}; - switch (Enum::A) {case Enum::A:case Enum::B:break;} - )"", - }, - { - // Only filling in missing enumerators (unscoped) - Function, - R""( - enum Enum {A,B,C}; - ^switch (A) {case B:break;} - )"", - R""( - enum Enum {A,B,C}; - switch (A) {case B:break;case A:case C:break;} - )"", - }, - { - // Only filling in missing enumerators, - // even when using integer literals - Function, - R""( - enum Enum {A,B=1,C}; - ^switch (A) {case 1:break;} - )"", - R""( - enum Enum {A,B=1,C}; - switch (A) {case 1:break;case A:case C:break;} - )"", - }, - { - // Only filling in missing enumerators (scoped) - Function, - R""( - enum class Enum {A,B,C}; - ^switch (Enum::A) - {case Enum::B:break;} - )"", - R""( - enum class Enum {A,B,C}; - switch (Enum::A) - {case Enum::B:break;case Enum::A:case Enum::C:break;} - )"", - }, - { - // Scoped enumerations in namespace - File, - R""( - namespace ns { enum class Enum {A}; } - void function() { ^switch (ns::Enum::A) {} } - )"", - R""( - namespace ns { enum class Enum {A}; } - void function() { switch (ns::Enum::A) {case ns::Enum::A:break;} } - )"", - }, - { - // Unscoped enumerations in namespace - File, - R""( - namespace ns { enum Enum {A}; } - void function() { ^switch (ns::A) {} } - )"", - R""( - namespace ns { enum Enum {A}; } - void function() { switch (ns::A) {case ns::A:break;} } - )"", - }, - { - // Duplicated constant names - Function, - R""(enum Enum {A,B,b=B}; ^switch (A) {})"", - R""(enum Enum {A,B,b=B}; switch (A) {case A:case B:break;})"", - }, - { - // Duplicated constant names all in switch - Function, - R""(enum Enum {A,B,b=B}; ^switch (A) {case A:case B:break;})"", - "unavailable", - }, - { - // Enum is dependent type - File, - R""(template void f() {enum Enum {A}; ^switch (A) {}})"", - "unavailable", - }, - }; - - for (const auto &Case : Cases) { - Context = Case.Context; - EXPECT_EQ(apply(Case.TestSource), Case.ExpectedSource); - } -} - -} // namespace -} // namespace clangd -} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp index c3c87bd628bdd30a53047efa8bce04a4f8604047..dfe1f6ce6cccc9673db6722b4381954320598ff9 100644 --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -349,6 +349,22 @@ TEST(LocateSymbol, WithIndex) { ElementsAre(Sym("Forward", SymbolHeader.range("forward"), Test.range()))); } +TEST(LocateSymbol, FindOverrides) { + auto Code = Annotations(R"cpp( + class Foo { + virtual void $1[[fo^o]]() = 0; + }; + class Bar : public Foo { + void $2[[foo]]() override; + }; + )cpp"); + TestTU TU = TestTU::withCode(Code.code()); + auto AST = TU.build(); + EXPECT_THAT(locateSymbolAt(AST, Code.point(), TU.index().get()), + UnorderedElementsAre(Sym("foo", Code.range("1"), llvm::None), + Sym("foo", Code.range("2"), llvm::None))); +} + TEST(LocateSymbol, WithIndexPreferredLocation) { Annotations SymbolHeader(R"cpp( class $p[[Proto]] {}; @@ -1624,6 +1640,14 @@ TEST(FindReferences, WithinAST) { } )cpp", + R"cpp(// Macro outside preamble + int breakPreamble; + #define [[MA^CRO]](X) (X+1) + void test() { + int x = [[MACRO]]([[MACRO]](1)); + } + )cpp", + R"cpp( int [[v^ar]] = 0; void foo(int s = [[var]]); diff --git a/clang-tools-extra/clangd/unittests/support/TraceTests.cpp b/clang-tools-extra/clangd/unittests/support/TraceTests.cpp index a48221259be3283d17bba6c15657069aa50235f2..0fda92a6aeffee15858d75cadf543d453143a1f0 100644 --- a/clang-tools-extra/clangd/unittests/support/TraceTests.cpp +++ b/clang-tools-extra/clangd/unittests/support/TraceTests.cpp @@ -154,7 +154,7 @@ protected: std::vector outputLines() { // Deliberately don't flush output stream, the tracer should do that. // This is important when clangd crashes. - llvm::SmallVector Lines; + llvm::SmallVector Lines; llvm::StringRef(Output).split(Lines, "\r\n"); return {Lines.begin(), Lines.end()}; } diff --git a/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0c66dbc14d77d873d0bb733b5ce912fbfe958b1 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp @@ -0,0 +1,472 @@ +//===-- AddUsingTests.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 "Config.h" +#include "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(AddUsing); + +TEST_F(AddUsingTest, Prepare) { + Config Cfg; + Cfg.Style.FullyQualifiedNamespaces.push_back("ban"); + WithContextValue WithConfig(Config::Key, std::move(Cfg)); + + const std::string Header = R"cpp( +#define NS(name) one::two::name +namespace ban { void foo() {} } +namespace banana { void foo() {} } +namespace one { +void oo() {} +template class tt {}; +namespace two { +enum ee {}; +void ff() {} +class cc { +public: + struct st {}; + static void mm() {} + cc operator|(const cc& x) const { return x; } +}; +} +})cpp"; + + EXPECT_AVAILABLE(Header + "void fun() { o^n^e^:^:^t^w^o^:^:^f^f(); }"); + EXPECT_AVAILABLE(Header + "void fun() { o^n^e^::^o^o(); }"); + EXPECT_AVAILABLE(Header + "void fun() { o^n^e^:^:^t^w^o^:^:^e^e E; }"); + EXPECT_AVAILABLE(Header + "void fun() { o^n^e^:^:^t^w^o:^:^c^c C; }"); + EXPECT_UNAVAILABLE(Header + + "void fun() { o^n^e^:^:^t^w^o^:^:^c^c^:^:^m^m(); }"); + EXPECT_UNAVAILABLE(Header + + "void fun() { o^n^e^:^:^t^w^o^:^:^c^c^:^:^s^t inst; }"); + EXPECT_UNAVAILABLE(Header + + "void fun() { o^n^e^:^:^t^w^o^:^:^c^c^:^:^s^t inst; }"); + EXPECT_UNAVAILABLE(Header + "void fun() { N^S(c^c) inst; }"); + // This used to crash. Ideally we would support this case, but for now we just + // test that we don't crash. + EXPECT_UNAVAILABLE(Header + + "template using foo = one::tt;"); + // Test that we don't crash or misbehave on unnamed DeclRefExpr. + EXPECT_UNAVAILABLE(Header + + "void fun() { one::two::cc() ^| one::two::cc(); }"); + // Do not offer code action when operating on a banned namespace. + EXPECT_UNAVAILABLE(Header + "void fun() { ban::fo^o(); }"); + EXPECT_UNAVAILABLE(Header + "void fun() { ::ban::fo^o(); }"); + EXPECT_AVAILABLE(Header + "void fun() { banana::fo^o(); }"); + + // Do not offer code action on typo-corrections. + EXPECT_UNAVAILABLE(Header + "/*error-ok*/c^c C;"); + + // NestedNameSpecifier, but no namespace. + EXPECT_UNAVAILABLE(Header + "class Foo {}; class F^oo foo;"); + + // Check that we do not trigger in header files. + FileName = "test.h"; + ExtraArgs.push_back("-xc++-header"); // .h file is treated a C by default. + EXPECT_UNAVAILABLE(Header + "void fun() { one::two::f^f(); }"); + FileName = "test.hpp"; + EXPECT_UNAVAILABLE(Header + "void fun() { one::two::f^f(); }"); +} + +TEST_F(AddUsingTest, Apply) { + FileName = "test.cpp"; + struct { + llvm::StringRef TestSource; + llvm::StringRef ExpectedSource; + } Cases[]{{ + // Function, no other using, namespace. + R"cpp( +#include "test.hpp" +namespace { +void fun() { + ^o^n^e^:^:^t^w^o^:^:^f^f(); +} +})cpp", + R"cpp( +#include "test.hpp" +namespace {using one::two::ff; + +void fun() { + ff(); +} +})cpp", + }, + // Type, no other using, namespace. + { + R"cpp( +#include "test.hpp" +namespace { +void fun() { + ::on^e::t^wo::c^c inst; +} +})cpp", + R"cpp( +#include "test.hpp" +namespace {using ::one::two::cc; + +void fun() { + cc inst; +} +})cpp", + }, + // Type, no other using, no namespace. + { + R"cpp( +#include "test.hpp" + +void fun() { + on^e::t^wo::e^e inst; +})cpp", + R"cpp( +#include "test.hpp" + +using one::two::ee; + +void fun() { + ee inst; +})cpp"}, + // Function, other usings. + { + R"cpp( +#include "test.hpp" + +using one::two::cc; +using one::two::ee; + +namespace { +void fun() { + one::two::f^f(); +} +})cpp", + R"cpp( +#include "test.hpp" + +using one::two::cc; +using one::two::ff;using one::two::ee; + +namespace { +void fun() { + ff(); +} +})cpp", + }, + // Function, other usings inside namespace. + { + R"cpp( +#include "test.hpp" + +using one::two::cc; + +namespace { + +using one::two::ff; + +void fun() { + o^ne::o^o(); +} +})cpp", + R"cpp( +#include "test.hpp" + +using one::two::cc; + +namespace { + +using one::oo;using one::two::ff; + +void fun() { + oo(); +} +})cpp"}, + // Using comes after cursor. + { + R"cpp( +#include "test.hpp" + +namespace { + +void fun() { + one::t^wo::ff(); +} + +using one::two::cc; + +})cpp", + R"cpp( +#include "test.hpp" + +namespace {using one::two::ff; + + +void fun() { + ff(); +} + +using one::two::cc; + +})cpp"}, + // Pointer type. + {R"cpp( +#include "test.hpp" + +void fun() { + one::two::c^c *p; +})cpp", + R"cpp( +#include "test.hpp" + +using one::two::cc; + +void fun() { + cc *p; +})cpp"}, + // Namespace declared via macro. + {R"cpp( +#include "test.hpp" +#define NS_BEGIN(name) namespace name { + +NS_BEGIN(foo) + +void fun() { + one::two::f^f(); +} +})cpp", + R"cpp( +#include "test.hpp" +#define NS_BEGIN(name) namespace name { + +using one::two::ff; + +NS_BEGIN(foo) + +void fun() { + ff(); +} +})cpp"}, + // Inside macro argument. + {R"cpp( +#include "test.hpp" +#define CALL(name) name() + +void fun() { + CALL(one::t^wo::ff); +})cpp", + R"cpp( +#include "test.hpp" +#define CALL(name) name() + +using one::two::ff; + +void fun() { + CALL(ff); +})cpp"}, + // Parent namespace != lexical parent namespace + {R"cpp( +#include "test.hpp" +namespace foo { void fun(); } + +void foo::fun() { + one::two::f^f(); +})cpp", + R"cpp( +#include "test.hpp" +using one::two::ff; + +namespace foo { void fun(); } + +void foo::fun() { + ff(); +})cpp"}, + // If all other using are fully qualified, add :: + {R"cpp( +#include "test.hpp" + +using ::one::two::cc; +using ::one::two::ee; + +void fun() { + one::two::f^f(); +})cpp", + R"cpp( +#include "test.hpp" + +using ::one::two::cc; +using ::one::two::ff;using ::one::two::ee; + +void fun() { + ff(); +})cpp"}, + // Make sure we don't add :: if it's already there + {R"cpp( +#include "test.hpp" + +using ::one::two::cc; +using ::one::two::ee; + +void fun() { + ::one::two::f^f(); +})cpp", + R"cpp( +#include "test.hpp" + +using ::one::two::cc; +using ::one::two::ff;using ::one::two::ee; + +void fun() { + ff(); +})cpp"}, + // If even one using doesn't start with ::, do not add it + {R"cpp( +#include "test.hpp" + +using ::one::two::cc; +using one::two::ee; + +void fun() { + one::two::f^f(); +})cpp", + R"cpp( +#include "test.hpp" + +using ::one::two::cc; +using one::two::ff;using one::two::ee; + +void fun() { + ff(); +})cpp"}, + // using alias; insert using for the spelled name. + {R"cpp( +#include "test.hpp" + +void fun() { + one::u^u u; +})cpp", + R"cpp( +#include "test.hpp" + +using one::uu; + +void fun() { + uu u; +})cpp"}, + // using namespace. + {R"cpp( +#include "test.hpp" +using namespace one; +namespace { +two::c^c C; +})cpp", + R"cpp( +#include "test.hpp" +using namespace one; +namespace {using two::cc; + +cc C; +})cpp"}, + // Type defined in main file, make sure using is after that. + {R"cpp( +namespace xx { + struct yy {}; +} + +x^x::yy X; +)cpp", + R"cpp( +namespace xx { + struct yy {}; +} + +using xx::yy; + +yy X; +)cpp"}, + // Type defined in main file via "using", insert after that. + {R"cpp( +#include "test.hpp" + +namespace xx { + using yy = one::two::cc; +} + +x^x::yy X; +)cpp", + R"cpp( +#include "test.hpp" + +namespace xx { + using yy = one::two::cc; +} + +using xx::yy; + +yy X; +)cpp"}, + // Using must come after function definition. + {R"cpp( +namespace xx { + void yy(); +} + +void fun() { + x^x::yy(); +} +)cpp", + R"cpp( +namespace xx { + void yy(); +} + +using xx::yy; + +void fun() { + yy(); +} +)cpp"}, + // Existing using with non-namespace part. + {R"cpp( +#include "test.hpp" +using one::two::ee::ee_one; +one::t^wo::cc c; +)cpp", + R"cpp( +#include "test.hpp" +using one::two::cc;using one::two::ee::ee_one; +cc c; +)cpp"}}; + llvm::StringMap EditedFiles; + for (const auto &Case : Cases) { + for (const auto &SubCase : expandCases(Case.TestSource)) { + ExtraFiles["test.hpp"] = R"cpp( +namespace one { +void oo() {} +namespace two { +enum ee {ee_one}; +void ff() {} +class cc { +public: + struct st { struct nested {}; }; + static void mm() {} +}; +} +using uu = two::cc; +})cpp"; + EXPECT_EQ(apply(SubCase, &EditedFiles), Case.ExpectedSource); + } + } +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/AnnotateHighlightingsTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/AnnotateHighlightingsTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c218f5f7b0436729e6bc181daac774ae5411890 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/AnnotateHighlightingsTests.cpp @@ -0,0 +1,34 @@ +//===-- AnnotateHighlightingsTests.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 "TweakTesting.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(AnnotateHighlightings); + +TEST_F(AnnotateHighlightingsTest, Test) { + EXPECT_AVAILABLE("^vo^id^ ^f(^) {^}^"); // available everywhere. + EXPECT_AVAILABLE("[[int a; int b;]]"); + EXPECT_EQ("void /* entity.name.function.cpp */f() {}", apply("void ^f() {}")); + + EXPECT_EQ(apply("[[void f1(); void f2();]]"), + "void /* entity.name.function.cpp */f1(); " + "void /* entity.name.function.cpp */f2();"); + + EXPECT_EQ(apply("void f1(); void f2() {^}"), + "void f1(); " + "void /* entity.name.function.cpp */f2() {}"); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/DefineInlineTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/DefineInlineTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f190a314bc4a593cfe6394d51bda883cc2ff4699 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/DefineInlineTests.cpp @@ -0,0 +1,1008 @@ +//===-- DefineInlineTests.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::ElementsAre; + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(DefineInline); + +TEST_F(DefineInlineTest, TriggersOnFunctionDecl) { + // Basic check for function body and signature. + EXPECT_AVAILABLE(R"cpp( + class Bar { + void baz(); + }; + + [[void [[Bar::[[b^a^z]]]]() [[{ + return; + }]]]] + + void foo(); + [[void [[f^o^o]]() [[{ + return; + }]]]] + )cpp"); + + EXPECT_UNAVAILABLE(R"cpp( + // Not a definition + vo^i[[d^ ^f]]^oo(); + + [[vo^id ]]foo[[()]] {[[ + [[(void)(5+3); + return;]] + }]] + + // Definition with no body. + class Bar { Bar() = def^ault; }; + )cpp"); +} + +TEST_F(DefineInlineTest, NoForwardDecl) { + Header = "void bar();"; + EXPECT_UNAVAILABLE(R"cpp( + void bar() { + return; + } + // FIXME: Generate a decl in the header. + void fo^o() { + return; + })cpp"); +} + +TEST_F(DefineInlineTest, ReferencedDecls) { + EXPECT_AVAILABLE(R"cpp( + void bar(); + void foo(int test); + + void fo^o(int baz) { + int x = 10; + bar(); + })cpp"); + + // Internal symbol usage. + Header = "void foo(int test);"; + EXPECT_UNAVAILABLE(R"cpp( + void bar(); + void fo^o(int baz) { + int x = 10; + bar(); + })cpp"); + + // Becomes available after making symbol visible. + Header = "void bar();" + Header; + EXPECT_AVAILABLE(R"cpp( + void fo^o(int baz) { + int x = 10; + bar(); + })cpp"); + + // FIXME: Move declaration below bar to make it visible. + Header.clear(); + EXPECT_UNAVAILABLE(R"cpp( + void foo(); + void bar(); + + void fo^o() { + bar(); + })cpp"); + + // Order doesn't matter within a class. + EXPECT_AVAILABLE(R"cpp( + class Bar { + void foo(); + void bar(); + }; + + void Bar::fo^o() { + bar(); + })cpp"); + + // FIXME: Perform include insertion to make symbol visible. + ExtraFiles["a.h"] = "void bar();"; + Header = "void foo(int test);"; + EXPECT_UNAVAILABLE(R"cpp( + #include "a.h" + void fo^o(int baz) { + int x = 10; + bar(); + })cpp"); +} + +TEST_F(DefineInlineTest, TemplateSpec) { + EXPECT_UNAVAILABLE(R"cpp( + template void foo(); + template<> void foo(); + + template<> void f^oo() { + })cpp"); + EXPECT_UNAVAILABLE(R"cpp( + template void foo(); + + template<> void f^oo() { + })cpp"); + EXPECT_UNAVAILABLE(R"cpp( + template struct Foo { void foo(); }; + + template void Foo::f^oo() { + })cpp"); + EXPECT_AVAILABLE(R"cpp( + template void foo(); + void bar(); + template <> void foo(); + + template<> void f^oo() { + bar(); + })cpp"); + EXPECT_UNAVAILABLE(R"cpp( + namespace bar { + template void f^oo() {} + template void foo(); + })cpp"); +} + +TEST_F(DefineInlineTest, CheckForCanonDecl) { + EXPECT_UNAVAILABLE(R"cpp( + void foo(); + + void bar() {} + void f^oo() { + // This bar normally refers to the definition just above, but it is not + // visible from the forward declaration of foo. + bar(); + })cpp"); + // Make it available with a forward decl. + EXPECT_AVAILABLE(R"cpp( + void bar(); + void foo(); + + void bar() {} + void f^oo() { + bar(); + })cpp"); +} + +TEST_F(DefineInlineTest, UsingShadowDecls) { + // Template body is not parsed until instantiation time on windows, which + // results in arbitrary failures as function body becomes NULL. + ExtraArgs.push_back("-fno-delayed-template-parsing"); + EXPECT_UNAVAILABLE(R"cpp( + namespace ns1 { void foo(int); } + namespace ns2 { void foo(int*); } + template + void bar(); + + using ns1::foo; + using ns2::foo; + + template + void b^ar() { + foo(T()); + })cpp"); +} + +TEST_F(DefineInlineTest, TransformNestedNamespaces) { + auto Test = R"cpp( + namespace a { + void bar(); + namespace b { + void baz(); + namespace c { + void aux(); + } + } + } + + void foo(); + using namespace a; + using namespace b; + using namespace c; + void f^oo() { + bar(); + a::bar(); + + baz(); + b::baz(); + a::b::baz(); + + aux(); + c::aux(); + b::c::aux(); + a::b::c::aux(); + })cpp"; + auto Expected = R"cpp( + namespace a { + void bar(); + namespace b { + void baz(); + namespace c { + void aux(); + } + } + } + + void foo(){ + a::bar(); + a::bar(); + + a::b::baz(); + a::b::baz(); + a::b::baz(); + + a::b::c::aux(); + a::b::c::aux(); + a::b::c::aux(); + a::b::c::aux(); + } + using namespace a; + using namespace b; + using namespace c; + )cpp"; + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, TransformUsings) { + auto Test = R"cpp( + namespace a { namespace b { namespace c { void aux(); } } } + + void foo(); + void f^oo() { + using namespace a; + using namespace b; + using namespace c; + using c::aux; + namespace d = c; + })cpp"; + auto Expected = R"cpp( + namespace a { namespace b { namespace c { void aux(); } } } + + void foo(){ + using namespace a; + using namespace a::b; + using namespace a::b::c; + using a::b::c::aux; + namespace d = a::b::c; + } + )cpp"; + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, TransformDecls) { + auto Test = R"cpp( + void foo(); + void f^oo() { + class Foo { + public: + void foo(); + int x; + }; + + enum En { Zero, One }; + En x = Zero; + + enum class EnClass { Zero, One }; + EnClass y = EnClass::Zero; + })cpp"; + auto Expected = R"cpp( + void foo(){ + class Foo { + public: + void foo(); + int x; + }; + + enum En { Zero, One }; + En x = Zero; + + enum class EnClass { Zero, One }; + EnClass y = EnClass::Zero; + } + )cpp"; + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, TransformTemplDecls) { + auto Test = R"cpp( + namespace a { + template class Bar { + public: + void bar(); + }; + template T bar; + template void aux() {} + } + + void foo(); + + using namespace a; + void f^oo() { + bar>.bar(); + aux>(); + })cpp"; + auto Expected = R"cpp( + namespace a { + template class Bar { + public: + void bar(); + }; + template T bar; + template void aux() {} + } + + void foo(){ + a::bar>.bar(); + a::aux>(); + } + + using namespace a; + )cpp"; + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, TransformMembers) { + auto Test = R"cpp( + class Foo { + void foo(); + }; + + void Foo::f^oo() { + return; + })cpp"; + auto Expected = R"cpp( + class Foo { + void foo(){ + return; + } + }; + + )cpp"; + EXPECT_EQ(apply(Test), Expected); + + ExtraFiles["a.h"] = R"cpp( + class Foo { + void foo(); + };)cpp"; + + llvm::StringMap EditedFiles; + Test = R"cpp( + #include "a.h" + void Foo::f^oo() { + return; + })cpp"; + Expected = R"cpp( + #include "a.h" + )cpp"; + EXPECT_EQ(apply(Test, &EditedFiles), Expected); + + Expected = R"cpp( + class Foo { + void foo(){ + return; + } + };)cpp"; + EXPECT_THAT(EditedFiles, + ElementsAre(FileWithContents(testPath("a.h"), Expected))); +} + +TEST_F(DefineInlineTest, TransformDependentTypes) { + auto Test = R"cpp( + namespace a { + template class Bar {}; + } + + template + void foo(); + + using namespace a; + template + void f^oo() { + Bar B; + Bar> q; + })cpp"; + auto Expected = R"cpp( + namespace a { + template class Bar {}; + } + + template + void foo(){ + a::Bar B; + a::Bar> q; + } + + using namespace a; + )cpp"; + + // Template body is not parsed until instantiation time on windows, which + // results in arbitrary failures as function body becomes NULL. + ExtraArgs.push_back("-fno-delayed-template-parsing"); + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, TransformFunctionTempls) { + // Check we select correct specialization decl. + std::pair Cases[] = { + {R"cpp( + template + void foo(T p); + + template <> + void foo(int p); + + template <> + void foo(char p); + + template <> + void fo^o(int p) { + return; + })cpp", + R"cpp( + template + void foo(T p); + + template <> + void foo(int p){ + return; + } + + template <> + void foo(char p); + + )cpp"}, + {// Make sure we are not selecting the first specialization all the time. + R"cpp( + template + void foo(T p); + + template <> + void foo(int p); + + template <> + void foo(char p); + + template <> + void fo^o(char p) { + return; + })cpp", + R"cpp( + template + void foo(T p); + + template <> + void foo(int p); + + template <> + void foo(char p){ + return; + } + + )cpp"}, + {R"cpp( + template + void foo(T p); + + template <> + void foo(int p); + + template + void fo^o(T p) { + return; + })cpp", + R"cpp( + template + void foo(T p){ + return; + } + + template <> + void foo(int p); + + )cpp"}, + }; + // Template body is not parsed until instantiation time on windows, which + // results in arbitrary failures as function body becomes NULL. + ExtraArgs.push_back("-fno-delayed-template-parsing"); + for (const auto &Case : Cases) + EXPECT_EQ(apply(Case.first), Case.second) << Case.first; +} + +TEST_F(DefineInlineTest, TransformTypeLocs) { + auto Test = R"cpp( + namespace a { + template class Bar { + public: + template class Baz {}; + }; + class Foo{}; + } + + void foo(); + + using namespace a; + void f^oo() { + Bar B; + Foo foo; + a::Bar>::Baz> q; + })cpp"; + auto Expected = R"cpp( + namespace a { + template class Bar { + public: + template class Baz {}; + }; + class Foo{}; + } + + void foo(){ + a::Bar B; + a::Foo foo; + a::Bar>::Baz> q; + } + + using namespace a; + )cpp"; + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, TransformDeclRefs) { + auto Test = R"cpp( + namespace a { + template class Bar { + public: + void foo(); + static void bar(); + int x; + static int y; + }; + void bar(); + void test(); + } + + void foo(); + using namespace a; + void f^oo() { + a::Bar B; + B.foo(); + a::bar(); + Bar>::bar(); + a::Bar::bar(); + B.x = Bar::y; + Bar::y = 3; + bar(); + a::test(); + })cpp"; + auto Expected = R"cpp( + namespace a { + template class Bar { + public: + void foo(); + static void bar(); + int x; + static int y; + }; + void bar(); + void test(); + } + + void foo(){ + a::Bar B; + B.foo(); + a::bar(); + a::Bar>::bar(); + a::Bar::bar(); + B.x = a::Bar::y; + a::Bar::y = 3; + a::bar(); + a::test(); + } + using namespace a; + )cpp"; + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, StaticMembers) { + auto Test = R"cpp( + namespace ns { class X { static void foo(); void bar(); }; } + void ns::X::b^ar() { + foo(); + })cpp"; + auto Expected = R"cpp( + namespace ns { class X { static void foo(); void bar(){ + foo(); + } }; } + )cpp"; + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, TransformParamNames) { + std::pair Cases[] = { + {R"cpp( + void foo(int, bool b, int T\ +est); + void ^foo(int f, bool x, int z) {})cpp", + R"cpp( + void foo(int f, bool x, int z){} + )cpp"}, + {R"cpp( + #define PARAM int Z + void foo(PARAM); + + void ^foo(int X) {})cpp", + "fail: Cant rename parameter inside macro body."}, + {R"cpp( + #define TYPE int + #define PARAM TYPE Z + #define BODY(x) 5 * (x) + 2 + template + void foo(PARAM, TYPE Q, TYPE, TYPE W = BODY(P)); + template + void ^foo(int Z, int b, int c, int d) {})cpp", + R"cpp( + #define TYPE int + #define PARAM TYPE Z + #define BODY(x) 5 * (x) + 2 + template + void foo(PARAM, TYPE b, TYPE c, TYPE d = BODY(x)){} + )cpp"}, + }; + ExtraArgs.push_back("-fno-delayed-template-parsing"); + for (const auto &Case : Cases) + EXPECT_EQ(apply(Case.first), Case.second) << Case.first; +} + +TEST_F(DefineInlineTest, TransformTemplParamNames) { + auto Test = R"cpp( + struct Foo { + struct Bar { + template class, template class Y, + int, int Z> + void foo(X, Y, int W = 5 * Z + 2); + }; + }; + + template class V, template class W, + int X, int Y> + void Foo::Bar::f^oo(U, W, int Q) {})cpp"; + auto Expected = R"cpp( + struct Foo { + struct Bar { + template class V, template class W, + int X, int Y> + void foo(U, W, int Q = 5 * Y + 2){} + }; + }; + + )cpp"; + ExtraArgs.push_back("-fno-delayed-template-parsing"); + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, TransformInlineNamespaces) { + auto Test = R"cpp( + namespace a { inline namespace b { namespace { struct Foo{}; } } } + void foo(); + + using namespace a; + void ^foo() {Foo foo;})cpp"; + auto Expected = R"cpp( + namespace a { inline namespace b { namespace { struct Foo{}; } } } + void foo(){a::Foo foo;} + + using namespace a; + )cpp"; + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineInlineTest, TokensBeforeSemicolon) { + std::pair Cases[] = { + {R"cpp( + void foo() /*Comment -_-*/ /*Com 2*/ ; + void fo^o() { return ; })cpp", + R"cpp( + void foo() /*Comment -_-*/ /*Com 2*/ { return ; } + )cpp"}, + + {R"cpp( + void foo(); + void fo^o() { return ; })cpp", + R"cpp( + void foo(){ return ; } + )cpp"}, + + {R"cpp( + #define SEMI ; + void foo() SEMI + void fo^o() { return ; })cpp", + "fail: Couldn't find semicolon for target declaration."}, + }; + for (const auto &Case : Cases) + EXPECT_EQ(apply(Case.first), Case.second) << Case.first; +} + +TEST_F(DefineInlineTest, HandleMacros) { + EXPECT_UNAVAILABLE(R"cpp( + #define BODY { return; } + void foo(); + void f^oo()BODY)cpp"); + + EXPECT_UNAVAILABLE(R"cpp( + #define BODY void foo(){ return; } + void foo(); + [[BODY]])cpp"); + + std::pair Cases[] = { + // We don't qualify declarations coming from macros. + {R"cpp( + #define BODY Foo + namespace a { class Foo{}; } + void foo(); + using namespace a; + void f^oo(){BODY();})cpp", + R"cpp( + #define BODY Foo + namespace a { class Foo{}; } + void foo(){BODY();} + using namespace a; + )cpp"}, + + // Macro is not visible at declaration location, but we proceed. + {R"cpp( + void foo(); + #define BODY return; + void f^oo(){BODY})cpp", + R"cpp( + void foo(){BODY} + #define BODY return; + )cpp"}, + + {R"cpp( + #define TARGET void foo() + TARGET; + void f^oo(){ return; })cpp", + R"cpp( + #define TARGET void foo() + TARGET{ return; } + )cpp"}, + + {R"cpp( + #define TARGET foo + void TARGET(); + void f^oo(){ return; })cpp", + R"cpp( + #define TARGET foo + void TARGET(){ return; } + )cpp"}, + }; + for (const auto &Case : Cases) + EXPECT_EQ(apply(Case.first), Case.second) << Case.first; +} + +TEST_F(DefineInlineTest, DropCommonNameSpecifiers) { + struct { + llvm::StringRef Test; + llvm::StringRef Expected; + } Cases[] = { + {R"cpp( + namespace a { namespace b { void aux(); } } + namespace ns1 { + void foo(); + namespace qq { void test(); } + namespace ns2 { + void bar(); + namespace ns3 { void baz(); } + } + } + + using namespace a; + using namespace a::b; + using namespace ns1::qq; + void ns1::ns2::ns3::b^az() { + foo(); + bar(); + baz(); + ns1::ns2::ns3::baz(); + aux(); + test(); + })cpp", + R"cpp( + namespace a { namespace b { void aux(); } } + namespace ns1 { + void foo(); + namespace qq { void test(); } + namespace ns2 { + void bar(); + namespace ns3 { void baz(){ + foo(); + bar(); + baz(); + ns1::ns2::ns3::baz(); + a::b::aux(); + qq::test(); + } } + } + } + + using namespace a; + using namespace a::b; + using namespace ns1::qq; + )cpp"}, + {R"cpp( + namespace ns1 { + namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; } + namespace ns2 { void baz(); } + } + + using namespace ns1::qq; + void ns1::ns2::b^az() { Foo f; B b; })cpp", + R"cpp( + namespace ns1 { + namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; } + namespace ns2 { void baz(){ qq::Foo f; qq::B b; } } + } + + using namespace ns1::qq; + )cpp"}, + {R"cpp( + namespace ns1 { + namespace qq { + template struct Foo { template struct Bar {}; }; + template + using B = typename Foo::template Bar; + } + namespace ns2 { void baz(); } + } + + using namespace ns1::qq; + void ns1::ns2::b^az() { B b; })cpp", + R"cpp( + namespace ns1 { + namespace qq { + template struct Foo { template struct Bar {}; }; + template + using B = typename Foo::template Bar; + } + namespace ns2 { void baz(){ qq::B b; } } + } + + using namespace ns1::qq; + )cpp"}, + }; + for (const auto &Case : Cases) + EXPECT_EQ(apply(Case.Test), Case.Expected) << Case.Test; +} + +TEST_F(DefineInlineTest, QualifyWithUsingDirectives) { + llvm::StringRef Test = R"cpp( + namespace a { + void bar(); + namespace b { struct Foo{}; void aux(); } + namespace c { void cux(); } + } + using namespace a; + using X = b::Foo; + void foo(); + + using namespace b; + using namespace c; + void ^foo() { + cux(); + bar(); + X x; + aux(); + using namespace c; + // FIXME: The last reference to cux() in body of foo should not be + // qualified, since there is a using directive inside the function body. + cux(); + })cpp"; + llvm::StringRef Expected = R"cpp( + namespace a { + void bar(); + namespace b { struct Foo{}; void aux(); } + namespace c { void cux(); } + } + using namespace a; + using X = b::Foo; + void foo(){ + c::cux(); + bar(); + X x; + b::aux(); + using namespace c; + // FIXME: The last reference to cux() in body of foo should not be + // qualified, since there is a using directive inside the function body. + c::cux(); + } + + using namespace b; + using namespace c; + )cpp"; + EXPECT_EQ(apply(Test), Expected) << Test; +} + +TEST_F(DefineInlineTest, AddInline) { + ExtraArgs.push_back("-fno-delayed-template-parsing"); + llvm::StringMap EditedFiles; + ExtraFiles["a.h"] = "void foo();"; + apply(R"cpp(#include "a.h" + void fo^o() {})cpp", + &EditedFiles); + EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( + testPath("a.h"), "inline void foo(){}"))); + + // Check we put inline before cv-qualifiers. + ExtraFiles["a.h"] = "const int foo();"; + apply(R"cpp(#include "a.h" + const int fo^o() {})cpp", + &EditedFiles); + EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( + testPath("a.h"), "inline const int foo(){}"))); + + // No double inline. + ExtraFiles["a.h"] = "inline void foo();"; + apply(R"cpp(#include "a.h" + inline void fo^o() {})cpp", + &EditedFiles); + EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( + testPath("a.h"), "inline void foo(){}"))); + + // Constexprs don't need "inline". + ExtraFiles["a.h"] = "constexpr void foo();"; + apply(R"cpp(#include "a.h" + constexpr void fo^o() {})cpp", + &EditedFiles); + EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( + testPath("a.h"), "constexpr void foo(){}"))); + + // Class members don't need "inline". + ExtraFiles["a.h"] = "struct Foo { void foo(); };"; + apply(R"cpp(#include "a.h" + void Foo::fo^o() {})cpp", + &EditedFiles); + EXPECT_THAT(EditedFiles, + testing::ElementsAre(FileWithContents( + testPath("a.h"), "struct Foo { void foo(){} };"))); + + // Function template doesn't need to be "inline"d. + ExtraFiles["a.h"] = "template void foo();"; + apply(R"cpp(#include "a.h" + template + void fo^o() {})cpp", + &EditedFiles); + EXPECT_THAT(EditedFiles, + testing::ElementsAre(FileWithContents( + testPath("a.h"), "template void foo(){}"))); + + // Specializations needs to be marked "inline". + ExtraFiles["a.h"] = R"cpp( + template void foo(); + template <> void foo();)cpp"; + apply(R"cpp(#include "a.h" + template <> + void fo^o() {})cpp", + &EditedFiles); + EXPECT_THAT(EditedFiles, + testing::ElementsAre(FileWithContents(testPath("a.h"), + R"cpp( + template void foo(); + template <> inline void foo(){})cpp"))); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a49a37503354638a5b5d0ea0223d0059d2f07cd --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp @@ -0,0 +1,541 @@ +//===-- DefineOutline.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::ElementsAre; + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(DefineOutline); + +TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) { + FileName = "Test.cpp"; + // Not available unless in a header file. + EXPECT_UNAVAILABLE(R"cpp( + [[void [[f^o^o]]() [[{ + return; + }]]]])cpp"); + + FileName = "Test.hpp"; + // Not available unless function name or fully body is selected. + EXPECT_UNAVAILABLE(R"cpp( + // Not a definition + vo^i[[d^ ^f]]^oo(); + + [[vo^id ]]foo[[()]] {[[ + [[(void)(5+3); + return;]] + }]])cpp"); + + // Available even if there are no implementation files. + EXPECT_AVAILABLE(R"cpp( + [[void [[f^o^o]]() [[{ + return; + }]]]])cpp"); + + // Not available for out-of-line methods. + EXPECT_UNAVAILABLE(R"cpp( + class Bar { + void baz(); + }; + + [[void [[Bar::[[b^a^z]]]]() [[{ + return; + }]]]])cpp"); + + // Basic check for function body and signature. + EXPECT_AVAILABLE(R"cpp( + class Bar { + [[void [[f^o^o^]]() [[{ return; }]]]] + }; + + void foo(); + [[void [[f^o^o]]() [[{ + return; + }]]]])cpp"); + + // Not available on defaulted/deleted members. + EXPECT_UNAVAILABLE(R"cpp( + class Foo { + Fo^o() = default; + F^oo(const Foo&) = delete; + };)cpp"); + + // Not available within templated classes, as it is hard to spell class name + // out-of-line in such cases. + EXPECT_UNAVAILABLE(R"cpp( + template struct Foo { void fo^o(){} }; + )cpp"); + + // Not available on function templates and specializations, as definition must + // be visible to all translation units. + EXPECT_UNAVAILABLE(R"cpp( + template void fo^o() {}; + template <> void fo^o() {}; + )cpp"); +} + +TEST_F(DefineOutlineTest, FailsWithoutSource) { + FileName = "Test.hpp"; + llvm::StringRef Test = "void fo^o() { return; }"; + llvm::StringRef Expected = + "fail: Couldn't find a suitable implementation file."; + EXPECT_EQ(apply(Test), Expected); +} + +TEST_F(DefineOutlineTest, ApplyTest) { + llvm::StringMap EditedFiles; + ExtraFiles["Test.cpp"] = ""; + FileName = "Test.hpp"; + // Template body is not parsed until instantiation time on windows, which + // results in arbitrary failures as function body becomes NULL. + ExtraArgs.push_back("-fno-delayed-template-parsing"); + + struct { + llvm::StringRef Test; + llvm::StringRef ExpectedHeader; + llvm::StringRef ExpectedSource; + } Cases[] = { + // Simple check + { + "void fo^o() { return; }", + "void foo() ;", + "void foo() { return; }", + }, + // Default args. + { + "void fo^o(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) {}", + "void foo(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) ;", + "void foo(int x, int y , int , int (*foo)(int) ) {}", + }, + // Constructors + { + R"cpp( + class Foo {public: Foo(); Foo(int);}; + class Bar { + Ba^r() {} + Bar(int x) : f1(x) {} + Foo f1; + Foo f2 = 2; + };)cpp", + R"cpp( + class Foo {public: Foo(); Foo(int);}; + class Bar { + Bar() ; + Bar(int x) : f1(x) {} + Foo f1; + Foo f2 = 2; + };)cpp", + "Bar::Bar() {}\n", + }, + // Ctor with initializer. + { + R"cpp( + class Foo {public: Foo(); Foo(int);}; + class Bar { + Bar() {} + B^ar(int x) : f1(x), f2(3) {} + Foo f1; + Foo f2 = 2; + };)cpp", + R"cpp( + class Foo {public: Foo(); Foo(int);}; + class Bar { + Bar() {} + Bar(int x) ; + Foo f1; + Foo f2 = 2; + };)cpp", + "Bar::Bar(int x) : f1(x), f2(3) {}\n", + }, + // Ctor initializer with attribute. + { + R"cpp( + class Foo { + F^oo(int z) __attribute__((weak)) : bar(2){} + int bar; + };)cpp", + R"cpp( + class Foo { + Foo(int z) __attribute__((weak)) ; + int bar; + };)cpp", + "Foo::Foo(int z) __attribute__((weak)) : bar(2){}\n", + }, + // Virt specifiers. + { + R"cpp( + struct A { + virtual void f^oo() {} + };)cpp", + R"cpp( + struct A { + virtual void foo() ; + };)cpp", + " void A::foo() {}\n", + }, + { + R"cpp( + struct A { + virtual virtual void virtual f^oo() {} + };)cpp", + R"cpp( + struct A { + virtual virtual void virtual foo() ; + };)cpp", + " void A::foo() {}\n", + }, + { + R"cpp( + struct A { + virtual void foo() = 0; + }; + struct B : A { + void fo^o() override {} + };)cpp", + R"cpp( + struct A { + virtual void foo() = 0; + }; + struct B : A { + void foo() override ; + };)cpp", + "void B::foo() {}\n", + }, + { + R"cpp( + struct A { + virtual void foo() = 0; + }; + struct B : A { + void fo^o() final {} + };)cpp", + R"cpp( + struct A { + virtual void foo() = 0; + }; + struct B : A { + void foo() final ; + };)cpp", + "void B::foo() {}\n", + }, + { + R"cpp( + struct A { + virtual void foo() = 0; + }; + struct B : A { + void fo^o() final override {} + };)cpp", + R"cpp( + struct A { + virtual void foo() = 0; + }; + struct B : A { + void foo() final override ; + };)cpp", + "void B::foo() {}\n", + }, + { + R"cpp( + struct A { + static void fo^o() {} + };)cpp", + R"cpp( + struct A { + static void foo() ; + };)cpp", + " void A::foo() {}\n", + }, + { + R"cpp( + struct A { + static static void fo^o() {} + };)cpp", + R"cpp( + struct A { + static static void foo() ; + };)cpp", + " void A::foo() {}\n", + }, + }; + for (const auto &Case : Cases) { + SCOPED_TRACE(Case.Test); + EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader); + EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( + testPath("Test.cpp"), Case.ExpectedSource))); + } +} + +TEST_F(DefineOutlineTest, HandleMacros) { + llvm::StringMap EditedFiles; + ExtraFiles["Test.cpp"] = ""; + FileName = "Test.hpp"; + ExtraArgs.push_back("-DVIRTUAL=virtual"); + ExtraArgs.push_back("-DOVER=override"); + + struct { + llvm::StringRef Test; + llvm::StringRef ExpectedHeader; + llvm::StringRef ExpectedSource; + } Cases[] = { + {R"cpp( + #define BODY { return; } + void f^oo()BODY)cpp", + R"cpp( + #define BODY { return; } + void foo();)cpp", + "void foo()BODY"}, + + {R"cpp( + #define BODY return; + void f^oo(){BODY})cpp", + R"cpp( + #define BODY return; + void foo();)cpp", + "void foo(){BODY}"}, + + {R"cpp( + #define TARGET void foo() + [[TARGET]]{ return; })cpp", + R"cpp( + #define TARGET void foo() + TARGET;)cpp", + "TARGET{ return; }"}, + + {R"cpp( + #define TARGET foo + void [[TARGET]](){ return; })cpp", + R"cpp( + #define TARGET foo + void TARGET();)cpp", + "void TARGET(){ return; }"}, + {R"cpp(#define VIRT virtual + struct A { + VIRT void f^oo() {} + };)cpp", + R"cpp(#define VIRT virtual + struct A { + VIRT void foo() ; + };)cpp", + " void A::foo() {}\n"}, + {R"cpp( + struct A { + VIRTUAL void f^oo() {} + };)cpp", + R"cpp( + struct A { + VIRTUAL void foo() ; + };)cpp", + " void A::foo() {}\n"}, + {R"cpp( + struct A { + virtual void foo() = 0; + }; + struct B : A { + void fo^o() OVER {} + };)cpp", + R"cpp( + struct A { + virtual void foo() = 0; + }; + struct B : A { + void foo() OVER ; + };)cpp", + "void B::foo() {}\n"}, + {R"cpp(#define STUPID_MACRO(X) virtual + struct A { + STUPID_MACRO(sizeof sizeof int) void f^oo() {} + };)cpp", + R"cpp(#define STUPID_MACRO(X) virtual + struct A { + STUPID_MACRO(sizeof sizeof int) void foo() ; + };)cpp", + " void A::foo() {}\n"}, + {R"cpp(#define STAT static + struct A { + STAT void f^oo() {} + };)cpp", + R"cpp(#define STAT static + struct A { + STAT void foo() ; + };)cpp", + " void A::foo() {}\n"}, + {R"cpp(#define STUPID_MACRO(X) static + struct A { + STUPID_MACRO(sizeof sizeof int) void f^oo() {} + };)cpp", + R"cpp(#define STUPID_MACRO(X) static + struct A { + STUPID_MACRO(sizeof sizeof int) void foo() ; + };)cpp", + " void A::foo() {}\n"}, + }; + for (const auto &Case : Cases) { + SCOPED_TRACE(Case.Test); + EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader); + EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( + testPath("Test.cpp"), Case.ExpectedSource))); + } +} + +TEST_F(DefineOutlineTest, QualifyReturnValue) { + FileName = "Test.hpp"; + ExtraFiles["Test.cpp"] = ""; + + struct { + llvm::StringRef Test; + llvm::StringRef ExpectedHeader; + llvm::StringRef ExpectedSource; + } Cases[] = { + {R"cpp( + namespace a { class Foo{}; } + using namespace a; + Foo fo^o() { return {}; })cpp", + R"cpp( + namespace a { class Foo{}; } + using namespace a; + Foo foo() ;)cpp", + "a::Foo foo() { return {}; }"}, + {R"cpp( + namespace a { + class Foo { + class Bar {}; + Bar fo^o() { return {}; } + }; + })cpp", + R"cpp( + namespace a { + class Foo { + class Bar {}; + Bar foo() ; + }; + })cpp", + "a::Foo::Bar a::Foo::foo() { return {}; }\n"}, + {R"cpp( + class Foo {}; + Foo fo^o() { return {}; })cpp", + R"cpp( + class Foo {}; + Foo foo() ;)cpp", + "Foo foo() { return {}; }"}, + }; + llvm::StringMap EditedFiles; + for (auto &Case : Cases) { + apply(Case.Test, &EditedFiles); + EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader); + EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( + testPath("Test.cpp"), Case.ExpectedSource))); + } +} + +TEST_F(DefineOutlineTest, QualifyFunctionName) { + FileName = "Test.hpp"; + struct { + llvm::StringRef TestHeader; + llvm::StringRef TestSource; + llvm::StringRef ExpectedHeader; + llvm::StringRef ExpectedSource; + } Cases[] = { + { + R"cpp( + namespace a { + namespace b { + class Foo { + void fo^o() {} + }; + } + })cpp", + "", + R"cpp( + namespace a { + namespace b { + class Foo { + void foo() ; + }; + } + })cpp", + "void a::b::Foo::foo() {}\n", + }, + { + "namespace a { namespace b { void f^oo() {} } }", + "namespace a{}", + "namespace a { namespace b { void foo() ; } }", + "namespace a{void b::foo() {} }", + }, + { + "namespace a { namespace b { void f^oo() {} } }", + "using namespace a;", + "namespace a { namespace b { void foo() ; } }", + // FIXME: Take using namespace directives in the source file into + // account. This can be spelled as b::foo instead. + "using namespace a;void a::b::foo() {} ", + }, + }; + llvm::StringMap EditedFiles; + for (auto &Case : Cases) { + ExtraFiles["Test.cpp"] = std::string(Case.TestSource); + EXPECT_EQ(apply(Case.TestHeader, &EditedFiles), Case.ExpectedHeader); + EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents( + testPath("Test.cpp"), Case.ExpectedSource))) + << Case.TestHeader; + } +} + +TEST_F(DefineOutlineTest, FailsMacroSpecifier) { + FileName = "Test.hpp"; + ExtraFiles["Test.cpp"] = ""; + ExtraArgs.push_back("-DFINALOVER=final override"); + + std::pair Cases[] = { + { + R"cpp( + #define VIRT virtual void + struct A { + VIRT fo^o() {} + };)cpp", + "fail: define outline: couldn't remove `virtual` keyword."}, + { + R"cpp( + #define OVERFINAL final override + struct A { + virtual void foo() {} + }; + struct B : A { + void fo^o() OVERFINAL {} + };)cpp", + "fail: define outline: Can't move out of line as function has a " + "macro `override` specifier.\ndefine outline: Can't move out of line " + "as function has a macro `final` specifier."}, + { + R"cpp( + struct A { + virtual void foo() {} + }; + struct B : A { + void fo^o() FINALOVER {} + };)cpp", + "fail: define outline: Can't move out of line as function has a " + "macro `override` specifier.\ndefine outline: Can't move out of line " + "as function has a macro `final` specifier."}, + }; + for (const auto &Case : Cases) { + EXPECT_EQ(apply(Case.first), Case.second); + } +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/DumpASTTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/DumpASTTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe9ab9a7099920b47735f7875dd55185b9f80039 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/DumpASTTests.cpp @@ -0,0 +1,36 @@ +//===-- DumpASTTests.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 "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::AllOf; +using ::testing::HasSubstr; +using ::testing::StartsWith; + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(DumpAST); + +TEST_F(DumpASTTest, Test) { + EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }"); + EXPECT_UNAVAILABLE("/*c^omment*/ int foo() { return 2 ^ + 2; }"); + EXPECT_THAT(apply("int x = 2 ^+ 2;"), + AllOf(StartsWith("message:"), HasSubstr("BinaryOperator"), + HasSubstr("'+'"), HasSubstr("|-IntegerLiteral"), + HasSubstr(" 'int' 2\n`-IntegerLiteral"), + HasSubstr(" 'int' 2"))); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/DumpRecordLayoutTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/DumpRecordLayoutTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75478dbb3b945728584d2a264247f1c95c2da9e2 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/DumpRecordLayoutTests.cpp @@ -0,0 +1,37 @@ +//===-- DumpRecordLayoutTests.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 "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::AllOf; +using ::testing::HasSubstr; +using ::testing::StartsWith; + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(DumpRecordLayout); + +TEST_F(DumpRecordLayoutTest, Test) { + EXPECT_AVAILABLE("^s^truct ^X ^{ int x; ^};"); + EXPECT_THAT("struct X { int ^a; };", Not(isAvailable())); + EXPECT_THAT("struct ^X;", Not(isAvailable())); + EXPECT_THAT("template struct ^X { T t; };", Not(isAvailable())); + EXPECT_THAT("enum ^X {};", Not(isAvailable())); + + EXPECT_THAT(apply("struct ^X { int x; int y; };"), + AllOf(StartsWith("message:"), HasSubstr("0 | int x"))); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/DumpSymbolTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/DumpSymbolTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a239275d4b1697719aa19a1ee5743a5d10937ba --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/DumpSymbolTests.cpp @@ -0,0 +1,35 @@ +//===-- DumpSymbolTests.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 "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include + +using ::testing::AllOf; +using ::testing::HasSubstr; +using ::testing::StartsWith; + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(DumpSymbol); + +TEST_F(DumpSymbolTest, Test) { + std::string ID = R"("id":"CA2EBE44A1D76D2A")"; + std::string USR = R"("usr":"c:@F@foo#")"; + EXPECT_THAT(apply("void f^oo();"), + AllOf(StartsWith("message:"), testing::HasSubstr(ID), + testing::HasSubstr(USR))); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba783e551e8477379ccdd0082f7157dbe8bdcfc4 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp @@ -0,0 +1,82 @@ +//===-- ExpandAutoTypeTests.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::StartsWith; + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(ExpandAutoType); + +TEST_F(ExpandAutoTypeTest, Test) { + Header = R"cpp( + namespace ns { + struct Class { + struct Nested {}; + }; + void Func(); + } + inline namespace inl_ns { + namespace { + struct Visible {}; + } + } + )cpp"; + + EXPECT_AVAILABLE("^a^u^t^o^ i = 0;"); + EXPECT_UNAVAILABLE("auto ^i^ ^=^ ^0^;^"); + + // check primitive type + EXPECT_EQ(apply("[[auto]] i = 0;"), "int i = 0;"); + EXPECT_EQ(apply("au^to i = 0;"), "int i = 0;"); + // check classes and namespaces + EXPECT_EQ(apply("^auto C = ns::Class::Nested();"), + "ns::Class::Nested C = ns::Class::Nested();"); + // check that namespaces are shortened + EXPECT_EQ(apply("namespace ns { void f() { ^auto C = Class(); } }"), + "namespace ns { void f() { Class C = Class(); } }"); + // undefined functions should not be replaced + EXPECT_THAT(apply("au^to x = doesnt_exist(); // error-ok"), + StartsWith("fail: Could not deduce type for 'auto' type")); + // function pointers should not be replaced + EXPECT_THAT(apply("au^to x = &ns::Func;"), + StartsWith("fail: Could not expand type of function pointer")); + // lambda types are not replaced + EXPECT_UNAVAILABLE("au^to x = []{};"); + // inline namespaces + EXPECT_EQ(apply("au^to x = inl_ns::Visible();"), + "Visible x = inl_ns::Visible();"); + // local class + EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"), + "namespace x { void y() { struct S{}; S z = S(); } }"); + // replace array types + EXPECT_EQ(apply(R"cpp(au^to x = "test";)cpp"), + R"cpp(const char * x = "test";)cpp"); + + EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;"); + // expanding types in structured bindings is syntactically invalid. + EXPECT_UNAVAILABLE("const ^auto &[x,y] = (int[]){1,2};"); + + // FIXME: Auto-completion in a template requires disabling delayed template + // parsing. + ExtraArgs.push_back("-fno-delayed-template-parsing"); + // unknown types in a template should not be replaced + EXPECT_THAT(apply("template void x() { ^auto y = T::z(); }"), + StartsWith("fail: Could not deduce type for 'auto' type")); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/ExpandMacroTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ExpandMacroTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6602fc7e6e6e1250b55afd418b021760f84cc1b3 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/ExpandMacroTests.cpp @@ -0,0 +1,55 @@ +//===-- ExpandMacroTests.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(ExpandMacro); + +TEST_F(ExpandMacroTest, Test) { + Header = R"cpp( + // error-ok: not real c++, just token manipulation + #define FOO 1 2 3 + #define FUNC(X) X+X+X + #define EMPTY + #define EMPTY_FN(X) + )cpp"; + + // Available on macro names, not available anywhere else. + EXPECT_AVAILABLE("^F^O^O^ BAR ^F^O^O^"); + EXPECT_AVAILABLE("^F^U^N^C^(1)"); + EXPECT_UNAVAILABLE("^#^d^efine^ ^XY^Z 1 ^2 ^3^"); + EXPECT_UNAVAILABLE("FOO ^B^A^R^ FOO ^"); + EXPECT_UNAVAILABLE("FUNC(^1^)^"); + + // Works as expected on object-like macros. + EXPECT_EQ(apply("^FOO BAR FOO"), "1 2 3 BAR FOO"); + EXPECT_EQ(apply("FOO BAR ^FOO"), "FOO BAR 1 2 3"); + // And function-like macros. + EXPECT_EQ(apply("F^UNC(2)"), "2 + 2 + 2"); + + // Works on empty macros. + EXPECT_EQ(apply("int a ^EMPTY;"), "int a ;"); + EXPECT_EQ(apply("int a ^EMPTY_FN(1 2 3);"), "int a ;"); + EXPECT_EQ(apply("int a = 123 ^EMPTY EMPTY_FN(1);"), + "int a = 123 EMPTY_FN(1);"); + EXPECT_EQ(apply("int a = 123 ^EMPTY_FN(1) EMPTY;"), "int a = 123 EMPTY;"); + EXPECT_EQ(apply("int a = 123 EMPTY_FN(1) ^EMPTY;"), + "int a = 123 EMPTY_FN(1) ;"); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2033b479896b740861e6ae605c77a0be769b9168 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp @@ -0,0 +1,202 @@ +//===-- ExtractFunctionTests.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::HasSubstr; +using ::testing::StartsWith; + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(ExtractFunction); + +TEST_F(ExtractFunctionTest, FunctionTest) { + Context = Function; + + // Root statements should have common parent. + EXPECT_EQ(apply("for(;;) [[1+2; 1+2;]]"), "unavailable"); + // Expressions aren't extracted. + EXPECT_EQ(apply("int x = 0; [[x++;]]"), "unavailable"); + // We don't support extraction from lambdas. + EXPECT_EQ(apply("auto lam = [](){ [[int x;]] }; "), "unavailable"); + // Partial statements aren't extracted. + EXPECT_THAT(apply("int [[x = 0]];"), "unavailable"); + // FIXME: Support hoisting. + EXPECT_THAT(apply(" [[int a = 5;]] a++; "), "unavailable"); + + // Ensure that end of Zone and Beginning of PostZone being adjacent doesn't + // lead to break being included in the extraction zone. + EXPECT_THAT(apply("for(;;) { [[int x;]]break; }"), HasSubstr("extracted")); + // FIXME: ExtractFunction should be unavailable inside loop construct + // initializer/condition. + EXPECT_THAT(apply(" for([[int i = 0;]];);"), HasSubstr("extracted")); + // Extract certain return + EXPECT_THAT(apply(" if(true) [[{ return; }]] "), HasSubstr("extracted")); + // Don't extract uncertain return + EXPECT_THAT(apply(" if(true) [[if (false) return;]] "), + StartsWith("unavailable")); + EXPECT_THAT( + apply("#define RETURN_IF_ERROR(x) if (x) return\nRETU^RN_IF_ERROR(4);"), + StartsWith("unavailable")); + + FileName = "a.c"; + EXPECT_THAT(apply(" for([[int i = 0;]];);"), HasSubstr("unavailable")); +} + +TEST_F(ExtractFunctionTest, FileTest) { + // Check all parameters are in order + std::string ParameterCheckInput = R"cpp( +struct Foo { + int x; +}; +void f(int a) { + int b; + int *ptr = &a; + Foo foo; + [[a += foo.x + b; + *ptr++;]] +})cpp"; + std::string ParameterCheckOutput = R"cpp( +struct Foo { + int x; +}; +void extracted(int &a, int &b, int * &ptr, Foo &foo) { +a += foo.x + b; + *ptr++; +} +void f(int a) { + int b; + int *ptr = &a; + Foo foo; + extracted(a, b, ptr, foo); +})cpp"; + EXPECT_EQ(apply(ParameterCheckInput), ParameterCheckOutput); + + // Check const qualifier + std::string ConstCheckInput = R"cpp( +void f(const int c) { + [[while(c) {}]] +})cpp"; + std::string ConstCheckOutput = R"cpp( +void extracted(const int &c) { +while(c) {} +} +void f(const int c) { + extracted(c); +})cpp"; + EXPECT_EQ(apply(ConstCheckInput), ConstCheckOutput); + + // Don't extract when we need to make a function as a parameter. + EXPECT_THAT(apply("void f() { [[int a; f();]] }"), StartsWith("fail")); + + // We don't extract from methods for now since they may involve multi-file + // edits + std::string MethodFailInput = R"cpp( + class T { + void f() { + [[int x;]] + } + }; + )cpp"; + EXPECT_EQ(apply(MethodFailInput), "unavailable"); + + // We don't extract from templated functions for now as templates are hard + // to deal with. + std::string TemplateFailInput = R"cpp( + template + void f() { + [[int x;]] + } + )cpp"; + EXPECT_EQ(apply(TemplateFailInput), "unavailable"); + + std::string MacroInput = R"cpp( + #define F(BODY) void f() { BODY } + F ([[int x = 0;]]) + )cpp"; + std::string MacroOutput = R"cpp( + #define F(BODY) void f() { BODY } + void extracted() { +int x = 0; +} +F (extracted();) + )cpp"; + EXPECT_EQ(apply(MacroInput), MacroOutput); + + // Shouldn't crash. + EXPECT_EQ(apply("void f([[int a]]);"), "unavailable"); + // Don't extract if we select the entire function body (CompoundStmt). + std::string CompoundFailInput = R"cpp( + void f() [[{ + int a; + }]] + )cpp"; + EXPECT_EQ(apply(CompoundFailInput), "unavailable"); +} + +TEST_F(ExtractFunctionTest, ControlFlow) { + Context = Function; + // We should be able to extract break/continue with a parent loop/switch. + EXPECT_THAT(apply(" [[for(;;) if(1) break;]] "), HasSubstr("extracted")); + EXPECT_THAT(apply(" for(;;) [[while(1) break;]] "), HasSubstr("extracted")); + EXPECT_THAT(apply(" [[switch(1) { break; }]]"), HasSubstr("extracted")); + EXPECT_THAT(apply(" [[while(1) switch(1) { continue; }]]"), + HasSubstr("extracted")); + // Don't extract break and continue without a loop/switch parent. + EXPECT_THAT(apply(" for(;;) [[if(1) continue;]] "), StartsWith("fail")); + EXPECT_THAT(apply(" while(1) [[if(1) break;]] "), StartsWith("fail")); + EXPECT_THAT(apply(" switch(1) { [[break;]] }"), StartsWith("fail")); + EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"), + StartsWith("fail")); +} + +TEST_F(ExtractFunctionTest, ExistingReturnStatement) { + Context = File; + const char *Before = R"cpp( + bool lucky(int N); + int getNum(bool Superstitious, int Min, int Max) { + if (Superstitious) [[{ + for (int I = Min; I <= Max; ++I) + if (lucky(I)) + return I; + return -1; + }]] else { + return (Min + Max) / 2; + } + } + )cpp"; + // FIXME: min/max should be by value. + // FIXME: avoid emitting redundant braces + const char *After = R"cpp( + bool lucky(int N); + int extracted(int &Min, int &Max) { +{ + for (int I = Min; I <= Max; ++I) + if (lucky(I)) + return I; + return -1; + } +} +int getNum(bool Superstitious, int Min, int Max) { + if (Superstitious) return extracted(Min, Max); else { + return (Min + Max) / 2; + } + } + )cpp"; + EXPECT_EQ(apply(Before), After); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/ExtractVariableTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ExtractVariableTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e9223cfe553f8dfdb5d6bb3866d32c354fb6b12 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/ExtractVariableTests.cpp @@ -0,0 +1,300 @@ +//===-- ExtractVariableTests.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(ExtractVariable); + +TEST_F(ExtractVariableTest, Test) { + const char *AvailableCases = R"cpp( + int xyz(int a = 1) { + struct T { + int bar(int a = 1); + int z; + } t; + // return statement + return [[[[t.b[[a]]r]](t.z)]]; + } + void f() { + int a = [[5 +]] [[4 * [[[[xyz]]()]]]]; + // multivariable initialization + if(1) + int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1; + // if without else + if([[1]]) + a = [[1]] + 1; + // if with else + if(a < [[3]]) + if(a == [[4]]) + a = [[5]] + 1; + else + a = [[5]] + 1; + else if (a < [[4]]) + a = [[4]] + 1; + else + a = [[5]] + 1; + // for loop + for(a = [[1]] + 1; a > [[[[3]] + [[4]]]]; a++) + a = [[2]] + 1; + // while + while(a < [[1]]) + a = [[1]] + 1; + // do while + do + a = [[1]] + 1; + while(a < [[3]]); + } + )cpp"; + EXPECT_AVAILABLE(AvailableCases); + + ExtraArgs = {"-xc"}; + const char *AvailableButC = R"cpp( + void foo() { + int x = [[1]]; + })cpp"; + EXPECT_UNAVAILABLE(AvailableButC); + ExtraArgs = {}; + + const char *NoCrashCases = R"cpp( + // error-ok: broken code, but shouldn't crash + template + struct Test { + Test(const T &v) :val[[(^]]) {} + T val; + }; + )cpp"; + EXPECT_UNAVAILABLE(NoCrashCases); + + const char *UnavailableCases = R"cpp( + int xyz(int a = [[1]]) { + struct T { + int bar(int a = [[1]]); + int z = [[1]]; + } t; + return [[t]].bar([[[[t]].z]]); + } + void v() { return; } + // function default argument + void f(int b = [[1]]) { + // empty selection + int a = ^1 ^+ ^2; + // void expressions + auto i = new int, j = new int; + [[[[delete i]], delete j]]; + [[v]](); + // if + if(1) + int x = 1, y = a + 1, a = 1, z = [[a + 1]]; + if(int a = 1) + if([[a + 1]] == 4) + a = [[[[a]] +]] 1; + // for loop + for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]]) + a = [[a + 1]]; + // lambda + auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}; + // assignment + xyz([[a = 5]]); + xyz([[a *= 5]]); + // Variable DeclRefExpr + a = [[b]]; + a = [[xyz()]]; + // statement expression + [[xyz()]]; + while (a) + [[++a]]; + // label statement + goto label; + label: + a = [[1]]; + } + )cpp"; + EXPECT_UNAVAILABLE(UnavailableCases); + + // vector of pairs of input and output strings + const std::vector> InputOutputs = { + // extraction from variable declaration/assignment + {R"cpp(void varDecl() { + int a = 5 * (4 + (3 [[- 1)]]); + })cpp", + R"cpp(void varDecl() { + auto dummy = (3 - 1); int a = 5 * (4 + dummy); + })cpp"}, + // FIXME: extraction from switch case + /*{R"cpp(void f(int a) { + if(1) + while(a < 1) + switch (1) { + case 1: + a = [[1 + 2]]; + break; + default: + break; + } + })cpp", + R"cpp(void f(int a) { + auto dummy = 1 + 2; if(1) + while(a < 1) + switch (1) { + case 1: + a = dummy; + break; + default: + break; + } + })cpp"},*/ + // Macros + {R"cpp(#define PLUS(x) x++ + void f(int a) { + int y = PLUS([[1+a]]); + })cpp", + /*FIXME: It should be extracted like this. + R"cpp(#define PLUS(x) x++ + void f(int a) { + auto dummy = 1+a; int y = PLUS(dummy); + })cpp"},*/ + R"cpp(#define PLUS(x) x++ + void f(int a) { + auto dummy = PLUS(1+a); int y = dummy; + })cpp"}, + // ensure InsertionPoint isn't inside a macro + {R"cpp(#define LOOP(x) while (1) {a = x;} + void f(int a) { + if(1) + LOOP(5 + [[3]]) + })cpp", + R"cpp(#define LOOP(x) while (1) {a = x;} + void f(int a) { + auto dummy = 3; if(1) + LOOP(5 + dummy) + })cpp"}, + {R"cpp(#define LOOP(x) do {x;} while(1); + void f(int a) { + if(1) + LOOP(5 + [[3]]) + })cpp", + R"cpp(#define LOOP(x) do {x;} while(1); + void f(int a) { + auto dummy = 3; if(1) + LOOP(5 + dummy) + })cpp"}, + // attribute testing + {R"cpp(void f(int a) { + [ [gsl::suppress("type")] ] for (;;) a = [[1]] + 1; + })cpp", + R"cpp(void f(int a) { + auto dummy = 1; [ [gsl::suppress("type")] ] for (;;) a = dummy + 1; + })cpp"}, + // MemberExpr + {R"cpp(class T { + T f() { + return [[T().f()]].f(); + } + };)cpp", + R"cpp(class T { + T f() { + auto dummy = T().f(); return dummy.f(); + } + };)cpp"}, + // Function DeclRefExpr + {R"cpp(int f() { + return [[f]](); + })cpp", + R"cpp(int f() { + auto dummy = f(); return dummy; + })cpp"}, + // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = [[1]]; + // since the attr is inside the DeclStmt and the bounds of + // DeclStmt don't cover the attribute. + + // Binary subexpressions + {R"cpp(void f() { + int x = 1 + [[2 + 3 + 4]] + 5; + })cpp", + R"cpp(void f() { + auto dummy = 2 + 3 + 4; int x = 1 + dummy + 5; + })cpp"}, + {R"cpp(void f() { + int x = [[1 + 2 + 3]] + 4 + 5; + })cpp", + R"cpp(void f() { + auto dummy = 1 + 2 + 3; int x = dummy + 4 + 5; + })cpp"}, + {R"cpp(void f() { + int x = 1 + 2 + [[3 + 4 + 5]]; + })cpp", + R"cpp(void f() { + auto dummy = 3 + 4 + 5; int x = 1 + 2 + dummy; + })cpp"}, + // Non-associative operations have no special support + {R"cpp(void f() { + int x = 1 - [[2 - 3 - 4]] - 5; + })cpp", + R"cpp(void f() { + auto dummy = 1 - 2 - 3 - 4; int x = dummy - 5; + })cpp"}, + // A mix of associative operators isn't associative. + {R"cpp(void f() { + int x = 0 + 1 * [[2 + 3]] * 4 + 5; + })cpp", + R"cpp(void f() { + auto dummy = 1 * 2 + 3 * 4; int x = 0 + dummy + 5; + })cpp"}, + // Overloaded operators are supported, we assume associativity + // as if they were built-in. + {R"cpp(struct S { + S(int); + }; + S operator+(S, S); + + void f() { + S x = S(1) + [[S(2) + S(3) + S(4)]] + S(5); + })cpp", + R"cpp(struct S { + S(int); + }; + S operator+(S, S); + + void f() { + auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5); + })cpp"}, + // Don't try to analyze across macro boundaries + // FIXME: it'd be nice to do this someday (in a safe way) + {R"cpp(#define ECHO(X) X + void f() { + int x = 1 + [[ECHO(2 + 3) + 4]] + 5; + })cpp", + R"cpp(#define ECHO(X) X + void f() { + auto dummy = 1 + ECHO(2 + 3) + 4; int x = dummy + 5; + })cpp"}, + {R"cpp(#define ECHO(X) X + void f() { + int x = 1 + [[ECHO(2) + ECHO(3) + 4]] + 5; + })cpp", + R"cpp(#define ECHO(X) X + void f() { + auto dummy = 1 + ECHO(2) + ECHO(3) + 4; int x = dummy + 5; + })cpp"}, + }; + for (const auto &IO : InputOutputs) { + EXPECT_EQ(IO.second, apply(IO.first)) << IO.first; + } +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/ObjCLocalizeStringLiteralTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ObjCLocalizeStringLiteralTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d52a1b3a78c1d239d4a5ae7034ba03a14dd00351 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/ObjCLocalizeStringLiteralTests.cpp @@ -0,0 +1,41 @@ +//===-- ObjCLocalizeStringLiteralTests.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(ObjCLocalizeStringLiteral); + +TEST_F(ObjCLocalizeStringLiteralTest, Test) { + ExtraArgs.push_back("-x"); + ExtraArgs.push_back("objective-c"); + + // Ensure the action can be initiated in the string literal. + EXPECT_AVAILABLE(R"(id x = ^[[@[[^"^t^est^"]]]];)"); + + // Ensure that the action can't be initiated in other places. + EXPECT_UNAVAILABLE(R"([[i^d ^[[x]] ^= @"test";^]])"); + + // Ensure that the action is not available for regular C strings. + EXPECT_UNAVAILABLE(R"(const char * x= "^test";)"); + + const char *Input = R"(id x = [[@"test"]];)"; + const char *Output = R"(id x = NSLocalizedString(@"test", @"");)"; + EXPECT_EQ(apply(Input), Output); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/PopulateSwitchTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/PopulateSwitchTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41518108a4f8df91769e7d72b83263966c7b379f --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/PopulateSwitchTests.cpp @@ -0,0 +1,213 @@ +//===-- PopulateSwitchTest.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(PopulateSwitch); + +TEST_F(PopulateSwitchTest, Test) { + struct Case { + CodeContext Context; + llvm::StringRef TestSource; + llvm::StringRef ExpectedSource; + }; + + Case Cases[]{ + { + // No enumerators + Function, + R""(enum Enum {}; ^switch ((Enum)0) {})"", + "unavailable", + }, + { + // All enumerators already in switch (unscoped) + Function, + R""(enum Enum {A,B}; ^switch (A) {case A:break;case B:break;})"", + "unavailable", + }, + { + // All enumerators already in switch (scoped) + Function, + R""( + enum class Enum {A,B}; + ^switch (Enum::A) {case Enum::A:break;case Enum::B:break;} + )"", + "unavailable", + }, + { + // Default case in switch + Function, + R""( + enum class Enum {A,B}; + ^switch (Enum::A) {default:break;} + )"", + "unavailable", + }, + { + // GNU range in switch + Function, + R""( + enum class Enum {A,B}; + ^switch (Enum::A) {case Enum::A ... Enum::B:break;} + )"", + "unavailable", + }, + { + // Value dependent case expression + File, + R""( + enum class Enum {A,B}; + template + void function() { + ^switch (Enum::A) {case Value:break;} + } + )"", + "unavailable", + }, + { + // Body not CompoundStmt + Function, + R""(enum Enum {A}; ^switch (A);)"", + "unavailable", + }, + { + // Selection on switch token + Function, + R""(enum Enum {A}; ^switch (A) {})"", + R""(enum Enum {A}; switch (A) {case A:break;})"", + }, + { + // Selection on switch condition + Function, + R""(enum Enum {A}; switch (^A) {})"", + R""(enum Enum {A}; switch (A) {case A:break;})"", + }, + { + // Selection in switch body + Function, + R""(enum Enum {A}; switch (A) {^})"", + R""(enum Enum {A}; switch (A) {case A:break;})"", + }, + { + // Scoped enumeration + Function, + R""(enum class Enum {A}; ^switch (Enum::A) {})"", + R""(enum class Enum {A}; switch (Enum::A) {case Enum::A:break;})"", + }, + { + // Scoped enumeration with multiple enumerators + Function, + R""( + enum class Enum {A,B}; + ^switch (Enum::A) {} + )"", + R""( + enum class Enum {A,B}; + switch (Enum::A) {case Enum::A:case Enum::B:break;} + )"", + }, + { + // Only filling in missing enumerators (unscoped) + Function, + R""( + enum Enum {A,B,C}; + ^switch (A) {case B:break;} + )"", + R""( + enum Enum {A,B,C}; + switch (A) {case B:break;case A:case C:break;} + )"", + }, + { + // Only filling in missing enumerators, + // even when using integer literals + Function, + R""( + enum Enum {A,B=1,C}; + ^switch (A) {case 1:break;} + )"", + R""( + enum Enum {A,B=1,C}; + switch (A) {case 1:break;case A:case C:break;} + )"", + }, + { + // Only filling in missing enumerators (scoped) + Function, + R""( + enum class Enum {A,B,C}; + ^switch (Enum::A) + {case Enum::B:break;} + )"", + R""( + enum class Enum {A,B,C}; + switch (Enum::A) + {case Enum::B:break;case Enum::A:case Enum::C:break;} + )"", + }, + { + // Scoped enumerations in namespace + File, + R""( + namespace ns { enum class Enum {A}; } + void function() { ^switch (ns::Enum::A) {} } + )"", + R""( + namespace ns { enum class Enum {A}; } + void function() { switch (ns::Enum::A) {case ns::Enum::A:break;} } + )"", + }, + { + // Unscoped enumerations in namespace + File, + R""( + namespace ns { enum Enum {A}; } + void function() { ^switch (ns::A) {} } + )"", + R""( + namespace ns { enum Enum {A}; } + void function() { switch (ns::A) {case ns::A:break;} } + )"", + }, + { + // Duplicated constant names + Function, + R""(enum Enum {A,B,b=B}; ^switch (A) {})"", + R""(enum Enum {A,B,b=B}; switch (A) {case A:case B:break;})"", + }, + { + // Duplicated constant names all in switch + Function, + R""(enum Enum {A,B,b=B}; ^switch (A) {case A:case B:break;})"", + "unavailable", + }, + { + // Enum is dependent type + File, + R""(template void f() {enum Enum {A}; ^switch (A) {}})"", + "unavailable", + }, + }; + + for (const auto &Case : Cases) { + Context = Case.Context; + EXPECT_EQ(apply(Case.TestSource), Case.ExpectedSource); + } +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/RawStringLiteralTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/RawStringLiteralTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db92928ba3d0e8cd995d2f2db6720547da5e6028 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/RawStringLiteralTests.cpp @@ -0,0 +1,42 @@ +//===-- RawStringLiteralTests.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(RawStringLiteral); + +TEST_F(RawStringLiteralTest, Test) { + Context = Expression; + EXPECT_AVAILABLE(R"cpp(^"^f^o^o^\^n^")cpp"); + EXPECT_AVAILABLE(R"cpp(R"(multi )" ^"token " "str\ning")cpp"); + EXPECT_UNAVAILABLE(R"cpp(^"f^o^o^o")cpp"); // no chars need escaping + EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii + EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw + EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro + EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char + + const char *Input = R"cpp(R"(multi +token)" "\nst^ring\n" "literal")cpp"; + const char *Output = R"cpp(R"(multi +token +string +literal)")cpp"; + EXPECT_EQ(apply(Input), Output); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a15f05041ad76136ae6c9d8325fd686332ba3ad --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp @@ -0,0 +1,237 @@ +//===-- RemoveUsingNamespaceTest.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(RemoveUsingNamespace); + +TEST_F(RemoveUsingNamespaceTest, All) { + std::pair Cases[] = { + {// Remove all occurrences of ns. Qualify only unqualified. + R"cpp( + namespace ns1 { struct vector {}; } + namespace ns2 { struct map {}; } + using namespace n^s1; + using namespace ns2; + using namespace ns1; + int main() { + ns1::vector v1; + vector v2; + map m1; + } + )cpp", + R"cpp( + namespace ns1 { struct vector {}; } + namespace ns2 { struct map {}; } + + using namespace ns2; + + int main() { + ns1::vector v1; + ns1::vector v2; + map m1; + } + )cpp"}, + {// Ident to be qualified is a macro arg. + R"cpp( + #define DECLARE(x, y) x y + namespace ns { struct vector {}; } + using namespace n^s; + int main() { + DECLARE(ns::vector, v1); + DECLARE(vector, v2); + } + )cpp", + R"cpp( + #define DECLARE(x, y) x y + namespace ns { struct vector {}; } + + int main() { + DECLARE(ns::vector, v1); + DECLARE(ns::vector, v2); + } + )cpp"}, + {// Nested namespace: Fully qualify ident from inner ns. + R"cpp( + namespace aa { namespace bb { struct map {}; }} + using namespace aa::b^b; + int main() { + map m; + } + )cpp", + R"cpp( + namespace aa { namespace bb { struct map {}; }} + + int main() { + aa::bb::map m; + } + )cpp"}, + {// Nested namespace: Fully qualify ident from inner ns. + R"cpp( + namespace aa { namespace bb { struct map {}; }} + using namespace a^a; + int main() { + bb::map m; + } + )cpp", + R"cpp( + namespace aa { namespace bb { struct map {}; }} + + int main() { + aa::bb::map m; + } + )cpp"}, + {// Typedef. + R"cpp( + namespace aa { namespace bb { struct map {}; }} + using namespace a^a; + typedef bb::map map; + int main() { map M; } + )cpp", + R"cpp( + namespace aa { namespace bb { struct map {}; }} + + typedef aa::bb::map map; + int main() { map M; } + )cpp"}, + {// FIXME: Nested namespaces: Not aware of using ns decl of outer ns. + R"cpp( + namespace aa { namespace bb { struct map {}; }} + using name[[space aa::b]]b; + using namespace aa; + int main() { + map m; + } + )cpp", + R"cpp( + namespace aa { namespace bb { struct map {}; }} + + using namespace aa; + int main() { + aa::bb::map m; + } + )cpp"}, + {// Does not qualify ident from inner namespace. + R"cpp( + namespace aa { namespace bb { struct map {}; }} + using namespace aa::bb; + using namespace a^a; + int main() { + map m; + } + )cpp", + R"cpp( + namespace aa { namespace bb { struct map {}; }} + using namespace aa::bb; + + int main() { + map m; + } + )cpp"}, + {// Available only for top level namespace decl. + R"cpp( + namespace aa { + namespace bb { struct map {}; } + using namespace b^b; + } + int main() { aa::map m; } + )cpp", + "unavailable"}, + {// FIXME: Unavailable for namespaces containing using-namespace decl. + R"cpp( + namespace aa { + namespace bb { struct map {}; } + using namespace bb; + } + using namespace a^a; + int main() { + map m; + } + )cpp", + "unavailable"}, + {R"cpp( + namespace a::b { struct Foo {}; } + using namespace a; + using namespace a::[[b]]; + using namespace b; + int main() { Foo F;} + )cpp", + R"cpp( + namespace a::b { struct Foo {}; } + using namespace a; + + + int main() { a::b::Foo F;} + )cpp"}, + {R"cpp( + namespace a::b { struct Foo {}; } + using namespace a; + using namespace a::b; + using namespace [[b]]; + int main() { Foo F;} + )cpp", + R"cpp( + namespace a::b { struct Foo {}; } + using namespace a; + + + int main() { b::Foo F;} + )cpp"}, + {// Enumerators. + R"cpp( + namespace tokens { + enum Token { + comma, identifier, numeric + }; + } + using namespace tok^ens; + int main() { + auto x = comma; + } + )cpp", + R"cpp( + namespace tokens { + enum Token { + comma, identifier, numeric + }; + } + + int main() { + auto x = tokens::comma; + } + )cpp"}, + {// inline namespaces. + R"cpp( + namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}} + using namespace st^d; + int main() { + vector V; + } + )cpp", + R"cpp( + namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}} + + int main() { + std::vector V; + } + )cpp"}}; + for (auto C : Cases) + EXPECT_EQ(C.second, apply(C.first)) << C.first; +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/ShowSelectionTreeTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ShowSelectionTreeTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ec3d3801c42a9fd4dd69714c8621ac540e1e180 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/ShowSelectionTreeTests.cpp @@ -0,0 +1,48 @@ +//===-- ShowSelectionTreeTests.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(ShowSelectionTree); + +TEST_F(ShowSelectionTreeTest, Test) { + EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }"); + EXPECT_AVAILABLE("/*c^omment*/ int foo() { return 2 ^ + 2; }"); + + const char *Output = R"(message: + TranslationUnitDecl + VarDecl int x = fcall(2 + 2) + .CallExpr fcall(2 + 2) + ImplicitCastExpr fcall + .DeclRefExpr fcall + .BinaryOperator 2 + 2 + *IntegerLiteral 2 +)"; + EXPECT_EQ(apply("int fcall(int); int x = fca[[ll(2 +]]2);"), Output); + + Output = R"(message: + TranslationUnitDecl + FunctionDecl void x() + CompoundStmt { … + ForStmt for (;;) … + *BreakStmt break; +)"; + EXPECT_EQ(apply("void x() { for (;;) br^eak; }"), Output); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/SwapIfBranchesTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/SwapIfBranchesTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..989cfbfcc237ee31bbb515acbfb7f4a2df4af6ee --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/SwapIfBranchesTests.cpp @@ -0,0 +1,48 @@ +//===-- SwapIfBranchesTests.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 "TestTU.h" +#include "TweakTesting.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TWEAK_TEST(SwapIfBranches); + +TEST_F(SwapIfBranchesTest, Test) { + Context = Function; + EXPECT_EQ(apply("^if (true) {return;} else {(void)0;}"), + "if (true) {(void)0;} else {return;}"); + EXPECT_EQ(apply("^if (/*error-ok*/) {return;} else {(void)0;}"), + "if (/*error-ok*/) {(void)0;} else {return;}") + << "broken condition"; + EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return; } ^e^l^s^e^ { return; }"); + EXPECT_UNAVAILABLE("if (true) {^return ^;^ } else { ^return^;^ }"); + // Available in subexpressions of the condition; + EXPECT_THAT("if(2 + [[2]] + 2) { return; } else {return;}", isAvailable()); + // But not as part of the branches. + EXPECT_THAT("if(2 + 2 + 2) { [[return]]; } else { return; }", + Not(isAvailable())); + // Range covers the "else" token, so available. + EXPECT_THAT("if(2 + 2 + 2) { return[[; } else {return;]]}", isAvailable()); + // Not available in compound statements in condition. + EXPECT_THAT("if([]{return [[true]];}()) { return; } else { return; }", + Not(isAvailable())); + // Not available if both sides aren't braced. + EXPECT_THAT("^if (1) return; else { return; }", Not(isAvailable())); + // Only one if statement is supported! + EXPECT_THAT("[[if(1){}else{}if(2){}else{}]]", Not(isAvailable())); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/TweakTesting.cpp b/clang-tools-extra/clangd/unittests/tweaks/TweakTesting.cpp similarity index 93% rename from clang-tools-extra/clangd/unittests/TweakTesting.cpp rename to clang-tools-extra/clangd/unittests/tweaks/TweakTesting.cpp index bbb1af46f93cbee1e1b664830f86a9ca7e7c2ddf..680280f8314945d6702113148806fdbaf290d7ad 100644 --- a/clang-tools-extra/clangd/unittests/TweakTesting.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/TweakTesting.cpp @@ -25,12 +25,12 @@ using Context = TweakTest::CodeContext; std::pair wrapping(Context Ctx) { switch (Ctx) { - case TweakTest::File: - return {"",""}; - case TweakTest::Function: - return {"void wrapperFunction(){\n", "\n}"}; - case TweakTest::Expression: - return {"auto expressionWrapper(){return\n", "\n;}"}; + case TweakTest::File: + return {"", ""}; + case TweakTest::Function: + return {"void wrapperFunction(){\n", "\n}"}; + case TweakTest::Expression: + return {"auto expressionWrapper(){return\n", "\n;}"}; } llvm_unreachable("Unknown TweakTest::CodeContext enum"); } @@ -46,7 +46,8 @@ llvm::StringRef unwrap(Context Ctx, llvm::StringRef Outer) { // Don't allow the begin/end wrapping to overlap! if (Outer.startswith(Wrapping.first) && Outer.endswith(Wrapping.second) && Outer.size() >= Wrapping.first.size() + Wrapping.second.size()) - return Outer.drop_front(Wrapping.first.size()).drop_back(Wrapping.second.size()); + return Outer.drop_front(Wrapping.first.size()) + .drop_back(Wrapping.second.size()); return Outer; } @@ -157,11 +158,11 @@ std::vector TweakTest::expandCases(llvm::StringRef MarkedCode) { Annotations Test(MarkedCode); llvm::StringRef Code = Test.code(); std::vector Cases; - for (const auto& Point : Test.points()) { + for (const auto &Point : Test.points()) { size_t Offset = llvm::cantFail(positionToOffset(Code, Point)); Cases.push_back((Code.substr(0, Offset) + "^" + Code.substr(Offset)).str()); } - for (const auto& Range : Test.ranges()) { + for (const auto &Range : Test.ranges()) { size_t Begin = llvm::cantFail(positionToOffset(Code, Range.start)); size_t End = llvm::cantFail(positionToOffset(Code, Range.end)); Cases.push_back((Code.substr(0, Begin) + "[[" + diff --git a/clang-tools-extra/clangd/unittests/TweakTesting.h b/clang-tools-extra/clangd/unittests/tweaks/TweakTesting.h similarity index 97% rename from clang-tools-extra/clangd/unittests/TweakTesting.h rename to clang-tools-extra/clangd/unittests/tweaks/TweakTesting.h index c771149a72fc5b4be5bc4e03bdf7be3f6d9169d0..7b1a117130bad9eaaa32d5402e59fbdbf8dfa72a 100644 --- a/clang-tools-extra/clangd/unittests/TweakTesting.h +++ b/clang-tools-extra/clangd/unittests/tweaks/TweakTesting.h @@ -100,6 +100,10 @@ protected: ::testing::Matcher isAvailable() const; }; +MATCHER_P2(FileWithContents, FileName, Contents, "") { + return arg.first() == FileName && arg.second == Contents; +} + #define TWEAK_TEST(TweakID) \ class TweakID##Test : public ::clang::clangd::TweakTest { \ protected: \ diff --git a/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c8dc5530e098f141e4dbc08fd5cc60b21176f5d --- /dev/null +++ b/clang-tools-extra/clangd/unittests/tweaks/TweakTests.cpp @@ -0,0 +1,66 @@ +//===-- TweakTests.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 "TestFS.h" +#include "TestTU.h" +#include "TweakTesting.h" +#include "refactor/Tweak.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Testing/Support/Error.h" +#include "gmock/gmock-matchers.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include +#include +#include +#include + +namespace clang { +namespace clangd { +namespace { + +TEST(FileEdits, AbsolutePath) { + auto RelPaths = {"a.h", "foo.cpp", "test/test.cpp"}; + + llvm::IntrusiveRefCntPtr MemFS( + new llvm::vfs::InMemoryFileSystem); + MemFS->setCurrentWorkingDirectory(testRoot()); + for (const auto *Path : RelPaths) + MemFS->addFile(Path, 0, llvm::MemoryBuffer::getMemBuffer("", Path)); + FileManager FM(FileSystemOptions(), MemFS); + DiagnosticsEngine DE(new DiagnosticIDs, new DiagnosticOptions); + SourceManager SM(DE, FM); + + for (const auto *Path : RelPaths) { + auto FID = SM.createFileID(*FM.getOptionalFileRef(Path), SourceLocation(), + clang::SrcMgr::C_User); + auto Res = Tweak::Effect::fileEdit(SM, FID, tooling::Replacements()); + ASSERT_THAT_EXPECTED(Res, llvm::Succeeded()); + EXPECT_EQ(Res->first, testPath(Path)); + } +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 3df5b1c8e2b7cc7cd77ee89ebcd8443e28d9d225..062216697111ecf18f96d8c7057df576aee3e610 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -135,6 +135,11 @@ New checks Alias to the :doc:`bugprone-signal-handler ` check. +- New :doc:`performance-no-int-to-ptr + ` check. + + Diagnoses every integer to pointer cast. + - New :doc:`readability-function-cognitive-complexity ` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-argument-comment.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-argument-comment.rst index 8c59541b8d42a7eb7caa324c757c66ecd76c1977..ab7e668b971c056e31efed4003ca813ad378aad0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-argument-comment.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-argument-comment.rst @@ -24,17 +24,17 @@ Options .. option:: StrictMode - When zero (default value), the check will ignore leading and trailing + When `false` (default value), the check will ignore leading and trailing underscores and case when comparing names -- otherwise they are taken into account. .. option:: IgnoreSingleArgument - When true, the check will ignore the single argument. + When `true`, the check will ignore the single argument. .. option:: CommentBoolLiterals - When true, the check will add argument comments in the format + When `true`, the check will add argument comments in the format ``/*ParameterName=*/`` right before the boolean literal argument. Before: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-widening-cast.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-widening-cast.rst index f42be76efaae2946e3db0905f11379c0e500e1ba..08c63c632eb2b7b0aa4b8583132667b1ff98fa57 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-widening-cast.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-misplaced-widening-cast.rst @@ -62,4 +62,4 @@ Options .. option:: CheckImplicitCasts - If non-zero, enables detection of implicit casts. Default is non-zero. + If `true`, enables detection of implicit casts. Default is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-not-null-terminated-result.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-not-null-terminated-result.rst index 54e48268181ca7218e75ea404da68614adb553cf..10a6eb35ae4443188e19ceafcfb65304c4ceeaa0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-not-null-terminated-result.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-not-null-terminated-result.rst @@ -57,9 +57,9 @@ Rewrite based on the destination array efficient than the safe version. - If copy to the destination array can overflow [1] and - ``AreSafeFunctionsAvailable`` is set to ``Yes``, ``y`` or non-zero and it is - possible to obtain the capacity of the destination array then the new function - could be the safe version (ending with ``cpy_s``). + :option:`WantToUseSafeFunctions` is set to `true` and it is possible to + obtain the capacity of the destination array then the new function could be + the safe version (ending with ``cpy_s``). - If the new function is could be safe version and C++ files are analysed and the destination array is plain ``char``/``wchar_t`` without ``un/signed`` then @@ -127,6 +127,6 @@ Options .. option:: WantToUseSafeFunctions - An integer non-zero value specifying if the target environment is considered - to implement '_s' suffixed memory and string handler functions which are - safer than older versions (e.g. 'memcpy_s()'). The default value is ``1``. + The value `true` specifies that the target environment is considered to + implement '_s' suffixed memory and string handler functions which are safer + than older versions (e.g. 'memcpy_s()'). The default value is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-reserved-identifier.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-reserved-identifier.rst index 388acf87efc7519b0d18f58049d12a5de3852c2b..3c69a26c90aa5b1c7cd3bb651eb145f98818421f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-reserved-identifier.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-reserved-identifier.rst @@ -48,8 +48,8 @@ Options .. option:: Invert - If non-zero, inverts the check, i.e. flags names that are not reserved. - Default is `0`. + If `true`, inverts the check, i.e. flags names that are not reserved. + Default is `false`. .. option:: AllowedIdentifiers diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst index 2894495995a08a9af84ace8ce87db2eb0df0479b..d0b18bd4595c743b2cd18d077e7664e80fcb93b4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-signed-char-misuse.rst @@ -4,7 +4,7 @@ bugprone-signed-char-misuse =========================== `cert-str34-c` redirects here as an alias for this check. For the CERT alias, -the `DiagnoseSignedUnsignedCharComparisons` option is set to `0`. +the `DiagnoseSignedUnsignedCharComparisons` option is set to `false`. Finds those ``signed char`` -> integer conversions which might indicate a programming error. The basic problem with the ``signed char``, that it might @@ -114,5 +114,5 @@ so both arguments will have the same type. .. option:: DiagnoseSignedUnsignedCharComparisons - When nonzero, the check will warn on ``signed char``/``unsigned char`` comparisons, - otherwise these comparisons are ignored. By default, this option is set to ``1``. + When `true`, the check will warn on ``signed char``/``unsigned char`` comparisons, + otherwise these comparisons are ignored. By default, this option is set to `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-expression.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-expression.rst index b58deaaef1da5a84821f179c46bd7b6f1b8c3961..74ceb71937cfc53360eef5c3c195b2e71b26af48 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-expression.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-sizeof-expression.rst @@ -169,21 +169,21 @@ Options .. option:: WarnOnSizeOfConstant - When non-zero, the check will warn on an expression like - ``sizeof(CONSTANT)``. Default is `1`. + When `true`, the check will warn on an expression like + ``sizeof(CONSTANT)``. Default is `true`. .. option:: WarnOnSizeOfIntegerExpression - When non-zero, the check will warn on an expression like ``sizeof(expr)`` - where the expression results in an integer. Default is `0`. + When `true`, the check will warn on an expression like ``sizeof(expr)`` + where the expression results in an integer. Default is `false`. .. option:: WarnOnSizeOfThis - When non-zero, the check will warn on an expression like ``sizeof(this)``. - Default is `1`. + When `true`, the check will warn on an expression like ``sizeof(this)``. + Default is `true`. .. option:: WarnOnSizeOfCompareToConstant - When non-zero, the check will warn on an expression like + When `true`, the check will warn on an expression like ``sizeof(epxr) <= k`` for a suspicious constant `k` while `k` is `0` or - greater than `0x8000`. Default is `1`. + greater than `0x8000`. Default is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-constructor.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-constructor.rst index c0b6e5004e8ce15515703517c7d632a695a05f18..b45c2ef4a931299a1aa00243084905ff8ee88808 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-constructor.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-string-constructor.rst @@ -38,8 +38,8 @@ Options .. option:: WarnOnLargeLength - When non-zero, the check will warn on a string with a length greater than - `LargeLengthThreshold`. Default is `1`. + When `true`, the check will warn on a string with a length greater than + :option:`LargeLengthThreshold`. Default is `true`. .. option:: LargeLengthThreshold diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-string-compare.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-string-compare.rst index be3d2b6fbdf8320928027fc1df9acd427f1f9866..54797d7ab87eee050da56518876aace128378271 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-string-compare.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-suspicious-string-compare.rst @@ -42,11 +42,11 @@ Options .. option:: WarnOnImplicitComparison - When non-zero, the check will warn on implicit comparison. `1` by default. + When `true`, the check will warn on implicit comparison. `true` by default. .. option:: WarnOnLogicalNotComparison - When non-zero, the check will warn on logical not comparison. `0` by default. + When `true`, the check will warn on logical not comparison. `false` by default. .. option:: StringCompareLikeFunctions diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst index c4ccdd9579d6ac738a8d4f1d0286bca58e357560..dee139861c8cfef2cd21b05c25d185b1c29379fc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst @@ -4,7 +4,7 @@ bugprone-unhandled-self-assignment ================================== `cert-oop54-cpp` redirects here as an alias for this check. For the CERT alias, -the `WarnOnlyIfThisHasSuspiciousField` option is set to `0`. +the `WarnOnlyIfThisHasSuspiciousField` option is set to `false`. Finds user-defined copy assignment operators which do not protect the code against self-assignment either by checking self-assignment explicitly or @@ -120,5 +120,5 @@ temporary object into ``this`` (needs a move assignment operator): .. option:: WarnOnlyIfThisHasSuspiciousField - When non-zero, the check will warn only if the container class of the copy assignment operator - has any suspicious fields (pointer or C array). This option is set to `1` by default. + When `true`, the check will warn only if the container class of the copy assignment operator + has any suspicious fields (pointer or C array). This option is set to `true` by default. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst index 01cfbd6a052b49c21eab4252643f251057fc87d1..dfb13a8f617b5bdf7963b93db043669531afdd42 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst @@ -25,9 +25,9 @@ Options Boolean flag to warn on all macros except those with CAPS_ONLY names. This option is intended to ease introduction of this check into older - code bases. Default value is `0`/`false`. + code bases. Default value is `false`. .. option:: IgnoreCommandLineMacros Boolean flag to toggle ignoring command-line-defined macros. - Default value is `1`/`true`. + Default value is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst index 2653fbcade199b3d59005ea3d14e53362d704e1d..79eb5828bd18601a2607633edae43ee0f1f00f7d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-narrowing-conversions.rst @@ -32,15 +32,15 @@ Options .. option:: WarnOnFloatingPointNarrowingConversion - When non-zero, the check will warn on narrowing floating point conversion - (e.g. ``double`` to ``float``). `1` by default. + When `true`, the check will warn on narrowing floating point conversion + (e.g. ``double`` to ``float``). `true` by default. .. option:: PedanticMode - When non-zero, the check will warn on assigning a floating point constant + When `true`, the check will warn on assigning a floating point constant to an integer value even if the floating point value is exactly representable in the destination type (e.g. ``int i = 1.0;``). - `0` by default. + `false` by default. FAQ --- diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst index c8a4c741fd1ef2d9d0079e3b635fa9820268276e..5a5ee3e57a8cb299d432c626d97422ecf594d806 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst @@ -85,7 +85,7 @@ Here ``n`` can be initialized in the constructor initialization list, unlike .. option:: UseAssignment - If this option is set to non-zero (default is `0`), the check will initialize + If this option is set to `true` (default is `false`), the check will initialize members with an assignment. In this case the fix of the first example looks like this: diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst index dcb4f1c4ca8ddb3b95eba9e85eed77da2c699c23..b75b91800094252113900e5bd38e415206573fd4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst @@ -29,13 +29,13 @@ Options .. option:: IgnoreArrays - If set to non-zero, the check will not warn about array members that are not + If set to `true`, the check will not warn about array members that are not zero-initialized during construction. For performance critical code, it may - be important to not initialize fixed-size array members. Default is `0`. + be important to not initialize fixed-size array members. Default is `false`. .. option:: UseAssignment - If set to non-zero, the check will provide fix-its with literal initializers + If set to `true`, the check will provide fix-its with literal initializers \( ``int i = 0;`` \) instead of curly braces \( ``int i{};`` \). This rule is part of the "Type safety" profile of the C++ Core diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-special-member-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-special-member-functions.rst index 4ced6c1bc563b2d4b55cb27952039bda9da4f414..7eb8d1422ea7ad01ac8e721c928c687b7a779014 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-special-member-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-special-member-functions.rst @@ -25,7 +25,7 @@ Options .. option:: AllowSoleDefaultDtor - When set to `1` (default is `0`), this check doesn't flag classes with a sole, explicitly + When set to `true` (default is `false`), this check doesn't flag classes with a sole, explicitly defaulted destructor. An example for such a class is: .. code-block:: c++ @@ -36,7 +36,7 @@ Options .. option:: AllowMissingMoveFunctions - When set to `1` (default is `0`), this check doesn't flag classes which define no move + When set to `true` (default is `false`), this check doesn't flag classes which define no move operations at all. It still flags classes which define only one of either move constructor or move assignment operator. With this option enabled, the following class won't be flagged: @@ -50,7 +50,7 @@ Options .. option:: AllowMissingMoveFunctionsWhenCopyIsDeleted - When set to `1` (default is `0`), this check doesn't flag classes which define deleted copy + When set to `true` (default is `false`), this check doesn't flag classes which define deleted copy operations but don't define move operations. This flags is related to Google C++ Style Guide https://google.github.io/styleguide/cppguide.html#Copyable_Movable_Types. With this option enabled, the following class won't be flagged: diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp-multiway-paths-covered.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp-multiway-paths-covered.rst index 6588132ca392f9a071130efe3f9f26ebe272d32d..2ceaa96ec4a7f47b8e7fddeb1d607d4ac8f00fb1 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp-multiway-paths-covered.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp-multiway-paths-covered.rst @@ -93,4 +93,4 @@ Options .. option:: WarnOnMissingElse Boolean flag that activates a warning for missing ``else`` branches. - Default is `0`. + Default is `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 9c7074e1ecf259652f62a24724bf9c9b4dcf40c0..6c882bb6e8e14a3211f996cc9c6bddde1c1ed268 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -265,6 +265,7 @@ Clang-Tidy Checks `performance-move-const-arg `_, "Yes" `performance-move-constructor-init `_, "Yes" `performance-no-automatic-move `_, + `performance-no-int-to-ptr `_, `performance-noexcept-move-constructor `_, "Yes" `performance-trivially-destructible `_, "Yes" `performance-type-promotion-in-math-fn `_, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc-definitions-in-headers.rst b/clang-tools-extra/docs/clang-tidy/checks/misc-definitions-in-headers.rst index 235e5cd2306d8ad01bdd1ee4f51934a008842e65..82a5052df986d73ffc878f3a0bf72d700479c82e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc-definitions-in-headers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc-definitions-in-headers.rst @@ -100,5 +100,5 @@ Options .. option:: UseHeaderFileExtension - When non-zero, the check will use the file extension to distinguish header - files. Default is `1`. + When `true`, the check will use the file extension to distinguish header + files. Default is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst b/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst index cc970fe014cc1c3913f627a874fe850ea9211171..b8776b272f9d77067d5afa91715a6d1488b2e125 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst @@ -33,7 +33,7 @@ Options Triggers detection of violations of the CERT recommendation ERR09-CPP. Throw anonymous temporaries. - Default is `1`. + Default is `true`. .. option:: WarnOnLargeObject @@ -41,12 +41,12 @@ Options object by value is not dangerous but affects the performance negatively. The maximum size of an object allowed to be caught without warning can be set using the `MaxSize` option. - Default is `0`. + Default is `false`. .. option:: MaxSize Determines the maximum size of an object allowed to be caught without - warning. Only applicable if `WarnOnLargeObject` is set to `1`. If option is - set by the user to `std::numeric_limits::max()` then it reverts to - the default value. + warning. Only applicable if :option:`WarnOnLargeObject` is set to `true`. If + the option is set by the user to `std::numeric_limits::max()` then + it reverts to the default value. Default is the size of `size_t`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc-unused-parameters.rst b/clang-tools-extra/docs/clang-tidy/checks/misc-unused-parameters.rst index d954c1ddb1c542e887c45edf6ee183b502aa9b90..7a454a283b7c14cde04c5a103139e58c67f15201 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc-unused-parameters.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc-unused-parameters.rst @@ -35,7 +35,7 @@ Options .. option:: StrictMode - When zero (default value), the check will ignore trivially unused parameters, + When `false` (default value), the check will ignore trivially unused parameters, i.e. when the corresponding function has an empty body (and in case of constructors - no constructor initializers). When the function body is empty, an unused parameter is unlikely to be unnoticed by a human reader, and diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-bind.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-bind.rst index 82c290e4a21b7609021a419525acc1e4c0362f53..9c8df6a7c8411003090cde587dd2addfbdd45913 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-bind.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-bind.rst @@ -46,7 +46,7 @@ Options .. option:: PermissiveParameterList - If the option is set to non-zero, the check will append ``auto&&...`` to the end + If the option is set to `true`, the check will append ``auto&&...`` to the end of every placeholder parameter list. Without this, it is possible for a fix-it to perform an incorrect transformation in the case where the result of the ``bind`` is used in the context of a type erased functor such as ``std::function`` which diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-make-shared.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-make-shared.rst index e73b32034f3d7348456e41421754e2309e213c83..9c1fceaa06000250b13398e51fcd596d87e9e86f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-make-shared.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-make-shared.rst @@ -46,5 +46,11 @@ Options .. option:: IgnoreMacros - If set to non-zero, the check will not give warnings inside macros. Default - is `1`. + If set to `true`, the check will not give warnings inside macros. Default + is `true`. + +.. option:: IgnoreDefaultInitialization + + If set to non-zero, the check does not suggest edits that will transform + default initialization into value initialization, as this can cause + performance regressions. Default is `1`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst index 6c0a0b981f2c4b8218f088adec43693a3fce0db3..cd474d352bac0dc0b34d8072d6bc95482f32ed16 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-make-unique.rst @@ -46,5 +46,11 @@ Options .. option:: IgnoreMacros - If set to non-zero, the check will not give warnings inside macros. Default - is `1`. + If set to `true`, the check will not give warnings inside macros. Default + is `true`. + +.. option:: IgnoreDefaultInitialization + + If set to non-zero, the check does not suggest edits that will transform + default initialization into value initialization, as this can cause + performance regressions. Default is `1`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-pass-by-value.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-pass-by-value.rst index e538135a66b36a4f7a23c49c0706a01f481b4024..a93bfeaa9d0ce276d609e604553c0650fd9d315c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-pass-by-value.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-pass-by-value.rst @@ -162,5 +162,5 @@ Options .. option:: ValuesOnly - When non-zero, the check only warns about copied parameters that are already - passed by value. Default is `0`. + When `true`, the check only warns about copied parameters that are already + passed by value. Default is `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-auto.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-auto.rst index a73e86effae1a2487de97ac1bb3cc46503772ccf..f7333fc5739a455d91974d79a78a8f200f56db91 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-auto.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-auto.rst @@ -183,8 +183,8 @@ Options names having a length less than the option value. The option affects expressions only, not iterators. Spaces between multi-lexeme type names (``long int``) are considered as one. - If ``RemoveStars`` option (see below) is set to non-zero, then ``*s`` in - the type are also counted as a part of the type name. + If the :option:`RemoveStars` option (see below) is set to `true`, then ``*s`` + in the type are also counted as a part of the type name. .. code-block:: c++ @@ -216,7 +216,7 @@ Options .. option:: RemoveStars - If the option is set to non-zero (default is `0`), the check will remove + If the option is set to `true` (default is `false`), the check will remove stars from the non-typedef pointer types when replacing type names with ``auto``. Otherwise, the check will leave stars. For example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-bool-literals.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-bool-literals.rst index 792d3a4c3dc43cb7e040fb18e2bd378615be4f76..27cf79b6e3a8c73be1d157e7843398fad5d5b612 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-bool-literals.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-bool-literals.rst @@ -24,5 +24,5 @@ Options .. option:: IgnoreMacros - If set to non-zero, the check will not give warnings inside macros. Default - is `1`. + If set to `true`, the check will not give warnings inside macros. Default + is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst index 6a199ecaccbaaf21b44eb4455105283f0cb02428..fd6c02269f5134e34fa7a30e34dbd443d1e62303 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst @@ -36,7 +36,7 @@ Options .. option:: UseAssignment - If this option is set to non-zero (default is `0`), the check will initialise + If this option is set to `true` (default is `false`), the check will initialise members with an assignment. For example: .. code-block:: c++ @@ -50,5 +50,5 @@ Options .. option:: IgnoreMacros - If this option is set to non-zero (default is `1`), the check will not warn + If this option is set to `true` (default is `true`), the check will not warn about members declared inside macros. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst index 447a110f99589624903a35acd0b8d70d00d875e3..8533c8958997768ca24c0802deea78ade08eb4a2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-emplace.rst @@ -104,15 +104,15 @@ Options .. option:: IgnoreImplicitConstructors - When non-zero, the check will ignore implicitly constructed arguments of + When `true`, the check will ignore implicitly constructed arguments of ``push_back``, e.g. .. code-block:: c++ std::vector v; - v.push_back("a"); // Ignored when IgnoreImplicitConstructors is ``1``. + v.push_back("a"); // Ignored when IgnoreImplicitConstructors is `true`. - Default is ``0``. + Default is `false`. .. option:: SmartPointers diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-default.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-default.rst index 4b2368ce0968402afc3db86cb1acdf37dcfc6a7d..5509a5414f8c5f338a4c803f8c57b0f0531c6c36 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-default.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-default.rst @@ -32,5 +32,5 @@ Options .. option:: IgnoreMacros - If set to non-zero, the check will not give warnings inside macros. Default - is `1`. + If set to `true`, the check will not give warnings inside macros. Default + is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-delete.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-delete.rst index f47826f9e8c1e7f528eaea111e2ba6d91870b3c4..c3de904e2538021a5712c421b63744d707902626 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-delete.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-equals-delete.rst @@ -26,5 +26,5 @@ all other member functions implemented. .. option:: IgnoreMacros - If this option is set to non-zero (default is `1`), the check will not warn + If this option is set to `true` (default is `true`), the check will not warn about functions declared inside macros. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-noexcept.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-noexcept.rst index 8addc8b4b66ddab23915a6f30791ad8c173d0fe7..eb6f005fc91b7c6b599b9a1904563576807e76c2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-noexcept.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-noexcept.rst @@ -87,4 +87,4 @@ transforms to: ~bar() noexcept(false); } -if the :option:`UseNoexceptFalse` option is set to `0`. +if the :option:`UseNoexceptFalse` option is set to `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst index 5daa4dea45d8fe1c33b2ae909e2f8897b37d1c10..61ffc955d92eb720562ccd74e6b182260d9574fd 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst @@ -25,15 +25,15 @@ Options .. option:: IgnoreDestructors - If set to non-zero, this check will not diagnose destructors. Default is `0`. + If set to `true`, this check will not diagnose destructors. Default is `false`. .. option:: AllowOverrideAndFinal - If set to non-zero, this check will not diagnose ``override`` as redundant + If set to `true`, this check will not diagnose ``override`` as redundant with ``final``. This is useful when code will be compiled by a compiler with warning/error checking flags requiring ``override`` explicitly on overridden members, such as ``gcc -Wsuggest-override``/``gcc -Werror=suggest-override``. - Default is `0`. + Default is `false`. .. option:: OverrideSpelling diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-transparent-functors.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-transparent-functors.rst index 20f955948282064eb71854cb79eea939b6cc11dd..624718affb948126a39c417176bc076d7e6f4b6f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-transparent-functors.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-transparent-functors.rst @@ -32,8 +32,8 @@ Options .. option:: SafeMode - If the option is set to non-zero, the check will not diagnose cases where + If the option is set to `true`, the check will not diagnose cases where using a transparent functor cannot be guaranteed to produce identical results - as the original code. The default value for this option is `0`. + as the original code. The default value for this option is `false`. This check requires using C++14 or higher to run. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst index 24c1c2b5c277d8534dd16bd11a6ed2c42dfded02..eeddaf8d8d65abee28c7aa3e902881a1b0845161 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst @@ -35,5 +35,5 @@ Options .. option:: IgnoreMacros - If set to non-zero, the check will not give warnings inside macros. Default - is `1`. + If set to `true`, the check will not give warnings inside macros. Default + is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance-for-range-copy.rst b/clang-tools-extra/docs/clang-tidy/checks/performance-for-range-copy.rst index 35747271c906584eea0bfbfcb8343cef23ddead3..a48d6d4cb53999ce38878f58dc249cd77ef37cdb 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/performance-for-range-copy.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/performance-for-range-copy.rst @@ -23,8 +23,8 @@ Options .. option:: WarnOnAllAutoCopies - When non-zero, warns on any use of `auto` as the type of the range-based for - loop variable. Default is `0`. + When `true`, warns on any use of `auto` as the type of the range-based for + loop variable. Default is `false`. .. option:: AllowedTypes diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-string-concatenation.rst b/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-string-concatenation.rst index 60910c6f70cf62a28f5ab9ccb4e1ce7a2b9f0f41..92b6b4e0370d639c38e3cbf58531291b7b08ac99 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-string-concatenation.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-string-concatenation.rst @@ -55,5 +55,5 @@ Options .. option:: StrictMode - When zero, the check will only check the string usage in ``while``, ``for`` - and ``for-range`` statements. Default is `0`. + When `false`, the check will only check the string usage in ``while``, ``for`` + and ``for-range`` statements. Default is `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst index 463356ec186e7548bbfab252d79b721936c94f77..75016eb72d279f6cf6559ff0859b564f01cb518f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/performance-inefficient-vector-operation.rst @@ -61,6 +61,6 @@ Options .. option:: EnableProto - When non-zero, the check will also warn on inefficient operations for proto + When `true`, the check will also warn on inefficient operations for proto repeated fields. Otherwise, the check only warns on inefficient vector - operations. Default is `0`. + operations. Default is `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance-move-const-arg.rst b/clang-tools-extra/docs/clang-tidy/checks/performance-move-const-arg.rst index 39e1ca4afbd593baae7a61f94a9138fac6e34bc8..a8ec18d99c274c5c16a6086796ffbc815ac455ed 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/performance-move-const-arg.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/performance-move-const-arg.rst @@ -33,5 +33,5 @@ Options .. option:: CheckTriviallyCopyableMove - If non-zero, enables detection of trivially copyable types that do not - have a move constructor. Default is non-zero. + If `true`, enables detection of trivially copyable types that do not + have a move constructor. Default is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance-no-int-to-ptr.rst b/clang-tools-extra/docs/clang-tidy/checks/performance-no-int-to-ptr.rst new file mode 100644 index 0000000000000000000000000000000000000000..8233ea13f94e0190f37e8a0b8d4cef68304dcd55 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/performance-no-int-to-ptr.rst @@ -0,0 +1,45 @@ +.. title:: clang-tidy - performance-no-int-to-ptr + +performance-no-int-to-ptr +========================= + +Diagnoses every integer to pointer cast. + +While casting an (integral) pointer to an integer is obvious - you just get +the integral value of the pointer, casting an integer to an (integral) pointer +is deceivingly different. While you will get a pointer with that integral value, +if you got that integral value via a pointer-to-integer cast originally, +the new pointer will lack the provenance information from the original pointer. + +So while (integral) pointer to integer casts are effectively no-ops, +and are transparent to the optimizer, integer to (integral) pointer casts +are *NOT* transparent, and may conceal information from optimizer. + +While that may be the intention, it is not always so. For example, +let's take a look at a routine to align the pointer up to the multiple of 16: +The obvious, naive implementation for that is: + +.. code-block:: c++ + + char* src(char* maybe_underbiased_ptr) { + uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr; + uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15; + uintptr_t aligned_intptr = aligned_biased_intptr & (~15); + return (char*)aligned_intptr; // warning: avoid integer to pointer casts [performance-no-int-to-ptr] + } + +The check will rightfully diagnose that cast. + +But when provenance concealment is not the goal of the code, but an accident, +this example can be rewritten as follows, without using integer to pointer cast: + +.. code-block:: c++ + + char* + tgt(char* maybe_underbiased_ptr) { + uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr; + uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15; + uintptr_t aligned_intptr = aligned_biased_intptr & (~15); + uintptr_t bias = aligned_intptr - maybe_underbiased_intptr; + return maybe_underbiased_ptr + bias; + } diff --git a/clang-tools-extra/docs/clang-tidy/checks/portability-simd-intrinsics.rst b/clang-tools-extra/docs/clang-tidy/checks/portability-simd-intrinsics.rst index ea328c0eecb7794a9168bde90e9ee292f284fc1b..ab43c2fa58d4c246fbf3c6139f3102aa03bfb362 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/portability-simd-intrinsics.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/portability-simd-intrinsics.rst @@ -6,7 +6,7 @@ portability-simd-intrinsics Finds SIMD intrinsics calls and suggests ``std::experimental::simd`` (`P0214`_) alternatives. -If the option ``Suggest`` is set to non-zero, for +If the option :option:`Suggest` is set to `true`, for .. code-block:: c++ @@ -37,7 +37,7 @@ Options .. option:: Suggest - If this option is set to non-zero (default is `0`), the check will suggest + If this option is set to `true` (default is `false`), the check will suggest `P0214`_ alternatives, otherwise it only points out the intrinsic function is non-portable. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst index 68c0abfcbdf6101c29ac19acb0949caff1ed5826..b696abaabb3e2f33c0130c12fec03f72f9dc43c8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-identifier-naming.rst @@ -138,9 +138,9 @@ After: .. option:: AggressiveDependentMemberLookup - When set to `1` the check will look in dependent base classes for dependent + When set to `true` the check will look in dependent base classes for dependent member references that need changing. This can lead to errors with template - specializations so the default value is `0`. + specializations so the default value is `false`. For example using values of: @@ -162,7 +162,7 @@ Before: } }; -After if AggressiveDependentMemberLookup is ``0``: +After if AggressiveDependentMemberLookup is `false`: .. code-block:: c++ @@ -178,7 +178,7 @@ After if AggressiveDependentMemberLookup is ``0``: } }; -After if AggressiveDependentMemberLookup is ``1``: +After if AggressiveDependentMemberLookup is `true`: .. code-block:: c++ @@ -999,9 +999,9 @@ After: .. option:: IgnoreMainLikeFunctions - When set to `1` functions that have a similar signature to ``main`` or + When set to `true` functions that have a similar signature to ``main`` or ``wmain`` won't enforce checks on the names of their parameters. - Default value is `0`. + Default value is `false`. .. option:: InlineNamespaceCase diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst index c938d45b36bfd04a4cfeb76651cb593cce864496..1ea67a0b55e96044829287e6b74aeac37ca17935 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-implicit-bool-conversion.rst @@ -126,10 +126,10 @@ Options .. option:: AllowIntegerConditions - When non-zero, the check will allow conditional integer conversions. Default - is `0`. + When `true`, the check will allow conditional integer conversions. Default + is `false`. .. option:: AllowPointerConditions - When non-zero, the check will allow conditional pointer conversions. Default - is `0`. + When `true`, the check will allow conditional pointer conversions. Default + is `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-inconsistent-declaration-parameter-name.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-inconsistent-declaration-parameter-name.rst index a47bb41b16be531d2c25b5b497c55a9189d4b691..95341d52da4f62ea1d4e80997ed0673220c5c94a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-inconsistent-declaration-parameter-name.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-inconsistent-declaration-parameter-name.rst @@ -54,10 +54,10 @@ the definition or the first declaration seen in a translation unit. .. option:: IgnoreMacros - If this option is set to non-zero (default is `1`), the check will not warn + If this option is set to `true` (default is `true`), the check will not warn about names declared inside macros. .. option:: Strict - If this option is set to non-zero (default is `0`), then names must match + If this option is set to `true` (default is `false`), then names must match exactly (or be absent). diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-qualified-auto.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-qualified-auto.rst index 413640fb7ca736f1bf1bb9cdcf5f08ede2f68847..6fd066d397c76defa6691d8e07415f7776257bf5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-qualified-auto.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-qualified-auto.rst @@ -55,9 +55,9 @@ Options .. option:: AddConstToQualified - When set to `1` the check will add const qualifiers variables defined as + When set to `true` the check will add const qualifiers variables defined as ``auto *`` or ``auto &`` when applicable. - Default value is '1'. + Default value is `true`. .. code-block:: c++ @@ -65,7 +65,7 @@ Options auto *Foo2 = cast(Bar2); auto &Foo3 = cast(Bar3); -If AddConstToQualified is set to `0`, it will be transformed into: +If AddConstToQualified is set to `false`, it will be transformed into: .. code-block:: c++ @@ -81,4 +81,4 @@ Otherwise it will be transformed into: const auto *Foo2 = cast(Bar2); const auto &Foo3 = cast(Bar3); -Note in the LLVM alias, the default value is `0`. +Note in the LLVM alias, the default value is `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-access-specifiers.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-access-specifiers.rst index 74e1a1539b5031f78771c556e6d21cb984a4b237..ee0eef9bf4088c98eee4a203af0d5467b38a253f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-access-specifiers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-access-specifiers.rst @@ -31,10 +31,10 @@ Options .. option:: CheckFirstDeclaration - If set to non-zero, the check will also diagnose if the first access + If set to `true`, the check will also diagnose if the first access specifier declaration is redundant (e.g. ``private`` inside ``class``, or ``public`` inside ``struct`` or ``union``). - Default is `0`. + Default is `false`. Example ^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-declaration.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-declaration.rst index 8ce7aacce69dd6c5cfa3e8f96e4830f27089b7ff..0cd05211469fd506b392b10ad52243012874b922 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-declaration.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-declaration.rst @@ -33,5 +33,5 @@ Options .. option:: IgnoreMacros - If set to non-zero, the check will not give warnings inside macros. Default - is `1`. + If set to `true`, the check will not give warnings inside macros. Default + is `true`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst index fbe32624e3c8b37fa69c80f5d4a414c7857507e7..57d551266ac0dea780e96481dd095f197ceb57e1 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst @@ -25,9 +25,9 @@ Options .. option:: IgnoreBaseInCopyConstructors - Default is ``0``. + Default is `false`. - When non-zero, the check will ignore unnecessary base class initializations + When `true`, the check will ignore unnecessary base class initializations within copy constructors, since some compilers issue warnings/errors when base classes are not explicitly intialized in copy constructors. For example, ``gcc`` with ``-Wextra`` or ``-Werror=extra`` issues warning or error diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-smartptr-get.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-smartptr-get.rst index 54894196877e7989dbea34de31b5522a0f0cc5ca..20851b0acad974ae6ff50b5f071d9f8ff2937dde 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-smartptr-get.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-smartptr-get.rst @@ -17,5 +17,5 @@ Examples: .. option:: IgnoreMacros - If this option is set to non-zero (default is `1`), the check will not warn + If this option is set to `true` (default is `true`), the check will not warn about calls inside macros. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst index b333e186d542f67da28cb390e0a299b0cd5b6075..ef28acd4ddb322e58d20116f56c5b5e864775f94 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst @@ -77,10 +77,10 @@ Options .. option:: ChainedConditionalReturn - If non-zero, conditional boolean return statements at the end of an - ``if/else if`` chain will be transformed. Default is `0`. + If `true`, conditional boolean return statements at the end of an + ``if/else if`` chain will be transformed. Default is `false`. .. option:: ChainedConditionalAssignment - If non-zero, conditional boolean assignments at the end of an ``if/else - if`` chain will be transformed. Default is `0`. + If `true`, conditional boolean assignments at the end of an ``if/else + if`` chain will be transformed. Default is `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst index 82c083dae752f1c6790fd884357e15dfbe01ae3a..f2809dbc0b5f9a08f0fb25cff7cb4c47032b2c0c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-uppercase-literal-suffix.rst @@ -52,5 +52,5 @@ Given a list `L;uL`: .. option:: IgnoreMacros - If this option is set to non-zero (default is `1`), the check will not warn + If this option is set to `true` (default is `true`), the check will not warn about literal suffixes inside macros. diff --git a/clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-str-contains.cpp b/clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-str-contains.cpp index 9d4b03aa22f2cb8c8bf596f491507ec5f1b32124..81a3fc4d3b971cd6a7aec26e0abc7f1bb7ef90b9 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-str-contains.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-str-contains.cpp @@ -226,17 +226,21 @@ void string_literal_and_char_ptr_tests() { // CHECK-FIXES: {{^[[:space:]]*}}!absl::StrContains(asv, cc);{{$}} } -// Confirms that it does *not* match when the parameter to find() is a char, -// because absl::StrContains is not implemented for char. -void no_char_param_tests() { +void char_param_tests() { std::string ss; ss.find('c') == std::string::npos; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StrContains instead of + // CHECK-FIXES: {{^[[:space:]]*}}!absl::StrContains(ss, 'c');{{$}} std::string_view ssv; ssv.find('c') == std::string_view::npos; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StrContains instead of + // CHECK-FIXES: {{^[[:space:]]*}}!absl::StrContains(ssv, 'c');{{$}} absl::string_view asv; asv.find('c') == absl::string_view::npos; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StrContains instead of + // CHECK-FIXES: {{^[[:space:]]*}}!absl::StrContains(asv, 'c');{{$}} } #define FOO(a, b, c, d) ((a).find(b) == std::string::npos ? (c) : (d)) diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-redundant-branch-condition.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone-redundant-branch-condition.cpp index dd001e836477a833ec109cb851dcd151f3872ac6..e59d664628993995f99f877bfa6d59ca25cdcf50 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-redundant-branch-condition.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-redundant-branch-condition.cpp @@ -6,7 +6,8 @@ extern unsigned fireFighters; bool isBurning(); bool isReallyBurning(); bool isCollapsing(); -void tryToExtinguish(bool&); +bool tryToExtinguish(bool&); +bool tryToExtinguishByVal(bool); void tryPutFireOut(); bool callTheFD(); void scream(); @@ -948,6 +949,30 @@ void negative_indirect2_outer_and_rhs_inner_or_rhs() { } } +void negative_by_ref(bool onFire) { + if (tryToExtinguish(onFire) && onFire) { + if (tryToExtinguish(onFire) && onFire) { + // NO-MESSAGE: fire may have been extinguished + scream(); + } + } +} + +void negative_by_val(bool onFire) { + if (tryToExtinguishByVal(onFire) && onFire) { + if (tryToExtinguish(onFire) && onFire) { + // NO-MESSAGE: fire may have been extinguished + scream(); + } + } + if (tryToExtinguish(onFire) && onFire) { + if (tryToExtinguishByVal(onFire) && onFire) { + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [bugprone-redundant-branch-condition] + scream(); + } + } +} + void negative_reassigned() { bool onFire = isBurning(); if (onFire) { @@ -1077,9 +1102,9 @@ void positive_comma_after_condition() { int positive_expr_with_cleanups() { class RetT { public: - RetT(const int _code) : code_(_code) {} - bool Ok() const { return code_ == 0; } - static RetT Test(bool &_isSet) { return 0; } + RetT(const int code); + bool Ok() const; + static RetT Test(bool isSet); private: int code_; diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions.cpp index cc817a021fde73234743d92522a3f8bf469f7012..493a447913bd4110e5346b93866d1cfd7404ff29 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-narrowing-conversions.cpp @@ -343,4 +343,17 @@ void macro_context() { DERP(i, .5l); } +// We understand typedefs. +void typedef_context() { + typedef long long myint64_t; + int i; + myint64_t i64; + + i64 = i64; // Okay, no conversion. + i64 = i; // Okay, no narrowing. + + i = i64; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'myint64_t' (aka 'long long') to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions] +} + } // namespace floats diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-make-shared.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-make-shared.cpp index e046801e24212f698d611ad635426a9b9d0b2f86..21f9cb116ec727345336d5ad0d575492ea3f8b2c 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize-make-shared.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-make-shared.cpp @@ -38,48 +38,61 @@ std::shared_ptr getPointer() { // CHECK-FIXES: return std::make_shared(); } +std::shared_ptr getPointerValue() { + return std::shared_ptr(new Base()); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_shared instead + // CHECK-FIXES: return std::make_shared(); +} + void basic() { std::shared_ptr P1 = std::shared_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_shared instead [modernize-make-shared] // CHECK-FIXES: std::shared_ptr P1 = std::make_shared(); + std::shared_ptr P2 = std::shared_ptr(new int); P1.reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead [modernize-make-shared] // CHECK-FIXES: P1 = std::make_shared(); + P1.reset(new int); P1 = std::shared_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead [modernize-make-shared] // CHECK-FIXES: P1 = std::make_shared(); + P1 = std::shared_ptr(new int); - // Without parenthesis. - std::shared_ptr P2 = std::shared_ptr(new int); - // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_shared instead [modernize-make-shared] - // CHECK-FIXES: std::shared_ptr P2 = std::make_shared(); + // Without parenthesis, default initialization. + std::shared_ptr P3 = std::shared_ptr(new int); - P2.reset(new int); + P2.reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead [modernize-make-shared] // CHECK-FIXES: P2 = std::make_shared(); + P2.reset(new int); - P2 = std::shared_ptr(new int); + P2 = std::shared_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead [modernize-make-shared] // CHECK-FIXES: P2 = std::make_shared(); + P2 = std::shared_ptr(new int); // With auto. - auto P3 = std::shared_ptr(new int()); + auto P4 = std::shared_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_shared instead - // CHECK-FIXES: auto P3 = std::make_shared(); + // CHECK-FIXES: auto P4 = std::make_shared(); + auto P5 = std::shared_ptr(new int); - std::shared_ptr P4 = std::shared_ptr((new int)); + std::shared_ptr P6 = std::shared_ptr((new int())); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_shared instead [modernize-make-shared] - // CHECK-FIXES: std::shared_ptr P4 = std::make_shared(); + // CHECK-FIXES: std::shared_ptr P6 = std::make_shared(); + std::shared_ptr P7 = std::shared_ptr((new int)); P4.reset((((new int())))); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead [modernize-make-shared] // CHECK-FIXES: P4 = std::make_shared(); + P4.reset((((new int)))); - P4 = std::shared_ptr(((new int))); + P4 = std::shared_ptr(((new int()))); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead [modernize-make-shared] // CHECK-FIXES: P4 = std::make_shared(); + P4 = std::shared_ptr(((new int))); { // No std. @@ -87,40 +100,54 @@ void basic() { shared_ptr Q = shared_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_shared instead // CHECK-FIXES: shared_ptr Q = std::make_shared(); + shared_ptr P = shared_ptr(new int); Q = shared_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead // CHECK-FIXES: Q = std::make_shared(); + Q = shared_ptr(new int); } std::shared_ptr R(new int()); + std::shared_ptr S(new int); // Create the shared_ptr as a parameter to a function. int T = g(std::shared_ptr(new int())); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_shared instead // CHECK-FIXES: int T = g(std::make_shared()); + T = g(std::shared_ptr(new int)); // Only replace if the type in the template is the same as the type returned // by the new operator. auto Pderived = std::shared_ptr(new Derived()); + auto PderivedNoparen = std::shared_ptr(new Derived); // OK to replace for reset and assign Pderived.reset(new Derived()); // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_shared instead // CHECK-FIXES: Pderived = std::make_shared(); + Pderived.reset(new Derived); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_shared instead + // CHECK-FIXES: Pderived = std::make_shared(); Pderived = std::shared_ptr(new Derived()); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use std::make_shared instead // CHECK-FIXES: Pderived = std::make_shared(); + Pderived = std::shared_ptr(new Derived); + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use std::make_shared instead + // CHECK-FIXES: Pderived = std::make_shared(); // FIXME: OK to replace if assigned to shared_ptr Pderived = std::shared_ptr(new Derived()); + Pderived = std::shared_ptr(new Derived); // FIXME: OK to replace when auto is not used std::shared_ptr PBase = std::shared_ptr(new Derived()); + std::shared_ptr PBase2 = std::shared_ptr(new Derived); // The pointer is returned by the function, nothing to do. std::shared_ptr RetPtr = getPointer(); + std::shared_ptr RetPtr2 = getPointerValue(); // This emulates std::move. std::shared_ptr Move = static_cast &&>(P1); @@ -130,6 +157,10 @@ void basic() { std::shared_ptr Placement = std::shared_ptr(new (PInt) int{3}); Placement.reset(new (PInt) int{3}); Placement = std::shared_ptr(new (PInt) int{3}); + + std::shared_ptr PlacementNoparen = std::shared_ptr(new (PInt) int); + PlacementNoparen.reset(new (PInt) int); + PlacementNoparen = std::shared_ptr(new (PInt) int); } // Calling make_smart_ptr from within a member function of a type with a @@ -231,15 +262,17 @@ void initialization(int T, Base b) { void aliases() { typedef std::shared_ptr IntPtr; - IntPtr Typedef = IntPtr(new int); + IntPtr Typedef = IntPtr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_shared instead // CHECK-FIXES: IntPtr Typedef = std::make_shared(); + IntPtr Typedef2 = IntPtr(new int); // We use 'bool' instead of '_Bool'. typedef std::shared_ptr BoolPtr; - BoolPtr BoolType = BoolPtr(new bool); + BoolPtr BoolType = BoolPtr(new bool()); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::make_shared instead // CHECK-FIXES: BoolPtr BoolType = std::make_shared(); + BoolPtr BoolType2 = BoolPtr(new bool); // We use 'Base' instead of 'struct Base'. typedef std::shared_ptr BasePtr; @@ -248,14 +281,16 @@ void aliases() { // CHECK-FIXES: BasePtr StructType = std::make_shared(); #define PTR shared_ptr - std::shared_ptr Macro = std::PTR(new int); -// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_shared instead -// CHECK-FIXES: std::shared_ptr Macro = std::make_shared(); + std::shared_ptr Macro = std::PTR(new int()); + // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_shared instead + // CHECK-FIXES: std::shared_ptr Macro = std::make_shared(); + std::shared_ptr Macro2 = std::PTR(new int); #undef PTR - std::shared_ptr Using = shared_ptr_(new int); + std::shared_ptr Using = shared_ptr_(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_shared instead // CHECK-FIXES: std::shared_ptr Using = std::make_shared(); + std::shared_ptr Using2 = shared_ptr_(new int); } void whitespaces() { @@ -263,10 +298,12 @@ void whitespaces() { auto Space = std::shared_ptr (new int()); // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_shared instead // CHECK-FIXES: auto Space = std::make_shared(); + auto Space2 = std::shared_ptr (new int); auto Spaces = std :: shared_ptr (new int()); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_shared instead // CHECK-FIXES: auto Spaces = std::make_shared(); + auto Spaces2 = std :: shared_ptr (new int); // clang-format on } @@ -277,9 +314,10 @@ void nesting() { Nest.reset(new std::shared_ptr(new int)); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead // CHECK-FIXES: Nest = std::make_shared>(new int); - Nest->reset(new int); + Nest->reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead // CHECK-FIXES: *Nest = std::make_shared(); + Nest->reset(new int); } void reset() { @@ -289,9 +327,11 @@ void reset() { P.reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use std::make_shared instead // CHECK-FIXES: P = std::make_shared(); + P.reset(new int); auto Q = &P; Q->reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead // CHECK-FIXES: *Q = std::make_shared(); + Q->reset(new int); } diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-make-unique-default-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-make-unique-default-init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d79e700784348b8780cc21b65945ff45212f249 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-make-unique-default-init.cpp @@ -0,0 +1,73 @@ +// RUN: %check_clang_tidy -std=c++14-or-later %s modernize-make-unique %t -- \ +// RUN: -config="{CheckOptions: \ +// RUN: [{key: modernize-make-unique.IgnoreDefaultInitialization, \ +// RUN: value: 'false'}] \ +// RUN: }" \ +// RUN: -- -I %S/Inputs/modernize-smart-ptr + +#include "initializer_list.h" +#include "unique_ptr.h" +// CHECK-FIXES: #include + +void basic() { + std::unique_ptr P1 = std::unique_ptr(new int()); + // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: std::unique_ptr P1 = std::make_unique(); + std::unique_ptr P2 = std::unique_ptr(new int); + // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: std::unique_ptr P2 = std::make_unique(); + + P1.reset(new int()); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P1 = std::make_unique(); + P2.reset(new int); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P2 = std::make_unique(); + + P1 = std::unique_ptr(new int()); + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P1 = std::make_unique(); + P2 = std::unique_ptr(new int); + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P2 = std::make_unique(); + + // With auto. + auto P3 = std::unique_ptr(new int()); + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead + // CHECK-FIXES: auto P3 = std::make_unique(); + auto P4 = std::unique_ptr(new int); + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead + // CHECK-FIXES: auto P4 = std::make_unique(); + + std::unique_ptr P5 = std::unique_ptr((new int())); + // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: std::unique_ptr P5 = std::make_unique(); + std::unique_ptr P6 = std::unique_ptr((new int)); + // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: std::unique_ptr P6 = std::make_unique(); + + P5.reset((new int())); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P5 = std::make_unique(); + P6.reset((new int)); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P6 = std::make_unique(); + + std::unique_ptr P7, P8; + P7.reset(new int[5]()); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P7 = std::make_unique(5); + + P8.reset(new int[5]); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P8 = std::make_unique(5); + + int Num = 3; + P7.reset(new int[Num]); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P7 = std::make_unique(Num); + + P8.reset(new int[Num]); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] + // CHECK-FIXES: P8 = std::make_unique(Num); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-make-unique.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-make-unique.cpp index 16cb5228b2db3703fb53ae37e25ec9cf2982f08d..f4241be20042f08ba029413d79c1bbe31f96abcc 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize-make-unique.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-make-unique.cpp @@ -83,49 +83,60 @@ std::unique_ptr getPointer() { // CHECK-FIXES: return std::make_unique(); } +std::unique_ptr getPointerValue() { + return std::unique_ptr(new Base()); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead + // CHECK-FIXES: return std::make_unique(); +} + void basic() { std::unique_ptr P1 = std::unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: std::unique_ptr P1 = std::make_unique(); + std::unique_ptr P2 = std::unique_ptr(new int); P1.reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: P1 = std::make_unique(); + P2.reset(new int); P1 = std::unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: P1 = std::make_unique(); + P1 = std::unique_ptr(new int); - // Without parenthesis. - std::unique_ptr P2 = std::unique_ptr(new int); - // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] - // CHECK-FIXES: std::unique_ptr P2 = std::make_unique(); + // Without parenthesis, default initialization. + std::unique_ptr P3 = std::unique_ptr(new int); P2.reset(new int); - // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] - // CHECK-FIXES: P2 = std::make_unique(); P2 = std::unique_ptr(new int); - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead [modernize-make-unique] - // CHECK-FIXES: P2 = std::make_unique(); // With auto. - auto P3 = std::unique_ptr(new int()); + auto P4 = std::unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead - // CHECK-FIXES: auto P3 = std::make_unique(); + // CHECK-FIXES: auto P4 = std::make_unique(); + auto P5 = std::unique_ptr(new int); - std::unique_ptr P4 = std::unique_ptr((new int)); + std::unique_ptr P6 = std::unique_ptr((new int())); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] - // CHECK-FIXES: std::unique_ptr P4 = std::make_unique(); - P4.reset((new int)); + // CHECK-FIXES: std::unique_ptr P6 = std::make_unique(); + std::unique_ptr P7 = std::unique_ptr((new int)); + + P4.reset((new int())); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: P4 = std::make_unique(); - std::unique_ptr P5 = std::unique_ptr((((new int)))); + P5.reset((new int)); + + std::unique_ptr P8 = std::unique_ptr((((new int())))); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique] - // CHECK-FIXES: std::unique_ptr P5 = std::make_unique(); - P5.reset(((((new int))))); + // CHECK-FIXES: std::unique_ptr P8 = std::make_unique(); + std::unique_ptr P9 = std::unique_ptr((((new int)))); + + P5.reset(((((new int()))))); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead [modernize-make-unique] // CHECK-FIXES: P5 = std::make_unique(); + P6.reset(((((new int))))); { // No std. @@ -133,40 +144,55 @@ void basic() { unique_ptr Q = unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead // CHECK-FIXES: unique_ptr Q = std::make_unique(); + unique_ptr P = unique_ptr(new int); Q = unique_ptr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead // CHECK-FIXES: Q = std::make_unique(); + + P = unique_ptr(new int); } std::unique_ptr R(new int()); + std::unique_ptr S(new int); // Create the unique_ptr as a parameter to a function. int T = g(std::unique_ptr(new int())); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead // CHECK-FIXES: int T = g(std::make_unique()); + T = g(std::unique_ptr(new int)); // Only replace if the type in the template is the same as the type returned // by the new operator. auto Pderived = std::unique_ptr(new Derived()); + auto PderivedNoparen = std::unique_ptr(new Derived); // OK to replace for reset and assign Pderived.reset(new Derived()); // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_unique instead // CHECK-FIXES: Pderived = std::make_unique(); + PderivedNoparen.reset(new Derived); + // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use std::make_unique instead + // CHECK-FIXES: PderivedNoparen = std::make_unique(); Pderived = std::unique_ptr(new Derived()); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use std::make_unique instead // CHECK-FIXES: Pderived = std::make_unique(); + PderivedNoparen = std::unique_ptr(new Derived); + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use std::make_unique instead + // CHECK-FIXES: PderivedNoparen = std::make_unique(); // FIXME: OK to replace if assigned to unique_ptr Pderived = std::unique_ptr(new Derived()); + Pderived = std::unique_ptr(new Derived); // FIXME: OK to replace when auto is not used std::unique_ptr PBase = std::unique_ptr(new Derived()); + std::unique_ptr PBaseNoparen = std::unique_ptr(new Derived); // The pointer is returned by the function, nothing to do. std::unique_ptr RetPtr = getPointer(); + RetPtr = getPointerValue(); // This emulates std::move. std::unique_ptr Move = static_cast &&>(P1); @@ -176,6 +202,10 @@ void basic() { std::unique_ptr Placement = std::unique_ptr(new (PInt) int{3}); Placement.reset(new (PInt) int{3}); Placement = std::unique_ptr(new (PInt) int{3}); + + std::unique_ptr PlacementNoparen = std::unique_ptr(new (PInt) int); + PlacementNoparen.reset(new (PInt) int); + PlacementNoparen = std::unique_ptr(new (PInt) int); } // Calling make_smart_ptr from within a member function of a type with a @@ -446,12 +476,12 @@ void initialization(int T, Base b) { // CHECK-FIXES: FFs = std::make_unique(Num2); std::unique_ptr FI; - FI.reset(new int[5]()); // default initialization. + FI.reset(new int[5]()); // value initialization. // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: // CHECK-FIXES: FI = std::make_unique(5); // The check doesn't give warnings and fixes for cases where the original new - // expression doesn't do any initialization. + // expression does default initialization. FI.reset(new int[5]); FI.reset(new int[Num]); FI.reset(new int[Num2]); @@ -459,15 +489,17 @@ void initialization(int T, Base b) { void aliases() { typedef std::unique_ptr IntPtr; - IntPtr Typedef = IntPtr(new int); + IntPtr Typedef = IntPtr(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_unique instead // CHECK-FIXES: IntPtr Typedef = std::make_unique(); + IntPtr Typedef2 = IntPtr(new int); // We use 'bool' instead of '_Bool'. typedef std::unique_ptr BoolPtr; - BoolPtr BoolType = BoolPtr(new bool); + BoolPtr BoolType = BoolPtr(new bool()); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::make_unique instead // CHECK-FIXES: BoolPtr BoolType = std::make_unique(); + BoolPtr BoolType2 = BoolPtr(new bool); // We use 'Base' instead of 'struct Base'. typedef std::unique_ptr BasePtr; @@ -476,14 +508,16 @@ void aliases() { // CHECK-FIXES: BasePtr StructType = std::make_unique(); #define PTR unique_ptr - std::unique_ptr Macro = std::PTR(new int); -// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead -// CHECK-FIXES: std::unique_ptr Macro = std::make_unique(); + std::unique_ptr Macro = std::PTR(new int()); + // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead + // CHECK-FIXES: std::unique_ptr Macro = std::make_unique(); + std::unique_ptr Macro2 = std::PTR(new int); #undef PTR - std::unique_ptr Using = unique_ptr_(new int); + std::unique_ptr Using = unique_ptr_(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead // CHECK-FIXES: std::unique_ptr Using = std::make_unique(); + std::unique_ptr Using2 = unique_ptr_(new int); } void whitespaces() { @@ -491,10 +525,12 @@ void whitespaces() { auto Space = std::unique_ptr (new int()); // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead // CHECK-FIXES: auto Space = std::make_unique(); + auto Space2 = std::unique_ptr (new int); auto Spaces = std :: unique_ptr (new int()); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead // CHECK-FIXES: auto Spaces = std::make_unique(); + auto Spaces2 = std :: unique_ptr (new int); // clang-format on } @@ -505,7 +541,7 @@ void nesting() { Nest.reset(new std::unique_ptr(new int)); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_unique instead // CHECK-FIXES: Nest = std::make_unique>(new int); - Nest->reset(new int); + Nest->reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_unique instead // CHECK-FIXES: *Nest = std::make_unique(); } @@ -517,11 +553,13 @@ void reset() { P.reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use std::make_unique instead // CHECK-FIXES: P = std::make_unique(); + P.reset(new int); auto Q = &P; Q->reset(new int()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_unique instead // CHECK-FIXES: *Q = std::make_unique(); + Q->reset(new int); } #define DEFINE(...) __VA_ARGS__ @@ -542,9 +580,15 @@ class UniqueFoo : public std::unique_ptr { this->reset(new Foo); // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use std::make_unique instead // CHECK-FIXES: *this = std::make_unique(); + this->reset(new Foo()); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use std::make_unique instead + // CHECK-FIXES: *this = std::make_unique(); (*this).reset(new Foo); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead // CHECK-FIXES: (*this) = std::make_unique(); + (*this).reset(new Foo()); + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead + // CHECK-FIXES: (*this) = std::make_unique(); } }; @@ -552,7 +596,9 @@ class UniqueFoo : public std::unique_ptr { template void template_fun(T* t) { std::unique_ptr t2 = std::unique_ptr(new T); + std::unique_ptr t3 = std::unique_ptr(new T()); t2.reset(new T); + t3.reset(new T()); } void invoke_template() { diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-no-int-to-ptr.c b/clang-tools-extra/test/clang-tidy/checkers/performance-no-int-to-ptr.c new file mode 100644 index 0000000000000000000000000000000000000000..90f51bc945f45dd31bb9ef93f95b94fc6d64c718 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-no-int-to-ptr.c @@ -0,0 +1,66 @@ +// RUN: %check_clang_tidy %s performance-no-int-to-ptr %t + +void *t0(char x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t1(signed char x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t2(unsigned char x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} + +void *t3(short x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t4(unsigned short x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t5(signed short x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} + +void *t6(int x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t7(unsigned int x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t8(signed int x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} + +void *t9(long x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t10(unsigned long x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t11(signed long x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} + +void *t12(long long x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t13(unsigned long long x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} +void *t14(signed long long x) { + return x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-no-int-to-ptr.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance-no-int-to-ptr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..adda32e09cd119913e00b4764472e338cc534d27 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-no-int-to-ptr.cpp @@ -0,0 +1,22 @@ +// RUN: %check_clang_tidy %s performance-no-int-to-ptr %t + +// can't implicitly cast int to a pointer. +// can't use static_cast<>() to cast integer to a pointer. +// can't use dynamic_cast<>() to cast integer to a pointer. +// can't use const_cast<>() to cast integer to a pointer. + +void *t0(long long int x) { + return (void *)x; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} + +void *t1(int x) { + return reinterpret_cast(x); + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr] +} + +// Don't diagnose casts from integer literals. +// It's a widely-used technique in embedded/microcontroller/hardware interfacing. +void *t3(long long int x) { + return (void *)0xFEEDFACE; +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp index 120902d0eade0379dbe777449af2ec54366de599..8cc095e431fda4c7c19e39886a7699b4b991d7cd 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp @@ -476,3 +476,35 @@ void negativeInvokedOnStdFunction( auto Copy = Orig.reference(); Update(Copy); } + +void negativeCopiedFromReferenceToModifiedVar() { + ExpensiveToCopyType Orig; + const auto &Ref = Orig; + const auto NecessaryCopy = Ref; + Orig.nonConstMethod(); +} + +void positiveCopiedFromReferenceToConstVar() { + ExpensiveToCopyType Orig; + const auto &Ref = Orig; + const auto UnnecessaryCopy = Ref; + // CHECK-MESSAGES: [[@LINE-1]]:14: warning: local copy 'UnnecessaryCopy' of + // CHECK-FIXES: const auto& UnnecessaryCopy = Ref; + Orig.constMethod(); +} + +void negativeCopiedFromGetterOfReferenceToModifiedVar() { + ExpensiveToCopyType Orig; + const auto &Ref = Orig.reference(); + const auto NecessaryCopy = Ref.reference(); + Orig.nonConstMethod(); +} + +void positiveCopiedFromGetterOfReferenceToConstVar() { + ExpensiveToCopyType Orig; + const auto &Ref = Orig.reference(); + auto UnnecessaryCopy = Ref.reference(); + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'UnnecessaryCopy' is + // CHECK-FIXES: const auto& UnnecessaryCopy = Ref.reference(); + Orig.constMethod(); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-case-violation.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-case-violation.cpp index 454999ed7c2529523d06eb16c209cd327b3919c8..aa4a76821d6667658a350f6610756250edd0f179 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-case-violation.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-identifier-naming-case-violation.cpp @@ -5,11 +5,11 @@ // RUN: {key: readability-identifier-naming.ClassCase, value: UUPER_CASE}, \ // RUN: {key: readability-identifier-naming.StructCase, value: CAMEL}, \ // RUN: {key: readability-identifier-naming.EnumCase, value: AnY_cASe}, \ -// RUN: ]}" 2>&1 | FileCheck %s --implicit-check-not warning +// RUN: ]}" 2>&1 | FileCheck %s --implicit-check-not="{{warning|error}}:" -// CHECK-DAG: warning: invalid configuration value 'camelback' for option 'readability-identifier-naming.FunctionCase'; did you mean 'camelBack'?{{$}} -// CHECK-DAG: warning: invalid configuration value 'UUPER_CASE' for option 'readability-identifier-naming.ClassCase'; did you mean 'UPPER_CASE'?{{$}} +// CHECK-DAG: warning: invalid configuration value 'camelback' for option 'readability-identifier-naming.FunctionCase'; did you mean 'camelBack'? [clang-tidy-config] +// CHECK-DAG: warning: invalid configuration value 'UUPER_CASE' for option 'readability-identifier-naming.ClassCase'; did you mean 'UPPER_CASE'? [clang-tidy-config] // Don't try to suggest an alternative for 'CAMEL' -// CHECK-DAG: warning: invalid configuration value 'CAMEL' for option 'readability-identifier-naming.StructCase'{{$}} +// CHECK-DAG: warning: invalid configuration value 'CAMEL' for option 'readability-identifier-naming.StructCase' [clang-tidy-config] // This fails on the EditDistance, but as it matches ignoring case suggest the correct value -// CHECK-DAG: warning: invalid configuration value 'AnY_cASe' for option 'readability-identifier-naming.EnumCase'; did you mean 'aNy_CasE'?{{$}} +// CHECK-DAG: warning: invalid configuration value 'AnY_cASe' for option 'readability-identifier-naming.EnumCase'; did you mean 'aNy_CasE'? [clang-tidy-config] diff --git a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp index 78d6f593777db922afd61b83f86d5db40a8e98a0..76ab85680b9fd52db26cdc6f162f524e1e82d8ec 100644 --- a/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp +++ b/clang-tools-extra/unittests/clang-query/QueryParserTest.cpp @@ -112,11 +112,9 @@ TEST_F(QueryParserTest, Set) { EXPECT_EQ(true, cast >(Q)->Value); Q = parse("set traversal AsIs"); - ASSERT_TRUE(isa>(Q)); - EXPECT_EQ(&QuerySession::TK, - cast>(Q)->Var); - EXPECT_EQ(ast_type_traits::TK_AsIs, - cast>(Q)->Value); + ASSERT_TRUE(isa>(Q)); + EXPECT_EQ(&QuerySession::TK, cast>(Q)->Var); + EXPECT_EQ(TK_AsIs, cast>(Q)->Value); Q = parse("set traversal NotATraversal"); ASSERT_TRUE(isa(Q)); diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp index 0894e5fd5eb91980b1256c14aa05212bfc944b28..fec9fddccd0a53368969c88810222afeaccba770 100644 --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp @@ -10,7 +10,9 @@ namespace { class TestCheck : public ClangTidyCheck { public: TestCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + : ClangTidyCheck(Name, Context) { + diag("DiagWithNoLoc"); + } void registerMatchers(ast_matchers::MatchFinder *Finder) override { Finder->addMatcher(ast_matchers::varDecl().bind("var"), this); } @@ -26,9 +28,10 @@ public: TEST(ClangTidyDiagnosticConsumer, SortsErrors) { std::vector Errors; runCheckOnCode("int a;", &Errors); - EXPECT_EQ(2ul, Errors.size()); - EXPECT_EQ("type specifier", Errors[0].Message.Message); - EXPECT_EQ("variable", Errors[1].Message.Message); + EXPECT_EQ(3ul, Errors.size()); + EXPECT_EQ("DiagWithNoLoc", Errors[0].Message.Message); + EXPECT_EQ("type specifier", Errors[1].Message.Message); + EXPECT_EQ("variable", Errors[2].Message.Message); } } // namespace test diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp index 729dfa80502d3419948792c7a4929379aa74920d..40cd9a5eff1511dad8ee9f0a020db6a41fabce50 100644 --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp @@ -72,10 +72,11 @@ TEST(ParseLineFilter, ValidFilter) { TEST(ParseConfiguration, ValidConfiguration) { llvm::ErrorOr Options = - parseConfiguration("Checks: \"-*,misc-*\"\n" - "HeaderFilterRegex: \".*\"\n" - "AnalyzeTemporaryDtors: true\n" - "User: some.user"); + parseConfiguration(llvm::MemoryBufferRef("Checks: \"-*,misc-*\"\n" + "HeaderFilterRegex: \".*\"\n" + "AnalyzeTemporaryDtors: true\n" + "User: some.user", + "Options")); EXPECT_TRUE(!!Options); EXPECT_EQ("-*,misc-*", *Options->Checks); EXPECT_EQ(".*", *Options->HeaderFilterRegex); @@ -83,7 +84,8 @@ TEST(ParseConfiguration, ValidConfiguration) { } TEST(ParseConfiguration, MergeConfigurations) { - llvm::ErrorOr Options1 = parseConfiguration(R"( + llvm::ErrorOr Options1 = + parseConfiguration(llvm::MemoryBufferRef(R"( Checks: "check1,check2" HeaderFilterRegex: "filter1" AnalyzeTemporaryDtors: true @@ -91,9 +93,11 @@ TEST(ParseConfiguration, MergeConfigurations) { ExtraArgs: ['arg1', 'arg2'] ExtraArgsBefore: ['arg-before1', 'arg-before2'] UseColor: false - )"); + )", + "Options1")); ASSERT_TRUE(!!Options1); - llvm::ErrorOr Options2 = parseConfiguration(R"( + llvm::ErrorOr Options2 = + parseConfiguration(llvm::MemoryBufferRef(R"( Checks: "check3,check4" HeaderFilterRegex: "filter2" AnalyzeTemporaryDtors: false @@ -101,7 +105,8 @@ TEST(ParseConfiguration, MergeConfigurations) { ExtraArgs: ['arg3', 'arg4'] ExtraArgsBefore: ['arg-before3', 'arg-before4'] UseColor: true - )"); + )", + "Options2")); ASSERT_TRUE(!!Options2); ClangTidyOptions Options = Options1->merge(*Options2, 0); EXPECT_EQ("check1,check2,check3,check4", *Options.Checks); @@ -166,6 +171,10 @@ TEST(CheckOptionsValidation, MissingOptions) { ClangTidyOptions Options; ClangTidyContext Context(std::make_unique( ClangTidyGlobalOptions(), Options)); + ClangTidyDiagnosticConsumer DiagConsumer(Context); + DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions, + &DiagConsumer, false); + Context.setDiagnosticsEngine(&DE); TestCheck TestCheck(&Context); CHECK_ERROR(TestCheck.getLocal("Opt"), MissingOptionError, "option not found 'test.Opt'"); @@ -191,6 +200,10 @@ TEST(CheckOptionsValidation, ValidIntOptions) { ClangTidyContext Context(std::make_unique( ClangTidyGlobalOptions(), Options)); + ClangTidyDiagnosticConsumer DiagConsumer(Context); + DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions, + &DiagConsumer, false); + Context.setDiagnosticsEngine(&DE); TestCheck TestCheck(&Context); #define CHECK_ERROR_INT(Name, Expected) \ diff --git a/clang-tools-extra/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp b/clang-tools-extra/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp index 536d6f8ef275eb103046e5d8f3ae0570ad5b3e06..e8df4bb600718777541be465299b6db038649f79 100644 --- a/clang-tools-extra/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/TransformerClangTidyCheckTest.cpp @@ -23,6 +23,7 @@ using namespace ::clang::ast_matchers; using transformer::cat; using transformer::change; using transformer::IncludeFormat; +using transformer::makeRule; using transformer::node; using transformer::RewriteRule; using transformer::statement; @@ -30,14 +31,14 @@ using transformer::statement; // Invert the code of an if-statement, while maintaining its semantics. RewriteRule invertIf() { StringRef C = "C", T = "T", E = "E"; - RewriteRule Rule = tooling::makeRule( - ifStmt(hasCondition(expr().bind(C)), hasThen(stmt().bind(T)), - hasElse(stmt().bind(E))), - change(statement(std::string(RewriteRule::RootID)), - cat("if(!(", node(std::string(C)), ")) ", - statement(std::string(E)), " else ", - statement(std::string(T)))), - cat("negate condition and reverse `then` and `else` branches")); + RewriteRule Rule = + makeRule(ifStmt(hasCondition(expr().bind(C)), hasThen(stmt().bind(T)), + hasElse(stmt().bind(E))), + change(statement(std::string(RewriteRule::RootID)), + cat("if(!(", node(std::string(C)), ")) ", + statement(std::string(E)), " else ", + statement(std::string(T)))), + cat("negate condition and reverse `then` and `else` branches")); return Rule; } @@ -70,10 +71,9 @@ TEST(TransformerClangTidyCheckTest, Basic) { class IntLitCheck : public TransformerClangTidyCheck { public: IntLitCheck(StringRef Name, ClangTidyContext *Context) - : TransformerClangTidyCheck(tooling::makeRule(integerLiteral(), - change(cat("LIT")), - cat("no message")), - Name, Context) {} + : TransformerClangTidyCheck( + makeRule(integerLiteral(), change(cat("LIT")), cat("no message")), + Name, Context) {} }; // Tests that two changes in a single macro expansion do not lead to conflicts @@ -95,7 +95,7 @@ class BinOpCheck : public TransformerClangTidyCheck { public: BinOpCheck(StringRef Name, ClangTidyContext *Context) : TransformerClangTidyCheck( - tooling::makeRule( + makeRule( binaryOperator(hasOperatorName("+"), hasRHS(expr().bind("r"))), change(node("r"), cat("RIGHT")), cat("no message")), Name, Context) {} @@ -122,8 +122,8 @@ Optional needsObjC(const LangOptions &LangOpts, const ClangTidyCheck::OptionsView &Options) { if (!LangOpts.ObjC) return None; - return tooling::makeRule(clang::ast_matchers::functionDecl(), - change(cat("void changed() {}")), cat("no message")); + return makeRule(clang::ast_matchers::functionDecl(), + change(cat("void changed() {}")), cat("no message")); } class NeedsObjCCheck : public TransformerClangTidyCheck { @@ -147,8 +147,8 @@ Optional noSkip(const LangOptions &LangOpts, const ClangTidyCheck::OptionsView &Options) { if (Options.get("Skip", "false") == "true") return None; - return tooling::makeRule(clang::ast_matchers::functionDecl(), - changeTo(cat("void nothing();")), cat("no message")); + return makeRule(clang::ast_matchers::functionDecl(), + changeTo(cat("void nothing();")), cat("no message")); } class ConfigurableCheck : public TransformerClangTidyCheck { @@ -174,9 +174,8 @@ TEST(TransformerClangTidyCheckTest, DisableByConfig) { RewriteRule replaceCall(IncludeFormat Format) { using namespace ::clang::ast_matchers; - RewriteRule Rule = - tooling::makeRule(callExpr(callee(functionDecl(hasName("f")))), - change(cat("other()")), cat("no message")); + RewriteRule Rule = makeRule(callExpr(callee(functionDecl(hasName("f")))), + change(cat("other()")), cat("no message")); addInclude(Rule, "clang/OtherLib.h", Format); return Rule; } diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 8c539e80946d6e91a79c83a1b35e51cacdbeeb1e..f947b820bdac07de551582a0dffbe0216f16af42 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -242,9 +242,6 @@ set(ENABLE_LINKER_BUILD_ID OFF CACHE BOOL "pass --build-id to ld") set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL "enable x86 relax relocations by default") -set(ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER FALSE CACHE BOOL - "Enable the experimental new pass manager by default.") - set(CLANG_SPAWN_CC1 OFF CACHE BOOL "Whether clang should use a new process for the CC1 invocation") diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index 6e9ae85e73181b35a7175201649b31c93956a962..16bc96be1138d77f67d791ccd75fad921ed57882 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -211,14 +211,24 @@ if(FUCHSIA_SDK) set(RUNTIMES_${target}-unknown-fuchsia+asan+noexcept_LIBCXXABI_ENABLE_EXCEPTIONS OFF CACHE BOOL "") set(RUNTIMES_${target}-unknown-fuchsia+asan+noexcept_LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+relative-vtables_LLVM_BUILD_COMPILER_RT OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+relative-vtables_CMAKE_CXX_FLAGS "${RUNTIMES_${target}-unknown-fuchsia+relative-vtables_CMAKE_CXX_FLAGS} -Xclang -fexperimental-relative-c++-abi-vtables" CACHE STRING "") + + set(RUNTIMES_${target}-unknown-fuchsia+relative-vtables+noexcept_LLVM_BUILD_COMPILER_RT OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+relative-vtables+noexcept_CMAKE_CXX_FLAGS "${RUNTIMES_${target}-unknown-fuchsia+relative-vtables+noexcept_CMAKE_CXX_FLAGS} -Xclang -fexperimental-relative-c++-abi-vtables" CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia+relative-vtables+noexcept_LIBCXXABI_ENABLE_EXCEPTIONS OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+relative-vtables+noexcept_LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "") + # Use .build-id link. list(APPEND RUNTIME_BUILD_ID_LINK "${target}-unknown-fuchsia") endforeach() - set(LLVM_RUNTIME_MULTILIBS "asan;noexcept;asan+noexcept" CACHE STRING "") + set(LLVM_RUNTIME_MULTILIBS "asan;noexcept;asan+noexcept;relative-vtables;relative-vtables+noexcept" CACHE STRING "") set(LLVM_RUNTIME_MULTILIB_asan_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") set(LLVM_RUNTIME_MULTILIB_noexcept_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") set(LLVM_RUNTIME_MULTILIB_asan+noexcept_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") + set(LLVM_RUNTIME_MULTILIB_relative-vtables_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") + set(LLVM_RUNTIME_MULTILIB_relative-vtables+noexcept_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") endif() set(LLVM_BUILTIN_TARGETS "${BUILTIN_TARGETS}" CACHE STRING "") @@ -235,6 +245,7 @@ set(LLVM_TOOLCHAIN_TOOLS llvm-dlltool llvm-dwarfdump llvm-dwp + llvm-elfabi llvm-gsymutil llvm-lib llvm-mt diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index 3674f3a62695ce7574f0a84175ba852b3809220f..b46008970f578becb7530a60be36e80ce12e1acd 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -2663,6 +2663,10 @@ Align selected branches (fused, jcc, jmp) within 32-byte boundary Legacy option to specify code object ABI V2 (-mnocode-object-v3) or V3 (-mcode-object-v3) (AMDGPU only) +.. option:: -mcode-object-version= + +Specify code object ABI version. Defaults to 4. (AMDGPU only) + .. option:: -mconsole .. program:: clang1 @@ -3169,8 +3173,6 @@ PowerPC .. option:: -mpower9-vector, -mno-power9-vector -.. option:: -mqpx, -mno-qpx - .. option:: -msecure-plt .. option:: -mspe, -mno-spe diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index ccc59cd6fc195996b69548aa3f8b80047f7f96e9..f63ed168f09918e84cb58b4ee130933d2a67c7da 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1382,6 +1382,18 @@ the configuration (without a prefix: ``Auto``). +**BreakBeforeConceptDeclarations** (``bool``) + If ``true``, concept will be placed on a new line. + + .. code-block:: c++ + + true: + template + concept ... + + false: + template concept ... + **BreakBeforeTernaryOperators** (``bool``) If ``true``, ternary operators will be placed after line breaks. @@ -1701,11 +1713,14 @@ the configuration (without a prefix: ``Auto``). always need to be first. There is a third and optional field ``SortPriority`` which can used while - ``IncludeBloks = IBS_Regroup`` to define the priority in which ``#includes`` - should be ordered, and value of ``Priority`` defines the order of - ``#include blocks`` and also enables to group ``#includes`` of different - priority for order.``SortPriority`` is set to the value of ``Priority`` - as default if it is not assigned. + ``IncludeBlocks = IBS_Regroup`` to define the priority in which + ``#includes`` should be ordered. The value of ``Priority`` defines the + order of ``#include blocks`` and also allows the grouping of ``#includes`` + of different priority. ``SortPriority`` is set to the value of + ``Priority`` as default if it is not assigned. + + Each regular expression can be marked as case sensitive with the field + ``CaseSensitive``, per default it is not. To configure this in the .clang-format file, use: @@ -1715,6 +1730,7 @@ the configuration (without a prefix: ``Auto``). - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 SortPriority: 2 + CaseSensitive: true - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 - Regex: '<[[:alnum:].]+>' @@ -1901,6 +1917,49 @@ the configuration (without a prefix: ``Auto``). +**IndentPragmas** (``bool``) + Indent pragmas + + When ``false``, pragmas are flushed left or follow IndentPPDirectives. + When ``true``, pragmas are indented to the current scope level. + + .. code-block:: c++ + + false: true: + #pragma once vs #pragma once + void foo() { void foo() { + #pragma omp simd #pragma omp simd + for (int i=0;i<10;i++) { for (int i=0;i<10;i++) { + #pragma omp simd #pragma omp simd + for (int i=0;i<10;i++) { for (int i=0;i<10;i++) { + } } + #if 1 #if 1 + #pragma omp simd #pragma omp simd + for (int i=0;i<10;i++) { for (int i=0;i<10;i++) { + } } + #endif #endif + } } + } } + +**IndentRequires** (``bool``) + Indent the requires clause in a template + + .. code-block:: c++ + + true: + template + requires Iterator + void sort(It begin, It end) { + //.... + } + + false: + template + requires Iterator + void sort(It begin, It end) { + //.... + } + **IndentWidth** (``unsigned``) The number of columns to use for indentation. @@ -2301,6 +2360,10 @@ the configuration (without a prefix: ``Auto``). **PenaltyExcessCharacter** (``unsigned``) The penalty for each character outside of the column limit. +**PenaltyIndentedWhitespace** (``unsigned``) + Penalty for each character of whitespace indentation + (counted relative to leading non-whitespace column). + **PenaltyReturnTypeOnItsOwnLine** (``unsigned``) Penalty for putting the return type of a function onto its own line. diff --git a/clang/docs/ClangFormattedStatus.rst b/clang/docs/ClangFormattedStatus.rst index 3e348eadd4ffa7c633fc6f92f6029d23b673a39b..108351c169313d28e425047cb64e07cff5b865ff 100644 --- a/clang/docs/ClangFormattedStatus.rst +++ b/clang/docs/ClangFormattedStatus.rst @@ -17,7 +17,7 @@ Clang Formatted Status ====================== :doc:`ClangFormattedStatus` describes the state of LLVM source -tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 (`eb50838ba08 `_). +tree in terms of conformance to :doc:`ClangFormat` as of: December 04, 2020 17:56:14 (`840e651dc6d `_). .. list-table:: LLVM Clang-Format Status @@ -49,6 +49,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` + * - clang/examples/CallSuperAttribute + - `1` + - `1` + - `0` + - :good:`100%` * - clang/examples/clang-interpreter - `1` - `0` @@ -60,10 +65,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - clang/include/clang/Analysis - - `14` - - `3` + - `15` + - `4` - `11` - - :part:`21%` + - :part:`26%` * - clang/include/clang/Analysis/Analyses - `14` - `2` @@ -84,30 +89,35 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` + * - clang/include/clang/APINotes + - `2` + - `2` + - `0` + - :good:`100%` * - clang/include/clang/ARCMigrate - `3` - `0` - `3` - :none:`0%` * - clang/include/clang/AST - - `113` - - `20` + - `114` + - `21` - `93` - - :part:`17%` + - :part:`18%` * - clang/include/clang/ASTMatchers - `5` - - `1` - - `4` - - :part:`20%` + - `0` + - `5` + - :none:`0%` * - clang/include/clang/ASTMatchers/Dynamic - `4` - `1` - `3` - :part:`25%` * - clang/include/clang/Basic - - `76` - - `26` - - `50` + - `78` + - `27` + - `51` - :part:`34%` * - clang/include/clang/CodeGen - `9` @@ -126,9 +136,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - clang/include/clang/Driver - `17` - - `4` - - `13` - - :part:`23%` + - `5` + - `12` + - :part:`29%` * - clang/include/clang/Edit - `5` - `1` @@ -154,6 +164,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - `5` - :part:`28%` + * - clang/include/clang/IndexSerialization + - `1` + - `1` + - `0` + - :good:`100%` * - clang/include/clang/Lex - `29` - `4` @@ -201,17 +216,17 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`25%` * - clang/include/clang/StaticAnalyzer/Core/PathSensitive - `36` - - `9` - - `27` - - :part:`25%` + - `10` + - `26` + - :part:`27%` * - clang/include/clang/StaticAnalyzer/Frontend - `5` - - `3` - `2` - - :part:`60%` + - `3` + - :part:`40%` * - clang/include/clang/Testing - - `1` - - `1` + - `2` + - `2` - `0` - :good:`100%` * - clang/include/clang/Tooling @@ -225,10 +240,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - clang/include/clang/Tooling/Core - - `3` - - `1` - `2` - - :part:`33%` + - `0` + - `2` + - :none:`0%` * - clang/include/clang/Tooling/DependencyScanning - `5` - `4` @@ -240,10 +255,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - :none:`0%` * - clang/include/clang/Tooling/Refactoring - - `14` - - `12` + - `15` + - `13` - `2` - - :part:`85%` + - :part:`86%` * - clang/include/clang/Tooling/Refactoring/Extract - `2` - `1` @@ -265,20 +280,20 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`87%` * - clang/include/clang-c - - `9` + - `10` - `3` - - `6` - - :part:`33%` + - `7` + - :part:`30%` * - clang/INPUTS - `2` - `0` - `2` - :none:`0%` * - clang/lib/Analysis - - `25` - - `2` + - `26` + - `3` - `23` - - :part:`8%` + - :part:`11%` * - clang/lib/Analysis/plugins/CheckerDependencyHandling - `1` - `1` @@ -294,6 +309,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` + * - clang/lib/APINotes + - `2` + - `2` + - `0` + - :good:`100%` * - clang/lib/ARCMigrate - `22` - `0` @@ -320,20 +340,20 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `5` - :part:`16%` * - clang/lib/Basic - - `34` - - `8` - - `26` - - :part:`23%` + - `35` + - `10` + - `25` + - :part:`28%` * - clang/lib/Basic/Targets - `48` - - `23` - - `25` - - :part:`47%` + - `24` + - `24` + - :part:`50%` * - clang/lib/CodeGen - - `87` - - `8` - - `79` - - :part:`9%` + - `91` + - `11` + - `80` + - :part:`12%` * - clang/lib/CrossTU - `1` - `0` @@ -366,14 +386,14 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :none:`0%` * - clang/lib/Driver - `16` - - `2` - - `14` - - :part:`12%` + - `3` + - `13` + - :part:`18%` * - clang/lib/Driver/ToolChains - - `83` - - `27` + - `85` + - `29` - `56` - - :part:`32%` + - :part:`34%` * - clang/lib/Driver/ToolChains/Arch - `18` - `4` @@ -385,8 +405,8 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - :none:`0%` * - clang/lib/Format - - `29` - - `29` + - `31` + - `31` - `0` - :good:`100%` * - clang/lib/Format/old @@ -410,13 +430,13 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - clang/lib/Headers - - `129` + - `136` - `12` - - `117` - - :part:`9%` + - `124` + - :part:`8%` * - clang/lib/Headers/openmp_wrappers - - `3` - - `3` + - `5` + - `5` - `0` - :good:`100%` * - clang/lib/Headers/ppc_wrappers @@ -429,6 +449,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - `10` - :part:`16%` + * - clang/lib/IndexSerialization + - `1` + - `1` + - `0` + - :good:`100%` * - clang/lib/Lex - `23` - `1` @@ -436,9 +461,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`4%` * - clang/lib/Parse - `15` - - `0` - - `15` - - :none:`0%` + - `1` + - `14` + - :part:`6%` * - clang/lib/Rewrite - `5` - `0` @@ -455,10 +480,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `16` - :part:`5%` * - clang/lib/StaticAnalyzer/Checkers - - `115` - - `13` - - `102` - - :part:`11%` + - `117` + - `16` + - `101` + - :part:`13%` * - clang/lib/StaticAnalyzer/Checkers/cert - `1` - `1` @@ -480,15 +505,15 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - :part:`33%` * - clang/lib/StaticAnalyzer/Checkers/WebKit + - `10` - `8` - - `6` - `2` - - :part:`75%` + - :part:`80%` * - clang/lib/StaticAnalyzer/Core - `46` - - `8` - - `38` - - :part:`17%` + - `9` + - `37` + - :part:`19%` * - clang/lib/StaticAnalyzer/Frontend - `8` - `3` @@ -510,10 +535,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - clang/lib/Tooling/Core - - `3` - - `1` - `2` - - :part:`33%` + - `0` + - `2` + - :none:`0%` * - clang/lib/Tooling/DependencyScanning - `5` - `2` @@ -525,10 +550,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - clang/lib/Tooling/Refactoring - - `4` - - `2` + - `5` + - `3` - `2` - - :part:`50%` + - :part:`60%` * - clang/lib/Tooling/Refactoring/Extract - `2` - `1` @@ -541,14 +566,19 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`40%` * - clang/lib/Tooling/Syntax - `7` - - `6` - - `1` - - :part:`85%` + - `7` + - `0` + - :good:`100%` * - clang/lib/Tooling/Transformer - `7` - `4` - `3` - :part:`57%` + * - clang/tools/apinotes-test + - `1` + - `1` + - `0` + - :good:`100%` * - clang/tools/arcmt-test - `1` - `0` @@ -660,9 +690,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - :part:`25%` * - clang/tools/libclang - - `34` + - `35` - `6` - - `28` + - `29` - :part:`17%` * - clang/tools/scan-build-py/tests/functional/src/include - `1` @@ -681,24 +711,24 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`22%` * - clang/unittests/ASTMatchers - `6` - - `0` - - `6` - - :none:`0%` + - `3` + - `3` + - :part:`50%` * - clang/unittests/ASTMatchers/Dynamic - `3` - `0` - `3` - :none:`0%` * - clang/unittests/Basic - - `5` - - `1` + - `6` + - `2` - `4` - - :part:`20%` + - :part:`33%` * - clang/unittests/CodeGen - - `5` - - `0` - - `5` - - :none:`0%` + - `7` + - `1` + - `6` + - :part:`14%` * - clang/unittests/CrossTU - `1` - `1` @@ -715,15 +745,15 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `4` - :part:`20%` * - clang/unittests/Format - - `18` - - `17` + - `21` + - `20` - `1` - - :part:`94%` + - :part:`95%` * - clang/unittests/Frontend - - `9` - - `5` + - `10` + - `6` - `4` - - :part:`55%` + - :part:`60%` * - clang/unittests/Index - `1` - `1` @@ -765,23 +795,23 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - clang/unittests/StaticAnalyzer - - `11` - - `4` + - `12` + - `5` - `7` - - :part:`36%` + - :part:`41%` * - clang/unittests/Tooling - `29` - - `7` - - `22` - - :part:`24%` + - `8` + - `21` + - :part:`27%` * - clang/unittests/Tooling/RecursiveASTVisitorTests - - `23` - - `9` - - `14` - - :part:`39%` + - `30` + - `13` + - `17` + - :part:`43%` * - clang/unittests/Tooling/Syntax - - `2` - - `2` + - `7` + - `7` - `0` - :good:`100%` * - clang/utils/perf-training/cxx @@ -790,10 +820,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - clang/utils/TableGen - - `20` - - `2` + - `21` + - `3` - `18` - - :part:`10%` + - :part:`14%` * - clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling - `1` - `1` @@ -866,9 +896,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - clang-tools-extra/clang-query - `5` - - `3` - - `2` - - :part:`60%` + - `4` + - `1` + - :part:`80%` * - clang-tools-extra/clang-query/tool - `1` - `1` @@ -886,14 +916,19 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :none:`0%` * - clang-tools-extra/clang-tidy - `18` - - `10` - - `8` - - :part:`55%` + - `11` + - `7` + - :part:`61%` * - clang-tools-extra/clang-tidy/abseil - `40` - `28` - `12` - :part:`70%` + * - clang-tools-extra/clang-tidy/altera + - `5` + - `3` + - `2` + - :part:`60%` * - clang-tools-extra/clang-tidy/android - `33` - `23` @@ -905,20 +940,25 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - clang-tools-extra/clang-tidy/bugprone - - `105` - - `85` - - `20` - - :part:`80%` + - `111` + - `89` + - `22` + - :part:`80%` * - clang-tools-extra/clang-tidy/cert - `29` - `27` - `2` - :part:`93%` - * - clang-tools-extra/clang-tidy/cppcoreguidelines - - `41` - - `38` + * - clang-tools-extra/clang-tidy/concurrency - `3` - - :part:`92%` + - `2` + - `1` + - :part:`66%` + * - clang-tools-extra/clang-tidy/cppcoreguidelines + - `43` + - `39` + - `4` + - :part:`90%` * - clang-tools-extra/clang-tidy/darwin - `5` - `2` @@ -930,15 +970,15 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `6` - :part:`60%` * - clang-tools-extra/clang-tidy/google - - `35` - - `23` - - `12` - - :part:`65%` + - `33` + - `22` + - `11` + - :part:`66%` * - clang-tools-extra/clang-tidy/hicpp - `9` - - `6` - - `3` - - :part:`66%` + - `7` + - `2` + - :part:`77%` * - clang-tools-extra/clang-tidy/linuxkernel - `3` - `2` @@ -961,9 +1001,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`86%` * - clang-tools-extra/clang-tidy/modernize - `67` - - `46` - - `21` - - :part:`68%` + - `48` + - `19` + - :part:`71%` * - clang-tools-extra/clang-tidy/mpi - `5` - `4` @@ -981,9 +1021,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - clang-tools-extra/clang-tidy/performance - `29` - - `24` - - `5` - - :part:`82%` + - `22` + - `7` + - :part:`75%` * - clang-tools-extra/clang-tidy/plugin - `1` - `1` @@ -995,9 +1035,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - :part:`60%` * - clang-tools-extra/clang-tidy/readability - - `77` - - `63` - - `14` + - `79` + - `64` + - `15` - :part:`81%` * - clang-tools-extra/clang-tidy/tool - `3` @@ -1005,35 +1045,40 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`66%` * - clang-tools-extra/clang-tidy/utils - - `33` - - `26` + - `35` + - `28` - `7` - - :part:`78%` + - :part:`80%` * - clang-tools-extra/clang-tidy/zircon - `3` - `3` - `0` - :good:`100%` * - clang-tools-extra/clangd - - `75` - - `58` - - `17` - - :part:`77%` + - `84` + - `70` + - `14` + - :part:`83%` * - clang-tools-extra/clangd/benchmarks - `1` - `1` - `0` - :good:`100%` + * - clang-tools-extra/clangd/benchmarks/CompletionModel + - `1` + - `1` + - `0` + - :good:`100%` * - clang-tools-extra/clangd/fuzzer - `2` - `2` - `0` - :good:`100%` * - clang-tools-extra/clangd/index - - `37` - - `34` + - `39` + - `36` - `3` - - :part:`91%` + - :part:`92%` * - clang-tools-extra/clangd/index/dex - `9` - `8` @@ -1075,33 +1120,38 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - clang-tools-extra/clangd/refactor/tweaks - - `13` - - `10` + - `14` + - `11` - `3` - - :part:`76%` + - :part:`78%` * - clang-tools-extra/clangd/support - - `18` - - `18` + - `22` + - `22` - `0` - :good:`100%` * - clang-tools-extra/clangd/tool + - `2` + - `2` + - `0` + - :good:`100%` + * - clang-tools-extra/clangd/unittests + - `75` + - `65` + - `10` + - :part:`86%` + * - clang-tools-extra/clangd/unittests/decision_forest_model - `1` - `1` - `0` - :good:`100%` - * - clang-tools-extra/clangd/unittests - - `64` - - `52` - - `12` - - :part:`81%` * - clang-tools-extra/clangd/unittests/remote - `1` - `1` - `0` - :good:`100%` * - clang-tools-extra/clangd/unittests/support - - `8` - - `8` + - `10` + - `10` - `0` - :good:`100%` * - clang-tools-extra/clangd/unittests/xpc @@ -1175,10 +1225,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - :none:`0%` * - clang-tools-extra/unittests/clang-tidy - - `14` - - `6` + - `15` + - `7` - `8` - - :part:`42%` + - :part:`46%` * - clang-tools-extra/unittests/include/common - `1` - `0` @@ -1190,10 +1240,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - compiler-rt/include/sanitizer - - `14` - - `1` + - `15` + - `2` - `13` - - :part:`7%` + - :part:`13%` * - compiler-rt/include/xray - `3` - `2` @@ -1236,14 +1286,14 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :none:`0%` * - compiler-rt/lib/dfsan - `5` - - `0` - - `5` - - :none:`0%` + - `1` + - `4` + - :part:`20%` * - compiler-rt/lib/fuzzer - - `43` - - `5` + - `45` + - `7` - `38` - - :part:`11%` + - :part:`15%` * - compiler-rt/lib/fuzzer/afl - `1` - `0` @@ -1260,18 +1310,18 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`50%` * - compiler-rt/lib/gwp_asan - - `14` - `13` - - `1` - - :part:`92%` + - `13` + - `0` + - :good:`100%` * - compiler-rt/lib/gwp_asan/optional - - `7` - - `7` + - `9` + - `9` - `0` - :good:`100%` * - compiler-rt/lib/gwp_asan/platform_specific - - `4` - - `4` + - `13` + - `13` - `0` - :good:`100%` * - compiler-rt/lib/gwp_asan/tests @@ -1304,6 +1354,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `7` - `13` - :part:`35%` + * - compiler-rt/lib/memprof + - `27` + - `27` + - `0` + - :good:`100%` * - compiler-rt/lib/msan - `18` - `4` @@ -1325,10 +1380,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - :part:`33%` * - compiler-rt/lib/sanitizer_common - - `159` - - `23` - - `136` - - :part:`14%` + - `160` + - `29` + - `131` + - :part:`18%` * - compiler-rt/lib/sanitizer_common/symbolizer - `2` - `2` @@ -1336,19 +1391,19 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - compiler-rt/lib/sanitizer_common/tests - `38` - - `1` - - `37` - - :part:`2%` + - `2` + - `36` + - :part:`5%` * - compiler-rt/lib/scudo - `20` - `0` - `20` - :none:`0%` * - compiler-rt/lib/scudo/standalone - - `46` - - `42` - - `4` - - :part:`91%` + - `47` + - `44` + - `3` + - :part:`93%` * - compiler-rt/lib/scudo/standalone/benchmarks - `1` - `1` @@ -1465,18 +1520,18 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - debuginfo-tests/dexter-tests - - `8` + - `11` - `3` - - `5` - - :part:`37%` + - `8` + - :part:`27%` * - debuginfo-tests/llgdb-tests - `7` - `0` - `7` - :none:`0%` * - debuginfo-tests/llvm-prettyprinters/gdb - - `1` - - `1` + - `2` + - `2` - `0` - :good:`100%` * - flang/include/flang @@ -1486,9 +1541,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - flang/include/flang/Common - `19` - - `19` - - `0` - - :good:`100%` + - `17` + - `2` + - :part:`89%` * - flang/include/flang/Decimal - `2` - `2` @@ -1496,14 +1551,24 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - flang/include/flang/Evaluate - `23` - - `23` + - `20` + - `3` + - :part:`86%` + * - flang/include/flang/Frontend + - `8` + - `8` - `0` - :good:`100%` - * - flang/include/flang/Lower - - `13` - - `12` + * - flang/include/flang/FrontendTool - `1` - - :part:`92%` + - `1` + - `0` + - :good:`100%` + * - flang/include/flang/Lower + - `18` + - `18` + - `0` + - :good:`100%` * - flang/include/flang/Lower/Support - `1` - `1` @@ -1516,24 +1581,29 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - flang/include/flang/Optimizer/Dialect - `5` - - `5` - - `0` - - :good:`100%` + - `3` + - `2` + - :part:`60%` * - flang/include/flang/Optimizer/Support - `2` - `2` - `0` - :good:`100%` - * - flang/include/flang/Parser - - `17` - - `17` + * - flang/include/flang/Optimizer/Transforms + - `1` + - `1` - `0` - :good:`100%` + * - flang/include/flang/Parser + - `17` + - `13` + - `4` + - :part:`76%` * - flang/include/flang/Semantics - `8` - - `8` - - `0` - - :good:`100%` + - `5` + - `3` + - :part:`62%` * - flang/lib/Common - `4` - `4` @@ -1545,45 +1615,60 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - flang/lib/Evaluate - - `32` - - `32` + - `31` + - `29` + - `2` + - :part:`93%` + * - flang/lib/Frontend + - `8` + - `7` + - `1` + - :part:`87%` + * - flang/lib/FrontendTool + - `1` + - `1` - `0` - :good:`100%` * - flang/lib/Lower - - `10` - - `9` - - `1` - - :part:`90%` - * - flang/lib/Optimizer/Dialect - - `4` - - `4` + - `16` + - `16` - `0` - :good:`100%` + * - flang/lib/Optimizer/Dialect + - `4` + - `2` + - `2` + - :part:`50%` * - flang/lib/Optimizer/Support - `2` - `2` - `0` - :good:`100%` - * - flang/lib/Parser - - `34` - - `34` + * - flang/lib/Optimizer/Transforms + - `1` + - `1` - `0` - :good:`100%` + * - flang/lib/Parser + - `35` + - `33` + - `2` + - :part:`94%` * - flang/lib/Semantics - - `68` - - `65` - - `3` - - :part:`95%` + - `77` + - `69` + - `8` + - :part:`89%` * - flang/module - `1` - - `0` - `1` - - :none:`0%` - * - flang/runtime - - `56` - - `56` - `0` - :good:`100%` + * - flang/runtime + - `59` + - `54` + - `5` + - :part:`91%` * - flang/tools/f18 - `2` - `2` @@ -1594,6 +1679,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - `0` - :good:`100%` + * - flang/tools/flang-driver + - `2` + - `2` + - `0` + - :good:`100%` * - flang/tools/tco - `1` - `1` @@ -1606,7 +1696,12 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - flang/unittests/Evaluate - `15` - - `15` + - `14` + - `1` + - :part:`93%` + * - flang/unittests/Frontend + - `3` + - `3` - `0` - :good:`100%` * - flang/unittests/Optimizer @@ -1615,8 +1710,8 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - flang/unittests/Runtime - - `7` - - `7` + - `8` + - `8` - `0` - :good:`100%` * - libc/AOR_v20.02/math @@ -1650,18 +1745,28 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - libc/benchmarks - - `14` - - `14` + - `16` + - `16` + - `0` + - :good:`100%` + * - libc/config/linux + - `1` + - `1` + - `0` + - :good:`100%` + * - libc/fuzzing/math + - `5` + - `5` - `0` - :good:`100%` * - libc/fuzzing/string + - `3` - `2` - `1` - - `1` - - :part:`50%` + - :part:`66%` * - libc/include - - `4` - - `4` + - `3` + - `3` - `0` - :good:`100%` * - libc/loader/linux/x86_64 @@ -1670,18 +1775,28 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - libc/src/assert + - `3` + - `1` - `2` + - :part:`33%` + * - libc/src/ctype + - `29` + - `29` - `0` - - `2` - - :none:`0%` + - :good:`100%` * - libc/src/errno - - `2` - - `2` + - `3` + - `3` + - `0` + - :good:`100%` + * - libc/src/fenv + - `10` + - `10` - `0` - :good:`100%` * - libc/src/math - - `70` - - `70` + - `122` + - `122` - `0` - :good:`100%` * - libc/src/signal @@ -1710,10 +1825,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - libc/src/string - - `14` - - `13` - - `1` - - :part:`92%` + - `39` + - `39` + - `0` + - :good:`100%` * - libc/src/string/memory_utils - `3` - `3` @@ -1744,6 +1859,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `7` - `0` - :good:`100%` + * - libc/src/time + - `2` + - `2` + - `0` + - :good:`100%` * - libc/src/unistd - `1` - `1` @@ -1760,8 +1880,13 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - libc/utils/FPUtil - - `9` - - `9` + - `18` + - `18` + - `0` + - :good:`100%` + * - libc/utils/FPUtil/x86_64 + - `1` + - `1` - `0` - :good:`100%` * - libc/utils/HdrGen @@ -1774,6 +1899,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` + * - libc/utils/LibcTableGenUtil + - `2` + - `2` + - `0` + - :good:`100%` * - libc/utils/MPFRWrapper - `3` - `2` @@ -1784,9 +1914,14 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `6` - `0` - :good:`100%` + * - libc/utils/tools/WrapperGen + - `1` + - `1` + - `0` + - :good:`100%` * - libc/utils/UnitTest - - `3` - - `3` + - `2` + - `2` - `0` - :good:`100%` * - libclc/generic/include @@ -1930,15 +2065,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - libcxx/benchmarks - - `16` - - `1` + - `21` + - `6` - `15` - - :part:`6%` - * - libcxx/fuzzing - - `4` - - `0` - - `4` - - :none:`0%` + - :part:`28%` * - libcxx/include - `21` - `0` @@ -1955,10 +2085,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - libcxx/include/support/ibm - - `4` + - `5` - `1` - - `3` - - :part:`25%` + - `4` + - :part:`20%` * - libcxx/include/support/musl - `1` - `0` @@ -1969,6 +2099,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` + * - libcxx/include/support/nuttx + - `1` + - `1` + - `0` + - :good:`100%` * - libcxx/include/support/solaris - `3` - `2` @@ -1985,9 +2120,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - :none:`0%` * - libcxx/src - - `35` + - `37` - `1` - - `34` + - `36` - :part:`2%` * - libcxx/src/experimental - `1` @@ -1996,9 +2131,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :none:`0%` * - libcxx/src/filesystem - `4` - - `2` - - `2` - - :part:`50%` + - `1` + - `3` + - :part:`25%` * - libcxx/src/include - `4` - `2` @@ -2040,19 +2175,19 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - :none:`0%` * - libcxxabi/src - - `26` - - `1` - `25` - - :part:`3%` + - `0` + - `25` + - :none:`0%` * - libcxxabi/src/demangle - `4` - `2` - `2` - :part:`50%` * - libcxxabi/src/include - - `2` + - `1` - `0` - - `2` + - `1` - :none:`0%` * - libunwind/include - `3` @@ -2070,20 +2205,20 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `9` - :none:`0%` * - lld/COFF - - `33` - - `10` - - `23` - - :part:`30%` + - `35` + - `11` + - `24` + - :part:`31%` * - lld/Common - `10` - - `9` - - `1` - - :part:`90%` + - `8` + - `2` + - :part:`80%` * - lld/ELF - `48` - - `26` - - `22` - - :part:`54%` + - `25` + - `23` + - :part:`52%` * - lld/ELF/Arch - `14` - `7` @@ -2130,10 +2265,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - lld/MachO - - `26` - - `26` - - `0` - - :good:`100%` + - `35` + - `31` + - `4` + - :part:`88%` * - lld/MachO/Arch - `1` - `1` @@ -2160,10 +2295,15 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `4` - :none:`0%` * - lld/wasm - - `27` - - `14` + - `29` + - `16` - `13` - - :part:`51%` + - :part:`55%` + * - lldb/bindings/python + - `1` + - `1` + - `0` + - :good:`100%` * - lldb/examples/darwin/heap_find/heap - `1` - `1` @@ -2196,34 +2336,34 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - lldb/include/lldb - `12` - - `7` - - `5` - - :part:`58%` + - `6` + - `6` + - :part:`50%` * - lldb/include/lldb/API - `71` - `59` - `12` - :part:`83%` * - lldb/include/lldb/Breakpoint - - `24` - - `10` - - `14` - - :part:`41%` + - `25` + - `9` + - `16` + - :part:`36%` * - lldb/include/lldb/Core - `57` - - `31` - - `26` - - :part:`54%` + - `30` + - `27` + - :part:`52%` * - lldb/include/lldb/DataFormatters - `18` - - `9` - - `9` - - :part:`50%` + - `10` + - `8` + - :part:`55%` * - lldb/include/lldb/Expression - `17` - - `6` - - `11` - - :part:`35%` + - `7` + - `10` + - :part:`41%` * - lldb/include/lldb/Host - `40` - `20` @@ -2281,24 +2421,24 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`33%` * - lldb/include/lldb/Interpreter - `47` - - `38` - - `9` - - :part:`80%` + - `39` + - `8` + - :part:`82%` * - lldb/include/lldb/Symbol - `36` - - `16` - - `20` - - :part:`44%` + - `17` + - `19` + - :part:`47%` * - lldb/include/lldb/Target - - `66` - - `37` + - `72` + - `43` - `29` - - :part:`56%` + - :part:`59%` * - lldb/include/lldb/Utility - - `58` - - `36` - - `22` - - :part:`62%` + - `61` + - `40` + - `21` + - :part:`65%` * - lldb/source - `1` - `1` @@ -2306,19 +2446,19 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - lldb/source/API - `75` - - `8` - - `67` - - :part:`10%` + - `7` + - `68` + - :part:`9%` * - lldb/source/Breakpoint - `24` - - `6` - - `18` - - :part:`25%` + - `5` + - `19` + - :part:`20%` * - lldb/source/Commands - - `56` - - `48` + - `66` + - `58` - `8` - - :part:`85%` + - :part:`87%` * - lldb/source/Core - `45` - `24` @@ -2351,14 +2491,19 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - lldb/source/Host/linux - `5` - - `3` - - `2` - - :part:`60%` + - `4` + - `1` + - :part:`80%` * - lldb/source/Host/macosx/cfcpp - `14` - `12` - `2` - :part:`85%` + * - lldb/source/Host/macosx/objcxx + - `1` + - `1` + - `0` + - :good:`100%` * - lldb/source/Host/netbsd - `2` - `0` @@ -2385,10 +2530,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - lldb/source/Interpreter - - `46` - - `25` - - `21` - - :part:`54%` + - `44` + - `23` + - `21` + - :part:`52%` * - lldb/source/Plugins/ABI/AArch64 - `6` - `2` @@ -2486,9 +2631,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`50%` * - lldb/source/Plugins/ExpressionParser/Clang - `51` - - `25` - `26` - - :part:`49%` + - `25` + - :part:`50%` * - lldb/source/Plugins/Instruction/ARM - `4` - `2` @@ -2619,6 +2764,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `2` - :none:`0%` + * - lldb/source/Plugins/ObjectFile/PDB + - `2` + - `2` + - `0` + - :good:`100%` * - lldb/source/Plugins/ObjectFile/PECOFF - `6` - `3` @@ -2655,10 +2805,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`50%` * - lldb/source/Plugins/Platform/MacOSX - - `24` - - `10` - - `14` - - :part:`41%` + - `20` + - `11` + - `9` + - :part:`55%` * - lldb/source/Plugins/Platform/MacOSX/objcxx - `1` - `1` @@ -2694,16 +2844,21 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `11` - `8` - :part:`57%` + * - lldb/source/Plugins/Process/FreeBSDRemote + - `8` + - `8` + - `0` + - :good:`100%` * - lldb/source/Plugins/Process/gdb-remote - `26` - `16` - `10` - :part:`61%` * - lldb/source/Plugins/Process/Linux - - `24` - - `12` + - `23` + - `11` - `12` - - :part:`50%` + - :part:`47%` * - lldb/source/Plugins/Process/mach-core - `4` - `3` @@ -2721,24 +2876,24 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`58%` * - lldb/source/Plugins/Process/NetBSD - `8` - - `3` - - `5` - - :part:`37%` + - `4` + - `4` + - :part:`50%` * - lldb/source/Plugins/Process/POSIX - `8` - `5` - `3` - :part:`62%` * - lldb/source/Plugins/Process/Utility - - `127` - - `86` + - `133` + - `92` - `41` - - :part:`67%` + - :part:`69%` * - lldb/source/Plugins/Process/Windows/Common - `34` - - `24` - - `10` - - :part:`70%` + - `23` + - `11` + - :part:`67%` * - lldb/source/Plugins/Process/Windows/Common/arm - `2` - `1` @@ -2761,9 +2916,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :none:`0%` * - lldb/source/Plugins/ScriptInterpreter/Lua - `4` - - `4` - - `0` - - :good:`100%` + - `3` + - `1` + - :part:`75%` * - lldb/source/Plugins/ScriptInterpreter/None - `2` - `2` @@ -2786,9 +2941,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :none:`0%` * - lldb/source/Plugins/SymbolFile/DWARF - `65` - - `35` - - `30` - - :part:`53%` + - `36` + - `29` + - :part:`55%` * - lldb/source/Plugins/SymbolFile/NativePDB - `20` - `11` @@ -2824,6 +2979,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `9` - :part:`10%` + * - lldb/source/Plugins/Trace/intel-pt + - `10` + - `10` + - `0` + - :good:`100%` * - lldb/source/Plugins/TypeSystem/Clang - `2` - `0` @@ -2845,15 +3005,15 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `14` - :part:`56%` * - lldb/source/Target - - `61` - - `28` + - `65` + - `32` - `33` - - :part:`45%` + - :part:`49%` * - lldb/source/Utility - - `54` - - `41` + - `57` + - `44` - `13` - - :part:`75%` + - :part:`77%` * - lldb/tools/argdumper - `1` - `1` @@ -2866,9 +3026,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - lldb/tools/debugserver/source - `49` - - `38` - - `11` - - :part:`77%` + - `39` + - `10` + - :part:`79%` * - lldb/tools/debugserver/source/MacOSX - `24` - `16` @@ -2891,14 +3051,14 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`90%` * - lldb/tools/debugserver/source/MacOSX/i386 - `3` - - `1` - - `2` - - :part:`33%` + - `0` + - `3` + - :none:`0%` * - lldb/tools/debugserver/source/MacOSX/x86_64 - `3` - - `1` - - `2` - - :part:`33%` + - `0` + - `3` + - :none:`0%` * - lldb/tools/driver - `4` - `4` @@ -2936,9 +3096,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`60%` * - lldb/tools/lldb-vscode - `19` - - `12` - - `7` - - :part:`63%` + - `18` + - `1` + - :part:`94%` * - lldb/unittests - `1` - `1` @@ -2955,13 +3115,13 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - lldb/unittests/Core + - `7` - `6` - - `5` - `1` - - :part:`83%` + - :part:`85%` * - lldb/unittests/DataFormatter - - `2` - - `2` + - `3` + - `3` - `0` - :good:`100%` * - lldb/unittests/debugserver @@ -3000,10 +3160,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - lldb/unittests/Interpreter + - `3` + - `1` - `2` - - `0` - - `2` - - :none:`0%` + - :part:`33%` * - lldb/unittests/Language/CLanguages - `1` - `1` @@ -3029,16 +3189,21 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` + * - lldb/unittests/ObjectFile/MachO + - `1` + - `0` + - `1` + - :none:`0%` * - lldb/unittests/ObjectFile/PECOFF - `1` - `0` - `1` - :none:`0%` * - lldb/unittests/Platform + - `2` - `1` - `1` - - `0` - - :good:`100%` + - :part:`50%` * - lldb/unittests/Platform/Android - `1` - `0` @@ -3050,10 +3215,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - lldb/unittests/Process/gdb-remote + - `7` - `6` - - `5` - `1` - - :part:`83%` + - :part:`85%` * - lldb/unittests/Process/Linux - `1` - `0` @@ -3074,11 +3239,16 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` - * - lldb/unittests/ScriptInterpreter/Lua - - `2` - - `2` + * - lldb/unittests/Process/Utility + - `3` + - `3` - `0` - :good:`100%` + * - lldb/unittests/ScriptInterpreter/Lua + - `2` + - `1` + - `1` + - :part:`50%` * - lldb/unittests/ScriptInterpreter/Python - `3` - `1` @@ -3195,8 +3365,8 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - :part:`50%` * - llvm/cmake - - `1` - - `1` + - `2` + - `2` - `0` - :good:`100%` * - llvm/examples/BrainF @@ -3246,29 +3416,19 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`50%` * - llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3 - `2` - - `0` - - `2` - - :none:`0%` + - `1` + - `1` + - :part:`50%` * - llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4 - `2` - `0` - `2` - :none:`0%` - * - llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5 - - `3` - - `0` - - `3` - - :none:`0%` - * - llvm/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server - - `1` - - `0` - - `1` - - :none:`0%` * - llvm/examples/Kaleidoscope/Chapter2 - `1` - - `0` - `1` - - :none:`0%` + - `0` + - :good:`100%` * - llvm/examples/Kaleidoscope/Chapter3 - `1` - `0` @@ -3374,6 +3534,21 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` + * - llvm/examples/OrcV2Examples/LLJITWithOptimizingIRTransform + - `1` + - `1` + - `0` + - :good:`100%` + * - llvm/examples/OrcV2Examples/LLJITWithTargetProcessControl + - `1` + - `1` + - `0` + - :good:`100%` + * - llvm/examples/OrcV2Examples/LLJITWithThinLTOSummaries + - `1` + - `0` + - `1` + - :none:`0%` * - llvm/examples/ParallelJIT - `1` - `0` @@ -3384,56 +3559,51 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` - * - llvm/examples/ThinLtoJIT - - `9` - - `8` - - `1` - - :part:`88%` * - llvm/include/llvm - `8` - `2` - `6` - :part:`25%` * - llvm/include/llvm/ADT - - `84` - - `24` - - `60` - - :part:`28%` + - `86` + - `25` + - `61` + - :part:`29%` * - llvm/include/llvm/Analysis - - `113` - - `34` - - `79` - - :part:`30%` + - `120` + - `40` + - `80` + - :part:`33%` * - llvm/include/llvm/Analysis/Utils + - `2` - `1` - - `0` - `1` - - :none:`0%` + - :part:`50%` * - llvm/include/llvm/AsmParser - `2` - `1` - `1` - :part:`50%` * - llvm/include/llvm/BinaryFormat - - `13` + - `14` - `9` - - `4` - - :part:`69%` - * - llvm/include/llvm/Bitcode - `5` - - `1` + - :part:`64%` + * - llvm/include/llvm/Bitcode + - `6` + - `2` - `4` - - :part:`20%` + - :part:`33%` * - llvm/include/llvm/Bitstream - `3` - `0` - `3` - :none:`0%` * - llvm/include/llvm/CodeGen - - `141` - - `32` - - `109` - - :part:`22%` + - `146` + - `38` + - `108` + - :part:`26%` * - llvm/include/llvm/CodeGen/GlobalISel - `27` - `10` @@ -3485,10 +3655,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `11` - :part:`45%` * - llvm/include/llvm/DebugInfo/PDB/Native - - `52` - - `34` - - `18` - - :part:`65%` + - `54` + - `35` + - `19` + - :part:`64%` * - llvm/include/llvm/DebugInfo/Symbolize - `3` - `0` @@ -3515,15 +3685,30 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - :part:`62%` * - llvm/include/llvm/ExecutionEngine/Orc - - `32` - - `11` - - `21` - - :part:`34%` + - `31` + - `19` + - `12` + - :part:`61%` * - llvm/include/llvm/ExecutionEngine/Orc/RPC + - `4` + - `1` - `3` + - :part:`25%` + * - llvm/include/llvm/ExecutionEngine/Orc/Shared + - `1` + - `1` - `0` + - :good:`100%` + * - llvm/include/llvm/ExecutionEngine/Orc/TargetProcess - `3` - - :none:`0%` + - `3` + - `0` + - :good:`100%` + * - llvm/include/llvm/FileCheck + - `1` + - `1` + - `0` + - :good:`100%` * - llvm/include/llvm/Frontend/OpenMP - `4` - `4` @@ -3534,11 +3719,16 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `6` - :none:`0%` + * - llvm/include/llvm/InterfaceStub + - `3` + - `3` + - `0` + - :good:`100%` * - llvm/include/llvm/IR - - `84` - - `15` - - `69` - - :part:`17%` + - `88` + - `22` + - `66` + - :part:`25%` * - llvm/include/llvm/IRReader - `1` - `0` @@ -3600,10 +3790,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `20` - :part:`33%` * - llvm/include/llvm/ObjectYAML - - `15` + - `16` - `13` - - `2` - - :part:`86%` + - `3` + - :part:`81%` * - llvm/include/llvm/Option - `5` - `1` @@ -3625,15 +3815,20 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`66%` * - llvm/include/llvm/Remarks + - `12` - `11` - - `10` - `1` - - :part:`90%` + - :part:`91%` * - llvm/include/llvm/Support - - `170` - - `50` - - `120` - - :part:`29%` + - `171` + - `53` + - `118` + - :part:`30%` + * - llvm/include/llvm/Support/FileSystem + - `1` + - `1` + - `0` + - :good:`100%` * - llvm/include/llvm/Support/Solaris/sys - `1` - `1` @@ -3645,10 +3840,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - llvm/include/llvm/TableGen - - `7` - - `1` + - `8` + - `2` - `6` - - :part:`14%` + - :part:`25%` * - llvm/include/llvm/Target - `5` - `1` @@ -3659,11 +3854,6 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - `1` - :part:`66%` - * - llvm/include/llvm/TextAPI/ELF - - `2` - - `0` - - `2` - - :none:`0%` * - llvm/include/llvm/TextAPI/MachO - `9` - `8` @@ -3694,36 +3884,41 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `4` - `0` - :good:`100%` - * - llvm/include/llvm/Transforms/InstCombine - - `2` + * - llvm/include/llvm/Transforms/HelloNew + - `1` + - `1` - `0` + - :good:`100%` + * - llvm/include/llvm/Transforms/InstCombine + - `3` + - `1` - `2` - - :none:`0%` + - :part:`33%` * - llvm/include/llvm/Transforms/Instrumentation - - `14` - - `8` + - `16` + - `10` - `6` - - :part:`57%` + - :part:`62%` * - llvm/include/llvm/Transforms/IPO - - `29` - - `19` - - `10` - - :part:`65%` + - `34` + - `23` + - `11` + - :part:`67%` * - llvm/include/llvm/Transforms/Scalar - - `61` - - `32` + - `71` + - `42` - `29` - - :part:`52%` + - :part:`59%` * - llvm/include/llvm/Transforms/Utils - - `57` - - `26` + - `66` + - `35` - `31` - - :part:`45%` + - :part:`53%` * - llvm/include/llvm/Transforms/Vectorize - `5` - - `1` - - `4` - - :part:`20%` + - `2` + - `3` + - :part:`40%` * - llvm/include/llvm/WindowsManifest - `1` - `1` @@ -3740,19 +3935,19 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - :part:`82%` * - llvm/include/llvm-c - - `26` - - `11` + - `27` + - `12` - `15` - - :part:`42%` + - :part:`44%` * - llvm/include/llvm-c/Transforms - `8` - `2` - `6` - :part:`25%` * - llvm/lib/Analysis - - `109` - - `33` - - `76` + - `114` + - `35` + - `79` - :part:`30%` * - llvm/lib/AsmParser - `6` @@ -3761,9 +3956,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`33%` * - llvm/lib/BinaryFormat - `11` - - `7` - - `4` - - :part:`63%` + - `8` + - `3` + - :part:`72%` * - llvm/lib/Bitcode/Reader - `7` - `2` @@ -3780,20 +3975,25 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - llvm/lib/CodeGen - - `196` - - `31` - - `165` - - :part:`15%` + - `200` + - `39` + - `161` + - :part:`19%` * - llvm/lib/CodeGen/AsmPrinter - - `42` - - `14` - - `28` - - :part:`33%` + - `43` + - `16` + - `27` + - :part:`37%` * - llvm/lib/CodeGen/GlobalISel - `24` - `8` - `16` - :part:`33%` + * - llvm/lib/CodeGen/LiveDebugValues + - `4` + - `2` + - `2` + - :part:`50%` * - llvm/lib/CodeGen/MIRParser - `4` - `1` @@ -3806,14 +4006,14 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`6%` * - llvm/lib/DebugInfo/CodeView - `40` - - `25` - - `15` - - :part:`62%` + - `24` + - `16` + - :part:`60%` * - llvm/lib/DebugInfo/DWARF - `28` - - `7` - - `21` - - :part:`25%` + - `8` + - `20` + - :part:`28%` * - llvm/lib/DebugInfo/GSYM - `11` - `1` @@ -3835,10 +4035,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - :part:`83%` * - llvm/lib/DebugInfo/PDB/Native - - `48` - - `36` - - `12` - - :part:`75%` + - `50` + - `37` + - `13` + - :part:`74%` * - llvm/lib/DebugInfo/Symbolize - `4` - `1` @@ -3885,15 +4085,20 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - :none:`0%` * - llvm/lib/ExecutionEngine/Orc - - `28` + - `26` - `15` - - `13` - - :part:`53%` - * - llvm/lib/ExecutionEngine/OrcError - - `2` + - `11` + - :part:`57%` + * - llvm/lib/ExecutionEngine/Orc/Shared + - `3` + - `3` - `0` + - :good:`100%` + * - llvm/lib/ExecutionEngine/Orc/TargetProcess - `2` - - :none:`0%` + - `2` + - `0` + - :good:`100%` * - llvm/lib/ExecutionEngine/PerfJITEvents - `1` - `0` @@ -3910,25 +4115,35 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `9` - :part:`10%` * - llvm/lib/Extensions - - `1` - `1` - `0` - - :good:`100%` + - `1` + - :none:`0%` + * - llvm/lib/FileCheck + - `2` + - `1` + - `1` + - :part:`50%` * - llvm/lib/Frontend/OpenMP - - `3` - `2` - `1` - - :part:`66%` + - `1` + - :part:`50%` * - llvm/lib/FuzzMutate - `5` - `2` - `3` - :part:`40%` + * - llvm/lib/InterfaceStub + - `3` + - `3` + - `0` + - :good:`100%` * - llvm/lib/IR - - `61` - - `11` + - `63` + - `13` - `50` - - :part:`18%` + - :part:`20%` * - llvm/lib/IRReader - `1` - `0` @@ -3980,15 +4195,15 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`85%` * - llvm/lib/Object - - `29` - - `10` - - `19` - - :part:`34%` + - `30` + - `12` + - `18` + - :part:`40%` * - llvm/lib/ObjectYAML - `22` - - `13` - - `9` - - :part:`59%` + - `11` + - `11` + - :part:`50%` * - llvm/lib/Option - `4` - `0` @@ -4001,9 +4216,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`66%` * - llvm/lib/ProfileData - `8` - - `2` - - `6` - - :part:`25%` + - `3` + - `5` + - :part:`37%` * - llvm/lib/ProfileData/Coverage - `3` - `0` @@ -4016,29 +4231,29 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`76%` * - llvm/lib/Support - `132` - - `44` - - `88` - - :part:`33%` + - `46` + - `86` + - :part:`34%` * - llvm/lib/Support/Unix - `1` - `0` - `1` - :none:`0%` * - llvm/lib/TableGen - - `11` + - `13` - `1` - - `10` - - :part:`9%` + - `12` + - :part:`7%` * - llvm/lib/Target - `5` - `0` - `5` - :none:`0%` * - llvm/lib/Target/AArch64 - - `59` - - `7` - - `52` - - :part:`11%` + - `58` + - `4` + - `54` + - :part:`6%` * - llvm/lib/Target/AArch64/AsmParser - `1` - `0` @@ -4050,10 +4265,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - :part:`25%` * - llvm/lib/Target/AArch64/GISel - - `9` - - `0` - - `9` - - :none:`0%` + - `12` + - `2` + - `10` + - :part:`16%` * - llvm/lib/Target/AArch64/MCTargetDesc - `21` - `6` @@ -4070,10 +4285,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - :none:`0%` * - llvm/lib/Target/AMDGPU - - `146` - - `12` - - `134` - - :part:`8%` + - `148` + - `17` + - `131` + - :part:`11%` * - llvm/lib/Target/AMDGPU/AsmParser - `1` - `0` @@ -4175,10 +4390,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`50%` * - llvm/lib/Target/BPF - - `28` - - `5` + - `30` + - `7` - `23` - - :part:`17%` + - :part:`23%` * - llvm/lib/Target/BPF/AsmParser - `1` - `0` @@ -4199,11 +4414,21 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `1` - :part:`50%` - * - llvm/lib/Target/Hexagon - - `77` + * - llvm/lib/Target/CSKY + - `2` + - `2` + - `0` + - :good:`100%` + * - llvm/lib/Target/CSKY/TargetInfo + - `2` - `2` + - `0` + - :good:`100%` + * - llvm/lib/Target/Hexagon + - `79` + - `4` - `75` - - :part:`2%` + - :part:`5%` * - llvm/lib/Target/Hexagon/AsmParser - `1` - `0` @@ -4315,9 +4540,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - llvm/lib/Target/PowerPC - - `53` + - `52` - `2` - - `51` + - `50` - :part:`3%` * - llvm/lib/Target/PowerPC/AsmParser - `1` @@ -4329,21 +4554,26 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` + * - llvm/lib/Target/PowerPC/GISel + - `7` + - `7` + - `0` + - :good:`100%` * - llvm/lib/Target/PowerPC/MCTargetDesc - `18` - - `2` - - `16` - - :part:`11%` + - `3` + - `15` + - :part:`16%` * - llvm/lib/Target/PowerPC/TargetInfo - `2` - `2` - `0` - :good:`100%` * - llvm/lib/Target/RISCV - - `31` - - `13` - - `18` - - :part:`41%` + - `32` + - `15` + - `17` + - :part:`46%` * - llvm/lib/Target/RISCV/AsmParser - `1` - `0` @@ -4420,10 +4650,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - llvm/lib/Target/VE - - `19` - - `15` + - `20` + - `16` - `4` - - :part:`78%` + - :part:`80%` * - llvm/lib/Target/VE/AsmParser - `1` - `1` @@ -4445,11 +4675,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`50%` * - llvm/lib/Target/WebAssembly - - `58` - - `40` - - `18` - - :part:`68%` - * - llvm/lib/Target/WebAssembly/AsmParser + - `60` + - `43` + - `17` + - :part:`71%` + * - llvm/lib/Target/WebAssembly/AsmParser - `1` - `0` - `1` @@ -4471,9 +4701,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - llvm/lib/Target/X86 - `75` - - `11` - - `64` - - :part:`14%` + - `12` + - `63` + - :part:`16%` * - llvm/lib/Target/X86/AsmParser - `3` - `0` @@ -4486,9 +4716,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :none:`0%` * - llvm/lib/Target/X86/MCTargetDesc - `25` - - `6` - - `19` - - :part:`24%` + - `5` + - `20` + - :part:`20%` * - llvm/lib/Target/X86/TargetInfo - `2` - `1` @@ -4519,11 +4749,6 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - `0` - :good:`100%` - * - llvm/lib/TextAPI/ELF - - `2` - - `1` - - `1` - - :part:`50%` * - llvm/lib/TextAPI/MachO - `11` - `8` @@ -4559,31 +4784,36 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` + * - llvm/lib/Transforms/HelloNew + - `1` + - `1` + - `0` + - :good:`100%` * - llvm/lib/Transforms/InstCombine - `16` - `1` - `15` - :part:`6%` * - llvm/lib/Transforms/Instrumentation - - `21` - - `3` - - `18` - - :part:`14%` - * - llvm/lib/Transforms/IPO - - `39` + - `22` - `5` - - `34` - - :part:`12%` + - `17` + - :part:`22%` + * - llvm/lib/Transforms/IPO + - `40` + - `7` + - `33` + - :part:`17%` * - llvm/lib/Transforms/ObjCARC - `15` - - `3` - - `12` - - :part:`20%` + - `4` + - `11` + - :part:`26%` * - llvm/lib/Transforms/Scalar - - `75` - - `10` + - `77` + - `12` - `65` - - :part:`13%` + - :part:`15%` * - llvm/lib/Transforms/Utils - `72` - `14` @@ -4735,10 +4965,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - :part:`25%` * - llvm/tools/llvm-elfabi - - `5` - - `2` - `3` - - :part:`40%` + - `3` + - `0` + - :good:`100%` * - llvm/tools/llvm-exegesis - `1` - `1` @@ -4765,10 +4995,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - llvm/tools/llvm-exegesis/lib/X86 + - `3` + - `2` - `1` - - `1` - - `0` - - :good:`100%` + - :part:`66%` * - llvm/tools/llvm-extract - `1` - `0` @@ -4799,11 +5029,21 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - `2` - :part:`50%` + * - llvm/tools/llvm-jitlink/llvm-jitlink-executor + - `1` + - `1` + - `0` + - :good:`100%` * - llvm/tools/llvm-jitlistener - `1` - `0` - `1` - :none:`0%` + * - llvm/tools/llvm-libtool-darwin + - `1` + - `1` + - `0` + - :good:`100%` * - llvm/tools/llvm-link - `1` - `0` @@ -4846,9 +5086,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`85%` * - llvm/tools/llvm-mca/Views - `20` - - `15` - - `5` - - :part:`75%` + - `13` + - `7` + - :part:`65%` * - llvm/tools/llvm-microsoft-demangle-fuzzer - `2` - `2` @@ -4881,14 +5121,14 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`66%` * - llvm/tools/llvm-objcopy/COFF - `8` - - `7` - - `1` - - :part:`87%` + - `8` + - `0` + - :good:`100%` * - llvm/tools/llvm-objcopy/ELF - `6` - - `3` - - `3` - - :part:`50%` + - `5` + - `1` + - :part:`83%` * - llvm/tools/llvm-objcopy/MachO - `10` - `10` @@ -4924,26 +5164,31 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` + * - llvm/tools/llvm-profgen + - `7` + - `7` + - `0` + - :good:`100%` * - llvm/tools/llvm-rc - `12` - `7` - `5` - :part:`58%` * - llvm/tools/llvm-readobj - - `21` - - `3` - - `18` - - :part:`14%` + - `19` + - `4` + - `15` + - :part:`21%` * - llvm/tools/llvm-reduce - `4` - - `2` - - `2` - - :part:`50%` + - `3` + - `1` + - :part:`75%` * - llvm/tools/llvm-reduce/deltas - - `14` - - `8` - - `6` - - :part:`57%` + - `24` + - `21` + - `3` + - :part:`87%` * - llvm/tools/llvm-rtdyld - `1` - `0` @@ -4999,21 +5244,26 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - `0` - :good:`100%` + * - llvm/tools/llvm-yaml-parser-fuzzer + - `2` + - `2` + - `0` + - :good:`100%` * - llvm/tools/lto - `2` - `1` - `1` - :part:`50%` * - llvm/tools/obj2yaml - - `11` - - `4` - - `7` - - :part:`36%` + - `10` + - `5` + - `5` + - :part:`50%` * - llvm/tools/opt - `10` - - `2` - - `8` - - :part:`20%` + - `3` + - `7` + - :part:`30%` * - llvm/tools/remarks-shlib - `1` - `0` @@ -5029,6 +5279,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` + * - llvm/tools/split-file + - `1` + - `1` + - `0` + - :good:`100%` * - llvm/tools/verify-uselistorder - `1` - `0` @@ -5045,15 +5300,15 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - llvm/unittests/ADT - - `74` - - `29` + - `76` + - `31` - `45` - - :part:`39%` + - :part:`40%` * - llvm/unittests/Analysis - - `34` + - `36` - `11` - - `23` - - :part:`32%` + - `25` + - :part:`30%` * - llvm/unittests/AsmParser - `1` - `1` @@ -5075,10 +5330,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`50%` * - llvm/unittests/CodeGen - - `10` - - `2` + - `17` - `8` - - :part:`20%` + - `9` + - :part:`47%` * - llvm/unittests/CodeGen/GlobalISel - `11` - `1` @@ -5090,10 +5345,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `2` - :part:`33%` * - llvm/unittests/DebugInfo/DWARF - - `13` - - `8` - - `5` - - :part:`61%` + - `15` + - `9` + - `6` + - :part:`60%` * - llvm/unittests/DebugInfo/GSYM - `1` - `0` @@ -5135,25 +5390,35 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `7` - :none:`0%` * - llvm/unittests/ExecutionEngine/Orc - - `20` + - `13` - `4` - - `16` - - :part:`20%` - * - llvm/unittests/Frontend - - `2` + - `9` + - :part:`30%` + * - llvm/unittests/FileCheck - `1` + - `0` - `1` - - :part:`50%` + - :none:`0%` + * - llvm/unittests/Frontend + - `4` + - `3` + - `1` + - :part:`75%` * - llvm/unittests/FuzzMutate - `4` - `0` - `4` - :none:`0%` + * - llvm/unittests/InterfaceStub + - `1` + - `1` + - `0` + - :good:`100%` * - llvm/unittests/IR - - `35` - - `7` - - `28` - - :part:`20%` + - `36` + - `6` + - `30` + - :part:`16%` * - llvm/unittests/LineEditor - `1` - `0` @@ -5180,40 +5445,40 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - llvm/unittests/Object - - `8` - - `7` - - `1` - - :part:`87%` + - `9` + - `6` + - `3` + - :part:`66%` * - llvm/unittests/ObjectYAML - - `4` - - `2` + - `5` + - `3` - `2` - - :part:`50%` + - :part:`60%` * - llvm/unittests/Option + - `2` - `1` - - `0` - `1` - - :none:`0%` + - :part:`50%` * - llvm/unittests/Passes - `3` - `3` - `0` - :good:`100%` * - llvm/unittests/ProfileData + - `4` + - `1` - `3` - - `0` - - `3` - - :none:`0%` + - :part:`25%` * - llvm/unittests/Remarks - `8` - `5` - `3` - :part:`62%` * - llvm/unittests/Support - - `89` - - `24` + - `93` + - `28` - `65` - - :part:`26%` + - :part:`30%` * - llvm/unittests/Support/DynamicLibrary - `4` - `0` @@ -5226,12 +5491,12 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :none:`0%` * - llvm/unittests/Target/AArch64 - `2` - - `1` - - `1` - - :part:`50%` + - `0` + - `2` + - :none:`0%` * - llvm/unittests/Target/AMDGPU - - `1` - - `1` + - `2` + - `2` - `0` - :good:`100%` * - llvm/unittests/Target/ARM @@ -5255,10 +5520,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - llvm/unittests/TextAPI - - `6` - - `3` + - `5` - `3` - - :part:`50%` + - `2` + - :part:`60%` * - llvm/unittests/tools/llvm-cfi-verify - `2` - `1` @@ -5290,20 +5555,20 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`80%` * - llvm/unittests/tools/llvm-exegesis/PowerPC + - `4` - `2` - - `0` - `2` - - :none:`0%` + - :part:`50%` * - llvm/unittests/tools/llvm-exegesis/X86 - `9` - `8` - `1` - :part:`88%` * - llvm/unittests/Transforms/IPO + - `4` - `2` - - `0` - `2` - - :none:`0%` + - :part:`50%` * - llvm/unittests/Transforms/Scalar - `2` - `0` @@ -5364,346 +5629,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/change-namespace - - `2` - - `2` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/change-namespace/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-apply-replacements/include/clang-apply-replacements/Tooling - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-apply-replacements/lib/Tooling - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-apply-replacements/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-doc - - `16` - - `16` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-doc/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-move - - `4` - - `4` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-move/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-query - - `5` - - `5` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-query/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-reorder-fields - - `2` - - `2` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-reorder-fields/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy - - `12` - - `12` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/abseil - - `36` - - `36` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/android - - `29` - - `29` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/boost - - `3` - - `3` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/bugprone - - `81` - - `81` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/cert - - `23` - - `23` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/cppcoreguidelines - - `37` - - `37` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/fuchsia - - `15` - - `15` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/google - - `31` - - `31` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/hicpp - - `9` - - `9` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/llvm - - `7` - - `7` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/misc - - `27` - - `27` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/modernize - - `63` - - `63` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/mpi - - `5` - - `5` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/objc - - `9` - - `9` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/performance - - `25` - - `25` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/plugin - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/portability - - `3` - - `3` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/readability - - `67` - - `67` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/utils - - `29` - - `29` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clang-tidy/zircon - - `3` - - `3` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd - - `66` - - `66` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/benchmarks - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/fuzzer - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/index - - `30` - - `30` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/index/dex - - `9` - - `9` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/index/dex/dexp - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/indexer - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/refactor - - `2` - - `2` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/refactor/tweaks - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/xpc - - `3` - - `3` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/xpc/framework - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/clangd/xpc/test-client - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/include-fixer - - `13` - - `13` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/include-fixer/find-all-symbols - - `17` - - `17` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/include-fixer/find-all-symbols/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/include-fixer/plugin - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/include-fixer/tool - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/modularize - - `9` - - `9` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/pp-trace - - `3` - - `3` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/tool-template - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/change-namespace - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/clang-apply-replacements - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/clang-doc - - `7` - - `7` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/clang-move - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/clang-query - - `2` - - `2` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/clang-tidy - - `11` - - `11` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/clangd - - `47` - - `47` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/clangd/xpc - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/include/common - - `1` - - `1` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/include-fixer - - `2` - - `2` - - `0` - - :good:`100%` - * - llvm/utils/release/llvm_package_355249/llvm/tools/clang/tools/extra/unittests/include-fixer/find-all-symbols - - `1` - - `1` - - `0` - - :good:`100%` * - llvm/utils/TableGen - `75` - - `9` - - `66` - - :part:`12%` + - `8` + - `67` + - :part:`10%` * - llvm/utils/TableGen/GlobalISel - `17` - `8` @@ -5915,20 +5845,40 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/include/mlir/Analysis + - `11` + - `10` + - `1` + - :part:`90%` + * - mlir/include/mlir/Analysis/Presburger + - `3` + - `3` + - `0` + - :good:`100%` + * - mlir/include/mlir/CAPI - `8` - - `7` + - `8` + - `0` + - :good:`100%` + * - mlir/include/mlir/Conversion - `1` - - :part:`87%` + - `1` + - `0` + - :good:`100%` * - mlir/include/mlir/Conversion/AffineToStandard - `1` - `1` - `0` - :good:`100%` - * - mlir/include/mlir/Conversion/AVX512ToLLVM + * - mlir/include/mlir/Conversion/AsyncToLLVM + - `1` - `1` - `0` + - :good:`100%` + * - mlir/include/mlir/Conversion/AVX512ToLLVM - `1` - - :none:`0%` + - `1` + - `0` + - :good:`100%` * - mlir/include/mlir/Conversion/GPUCommon - `1` - `1` @@ -5969,17 +5919,32 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` + * - mlir/include/mlir/Conversion/OpenMPToLLVM + - `1` + - `0` + - `1` + - :none:`0%` + * - mlir/include/mlir/Conversion/PDLToPDLInterp + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/include/mlir/Conversion/SCFToGPU - `2` - `2` - `0` - :good:`100%` - * - mlir/include/mlir/Conversion/SCFToStandard + * - mlir/include/mlir/Conversion/SCFToOpenMP + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/include/mlir/Conversion/SCFToSPIRV - `1` - `1` - `0` - :good:`100%` - * - mlir/include/mlir/Conversion/ShapeToSCF + * - mlir/include/mlir/Conversion/SCFToStandard - `1` - `1` - `0` @@ -5996,9 +5961,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - mlir/include/mlir/Conversion/StandardToLLVM - `2` - - `1` - - `1` - - :part:`50%` + - `2` + - `0` + - :good:`100%` * - mlir/include/mlir/Conversion/StandardToSPIRV - `2` - `2` @@ -6019,6 +5984,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` + * - mlir/include/mlir/Conversion/VectorToSPIRV + - `2` + - `2` + - `0` + - :good:`100%` * - mlir/include/mlir/Dialect - `2` - `2` @@ -6026,9 +5996,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - mlir/include/mlir/Dialect/Affine - `2` - - `1` - - `1` - - :part:`50%` + - `2` + - `0` + - :good:`100%` * - mlir/include/mlir/Dialect/Affine/EDSC - `2` - `2` @@ -6039,6 +6009,16 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `3` - `0` - :good:`100%` + * - mlir/include/mlir/Dialect/Async + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/include/mlir/Dialect/Async/IR + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/include/mlir/Dialect/AVX512 - `1` - `1` @@ -6046,14 +6026,14 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - mlir/include/mlir/Dialect/GPU - `5` - - `4` - - `1` - - :part:`80%` + - `5` + - `0` + - :good:`100%` * - mlir/include/mlir/Dialect/Linalg - `1` - - `0` - `1` - - :none:`0%` + - `0` + - :good:`100%` * - mlir/include/mlir/Dialect/Linalg/Analysis - `1` - `1` @@ -6070,21 +6050,26 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`66%` * - mlir/include/mlir/Dialect/Linalg/Transforms - - `2` - - `1` - - `1` - - :part:`50%` + - `3` + - `3` + - `0` + - :good:`100%` * - mlir/include/mlir/Dialect/Linalg/Utils - `1` - `1` - `0` - :good:`100%` * - mlir/include/mlir/Dialect/LLVMIR - - `4` - - `4` + - `5` + - `5` - `0` - :good:`100%` * - mlir/include/mlir/Dialect/LLVMIR/Transforms + - `2` + - `2` + - `0` + - :good:`100%` + * - mlir/include/mlir/Dialect/OpenACC - `1` - `1` - `0` @@ -6094,21 +6079,31 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` + * - mlir/include/mlir/Dialect/PDL/IR + - `2` + - `1` + - `1` + - :part:`50%` + * - mlir/include/mlir/Dialect/PDLInterp/IR + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/include/mlir/Dialect/Quant - `6` - - `5` - - `1` - - :part:`83%` - * - mlir/include/mlir/Dialect/SCF - - `4` - - `4` + - `6` - `0` - :good:`100%` + * - mlir/include/mlir/Dialect/SCF + - `4` + - `3` + - `1` + - :part:`75%` * - mlir/include/mlir/Dialect/SCF/EDSC - `2` - - `2` - - `0` - - :good:`100%` + - `1` + - `1` + - :part:`50%` * - mlir/include/mlir/Dialect/SDBM - `3` - `2` @@ -6125,10 +6120,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/include/mlir/Dialect/SPIRV - - `11` - - `10` + - `13` + - `12` - `1` - - :part:`90%` + - :part:`92%` * - mlir/include/mlir/Dialect/StandardOps/EDSC - `2` - `2` @@ -6140,10 +6135,25 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/include/mlir/Dialect/StandardOps/Transforms + - `3` + - `3` + - `0` + - :good:`100%` + * - mlir/include/mlir/Dialect/Tosa/IR + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/include/mlir/Dialect/Tosa/Transforms - `2` - `2` - `0` - :good:`100%` + * - mlir/include/mlir/Dialect/Tosa/Utils + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/include/mlir/Dialect/Utils - `1` - `1` @@ -6165,60 +6175,115 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/include/mlir/ExecutionEngine - - `5` + - `6` + - `4` - `2` - - `3` - - :part:`40%` + - :part:`66%` * - mlir/include/mlir/Interfaces - - `7` - - `6` + - `11` + - `10` - `1` - - :part:`85%` + - :part:`90%` * - mlir/include/mlir/IR - - `42` - - `9` - - `33` - - :part:`21%` + - `46` + - `15` + - `31` + - :part:`32%` * - mlir/include/mlir/Pass - `6` - `0` - `6` - :none:`0%` + * - mlir/include/mlir/Reducer + - `6` + - `6` + - `0` + - :good:`100%` + * - mlir/include/mlir/Reducer/Passes + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/include/mlir/Rewrite + - `2` + - `2` + - `0` + - :good:`100%` * - mlir/include/mlir/Support - - `10` - - `4` + - `12` - `6` - - :part:`40%` + - `6` + - :part:`50%` * - mlir/include/mlir/TableGen + - `20` - `18` - - `17` - - `1` - - :part:`94%` + - `2` + - :part:`90%` * - mlir/include/mlir/Target - `3` - `3` - `0` - :good:`100%` * - mlir/include/mlir/Target/LLVMIR - - `1` - - `1` + - `2` + - `2` - `0` - :good:`100%` * - mlir/include/mlir/Transforms - - `12` - - `7` + - `14` + - `9` - `5` - - :part:`58%` + - :part:`64%` * - mlir/include/mlir-c + - `11` + - `11` + - `0` + - :good:`100%` + * - mlir/include/mlir-c/Bindings/Python - `1` - `1` - `0` - :good:`100%` * - mlir/lib/Analysis + - `11` + - `10` + - `1` + - :part:`90%` + * - mlir/lib/Analysis/Presburger + - `2` + - `2` + - `0` + - :good:`100%` + * - mlir/lib/Bindings/Python - `8` - - `7` + - `8` + - `0` + - :good:`100%` + * - mlir/lib/Bindings/Python/Transforms - `1` - - :part:`87%` + - `1` + - `0` + - :good:`100%` + * - mlir/lib/CAPI/IR + - `8` + - `8` + - `0` + - :good:`100%` + * - mlir/lib/CAPI/Registration + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/lib/CAPI/Standard + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/lib/CAPI/Transforms + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/lib/Conversion - `1` - `1` @@ -6229,6 +6294,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - `1` - :none:`0%` + * - mlir/lib/Conversion/AsyncToLLVM + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/lib/Conversion/AVX512ToLLVM - `1` - `1` @@ -6241,9 +6311,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - mlir/lib/Conversion/GPUToNVVM - `1` - - `0` - `1` - - :none:`0%` + - `0` + - :good:`100%` * - mlir/lib/Conversion/GPUToROCDL - `1` - `1` @@ -6251,9 +6321,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - mlir/lib/Conversion/GPUToSPIRV - `2` - - `2` - - `0` - - :good:`100%` + - `1` + - `1` + - :part:`50%` * - mlir/lib/Conversion/GPUToVulkan - `2` - `2` @@ -6274,46 +6344,61 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` + * - mlir/lib/Conversion/OpenMPToLLVM + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/lib/Conversion/PDLToPDLInterp + - `5` + - `4` + - `1` + - :part:`80%` * - mlir/lib/Conversion/SCFToGPU - `2` - `2` - `0` - :good:`100%` - * - mlir/lib/Conversion/SCFToStandard + * - mlir/lib/Conversion/SCFToOpenMP - `1` - `1` - `0` - :good:`100%` - * - mlir/lib/Conversion/ShapeToSCF + * - mlir/lib/Conversion/SCFToSPIRV - `1` - `1` - `0` - :good:`100%` - * - mlir/lib/Conversion/ShapeToStandard + * - mlir/lib/Conversion/SCFToStandard - `1` - `1` - `0` - :good:`100%` + * - mlir/lib/Conversion/ShapeToStandard + - `2` + - `2` + - `0` + - :good:`100%` * - mlir/lib/Conversion/SPIRVToLLVM + - `3` - `2` - `1` - - `1` - - :part:`50%` + - :part:`66%` * - mlir/lib/Conversion/StandardToLLVM - - `1` - `1` - `0` - - :good:`100%` + - `1` + - :none:`0%` * - mlir/lib/Conversion/StandardToSPIRV - `3` - `3` - `0` - :good:`100%` * - mlir/lib/Conversion/VectorToLLVM + - `2` - `1` - `1` - - `0` - - :good:`100%` + - :part:`50%` * - mlir/lib/Conversion/VectorToROCDL - `1` - `1` @@ -6324,6 +6409,11 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` + * - mlir/lib/Conversion/VectorToSPIRV + - `1` + - `0` + - `1` + - :none:`0%` * - mlir/lib/Dialect - `1` - `1` @@ -6340,8 +6430,8 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/lib/Dialect/Affine/Transforms - - `8` - - `8` + - `10` + - `10` - `0` - :good:`100%` * - mlir/lib/Dialect/Affine/Utils @@ -6349,26 +6439,36 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` - * - mlir/lib/Dialect/AVX512/IR + * - mlir/lib/Dialect/Async/IR + - `1` - `1` - `0` + - :good:`100%` + * - mlir/lib/Dialect/Async/Transforms + - `4` + - `4` + - `0` + - :good:`100%` + * - mlir/lib/Dialect/AVX512/IR - `1` - - :none:`0%` + - `1` + - `0` + - :good:`100%` * - mlir/lib/Dialect/GPU/IR - `1` - `0` - `1` - :none:`0%` * - mlir/lib/Dialect/GPU/Transforms + - `6` - `5` - - `4` - `1` - - :part:`80%` + - :part:`83%` * - mlir/lib/Dialect/Linalg/Analysis - `1` - - `0` - `1` - - :none:`0%` + - `0` + - :good:`100%` * - mlir/lib/Dialect/Linalg/EDSC - `1` - `1` @@ -6380,30 +6480,45 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/lib/Dialect/Linalg/Transforms - - `11` - - `10` - - `1` - - :part:`90%` + - `16` + - `16` + - `0` + - :good:`100%` * - mlir/lib/Dialect/Linalg/Utils - `1` - `1` - `0` - :good:`100%` * - mlir/lib/Dialect/LLVMIR/IR - - `4` + - `7` + - `6` - `1` - - `3` - - :part:`25%` + - :part:`85%` * - mlir/lib/Dialect/LLVMIR/Transforms - `2` - `2` - `0` - :good:`100%` + * - mlir/lib/Dialect/OpenACC/IR + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/lib/Dialect/OpenMP/IR - `1` - `1` - `0` - :good:`100%` + * - mlir/lib/Dialect/PDL/IR + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/lib/Dialect/PDLInterp/IR + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/lib/Dialect/Quant/IR - `4` - `4` @@ -6425,13 +6540,13 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/lib/Dialect/SCF/EDSC - - `1` - `1` - `0` - - :good:`100%` + - `1` + - :none:`0%` * - mlir/lib/Dialect/SCF/Transforms - - `5` - - `5` + - `7` + - `7` - `0` - :good:`100%` * - mlir/lib/Dialect/SDBM @@ -6445,8 +6560,8 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/lib/Dialect/Shape/Transforms - - `3` - - `3` + - `5` + - `5` - `0` - :good:`100%` * - mlir/lib/Dialect/SPIRV @@ -6454,11 +6569,16 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `6` - `2` - :part:`75%` + * - mlir/lib/Dialect/SPIRV/Linking/ModuleCombiner + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/lib/Dialect/SPIRV/Serialization - `4` - - `2` - - `2` - - :part:`50%` + - `4` + - `0` + - :good:`100%` * - mlir/lib/Dialect/SPIRV/Transforms - `5` - `5` @@ -6475,40 +6595,55 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/lib/Dialect/StandardOps/Transforms - - `4` - - `4` + - `8` + - `8` + - `0` + - :good:`100%` + * - mlir/lib/Dialect/Tosa/IR + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/lib/Dialect/Tosa/Transforms + - `1` + - `1` + - `0` + - :good:`100%` + * - mlir/lib/Dialect/Tosa/Utils + - `1` + - `1` - `0` - :good:`100%` * - mlir/lib/Dialect/Vector + - `4` - `3` - - `2` - `1` - - :part:`66%` + - :part:`75%` * - mlir/lib/Dialect/Vector/EDSC - `1` - `1` - `0` - :good:`100%` * - mlir/lib/EDSC - - `2` - `1` + - `0` - `1` - - :part:`50%` + - :none:`0%` * - mlir/lib/ExecutionEngine - - `5` - - `5` - - `0` - - :good:`100%` - * - mlir/lib/Interfaces - `7` - `7` - `0` - :good:`100%` - * - mlir/lib/IR - - `32` - - `32` + * - mlir/lib/Interfaces + - `9` + - `9` - `0` - :good:`100%` + * - mlir/lib/IR + - `35` + - `34` + - `1` + - :part:`97%` * - mlir/lib/Parser - `12` - `12` @@ -6519,31 +6654,41 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `6` - `1` - :part:`85%` - * - mlir/lib/Support - - `4` - - `4` + * - mlir/lib/Reducer + - `1` + - `1` - `0` - :good:`100%` - * - mlir/lib/TableGen - - `16` - - `16` + * - mlir/lib/Rewrite + - `4` + - `3` + - `1` + - :part:`75%` + * - mlir/lib/Support + - `5` + - `5` - `0` - :good:`100%` + * - mlir/lib/TableGen + - `17` + - `15` + - `2` + - :part:`88%` * - mlir/lib/Target/LLVMIR - - `8` - - `8` + - `9` + - `9` - `0` - :good:`100%` * - mlir/lib/Transforms + - `24` - `19` - - `16` - - `3` - - :part:`84%` + - `5` + - :part:`79%` * - mlir/lib/Transforms/Utils - - `7` + - `8` - `6` - - `1` - - :part:`85%` + - `2` + - :part:`75%` * - mlir/lib/Translation - `1` - `1` @@ -6565,10 +6710,20 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/tools/mlir-opt + - `1` - `1` - `0` + - :good:`100%` + * - mlir/tools/mlir-reduce + - `4` + - `3` - `1` - - :none:`0%` + - :part:`75%` + * - mlir/tools/mlir-reduce/Passes + - `1` + - `1` + - `0` + - :good:`100%` * - mlir/tools/mlir-rocm-runner - `2` - `2` @@ -6579,11 +6734,16 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - `0` - :good:`100%` - * - mlir/tools/mlir-tblgen - - `16` - - `16` + * - mlir/tools/mlir-spirv-cpu-runner + - `1` + - `1` - `0` - :good:`100%` + * - mlir/tools/mlir-tblgen + - `20` + - `19` + - `1` + - :part:`95%` * - mlir/tools/mlir-translate - `1` - `1` @@ -6591,7 +6751,17 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - mlir/tools/mlir-vulkan-runner - `4` - - `4` + - `3` + - `1` + - :part:`75%` + * - mlir/unittests/Analysis + - `2` + - `2` + - `0` + - :good:`100%` + * - mlir/unittests/Analysis/Presburger + - `2` + - `2` - `0` - :good:`100%` * - mlir/unittests/Dialect @@ -6615,20 +6785,25 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - mlir/unittests/Pass - - `1` - - `1` + - `2` + - `2` - `0` - :good:`100%` * - mlir/unittests/SDBM - `1` + - `0` - `1` + - :none:`0%` + * - mlir/unittests/Support + - `2` + - `2` - `0` - :good:`100%` * - mlir/unittests/TableGen - - `3` - - `3` - - `0` - - :good:`100%` + - `4` + - `2` + - `2` + - :part:`50%` * - openmp/libomptarget/deviceRTLs - `1` - `0` @@ -6650,10 +6825,20 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :part:`50%` * - openmp/libomptarget/include + - `4` - `2` + - `2` + - :part:`50%` + * - openmp/libomptarget/plugins/amdgpu/impl + - `14` + - `14` + - `0` + - :good:`100%` + * - openmp/libomptarget/plugins/amdgpu/src - `1` - `1` - - :part:`50%` + - `0` + - :good:`100%` * - openmp/libomptarget/plugins/cuda/src - `1` - `0` @@ -6670,10 +6855,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `1` - :none:`0%` * - openmp/libomptarget/src + - `10` + - `2` - `8` - - `0` - - `8` - - :none:`0%` + - :part:`20%` * - openmp/runtime/doc/doxygen - `1` - `0` @@ -6681,9 +6866,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :none:`0%` * - openmp/runtime/src - `74` - - `37` - - `37` - - :part:`50%` + - `36` + - `38` + - :part:`48%` * - openmp/runtime/src/thirdparty/ittnotify - `6` - `0` @@ -6705,10 +6890,10 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `0` - :good:`100%` * - openmp/tools/multiplex - - `1` - `1` - `0` - - :good:`100%` + - `1` + - :none:`0%` * - openmp/tools/multiplex/tests - `1` - `1` @@ -6741,9 +6926,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :part:`80%` * - polly/include/polly - `22` - - `22` - - `0` - - :good:`100%` + - `21` + - `1` + - :part:`95%` * - polly/include/polly/CodeGen - `14` - `14` @@ -6756,9 +6941,9 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - :good:`100%` * - polly/lib/Analysis - `9` - - `9` - - `0` - - :good:`100%` + - `8` + - `1` + - :part:`88%` * - polly/lib/CodeGen - `15` - `15` @@ -6860,7 +7045,7 @@ tree in terms of conformance to :doc:`ClangFormat` as of: June 27, 2020 11:36:24 - `4` - :part:`81%` * - Total - - :total:`14021` - - :total:`6759` - - :total:`7262` + - :total:`13993` + - :total:`6737` + - :total:`7256` - :total:`48%` diff --git a/clang/docs/ClangOffloadBundler.rst b/clang/docs/ClangOffloadBundler.rst new file mode 100644 index 0000000000000000000000000000000000000000..050925be993b903d3f4429a3622624534776cc25 --- /dev/null +++ b/clang/docs/ClangOffloadBundler.rst @@ -0,0 +1,211 @@ +===================== +Clang Offload Bundler +===================== + +.. contents:: + :local: + +.. _clang-offload-bundler: + +Introduction +============ + +For heterogeneous single source programming languages, use one or more +``--offload-arch=`` Clang options to specify the target IDs of the +code to generate for the offload code regions. + +The tool chain may perform multiple compilations of a translation unit to +produce separate code objects for the host and potentially multiple offloaded +devices. The ``clang-offload-bundler`` tool may be used as part of the tool +chain to combine these multiple code objects into a single bundled code object. + +The tool chain may use a bundled code object as an intermediate step so that +each tool chain step consumes and produces a single file as in traditional +non-heterogeneous tool chains. The bundled code object contains the code objects +for the host and all the offload devices. + +A bundled code object may also be used to bundle just the offloaded code +objects, and embedded as data into the host code object. The host compilation +includes an ``init`` function that will use the runtime corresponding to the +offload kind (see :ref:`clang-offload-kind-table`) to load the offload code +objects appropriate to the devices present when the host program is executed. + +.. _clang-bundled-code-object-layout: + +Bundled Code Object Layout +========================== + +The layout of a bundled code object is defined by the following table: + + .. table:: Bundled Code Object Layout + :name: bundled-code-object-layout-table + + =================================== ======= ================ =============================== + Field Type Size in Bytes Description + =================================== ======= ================ =============================== + Magic String string 24 ``__CLANG_OFFLOAD_BUNDLE__`` + Number Of Code Objects integer 8 Number od bundled code objects. + 1st Bundle Entry Code Object Offset integer 8 Byte offset from beginning of + bundled code object to 1st code + object. + 1st Bundle Entry Code Object Size integer 8 Byte size of 1st code object. + 1st Bundle Entry ID Length integer 8 Character length of bundle + entry ID of 1st code object. + 1st Bundle Entry ID string 1st Bundle Entry Bundle entry ID of 1st code + ID Length object. This is not NUL + terminated. See + :ref:`clang-bundle-entry-id`. + \... + Nth Bundle Entry Code Object Offset integer 8 + Nth Bundle Entry Code Object Size integer 8 + Nth Bundle Entry ID Length integer 8 + Nth Bundle Entry ID string 1st Bundle Entry + ID Length + 1st Bundle Entry Code Object bytes 1st Bundle Entry + Code Object Size + \... + Nth Bundle Entry Code Object bytes Nth Bundle Entry + Code Object Size + =================================== ======= ================ =============================== + +.. _clang-bundle-entry-id: + +Bundle Entry ID +=============== + +Each entry in a bundled code object (see +:ref:`clang-bundled-code-object-layout`) has a bundle entry ID that indicates +the kind of the entry's code object and the runtime that manages it. + +Bundle entry ID syntax is defined by the following BNF syntax: + +.. code:: + + ::== "-" [ "-" ] + +Where: + +**offload-kind** + The runtime responsible for managing the bundled entry code object. See + :ref:`clang-offload-kind-table`. + + .. table:: Bundled Code Object Offload Kind + :name: clang-offload-kind-table + + ============= ============================================================== + Offload Kind Description + ============= ============================================================== + host Host code object. ``clang-offload-bundler`` always includes + this entry as the first bundled code object entry. For an + embedded bundled code object this entry is not used by the + runtime and so is generally an empty code object. + + hip Offload code object for the HIP language. Used for all + HIP language offload code objects when the + ``clang-offload-bundler`` is used to bundle code objects as + intermediate steps of the tool chain. Also used for AMD GPU + code objects before ABI version V4 when the + ``clang-offload-bundler`` is used to create a *fat binary* + to be loaded by the HIP runtime. The fat binary can be + loaded directly from a file, or be embedded in the host code + object as a data section with the name ``.hip_fatbin``. + + hipv4 Offload code object for the HIP language. Used for AMD GPU + code objects with at least ABI version V4 when the + ``clang-offload-bundler`` is used to create a *fat binary* + to be loaded by the HIP runtime. The fat binary can be + loaded directly from a file, or be embedded in the host code + object as a data section with the name ``.hip_fatbin``. + + openmp Offload code object for the OpenMP language extension. + ============= ============================================================== + +**target-triple** + The target triple of the code object. + +**target-id** + The canonical target ID of the code object. Present only if the target + supports a target ID. See :ref:`clang-target-id`. + +Each entry of a bundled code object must have a different bundle entry ID. There +can be multiple entries for the same processor provided they differ in target +feature settings. If there is an entry with a target feature specified as *Any*, +then all entries must specify that target feature as *Any* for the same +processor. There may be additional target specific restrictions. + +.. _clang-target-id: + +Target ID +========= + +A target ID is used to indicate the processor and optionally its configuration, +expressed by a set of target features, that affect ISA generation. It is target +specific if a target ID is supported, or if the target triple alone is +sufficient to specify the ISA generation. + +It is used with the ``-mcpu=`` and ``--offload-arch=`` +Clang compilation options to specify the kind of code to generate. + +It is also used as part of the bundle entry ID to identify the code object. See +:ref:`clang-bundle-entry-id`. + +Target ID syntax is defined by the following BNF syntax: + +.. code:: + + ::== ( ":" ( "+" | "-" ) )* + +Where: + +**processor** + Is a the target specific processor or any alternative processor name. + +**target-feature** + Is a target feature name that is supported by the processor. Each target + feature must appear at most once in a target ID and can have one of three + values: + + *Any* + Specified by omitting the target feature from the target ID. + A code object compiled with a target ID specifying the default + value of a target feature can be loaded and executed on a processor + configured with the target feature on or off. + + *On* + Specified by ``+``, indicating the target feature is enabled. A code + object compiled with a target ID specifying a target feature on + can only be loaded on a processor configured with the target feature on. + + *Off* + specified by ``-``, indicating the target feature is disabled. A code + object compiled with a target ID specifying a target feature off + can only be loaded on a processor configured with the target feature off. + +There are two forms of target ID: + +*Non-Canonical Form* + The non-canonical form is used as the input to user commands to allow the user + greater convenience. It allows both the primary and alternative processor name + to be used and the target features may be specified in any order. + +*Canonical Form* + The canonical form is used for all generated output to allow greater + convenience for tools that consume the information. It is also used for + internal passing of information between tools. Only the primary and not + alternative processor name is used and the target features are specified in + alphabetic order. Command line tools convert non-canonical form to canonical + form. + +Target Specific information +=========================== + +Target specific information is available for the following: + +*AMD GPU* + AMD GPU supports target ID and target features. See `User Guide for AMDGPU Backend + `_ which defines the `processors + `_ and `target + features `_ + supported. + +Most other targets do not support target IDs. \ No newline at end of file diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 9f14ab9f4c5b9c2e47ae57adc432b238deed89a8..203840c214a264a49c451b14f04a7983c53ec08d 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -89,7 +89,7 @@ mode requires careful consideration and testing to get the desired behavior from an AST matcher.

-

In addition, because template instantations are matched in the default mode, +

In addition, because template instantiations are matched in the default mode, transformations can be accidentally made to template declarations. Finally, because implicit nodes are matched by default, transformations can be made on entirely incorrect places in the code.

diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index 227b373957eabddf46c84d0c7bf4ed2f22c86558..afa357a4d873684fb63003f3b055413e96447936 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -272,7 +272,7 @@ want to help with the implementation. +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | device extension | 'present' motion modifier | :good:`done` | D84711, D84712 | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| device extension | 'present' in defaultmap clause | :none:`unclaimed` | | +| device extension | 'present' in defaultmap clause | :part:`worked on` | D92427 | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | device extension | map clause reordering reordering based on 'present' modifier | :none:`unclaimed` | | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d62c62dad3d2a52f398dbb230c4c28a35b26484c..ef7903e16f7face0f7b24ecd22fafa383b240a3d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -117,6 +117,7 @@ Modified Compiler Flags - Now that `this` pointers are tagged with `nonnull` and `dereferenceable(N)`, `-fno-delete-null-pointer-checks` has gained the power to remove the `nonnull` attribute on `this` for configurations that need it to be nullable. +- ``-gsplit-dwarf`` no longer implies ``-g2``. New Pragmas in Clang -------------------- @@ -271,6 +272,16 @@ clang-format }; +- Experimental Support in clang-format for concepts has been improved, to + aid this the follow options have been added + +- Option ``IndentRequires`` has been added to indent the ``requires`` keyword + in templates. +- Option ``BreakBeforeConceptDeclarations`` has been added to aid the formatting of concepts. + +- Option ``IndentPragmas`` has been added to allow #pragma to indented with the current scope level. This is especially useful when using #pragma to mark OpenMP sections of code. + + libclang -------- diff --git a/clang/docs/index.rst b/clang/docs/index.rst index 2c7728713cabd7d4a3ab84a8ad5a50e44ce3a62d..a3a76c073b991938add11051b7921a79fd289a21 100644 --- a/clang/docs/index.rst +++ b/clang/docs/index.rst @@ -79,6 +79,7 @@ Using Clang Tools ClangFormat ClangFormatStyleOptions ClangFormattedStatus + ClangOffloadBundler Design Documents ================ diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 1c91e059c32229b9b03b8e703f8b57162d43118b..e305283bbaf19759f366788bb636a4f76127ce04 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -3861,7 +3861,15 @@ enum CXTypeNullabilityKind { /** * Nullability is not applicable to this type. */ - CXTypeNullability_Invalid = 3 + CXTypeNullability_Invalid = 3, + + /** + * Generally behaves like Nullable, except when used in a block parameter that + * was imported into a swift async method. There, swift will assume that the + * parameter can get null even if no error occured. _Nullable parameters are + * assumed to only get null on error. + */ + CXTypeNullability_NullableResult = 4 }; /** diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 3095bfbf1718efccd11ba5192b522e99d951814e..d9bf2f07291f5b95b902dc4165b3cc68e9e84222 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -105,7 +105,7 @@ public: return *this; } - LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); + LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; }; inline bool operator==(const CommonEntityInfo &LHS, @@ -176,7 +176,7 @@ public: return *this; } - LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); + LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; }; inline bool operator==(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) { @@ -338,7 +338,7 @@ public: return *this; } - LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); + LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; }; inline bool operator==(const VariableInfo &LHS, const VariableInfo &RHS) { @@ -394,7 +394,7 @@ public: return *this; } - LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); + LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; }; inline bool operator==(const ObjCPropertyInfo &LHS, @@ -464,7 +464,7 @@ public: friend bool operator==(const ParamInfo &, const ParamInfo &); - LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); + LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; }; inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) { @@ -582,7 +582,7 @@ private: } public: - LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); + LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; }; inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) { @@ -717,7 +717,7 @@ public: friend bool operator==(const TypedefInfo &, const TypedefInfo &); - LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); + LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; }; inline bool operator==(const TypedefInfo &LHS, const TypedefInfo &RHS) { diff --git a/clang/include/clang/ARCMigrate/FileRemapper.h b/clang/include/clang/ARCMigrate/FileRemapper.h index 76b65b2f6884c911601964e74d08c59978914aad..4da68a678be20272a744ae7a45556867a5e97ed4 100644 --- a/clang/include/clang/ARCMigrate/FileRemapper.h +++ b/clang/include/clang/ARCMigrate/FileRemapper.h @@ -12,11 +12,13 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include namespace llvm { class MemoryBuffer; + class MemoryBufferRef; } namespace clang { @@ -55,6 +57,12 @@ public: void applyMappings(PreprocessorOptions &PPOpts) const; + /// Iterate through all the mappings. + void forEachMapping( + llvm::function_ref CaptureFile, + llvm::function_ref + CaptureBuffer) const; + void clear(StringRef outputDir = StringRef()); private: diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index d921a106b9f1669182ea5be1fbf92e6772c67cc6..d6a33c13b0961c28dcf880cae3e154f87e2b5e8f 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -20,7 +20,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" -#include "llvm/Support/AlignOf.h" +#include namespace clang { class AddrLabelExpr; @@ -286,9 +286,10 @@ private: struct MemberPointerData; // We ensure elsewhere that Data is big enough for LV and MemberPointerData. - typedef llvm::AlignedCharArrayUnion DataType; + typedef std::aligned_union_t<1, void *, APSInt, APFloat, ComplexAPSInt, + ComplexAPFloat, Vec, Arr, StructData, UnionData, + AddrLabelDiffData> + DataType; static const size_t DataSize = sizeof(DataType); DataType Data; @@ -402,7 +403,7 @@ public: APSInt &getInt() { assert(isInt() && "Invalid accessor"); - return *(APSInt*)(char*)Data.buffer; + return *(APSInt *)(char *)&Data; } const APSInt &getInt() const { return const_cast(this)->getInt(); @@ -416,7 +417,7 @@ public: APFloat &getFloat() { assert(isFloat() && "Invalid accessor"); - return *(APFloat*)(char*)Data.buffer; + return *(APFloat *)(char *)&Data; } const APFloat &getFloat() const { return const_cast(this)->getFloat(); @@ -424,7 +425,7 @@ public: APFixedPoint &getFixedPoint() { assert(isFixedPoint() && "Invalid accessor"); - return *(APFixedPoint *)(char *)Data.buffer; + return *(APFixedPoint *)(char *)&Data; } const APFixedPoint &getFixedPoint() const { return const_cast(this)->getFixedPoint(); @@ -432,7 +433,7 @@ public: APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data.buffer)->Real; + return ((ComplexAPSInt *)(char *)&Data)->Real; } const APSInt &getComplexIntReal() const { return const_cast(this)->getComplexIntReal(); @@ -440,7 +441,7 @@ public: APSInt &getComplexIntImag() { assert(isComplexInt() && "Invalid accessor"); - return ((ComplexAPSInt*)(char*)Data.buffer)->Imag; + return ((ComplexAPSInt *)(char *)&Data)->Imag; } const APSInt &getComplexIntImag() const { return const_cast(this)->getComplexIntImag(); @@ -448,7 +449,7 @@ public: APFloat &getComplexFloatReal() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data.buffer)->Real; + return ((ComplexAPFloat *)(char *)&Data)->Real; } const APFloat &getComplexFloatReal() const { return const_cast(this)->getComplexFloatReal(); @@ -456,7 +457,7 @@ public: APFloat &getComplexFloatImag() { assert(isComplexFloat() && "Invalid accessor"); - return ((ComplexAPFloat*)(char*)Data.buffer)->Imag; + return ((ComplexAPFloat *)(char *)&Data)->Imag; } const APFloat &getComplexFloatImag() const { return const_cast(this)->getComplexFloatImag(); @@ -477,20 +478,20 @@ public: APValue &getVectorElt(unsigned I) { assert(isVector() && "Invalid accessor"); assert(I < getVectorLength() && "Index out of range"); - return ((Vec*)(char*)Data.buffer)->Elts[I]; + return ((Vec *)(char *)&Data)->Elts[I]; } const APValue &getVectorElt(unsigned I) const { return const_cast(this)->getVectorElt(I); } unsigned getVectorLength() const { assert(isVector() && "Invalid accessor"); - return ((const Vec*)(const void *)Data.buffer)->NumElts; + return ((const Vec *)(const void *)&Data)->NumElts; } APValue &getArrayInitializedElt(unsigned I) { assert(isArray() && "Invalid accessor"); assert(I < getArrayInitializedElts() && "Index out of range"); - return ((Arr*)(char*)Data.buffer)->Elts[I]; + return ((Arr *)(char *)&Data)->Elts[I]; } const APValue &getArrayInitializedElt(unsigned I) const { return const_cast(this)->getArrayInitializedElt(I); @@ -501,35 +502,35 @@ public: APValue &getArrayFiller() { assert(isArray() && "Invalid accessor"); assert(hasArrayFiller() && "No array filler"); - return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()]; + return ((Arr *)(char *)&Data)->Elts[getArrayInitializedElts()]; } const APValue &getArrayFiller() const { return const_cast(this)->getArrayFiller(); } unsigned getArrayInitializedElts() const { assert(isArray() && "Invalid accessor"); - return ((const Arr*)(const void *)Data.buffer)->NumElts; + return ((const Arr *)(const void *)&Data)->NumElts; } unsigned getArraySize() const { assert(isArray() && "Invalid accessor"); - return ((const Arr*)(const void *)Data.buffer)->ArrSize; + return ((const Arr *)(const void *)&Data)->ArrSize; } unsigned getStructNumBases() const { assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data.buffer)->NumBases; + return ((const StructData *)(const char *)&Data)->NumBases; } unsigned getStructNumFields() const { assert(isStruct() && "Invalid accessor"); - return ((const StructData*)(const char*)Data.buffer)->NumFields; + return ((const StructData *)(const char *)&Data)->NumFields; } APValue &getStructBase(unsigned i) { assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data.buffer)->Elts[i]; + return ((StructData *)(char *)&Data)->Elts[i]; } APValue &getStructField(unsigned i) { assert(isStruct() && "Invalid accessor"); - return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i]; + return ((StructData *)(char *)&Data)->Elts[getStructNumBases() + i]; } const APValue &getStructBase(unsigned i) const { return const_cast(this)->getStructBase(i); @@ -540,11 +541,11 @@ public: const FieldDecl *getUnionField() const { assert(isUnion() && "Invalid accessor"); - return ((const UnionData*)(const char*)Data.buffer)->Field; + return ((const UnionData *)(const char *)&Data)->Field; } APValue &getUnionValue() { assert(isUnion() && "Invalid accessor"); - return *((UnionData*)(char*)Data.buffer)->Value; + return *((UnionData *)(char *)&Data)->Value; } const APValue &getUnionValue() const { return const_cast(this)->getUnionValue(); @@ -556,24 +557,24 @@ public: const AddrLabelExpr* getAddrLabelDiffLHS() const { assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr; + return ((const AddrLabelDiffData *)(const char *)&Data)->LHSExpr; } const AddrLabelExpr* getAddrLabelDiffRHS() const { assert(isAddrLabelDiff() && "Invalid accessor"); - return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr; + return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr; } void setInt(APSInt I) { assert(isInt() && "Invalid accessor"); - *(APSInt *)(char *)Data.buffer = std::move(I); + *(APSInt *)(char *)&Data = std::move(I); } void setFloat(APFloat F) { assert(isFloat() && "Invalid accessor"); - *(APFloat *)(char *)Data.buffer = std::move(F); + *(APFloat *)(char *)&Data = std::move(F); } void setFixedPoint(APFixedPoint FX) { assert(isFixedPoint() && "Invalid accessor"); - *(APFixedPoint *)(char *)Data.buffer = std::move(FX); + *(APFixedPoint *)(char *)&Data = std::move(FX); } void setVector(const APValue *E, unsigned N) { MutableArrayRef InternalElts = setVectorUninit(N); @@ -584,15 +585,15 @@ public: assert(R.getBitWidth() == I.getBitWidth() && "Invalid complex int (type mismatch)."); assert(isComplexInt() && "Invalid accessor"); - ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R); - ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I); + ((ComplexAPSInt *)(char *)&Data)->Real = std::move(R); + ((ComplexAPSInt *)(char *)&Data)->Imag = std::move(I); } void setComplexFloat(APFloat R, APFloat I) { assert(&R.getSemantics() == &I.getSemantics() && "Invalid complex float (type mismatch)."); assert(isComplexFloat() && "Invalid accessor"); - ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R); - ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); + ((ComplexAPFloat *)(char *)&Data)->Real = std::move(R); + ((ComplexAPFloat *)(char *)&Data)->Imag = std::move(I); } void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, bool IsNullPtr); @@ -602,59 +603,59 @@ public: void setUnion(const FieldDecl *Field, const APValue &Value); void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) { - ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; - ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr; + ((AddrLabelDiffData *)(char *)&Data)->LHSExpr = LHSExpr; + ((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr; } private: void DestroyDataAndMakeUninit(); void MakeInt() { assert(isAbsent() && "Bad state change"); - new ((void*)Data.buffer) APSInt(1); + new ((void *)&Data) APSInt(1); Kind = Int; } void MakeFloat() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) APFloat(0.0); + new ((void *)(char *)&Data) APFloat(0.0); Kind = Float; } void MakeFixedPoint(APFixedPoint &&FX) { assert(isAbsent() && "Bad state change"); - new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX)); + new ((void *)(char *)&Data) APFixedPoint(std::move(FX)); Kind = FixedPoint; } void MakeVector() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) Vec(); + new ((void *)(char *)&Data) Vec(); Kind = Vector; } void MakeComplexInt() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) ComplexAPSInt(); + new ((void *)(char *)&Data) ComplexAPSInt(); Kind = ComplexInt; } void MakeComplexFloat() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) ComplexAPFloat(); + new ((void *)(char *)&Data) ComplexAPFloat(); Kind = ComplexFloat; } void MakeLValue(); void MakeArray(unsigned InitElts, unsigned Size); void MakeStruct(unsigned B, unsigned M) { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) StructData(B, M); + new ((void *)(char *)&Data) StructData(B, M); Kind = Struct; } void MakeUnion() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) UnionData(); + new ((void *)(char *)&Data) UnionData(); Kind = Union; } void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, ArrayRef Path); void MakeAddrLabelDiff() { assert(isAbsent() && "Bad state change"); - new ((void*)(char*)Data.buffer) AddrLabelDiffData(); + new ((void *)(char *)&Data) AddrLabelDiffData(); Kind = AddrLabelDiff; } @@ -664,7 +665,7 @@ private: /// filled in by those steps. MutableArrayRef setVectorUninit(unsigned N) { assert(isVector() && "Invalid accessor"); - Vec *V = ((Vec *)(char *)Data.buffer); + Vec *V = ((Vec *)(char *)&Data); V->Elts = new APValue[N]; V->NumElts = N; return {V->Elts, V->NumElts}; diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index eff8e34a19b2d76d2ab044f6f09c4a4a01a1a0d2..26f4037870cdf48de3efed693ef93cda9b079388 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -57,7 +57,6 @@ #include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator_range.h" -#include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" @@ -1456,7 +1455,7 @@ public: /// Return the unique reference to the type for the specified /// typedef-name decl. QualType getTypedefType(const TypedefNameDecl *Decl, - QualType Canon = QualType()) const; + QualType Underlying = QualType()) const; QualType getRecordType(const RecordDecl *Decl) const; diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h index 034260cc8ed3f024c4728c479c5248637d9d6734..ea3da8d90c5b9dfe36e447813f9d9df8cce93d59 100644 --- a/clang/include/clang/AST/ASTTypeTraits.h +++ b/clang/include/clang/AST/ASTTypeTraits.h @@ -22,7 +22,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMapInfo.h" -#include "llvm/Support/AlignOf.h" +#include namespace llvm { @@ -246,9 +246,8 @@ public: /// in the \c DynTypedNode, and the returned pointer points at /// the storage inside DynTypedNode. For those nodes, do not /// use the pointer outside the scope of the DynTypedNode. - template - const T *get() const { - return BaseConverter::get(NodeKind, Storage.buffer); + template const T *get() const { + return BaseConverter::get(NodeKind, &Storage); } /// Retrieve the stored node as type \c T. @@ -256,7 +255,7 @@ public: /// Similar to \c get(), but asserts that the type is what we are expecting. template const T &getUnchecked() const { - return BaseConverter::getUnchecked(NodeKind, Storage.buffer); + return BaseConverter::getUnchecked(NodeKind, &Storage); } ASTNodeKind getNodeKind() const { return NodeKind; } @@ -268,7 +267,7 @@ public: /// method returns NULL. const void *getMemoizationData() const { return NodeKind.hasPointerIdentity() - ? *reinterpret_cast(Storage.buffer) + ? *reinterpret_cast(&Storage) : nullptr; } @@ -390,12 +389,12 @@ private: /// Converter that uses dyn_cast from a stored BaseT*. template struct DynCastPtrConverter { - static const T *get(ASTNodeKind NodeKind, const char Storage[]) { + static const T *get(ASTNodeKind NodeKind, const void *Storage) { if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) return &getUnchecked(NodeKind, Storage); return nullptr; } - static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) { assert(ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)); return *cast(static_cast( *reinterpret_cast(Storage))); @@ -403,19 +402,19 @@ private: static DynTypedNode create(const BaseT &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNode(Node); - new (Result.Storage.buffer) const void *(&Node); + new (&Result.Storage) const void *(&Node); return Result; } }; /// Converter that stores T* (by pointer). template struct PtrConverter { - static const T *get(ASTNodeKind NodeKind, const char Storage[]) { + static const T *get(ASTNodeKind NodeKind, const void *Storage) { if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) return &getUnchecked(NodeKind, Storage); return nullptr; } - static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) { assert(ASTNodeKind::getFromNodeKind().isSame(NodeKind)); return *static_cast( *reinterpret_cast(Storage)); @@ -423,26 +422,26 @@ private: static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind(); - new (Result.Storage.buffer) const void *(&Node); + new (&Result.Storage) const void *(&Node); return Result; } }; /// Converter that stores T (by value). template struct ValueConverter { - static const T *get(ASTNodeKind NodeKind, const char Storage[]) { + static const T *get(ASTNodeKind NodeKind, const void *Storage) { if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) return reinterpret_cast(Storage); return nullptr; } - static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) { assert(ASTNodeKind::getFromNodeKind().isSame(NodeKind)); return *reinterpret_cast(Storage); } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind(); - new (Result.Storage.buffer) T(Node); + new (&Result.Storage) T(Node); return Result; } }; @@ -457,9 +456,8 @@ private: /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs, /// \c TemplateArguments and \c TemplateArgumentLocs on the other hand do not /// have storage or unique pointers and thus need to be stored by value. - llvm::AlignedCharArrayUnion + std::aligned_union_t<1, const void *, TemplateArgument, TemplateArgumentLoc, + NestedNameSpecifierLoc, QualType, TypeLoc> Storage; }; diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index 545dc992c5edf46d7663f8a31034570310a62f15..8d9fb8f2bf27f5233bc8398fcf320fb2bb09c03f 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -259,7 +259,10 @@ public: /// Construct from a result from \c serialize. static ParamIdx deserialize(SerialType S) { - ParamIdx P(*reinterpret_cast(&S)); + // Using this two-step static_cast via void * instead of reinterpret_cast + // silences a -Wstrict-aliasing false positive from GCC7 and earlier. + void *ParamIdxPtr = static_cast(&S); + ParamIdx P(*static_cast(ParamIdxPtr)); assert((!P.IsValid || P.Idx >= 1) && "valid Idx must be one-origin"); return P; } diff --git a/clang/include/clang/AST/CXXInheritance.h b/clang/include/clang/AST/CXXInheritance.h index 8b1bcb367b3b47021fc2aaf75a596c377806a0e7..709f08bff82aee84794a3c3d8b4781891fce0fc2 100644 --- a/clang/include/clang/AST/CXXInheritance.h +++ b/clang/include/clang/AST/CXXInheritance.h @@ -149,12 +149,6 @@ class CXXBasePaths { /// to help build the set of paths. CXXBasePath ScratchPath; - /// Array of the declarations that have been found. This - /// array is constructed only if needed, e.g., to iterate over the - /// results within LookupResult. - std::unique_ptr DeclsFound; - unsigned NumDeclsFound = 0; - /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find /// ambiguous paths while it is looking for a path from a derived /// type to a base type. @@ -170,8 +164,6 @@ class CXXBasePaths { /// is also recorded. bool DetectVirtual; - void ComputeDeclsFound(); - bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record, CXXRecordDecl::BaseMatchesCallback BaseMatches, bool LookupInDependent = false); @@ -198,8 +190,6 @@ public: using decl_range = llvm::iterator_range; - decl_range found_decls(); - /// Determine whether the path from the most-derived type to the /// given base type is ambiguous (i.e., it refers to multiple subobjects of /// the same base type). diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 641647659c17efc1770d99fa4ae2e71323ca5680..7fbf6294970eb722b5b24f74198f8fcbb34bd708 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -3353,6 +3353,36 @@ inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) { : nullptr; } +/// Check whether the template parameter is a pack expansion, and if so, +/// determine the number of parameters produced by that expansion. For instance: +/// +/// \code +/// template struct A { +/// template class ...TTs, typename ...Us> struct B; +/// }; +/// \endcode +/// +/// In \c A::B, \c NTs and \c TTs have expanded pack size 2, and \c Us +/// is not a pack expansion, so returns an empty Optional. +inline Optional getExpandedPackSize(const NamedDecl *Param) { + if (const auto *TTP = dyn_cast(Param)) { + if (TTP->isExpandedParameterPack()) + return TTP->getNumExpansionParameters(); + } + + if (const auto *NTTP = dyn_cast(Param)) { + if (NTTP->isExpandedParameterPack()) + return NTTP->getNumExpansionTypes(); + } + + if (const auto *TTP = dyn_cast(Param)) { + if (TTP->isExpandedParameterPack()) + return TTP->getNumExpansionTemplateParameters(); + } + + return None; +} + } // namespace clang #endif // LLVM_CLANG_AST_DECLTEMPLATE_H diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 3ea2817f1926c22a00267aff0cfdd29c6c396380..c8d87ec48a3f0cece3ab71d9f9d42ae55d8980c9 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1284,7 +1284,7 @@ public: ValueDecl *getDecl() { return D; } const ValueDecl *getDecl() const { return D; } - void setDecl(ValueDecl *NewD) { D = NewD; } + void setDecl(ValueDecl *NewD); DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDecl()->getDeclName(), getLocation(), DNLoc); @@ -3167,7 +3167,7 @@ public: /// The returned declaration will be a FieldDecl or (in C++) a VarDecl (for /// static data members), a CXXMethodDecl, or an EnumConstantDecl. ValueDecl *getMemberDecl() const { return MemberDecl; } - void setMemberDecl(ValueDecl *D) { MemberDecl = D; } + void setMemberDecl(ValueDecl *D); /// Retrieves the declaration found by lookup. DeclAccessPair getFoundDecl() const { diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 2f89b43267b619c05dd6f1df9a78faaa539fccee..1efa78fc42940a45ac37b3d8d395a48f33d8007b 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -2029,6 +2029,9 @@ public: /// invented by use of an auto parameter). ArrayRef getExplicitTemplateParameters() const; + /// Get the trailing requires clause, if any. + Expr *getTrailingRequiresClause() const; + /// Whether this is a generic lambda. bool isGenericLambda() const { return getTemplateParameterList(); } diff --git a/clang/include/clang/AST/ParentMapContext.h b/clang/include/clang/AST/ParentMapContext.h index be4d75df7b9990ecccbee004b1c5551f2d9db3c6..a15790605a3d540f006f38a4990a0651613c4e0d 100644 --- a/clang/include/clang/AST/ParentMapContext.h +++ b/clang/include/clang/AST/ParentMapContext.h @@ -89,30 +89,29 @@ public: /// Container for either a single DynTypedNode or for an ArrayRef to /// DynTypedNode. For use with ParentMap. class DynTypedNodeList { - llvm::AlignedCharArrayUnion> Storage; + std::aligned_union_t<1, DynTypedNode, ArrayRef> Storage; bool IsSingleNode; public: DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) { - new (Storage.buffer) DynTypedNode(N); + new (&Storage) DynTypedNode(N); } DynTypedNodeList(ArrayRef A) : IsSingleNode(false) { - new (Storage.buffer) ArrayRef(A); + new (&Storage) ArrayRef(A); } const DynTypedNode *begin() const { if (!IsSingleNode) - return reinterpret_cast *>(Storage.buffer) + return reinterpret_cast *>(&Storage) ->begin(); - return reinterpret_cast(Storage.buffer); + return reinterpret_cast(&Storage); } const DynTypedNode *end() const { if (!IsSingleNode) - return reinterpret_cast *>(Storage.buffer) - ->end(); - return reinterpret_cast(Storage.buffer) + 1; + return reinterpret_cast *>(&Storage)->end(); + return reinterpret_cast(&Storage) + 1; } size_t size() const { return end() - begin(); } diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 0a36ec9ad687c2682f591473a5a8b6e35f1d70f3..612e60cf4df1cd7b93bd0317652657a4dc90ce62 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2503,17 +2503,12 @@ DEF_TRAVERSE_STMT(LambdaExpr, { TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); FunctionProtoTypeLoc Proto = TL.getAsAdjusted(); - for (Decl *D : S->getExplicitTemplateParameters()) { - // Visit explicit template parameters. - TRY_TO(TraverseDecl(D)); - } + TRY_TO(TraverseTemplateParameterListHelper(S->getTemplateParameterList())); if (S->hasExplicitParameters()) { // Visit parameters. for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) TRY_TO(TraverseDecl(Proto.getParam(I))); } - if (S->hasExplicitResultType()) - TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); auto *T = Proto.getTypePtr(); for (const auto &E : T->exceptions()) @@ -2522,6 +2517,10 @@ DEF_TRAVERSE_STMT(LambdaExpr, { if (Expr *NE = T->getNoexceptExpr()) TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE); + if (S->hasExplicitResultType()) + TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getTrailingRequiresClause()); + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); } ShouldVisitChildren = false; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 4d96d2b533e8894c37b55b92fb68e8e4d86b143b..53139f8ee8d00a7a492abcbb8b8a4b5ce1cfb795 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -4365,10 +4365,11 @@ public: class TypedefType : public Type { TypedefNameDecl *Decl; -protected: +private: friend class ASTContext; // ASTContext creates these. - TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can); + TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType underlying, + QualType can); public: TypedefNameDecl *getDecl() const { return Decl; } @@ -4719,6 +4720,9 @@ public: case NullabilityKind::Nullable: return attr::TypeNullable; + case NullabilityKind::NullableResult: + return attr::TypeNullableResult; + case NullabilityKind::Unspecified: return attr::TypeNullUnspecified; } diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index a183ac0479c6a8f1147947e9fedfc6848b0734f5..b582395c44a642ac95e4ac0a9bc44f71499b1fb6 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -484,8 +484,12 @@ let Class = TagType in { let Read = [{ node->isDependentType() }]; } def : Property<"declaration", DeclRef> { - // Serializing a reference to the canonical declaration is apparently - // necessary to make module-merging work. + // We don't know which declaration was originally referenced here, and we + // cannot reference a declaration that follows the use (because that can + // introduce deserialization cycles), so conservatively generate a + // reference to the first declaration. + // FIXME: If this is a reference to a class template specialization, that + // can still introduce a deserialization cycle. let Read = [{ node->getDecl()->getCanonicalDecl() }]; } } diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 8555bd35174760583e17bbde33bddbb7043968b9..51f654fc7613aa65f22dfbb18396f7fe07d0a81f 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -126,6 +126,9 @@ def FunctionTmpl FunctionDecl::TK_FunctionTemplate}], "function templates">; +def ClassTmpl : SubsetSubjectgetDescribedClassTemplate()}], + "class templates">; + // FIXME: this hack is needed because DeclNodes.td defines the base Decl node // type to be a class, not a definition. This makes it impossible to create an // attribute subject which accepts a Decl. Normally, this is not a problem, @@ -1802,6 +1805,11 @@ def TypeNullable : TypeAttr { let Documentation = [TypeNullableDocs]; } +def TypeNullableResult : TypeAttr { + let Spellings = [Keyword<"_Nullable_result">]; + let Documentation = [TypeNullableResultDocs]; +} + def TypeNullUnspecified : TypeAttr { let Spellings = [Keyword<"_Null_unspecified">]; let Documentation = [TypeNullUnspecifiedDocs]; @@ -2149,6 +2157,19 @@ def Regparm : TypeAttr { let ASTNode = 0; } +def SwiftAsyncName : InheritableAttr { + let Spellings = [GNU<"swift_async_name">]; + let Args = [StringArgument<"Name">]; + let Subjects = SubjectList<[ObjCMethod, Function], ErrorDiag>; + let Documentation = [SwiftAsyncNameDocs]; +} + +def SwiftAttr : InheritableAttr { + let Spellings = [GNU<"swift_attr">]; + let Args = [StringArgument<"Attribute">]; + let Documentation = [SwiftAttrDocs]; +} + def SwiftBridge : InheritableAttr { let Spellings = [GNU<"swift_bridge">]; let Args = [StringArgument<"SwiftType">]; @@ -2331,6 +2352,16 @@ def SwiftIndirectResult : ParameterABIAttr { let Documentation = [SwiftIndirectResultDocs]; } +def SwiftAsync : InheritableAttr { + let Spellings = [Clang<"swift_async">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; + let Args = [EnumArgument<"Kind", "Kind", + ["none", "swift_private", "not_swift_private"], + ["None", "SwiftPrivate", "NotSwiftPrivate"]>, + ParamIdxArgument<"CompletionHandlerIndex", /*opt=*/1>]; + let Documentation = [SwiftAsyncDocs]; +} + def Suppress : StmtAttr { let Spellings = [CXX11<"gsl", "suppress">]; let Args = [VariadicStringArgument<"DiagnosticIdentifiers">]; @@ -2363,6 +2394,16 @@ def Pascal : DeclOrTypeAttr { let Documentation = [Undocumented]; } +def PreferredName : InheritableAttr { + let Spellings = [Clang<"preferred_name", /*AllowInC*/0>]; + let Subjects = SubjectList<[ClassTmpl]>; + let Args = [TypeArgument<"TypedefType">]; + let Documentation = [PreferredNameDocs]; + let InheritEvenIfAlreadyPresent = 1; + let MeaningfulToClassTemplateDefinition = 1; + let TemplateDependent = 1; +} + def PreserveMost : DeclOrTypeAttr { let Spellings = [Clang<"preserve_most">]; let Documentation = [PreserveMostDocs]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 1781543cc4f3275542979f4e1c059542772ed21f..28f35cf2c0c7474846a27e4c81e5ac0d117d4490 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3508,6 +3508,29 @@ a caller of ``fetch_or_zero`` can provide null. }]; } +def TypeNullableResultDocs : Documentation { + let Category = NullabilityDocs; + let Content = [{ +The ``_Nullable_result`` nullability qualifier means that a value of the +``_Nullable_result`` pointer can be ``nil``, just like ``_Nullable``. Where this +attribute differs from ``_Nullable`` is when it's used on a parameter to a +completion handler in a Swift async method. For instance, here: + + .. code-block:: objc + + -(void)fetchSomeDataWithID:(int)identifier + completionHandler:(void (^)(Data *_Nullable_result result, NSError *error))completionHandler; + +This method asynchronously calls ``completionHandler`` when the data is +available, or calls it with an error. ``_Nullable_result`` indicates to the +Swift importer that this is the uncommon case where ``result`` can get ``nil`` +even if no error has occured, and will therefore import it as a Swift optional +type. Otherwise, if ``result`` was annotated with ``_Nullable``, the Swift +importer will assume that ``result`` will always be non-nil unless an error +occured. +}]; +} + def TypeNullUnspecifiedDocs : Documentation { let Category = NullabilityDocs; let Content = [{ @@ -3628,6 +3651,40 @@ Swift. }]; } +def SwiftAsyncNameDocs : Documentation { + let Category = SwiftDocs; + let Heading = "swift_async_name"; + let Content = [{ +The ``swift_async_name`` attribute provides the name of the ``async`` overload for +the given declaration in Swift. If this attribute is absent, the name is +transformed according to the algorithm built into the Swift compiler. + +The argument is a string literal that contains the Swift name of the function or +method. The name may be a compound Swift name. The function or method with such +an attribute must have more than zero parameters, as its last parameter is +assumed to be a callback that's eliminated in the Swift ``async`` name. + + .. code-block:: objc + + @interface URL + + (void) loadContentsFrom:(URL *)url callback:(void (^)(NSData *))data __attribute__((__swift_async_name__("URL.loadContentsFrom(_:)"))) + @end + }]; +} + +def SwiftAttrDocs : Documentation { + let Category = SwiftDocs; + let Heading = "swift_attr"; + let Content = [{ +The ``swift_attr`` provides a Swift-specific annotation for the declaration +to which the attribute appertains to. It can be used on any declaration +in Clang. This kind of annotation is ignored by Clang as it doesn't have any +semantic meaning in languages supported by Clang. The Swift compiler can +interpret these annotations according to its own rules when importing C or +Objective-C declarations. +}]; +} + def SwiftBridgeDocs : Documentation { let Category = SwiftDocs; let Heading = "swift_bridge"; @@ -4343,6 +4400,37 @@ optimizations like C++'s named return value optimization (NRVO). }]; } +def SwiftAsyncDocs : Documentation { + let Category = SwiftDocs; + let Heading = "swift_async"; + let Content = [{ +The ``swift_async`` attribute specifies if and how a particular function or +Objective-C method is imported into a swift async method. For instance: + +.. code-block:: objc + + @interface MyClass : NSObject + -(void)notActuallyAsync:(int)p1 withCompletionHandler:(void (^)())handler + __attribute__((swift_async(none))); + + -(void)actuallyAsync:(int)p1 callThisAsync:(void (^)())fun + __attribute__((swift_async(swift_private, 1))); + @end + +Here, ``notActuallyAsync:withCompletionHandler`` would have been imported as +``async`` (because it's last parameter's selector piece is +``withCompletionHandler``) if not for the ``swift_async(none)`` attribute. +Conversely, ``actuallyAsync:callThisAsync`` wouldn't have been imported as +``async`` if not for the ``swift_async`` attribute because it doesn't match the +naming convention. + +When using ``swift_async`` to enable importing, the first argument to the +attribute is either ``swift_private`` or ``not_swift_private`` to indicate +whether the function/method is private to the current framework, and the second +argument is the index of the completion handler parameter. + }]; +} + def SuppressDocs : Documentation { let Category = DocCatStmt; let Content = [{ @@ -4383,6 +4471,30 @@ the old mangled name and the new code will use the new mangled name with tags. }]; } +def PreferredNameDocs : Documentation { + let Category = DocCatDecl; + let Content = [{ +The ``preferred_name`` attribute can be applied to a class template, and +specifies a preferred way of naming a specialization of the template. The +preferred name will be used whenever the corresponding template specialization +would otherwise be printed in a diagnostic or similar context. + +The preferred name must be a typedef or type alias declaration that refers to a +specialization of the class template (not including any type qualifiers). In +general this requires the template to be declared at least twice. For example: + +.. code-block:: c++ + + template struct basic_string; + using string = basic_string; + using wstring = basic_string; + template struct [[clang::preferred_name(string), + clang::preferred_name(wstring)]] basic_string { + // ... + }; + }]; +} + def PreserveMostDocs : Documentation { let Category = DocCatCallingConvs; let Content = [{ diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def index 78ce77043b6f58927d351c2df66e06e96e196607..8975d126b89730a0a72268e8cf661bc9cd7edc64 100644 --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -638,6 +638,11 @@ BUILTIN(__builtin_cfuged, "ULLiULLiULLi", "") BUILTIN(__builtin_cntlzdm, "ULLiULLiULLi", "") BUILTIN(__builtin_cnttzdm, "ULLiULLiULLi", "") +// Generate random number +BUILTIN(__builtin_darn, "LLi", "") +BUILTIN(__builtin_darn_raw, "LLi", "") +BUILTIN(__builtin_darn_32, "i", "") + // Vector int128 (un)pack BUILTIN(__builtin_unpack_vector_int128, "ULLiV1LLLii", "") BUILTIN(__builtin_pack_vector_int128, "V1LLLiULLiULLi", "") diff --git a/clang/include/clang/Basic/BuiltinsX86.def b/clang/include/clang/Basic/BuiltinsX86.def index 0f5594f1a4e68b6ff0b07a6fbfd316fb9cec0f3c..16fb7dd7b0e618c6401a07e3cb9a9bbcc9d21726 100644 --- a/clang/include/clang/Basic/BuiltinsX86.def +++ b/clang/include/clang/Basic/BuiltinsX86.def @@ -1876,6 +1876,10 @@ TARGET_BUILTIN(__builtin_ia32_reduce_add_d512, "iV16i", "ncV:512:", "avx512f") TARGET_BUILTIN(__builtin_ia32_reduce_add_q512, "OiV8Oi", "ncV:512:", "avx512f") TARGET_BUILTIN(__builtin_ia32_reduce_and_d512, "iV16i", "ncV:512:", "avx512f") TARGET_BUILTIN(__builtin_ia32_reduce_and_q512, "OiV8Oi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_reduce_fadd_pd512, "ddV8d", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_reduce_fadd_ps512, "ffV16f", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_reduce_fmul_pd512, "ddV8d", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_reduce_fmul_ps512, "ffV16f", "ncV:512:", "avx512f") TARGET_BUILTIN(__builtin_ia32_reduce_mul_d512, "iV16i", "ncV:512:", "avx512f") TARGET_BUILTIN(__builtin_ia32_reduce_mul_q512, "OiV8Oi", "ncV:512:", "avx512f") TARGET_BUILTIN(__builtin_ia32_reduce_or_d512, "iV16i", "ncV:512:", "avx512f") diff --git a/clang/include/clang/Basic/BuiltinsX86_64.def b/clang/include/clang/Basic/BuiltinsX86_64.def index 3e186af82ff71aa6e2c4d21729bfb8825900239b..98327ade17e8c881979773796e6adb6dfc309c60 100644 --- a/clang/include/clang/Basic/BuiltinsX86_64.def +++ b/clang/include/clang/Basic/BuiltinsX86_64.def @@ -100,6 +100,10 @@ TARGET_BUILTIN(__builtin_ia32_stui, "v", "n", "uintr") TARGET_BUILTIN(__builtin_ia32_testui, "Uc", "n", "uintr") TARGET_BUILTIN(__builtin_ia32_senduipi, "vUWi", "n", "uintr") +// AMX internal builtin +TARGET_BUILTIN(__builtin_ia32_tileloadd64_internal, "V256iUsUsvC*z", "n", "amx-tile") +TARGET_BUILTIN(__builtin_ia32_tdpbssd_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-int8") +TARGET_BUILTIN(__builtin_ia32_tilestored64_internal, "vUsUsv*zV256i", "n", "amx-tile") // AMX TARGET_BUILTIN(__builtin_ia32_tile_loadconfig, "vvC*", "n", "amx-tile") TARGET_BUILTIN(__builtin_ia32_tile_storeconfig, "vvC*", "n", "amx-tile") diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index d90e403915ed376852da2e7140f899caa0517919..50a778e2a328a436f4b5291c0b28c6d5dbde351f 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -61,8 +61,7 @@ CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0 CODEGENOPT(ExperimentalStrictFloatingPoint, 1, 0) ///< Enables the new, experimental ///< strict floating point. -CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental - ///< pass manager. +CODEGENOPT(LegacyPassManager, 1, 0) ///< Use the legacy pass manager. CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new ///< pass manager. CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. @@ -252,7 +251,8 @@ CODEGENOPT(SpeculativeLoadHardening, 1, 0) ///< Enable speculative load hardenin CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers -CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled. +CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report or -ftime-report= is enabled. +CODEGENOPT(TimePassesPerRun , 1, 0) ///< Set when -ftime-report=per-pass-run is enabled. CODEGENOPT(TimeTrace , 1, 0) ///< Set when -ftime-trace is enabled. VALUE_CODEGENOPT(TimeTraceGranularity, 32, 500) ///< Minimum time granularity (in microseconds), ///< traced by time profiler @@ -366,10 +366,6 @@ VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0) /// Whether to report the hotness of the code region for optimization remarks. CODEGENOPT(DiagnosticsWithHotness, 1, 0) -/// The minimum hotness value a diagnostic needs in order to be included in -/// optimization diagnostics. -VALUE_CODEGENOPT(DiagnosticsHotnessThreshold, 32, 0) - /// Whether copy relocations support is available when building as PIE. CODEGENOPT(PIECopyRelocations, 1, 0) @@ -380,6 +376,9 @@ CODEGENOPT(StrictReturn, 1, 1) /// Whether emit extra debug info for sample pgo profile collection. CODEGENOPT(DebugInfoForProfiling, 1, 0) +/// Whether emit pseudo probes for sample pgo profile collection. +CODEGENOPT(PseudoProbeForProfiling, 1, 0) + /// Whether 3-component vector type is preserved. CODEGENOPT(PreserveVec3Type, 1, 0) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index e710c5792d76254049d0a88dd9a9a302fbec6a18..5c540812ed312511447a7549f5a8e719b6f680eb 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -346,6 +346,21 @@ public: const char *Argv0 = nullptr; ArrayRef CommandLineArgs; + /// The minimum hotness value a diagnostic needs in order to be included in + /// optimization diagnostics. + /// + /// The threshold is an Optional value, which maps to one of the 3 states: + /// 1. 0 => threshold disabled. All remarks will be printed. + /// 2. positive int => manual threshold by user. Remarks with hotness exceed + /// threshold will be printed. + /// 3. None => 'auto' threshold by user. The actual value is not + /// available at command line, but will be synced with + /// hotness threshold from profile summary during + /// compilation. + /// + /// If threshold option is not specified, it is disabled by default. + Optional DiagnosticsHotnessThreshold = 0; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 2f4e4ce924ad2f90793ef5af7f0ad398b13e5134..dd94fd1a7ff88154191658e6d37fcabde957cbbf 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -81,7 +81,7 @@ def err_drv_cuda_host_arch : Error<"unsupported architecture '%0' for host compi def err_drv_mix_cuda_hip : Error<"Mixed Cuda and HIP compilation is not supported.">; def err_drv_bad_target_id : Error<"Invalid target ID: %0 (A target ID is a processor name " "followed by an optional list of predefined features post-fixed by a plus or minus sign deliminated " - "by colon, e.g. 'gfx908:sram-ecc+:xnack-')">; + "by colon, e.g. 'gfx908:sramecc+:xnack-')">; def err_drv_bad_offload_arch_combo : Error<"Invalid offload arch combinations: %0 and %1 (For a specific " "processor, a feature should either exist in all offload archs, or not exist in any offload archs)">; def err_drv_invalid_thread_model_for_target : Error< @@ -119,6 +119,8 @@ def err_drv_command_failure : Error< "unable to execute command: %0">; def err_drv_invalid_darwin_version : Error< "invalid Darwin version number: %0">; +def err_drv_invalid_diagnotics_hotness_threshold : Error< + "invalid argument in '%0', only integer or 'auto' is supported">; def err_drv_missing_argument : Error< "argument to '%0' is missing (expected %1 value%s1)">; def err_drv_invalid_Xarch_argument_with_args : Error< @@ -292,6 +294,9 @@ def warn_drv_unsupported_opt_for_target : Warning< def warn_drv_unsupported_debug_info_opt_for_target : Warning< "debug information option '%0' is not supported for target '%1'">, InGroup; +def warn_drv_dwarf_version_limited_by_target : Warning< + "debug information option '%0' is not supported. It needs DWARF-%2 but target '%1' only provides DWARF-%3.">, + InGroup; def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">; def warn_ignoring_fdiscard_for_bitcode : Warning< @@ -531,9 +536,6 @@ def err_drv_cannot_mix_options : Error<"cannot specify '%1' along with '%0'">; def err_drv_invalid_object_mode : Error<"OBJECT_MODE setting %0 is not recognized and is not a valid setting.">; -def err_drv_invalid_sve_vector_bits : Error< - "'-msve-vector-bits' is not supported without SVE enabled">; - def err_aix_default_altivec_abi : Error< "The default Altivec ABI on AIX is not yet supported, use '-mabi=vec-extabi' for the extended Altivec ABI">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4e7e16156beacf070eb55ca483301c438c91cf47..cc1a20bbc1de18a99ad57805b278db35c0feca22 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1062,6 +1062,10 @@ def warn_objc_direct_property_ignored : Warning< InGroup; def err_objc_direct_dynamic_property : Error< "direct property cannot be @dynamic">; +def err_objc_direct_protocol_conformance : Error< + "%select{category %1|class extension}0 cannot conform to protocol %2 because " + "of direct members declared in interface %3">; +def note_direct_member_here : Note<"direct member declared here">; def warn_conflicting_overriding_ret_types : Warning< "conflicting return type in " @@ -2448,7 +2452,7 @@ def err_for_range_decl_must_be_var : Error< "for range declaration must declare a variable">; def err_for_range_storage_class : Error< "loop variable %0 may not be declared %select{'extern'|'static'|" - "'__private_extern__'|'auto'|'register'|'constexpr'}1">; + "'__private_extern__'|'auto'|'register'|'constexpr'|'thread_local'}1">; def err_type_defined_in_for_range : Error< "types may not be defined in a for range declaration">; def err_for_range_deduction_failure : Error< @@ -2839,7 +2843,8 @@ def warn_unsupported_target_attribute "attribute ignored">, InGroup; def err_attribute_unsupported - : Error<"%0 attribute is not supported for this target">; + : Error<"%0 attribute is not supported on targets missing %1;" + " specify an appropriate -march= or -mcpu=">; // The err_*_attribute_argument_not_int are separate because they're used by // VerifyIntegerConstantExpression. def err_aligned_attribute_argument_not_int : Error< @@ -3937,6 +3942,9 @@ def note_protocol_decl : Note< "protocol is declared here">; def note_protocol_decl_undefined : Note< "protocol %0 has no definition">; +def err_attribute_preferred_name_arg_invalid : Error< + "argument %0 to 'preferred_name' attribute is not a typedef for " + "a specialization of %1">; // objc_designated_initializer attribute diagnostics. def warn_objc_designated_init_missing_super_call : Warning< @@ -4028,7 +4036,12 @@ def warn_attr_swift_name_subscript_getter_newValue : Warning<"%0 attribute for 'subscript' getter cannot have a 'newValue:' parameter">, InGroup; def warn_attr_swift_name_num_params - : Warning<"too %select{few|many}0 parameters in %1 attribute (expected %2; got %3)">, + : Warning<"too %select{few|many}0 parameters in the signature specified by " + "the %1 attribute (expected %2; got %3)">, + InGroup; +def warn_attr_swift_name_decl_missing_params + : Warning<"%0 attribute cannot be applied to a %select{function|method}1 " + "with no parameters">, InGroup; def err_attr_swift_error_no_error_parameter : Error< @@ -4038,6 +4051,13 @@ def err_attr_swift_error_return_type : Error< "%0 attribute with '%1' convention can only be applied to a " "%select{function|method}2 returning %select{an integral type|a pointer}3">; +def err_swift_async_no_access : Error< + "first argument to 'swift_async' must be either 'none', 'swift_private', or " + "'not_swift_private'">; +def err_swift_async_bad_block_type : Error< + "'swift_async' completion handler parameter must have block type returning" + " 'void', type here is %0">; + def warn_ignored_objc_externally_retained : Warning< "'objc_externally_retained' can only be applied to local variables " "%select{of retainable type|with strong ownership}0">, @@ -5158,7 +5178,8 @@ def err_unexpanded_parameter_pack : Error< "using declaration|friend declaration|qualifier|initializer|default argument|" "non-type template parameter type|exception type|partial specialization|" "__if_exists name|__if_not_exists name|lambda|block|type constraint|" - "requirement}0 contains%plural{0: an|:}1 unexpanded parameter pack" + "requirement|requires clause}0 " + "contains%plural{0: an|:}1 unexpanded parameter pack" "%plural{0:|1: %2|2:s %2 and %3|:s %2, %3, ...}1">; def err_pack_expansion_without_parameter_packs : Error< @@ -5204,11 +5225,17 @@ def ext_undeclared_unqual_id_with_dependent_base : ExtWarn< "use of undeclared identifier %0; " "unqualified lookup into dependent bases of class template %1 is a Microsoft extension">, InGroup; -def ext_found_via_dependent_bases_lookup : ExtWarn<"use of identifier %0 " +def err_found_in_dependent_base : Error< + "explicit qualification required to use member %0 from dependent base class">; +def ext_found_in_dependent_base : ExtWarn<"use of member %0 " "found via unqualified lookup into dependent bases of class templates is a " "Microsoft extension">, InGroup; -def note_dependent_var_use : Note<"must qualify identifier to find this " - "declaration in dependent base class">; +def err_found_later_in_class : Error<"member %0 used before its declaration">; +def ext_found_later_in_class : ExtWarn< + "use of member %0 before its declaration is a Microsoft extension">, + InGroup; +def note_dependent_member_use : Note< + "must qualify identifier to find this declaration in dependent base class">; def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neither " "visible in the template definition nor found by argument-dependent lookup">; def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to the " @@ -8145,7 +8172,7 @@ def err_global_call_not_config : Error< "call to global function %0 not configured">; def err_ref_bad_target : Error< "reference to %select{__device__|__global__|__host__|__host__ __device__}0 " - "function %1 in %select{__device__|__global__|__host__|__host__ __device__}2 function">; + "%select{function|variable}1 %2 in %select{__device__|__global__|__host__|__host__ __device__}3 function">; def err_ref_bad_target_global_initializer : Error< "reference to %select{__device__|__global__|__host__|__host__ __device__}0 " "function %1 in global initializer">; diff --git a/clang/include/clang/Basic/DirectoryEntry.h b/clang/include/clang/Basic/DirectoryEntry.h index 7c634709ca9b2e05caf228e7aaed1a18c053560e..e0f4ae28321a35121ab9b18a9621aaeaee11ce13 100644 --- a/clang/include/clang/Basic/DirectoryEntry.h +++ b/clang/include/clang/Basic/DirectoryEntry.h @@ -15,11 +15,18 @@ #define LLVM_CLANG_BASIC_DIRECTORYENTRY_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorOr.h" namespace clang { +namespace FileMgr { + +template class MapEntryOptionalStorage; + +} // end namespace FileMgr /// Cached information about one directory (either on disk or in /// the virtual file system). @@ -37,20 +44,255 @@ public: /// as it was accessed by the FileManager's client. class DirectoryEntryRef { public: - const DirectoryEntry &getDirEntry() const { return *Entry->getValue(); } + const DirectoryEntry &getDirEntry() const { return *ME->getValue(); } + + StringRef getName() const { return ME->getKey(); } + + /// Hash code is based on the DirectoryEntry, not the specific named + /// reference. + friend llvm::hash_code hash_value(DirectoryEntryRef Ref) { + return llvm::hash_value(&Ref.getDirEntry()); + } + + using MapEntry = llvm::StringMapEntry>; + + const MapEntry &getMapEntry() const { return *ME; } + + /// Check if RHS referenced the file in exactly the same way. + bool isSameRef(DirectoryEntryRef RHS) const { return ME == RHS.ME; } - StringRef getName() const { return Entry->getKey(); } + DirectoryEntryRef() = delete; + DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {} + + /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to + /// facilitate incremental adoption. + /// + /// The goal is to avoid code churn due to dances like the following: + /// \code + /// // Old code. + /// lvalue = rvalue; + /// + /// // Temporary code from an incremental patch. + /// lvalue = &rvalue.getDirectoryEntry(); + /// + /// // Final code. + /// lvalue = rvalue; + /// \endcode + /// + /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::getName + /// has been deleted, delete this implicit conversion. + operator const DirectoryEntry *() const { return &getDirEntry(); } private: - friend class FileManager; + friend class FileMgr::MapEntryOptionalStorage; + struct optional_none_tag {}; + + // Private constructor for use by OptionalStorage. + DirectoryEntryRef(optional_none_tag) : ME(nullptr) {} + bool hasOptionalValue() const { return ME; } + + friend struct llvm::DenseMapInfo; + struct dense_map_empty_tag {}; + struct dense_map_tombstone_tag {}; + + // Private constructors for use by DenseMapInfo. + DirectoryEntryRef(dense_map_empty_tag) + : ME(llvm::DenseMapInfo::getEmptyKey()) {} + DirectoryEntryRef(dense_map_tombstone_tag) + : ME(llvm::DenseMapInfo::getTombstoneKey()) {} + bool isSpecialDenseMapKey() const { + return isSameRef(DirectoryEntryRef(dense_map_empty_tag())) || + isSameRef(DirectoryEntryRef(dense_map_tombstone_tag())); + } + + const MapEntry *ME; +}; - DirectoryEntryRef( - llvm::StringMapEntry> *Entry) - : Entry(Entry) {} +namespace FileMgr { - const llvm::StringMapEntry> *Entry; +/// Customized storage for refs derived from map entires in FileManager, using +/// the private optional_none_tag to keep it to the size of a single pointer. +template class MapEntryOptionalStorage { + using optional_none_tag = typename RefTy::optional_none_tag; + RefTy MaybeRef; + +public: + MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {} + + template + explicit MapEntryOptionalStorage(llvm::optional_detail::in_place_t, + ArgTypes &&...Args) + : MaybeRef(std::forward(Args)...) {} + + void reset() { MaybeRef = optional_none_tag(); } + + bool hasValue() const { return MaybeRef.hasOptionalValue(); } + + RefTy &getValue() LLVM_LVALUE_FUNCTION { + assert(hasValue()); + return MaybeRef; + } + RefTy const &getValue() const LLVM_LVALUE_FUNCTION { + assert(hasValue()); + return MaybeRef; + } +#if LLVM_HAS_RVALUE_REFERENCE_THIS + RefTy &&getValue() && { + assert(hasValue()); + return std::move(MaybeRef); + } +#endif + + template void emplace(Args &&...args) { + MaybeRef = RefTy(std::forward(args)...); + } + + MapEntryOptionalStorage &operator=(RefTy Ref) { + MaybeRef = Ref; + return *this; + } }; +} // end namespace FileMgr +} // end namespace clang + +namespace llvm { +namespace optional_detail { + +/// Customize OptionalStorage to use DirectoryEntryRef and +/// its optional_none_tag to keep it the size of a single pointer. +template <> +class OptionalStorage + : public clang::FileMgr::MapEntryOptionalStorage { + using StorageImpl = + clang::FileMgr::MapEntryOptionalStorage; + +public: + OptionalStorage() = default; + + template + explicit OptionalStorage(in_place_t, ArgTypes &&...Args) + : StorageImpl(in_place_t{}, std::forward(Args)...) {} + + OptionalStorage &operator=(clang::DirectoryEntryRef Ref) { + StorageImpl::operator=(Ref); + return *this; + } +}; + +static_assert(sizeof(Optional) == + sizeof(clang::DirectoryEntryRef), + "Optional must avoid size overhead"); + +static_assert( + std::is_trivially_copyable>::value, + "Optional should be trivially copyable"); + +} // end namespace optional_detail + +/// Specialisation of DenseMapInfo for DirectoryEntryRef. +template <> struct DenseMapInfo { + static inline clang::DirectoryEntryRef getEmptyKey() { + return clang::DirectoryEntryRef( + clang::DirectoryEntryRef::dense_map_empty_tag()); + } + + static inline clang::DirectoryEntryRef getTombstoneKey() { + return clang::DirectoryEntryRef( + clang::DirectoryEntryRef::dense_map_tombstone_tag()); + } + + static unsigned getHashValue(clang::DirectoryEntryRef Val) { + return hash_value(Val); + } + + static bool isEqual(clang::DirectoryEntryRef LHS, + clang::DirectoryEntryRef RHS) { + // Catch the easy cases: both empty, both tombstone, or the same ref. + if (LHS.isSameRef(RHS)) + return true; + + // Confirm LHS and RHS are valid. + if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey()) + return false; + + // It's safe to use operator==. + return LHS == RHS; + } +}; + +} // end namespace llvm + +namespace clang { + +/// Wrapper around Optional that degrades to 'const +/// DirectoryEntry*', facilitating incremental patches to propagate +/// DirectoryEntryRef. +/// +/// This class can be used as return value or field where it's convenient for +/// an Optional to degrade to a 'const DirectoryEntry*'. The +/// purpose is to avoid code churn due to dances like the following: +/// \code +/// // Old code. +/// lvalue = rvalue; +/// +/// // Temporary code from an incremental patch. +/// Optional MaybeF = rvalue; +/// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr; +/// +/// // Final code. +/// lvalue = rvalue; +/// \endcode +/// +/// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef +/// and DirectoryEntry::getName have been deleted, delete this class and +/// replace instances with Optional. +class OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr + : public Optional { +public: + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr() = default; + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr( + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default; + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr( + const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default; + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & + operator=(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default; + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & + operator=(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default; + + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(llvm::NoneType) {} + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(DirectoryEntryRef Ref) + : Optional(Ref) {} + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(Optional MaybeRef) + : Optional(MaybeRef) {} + + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(llvm::NoneType) { + Optional::operator=(None); + return *this; + } + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(DirectoryEntryRef Ref) { + Optional::operator=(Ref); + return *this; + } + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & + operator=(Optional MaybeRef) { + Optional::operator=(MaybeRef); + return *this; + } + + /// Degrade to 'const DirectoryEntry *' to allow DirectoryEntry::LastRef and + /// DirectoryEntry::getName have been deleted, delete this class and replace + /// instances with Optional + operator const DirectoryEntry *() const { + return hasValue() ? &getValue().getDirEntry() : nullptr; + } +}; + +static_assert(std::is_trivially_copyable< + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value, + "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be " + "trivially copyable"); + } // end namespace clang #endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 302c56763c39a9ff91efdc4cdb9fdca037fb16ad..5424da67b62daaff37e1f71414decc54ac768b58 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -85,6 +85,7 @@ FEATURE(cxx_rtti, LangOpts.RTTI &&LangOpts.RTTIData) FEATURE(enumerator_attributes, true) FEATURE(nullability, true) FEATURE(nullability_on_arrays, true) +FEATURE(nullability_nullable_result, true) FEATURE(memory_sanitizer, LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory)) diff --git a/clang/include/clang/Basic/FileEntry.h b/clang/include/clang/Basic/FileEntry.h index e4c2e7e34db9680da0da5ac6a5374962e6b546ba..aa7bedec44ac13b3cf5ef25d78ab62b44e080f61 100644 --- a/clang/include/clang/Basic/FileEntry.h +++ b/clang/include/clang/Basic/FileEntry.h @@ -14,7 +14,10 @@ #ifndef LLVM_CLANG_BASIC_FILEENTRY_H #define LLVM_CLANG_BASIC_FILEENTRY_H +#include "clang/Basic/DirectoryEntry.h" #include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -47,7 +50,6 @@ class OptionalStorage; namespace clang { -class DirectoryEntry; class FileEntry; /// A reference to a \c FileEntry that includes the name of the file as it was @@ -58,6 +60,7 @@ public: const FileEntry &getFileEntry() const { return *ME->second->V.get(); } + DirectoryEntryRef getDir() const { return *ME->second->Dir; } inline bool isValid() const; inline off_t getSize() const; @@ -87,6 +90,12 @@ public: return !(LHS == RHS); } + /// Hash code is based on the FileEntry, not the specific named reference, + /// just like operator==. + friend llvm::hash_code hash_value(FileEntryRef Ref) { + return llvm::hash_value(&Ref.getFileEntry()); + } + struct MapValue; /// Type used in the StringMap. @@ -104,8 +113,11 @@ public: /// gcc5.3. Once that's no longer supported, change this back. llvm::PointerUnion V; + /// Directory the file was found in. Set if and only if V is a FileEntry. + Optional Dir; + MapValue() = delete; - MapValue(FileEntry &FE) : V(&FE) {} + MapValue(FileEntry &FE, DirectoryEntryRef Dir) : V(&FE), Dir(Dir) {} MapValue(MapEntry &ME) : V(&ME) {} }; @@ -143,14 +155,27 @@ public: const clang::FileEntryRef::MapEntry &getMapEntry() const { return *ME; } private: - friend class llvm::optional_detail::OptionalStorage< - FileEntryRef, /*is_trivially_copyable*/ true>; + friend class FileMgr::MapEntryOptionalStorage; struct optional_none_tag {}; // Private constructor for use by OptionalStorage. FileEntryRef(optional_none_tag) : ME(nullptr) {} bool hasOptionalValue() const { return ME; } + friend struct llvm::DenseMapInfo; + struct dense_map_empty_tag {}; + struct dense_map_tombstone_tag {}; + + // Private constructors for use by DenseMapInfo. + FileEntryRef(dense_map_empty_tag) + : ME(llvm::DenseMapInfo::getEmptyKey()) {} + FileEntryRef(dense_map_tombstone_tag) + : ME(llvm::DenseMapInfo::getTombstoneKey()) {} + bool isSpecialDenseMapKey() const { + return isSameRef(FileEntryRef(dense_map_empty_tag())) || + isSameRef(FileEntryRef(dense_map_tombstone_tag())); + } + const MapEntry *ME; }; @@ -167,46 +192,21 @@ namespace optional_detail { /// Customize OptionalStorage to use FileEntryRef and its /// optional_none_tag to keep it the size of a single pointer. -template <> class OptionalStorage { - clang::FileEntryRef MaybeRef; +template <> +class OptionalStorage + : public clang::FileMgr::MapEntryOptionalStorage { + using StorageImpl = + clang::FileMgr::MapEntryOptionalStorage; public: - ~OptionalStorage() = default; - OptionalStorage() : MaybeRef(clang::FileEntryRef::optional_none_tag()) {} - OptionalStorage(OptionalStorage const &Other) = default; - OptionalStorage(OptionalStorage &&Other) = default; - OptionalStorage &operator=(OptionalStorage const &Other) = default; - OptionalStorage &operator=(OptionalStorage &&Other) = default; + OptionalStorage() = default; template explicit OptionalStorage(in_place_t, ArgTypes &&...Args) - : MaybeRef(std::forward(Args)...) {} - - void reset() { MaybeRef = clang::FileEntryRef::optional_none_tag(); } - - bool hasValue() const { return MaybeRef.hasOptionalValue(); } - - clang::FileEntryRef &getValue() LLVM_LVALUE_FUNCTION { - assert(hasValue()); - return MaybeRef; - } - clang::FileEntryRef const &getValue() const LLVM_LVALUE_FUNCTION { - assert(hasValue()); - return MaybeRef; - } -#if LLVM_HAS_RVALUE_REFERENCE_THIS - clang::FileEntryRef &&getValue() && { - assert(hasValue()); - return std::move(MaybeRef); - } -#endif - - template void emplace(Args &&...args) { - MaybeRef = clang::FileEntryRef(std::forward(args)...); - } + : StorageImpl(in_place_t{}, std::forward(Args)...) {} OptionalStorage &operator=(clang::FileEntryRef Ref) { - MaybeRef = Ref; + StorageImpl::operator=(Ref); return *this; } }; @@ -219,6 +219,35 @@ static_assert(std::is_trivially_copyable>::value, "Optional should be trivially copyable"); } // end namespace optional_detail + +/// Specialisation of DenseMapInfo for FileEntryRef. +template <> struct DenseMapInfo { + static inline clang::FileEntryRef getEmptyKey() { + return clang::FileEntryRef(clang::FileEntryRef::dense_map_empty_tag()); + } + + static inline clang::FileEntryRef getTombstoneKey() { + return clang::FileEntryRef(clang::FileEntryRef::dense_map_tombstone_tag()); + } + + static unsigned getHashValue(clang::FileEntryRef Val) { + return hash_value(Val); + } + + static bool isEqual(clang::FileEntryRef LHS, clang::FileEntryRef RHS) { + // Catch the easy cases: both empty, both tombstone, or the same ref. + if (LHS.isSameRef(RHS)) + return true; + + // Confirm LHS and RHS are valid. + if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey()) + return false; + + // It's safe to use operator==. + return LHS == RHS; + } +}; + } // end namespace llvm namespace clang { @@ -299,13 +328,13 @@ class FileEntry { friend class FileManager; std::string RealPathName; // Real path to the file; could be empty. - off_t Size; // File size in bytes. - time_t ModTime; // Modification time of file. - const DirectoryEntry *Dir; // Directory file lives in. + off_t Size = 0; // File size in bytes. + time_t ModTime = 0; // Modification time of file. + const DirectoryEntry *Dir = nullptr; // Directory file lives in. llvm::sys::fs::UniqueID UniqueID; - unsigned UID; // A unique (small) ID for the file. - bool IsNamedPipe; - bool IsValid; // Is this \c FileEntry initialized and valid? + unsigned UID = 0; // A unique (small) ID for the file. + bool IsNamedPipe = false; + bool IsValid = false; // Is this \c FileEntry initialized and valid? /// The open file, if it is owned by the \p FileEntry. mutable std::unique_ptr File; diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index d7135a4f0ac3b3f126a343f6ffcbedd6444bb457..449aec2b3541e975876cc46f7786b661de1da50d 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -239,6 +239,9 @@ public: /// if there were a file with the given name on disk. /// /// The file itself is not accessed. + FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size, + time_t ModificationTime); + const FileEntry *getVirtualFile(StringRef Filename, off_t Size, time_t ModificationTime); diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index b718a385efaa9f09802e0bbb103fb4ac09b458f2..7228f06fa907fcf2f8969f113860d9b0f359658b 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -92,6 +92,7 @@ LANGOPT(CPlusPlus11 , 1, 0, "C++11") LANGOPT(CPlusPlus14 , 1, 0, "C++14") LANGOPT(CPlusPlus17 , 1, 0, "C++17") LANGOPT(CPlusPlus20 , 1, 0, "C++20") +LANGOPT(CPlusPlus2b , 1, 0, "C++2b") LANGOPT(ObjC , 1, 0, "Objective-C") BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0, "Objective-C auto-synthesized properties") @@ -244,6 +245,7 @@ LANGOPT(GPURelocatableDeviceCode, 1, 0, "generate relocatable device code") LANGOPT(GPUAllowDeviceInit, 1, 0, "allowing device side global init functions for HIP") LANGOPT(GPUMaxThreadsPerBlock, 32, 256, "default max threads per block for kernel launch bounds for HIP") LANGOPT(GPUDeferDiag, 1, 0, "defer host/device related diagnostic messages for CUDA/HIP") +LANGOPT(GPUExcludeWrongSideOverloads, 1, 0, "always exclude wrong side overloads in overloading resolution for CUDA/HIP") LANGOPT(SYCL , 1, 0, "SYCL") LANGOPT(SYCLIsDevice , 1, 0, "Generate code for SYCL device") diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h index ad7f7510b2348d0bacb1e621085ac6ce5608e899..f82ce05a6369282683e9f61c7a572f52616f0895 100644 --- a/clang/include/clang/Basic/LangStandard.h +++ b/clang/include/clang/Basic/LangStandard.h @@ -49,11 +49,12 @@ enum LangFeatures { CPlusPlus14 = (1 << 7), CPlusPlus17 = (1 << 8), CPlusPlus20 = (1 << 9), - Digraphs = (1 << 10), - GNUMode = (1 << 11), - HexFloat = (1 << 12), - ImplicitInt = (1 << 13), - OpenCL = (1 << 14) + CPlusPlus2b = (1 << 10), + Digraphs = (1 << 11), + GNUMode = (1 << 12), + HexFloat = (1 << 13), + ImplicitInt = (1 << 14), + OpenCL = (1 << 15) }; /// LangStandard - Information about the properties of a particular language @@ -111,6 +112,9 @@ public: /// isCPlusPlus20 - Language is a C++20 variant (or later). bool isCPlusPlus20() const { return Flags & CPlusPlus20; } + /// isCPlusPlus2b - Language is a post-C++20 variant (or later). + bool isCPlusPlus2b() const { return Flags & CPlusPlus2b; } + /// hasDigraphs - Language supports digraphs. bool hasDigraphs() const { return Flags & Digraphs; } diff --git a/clang/include/clang/Basic/LangStandards.def b/clang/include/clang/Basic/LangStandards.def index 7b915c31274654616c8ba0380fb742bdce3dbe19..f086d8a43ccb5920c1f8169c046f86c7d310c6d4 100644 --- a/clang/include/clang/Basic/LangStandards.def +++ b/clang/include/clang/Basic/LangStandards.def @@ -152,6 +152,16 @@ LANGSTANDARD(gnucxx20, "gnu++20", CPlusPlus20 | Digraphs | HexFloat | GNUMode) LANGSTANDARD_ALIAS_DEPR(gnucxx20, "gnu++2a") +LANGSTANDARD(cxx2b, "c++2b", + CXX, "Working draft for ISO C++ 2023 DIS", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | + CPlusPlus20 | CPlusPlus2b | Digraphs | HexFloat) + +LANGSTANDARD(gnucxx2b, "gnu++2b", + CXX, "Working draft for ISO C++ 2023 DIS with GNU extensions", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | + CPlusPlus20 | CPlusPlus2b | Digraphs | HexFloat | GNUMode) + // OpenCL LANGSTANDARD(opencl10, "cl1.0", OpenCL, "OpenCL 1.0", diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index 82ea1f462949a8fc27ab1b944f8cbb798a6055ba..f5b176f8d20b205b7030f90789ba7c5f51829185 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -133,7 +133,9 @@ public: std::string PresumedModuleMapFile; /// The umbrella header or directory. - llvm::PointerUnion Umbrella; + llvm::PointerUnion + Umbrella; /// The module signature. ASTFileSignature Signature; @@ -188,18 +190,18 @@ public: /// file. struct Header { std::string NameAsWritten; - const FileEntry *Entry; + OptionalFileEntryRefDegradesToFileEntryPtr Entry; - explicit operator bool() { return Entry; } + explicit operator bool() { return Entry != None; } }; /// Information about a directory name as found in the module map /// file. struct DirectoryName { std::string NameAsWritten; - const DirectoryEntry *Entry; + OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr Entry; - explicit operator bool() { return Entry; } + explicit operator bool() { return Entry != None; } }; /// The headers that are part of this module. @@ -544,15 +546,15 @@ public: /// Retrieve the header that serves as the umbrella header for this /// module. Header getUmbrellaHeader() const { - if (auto *FE = Umbrella.dyn_cast()) - return Header{UmbrellaAsWritten, FE}; + if (auto *ME = Umbrella.dyn_cast()) + return Header{UmbrellaAsWritten, FileEntryRef(*ME)}; return Header{}; } /// Determine whether this module has an umbrella directory that is /// not based on an umbrella header. bool hasUmbrellaDir() const { - return Umbrella && Umbrella.is(); + return Umbrella && Umbrella.is(); } /// Add a top-level header associated with this module. diff --git a/clang/include/clang/Basic/OpenCLExtensions.def b/clang/include/clang/Basic/OpenCLExtensions.def index d67cb3ff019b4d848b5720fe8089a71819ba564c..17d402f300f1f4709dc3c59212799d89aef02c1f 100644 --- a/clang/include/clang/Basic/OpenCLExtensions.def +++ b/clang/include/clang/Basic/OpenCLExtensions.def @@ -66,13 +66,6 @@ OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_mipmap_image_writes, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_subgroups, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_extended_types, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_vote, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_ballot, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_arithmetic, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_shuffle_relative, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_subgroup_clustered_reduce, 200, ~0U) // Clang Extensions. OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U) diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index b231644330ed127ff9df8f622d063c4b07edf804..a43b4766218045142395d55990663e74d3db50c1 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -35,6 +35,7 @@ #define LLVM_CLANG_BASIC_SOURCEMANAGER_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/FileEntry.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" @@ -60,8 +61,6 @@ namespace clang { class ASTReader; class ASTWriter; class FileManager; -class FileEntry; -class FileEntryRef; class LineTableInfo; class SourceManager; @@ -959,6 +958,10 @@ public: /// data in the given source file. void overrideFileContents(const FileEntry *SourceFile, std::unique_ptr Buffer); + void overrideFileContents(FileEntryRef SourceFile, + std::unique_ptr Buffer) { + overrideFileContents(&SourceFile.getFileEntry(), std::move(Buffer)); + } /// Override the given source file with another one. /// @@ -982,11 +985,11 @@ public: } /// Bypass the overridden contents of a file. This creates a new FileEntry - /// and initializes the content cache for it. Returns nullptr if there is no + /// and initializes the content cache for it. Returns None if there is no /// such file in the filesystem. /// /// This should be called before parsing has begun. - const FileEntry *bypassFileContentsOverride(const FileEntry &File); + Optional bypassFileContentsOverride(FileEntryRef File); /// Specify that a file is transient. void setFileIsTransient(const FileEntry *SourceFile); @@ -1030,6 +1033,13 @@ public: return nullptr; } + /// Returns the FileEntryRef for the provided FileID. + Optional getFileEntryRefForID(FileID FID) const { + if (auto *Entry = getFileEntryForID(FID)) + return Entry->getLastRef(); + return None; + } + /// Returns the filename for the provided FileID, unless it's a built-in /// buffer that's not represented by a filename. /// @@ -1583,6 +1593,9 @@ public: /// If the source file is included multiple times, the FileID will be the /// first inclusion. FileID translateFile(const FileEntry *SourceFile) const; + FileID translateFile(FileEntryRef SourceFile) const { + return translateFile(&SourceFile.getFileEntry()); + } /// Get the source location in \p FID for the given line:col. /// Returns null location if \p FID is not a file SLocEntry. diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index 46e7caa1e725b3e1a0307ac071bac213f458f5ff..6b8457e2fd381375f3b4dca11d009e14409c9d6b 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -314,7 +314,12 @@ namespace clang { /// unspecified. This captures a (fairly rare) case where we /// can't conclude anything about the nullability of the type even /// though it has been considered. - Unspecified + Unspecified, + // Generally behaves like Nullable, except when used in a block parameter + // that was imported into a swift async method. There, swift will assume + // that the parameter can get null even if no error occured. _Nullable + // parameters are assumed to only get null on error. + NullableResult, }; /// Return true if \p L has a weaker nullability annotation than \p R. The diff --git a/clang/include/clang/Basic/TargetCXXABI.h b/clang/include/clang/Basic/TargetCXXABI.h index 30145ac6913860a25b56c45bf6f14d6e57928a4e..2d267f43f92b5715fb0be534810b4f2dd2362d06 100644 --- a/clang/include/clang/Basic/TargetCXXABI.h +++ b/clang/include/clang/Basic/TargetCXXABI.h @@ -62,17 +62,17 @@ public: /// - constructor/destructor signatures. iOS, - /// The iOS 64-bit ABI is follows ARM's published 64-bit ABI more - /// closely, but we don't guarantee to follow it perfectly. + /// The iOS 64-bit and macOS 64-bit ARM ABI follows ARM's published 64-bit + /// ABI more closely, but we don't guarantee to follow it perfectly. /// /// It is documented here: /// http://infocenter.arm.com /// /help/topic/com.arm.doc.ihi0059a/IHI0059A_cppabi64.pdf - iOS64, + AppleARM64, /// WatchOS is a modernisation of the iOS ABI, which roughly means it's - /// the iOS64 ABI ported to 32-bits. The primary difference from iOS64 is - /// that RTTI objects must still be unique at the moment. + /// the AppleARM64 ABI ported to 32-bits. The primary difference from + /// AppleARM64 is that RTTI objects must still be unique at the moment. WatchOS, /// The generic AArch64 ABI is also a modified version of the Itanium ABI, @@ -98,7 +98,7 @@ public: /// - guard variables are 32-bit on wasm32, as in ARM; /// - unused bits of guard variables are reserved, as in ARM; /// - inline functions are never key functions, as in ARM; - /// - C++11 POD rules are used for tail padding, as in iOS64. + /// - C++11 POD rules are used for tail padding, as in AppleARM64. /// /// TODO: At present the WebAssembly ABI is not considered stable, so none /// of these details is necessarily final yet. @@ -147,12 +147,12 @@ public: /// Does this ABI generally fall into the Itanium family of ABIs? bool isItaniumFamily() const { switch (getKind()) { + case AppleARM64: case Fuchsia: case GenericAArch64: case GenericItanium: case GenericARM: case iOS: - case iOS64: case WatchOS: case GenericMIPS: case WebAssembly: @@ -168,12 +168,12 @@ public: /// Is this ABI an MSVC-compatible ABI? bool isMicrosoft() const { switch (getKind()) { + case AppleARM64: case Fuchsia: case GenericAArch64: case GenericItanium: case GenericARM: case iOS: - case iOS64: case WatchOS: case GenericMIPS: case WebAssembly: @@ -200,6 +200,7 @@ public: case WebAssembly: // WebAssembly doesn't require any special alignment for member functions. return false; + case AppleARM64: case Fuchsia: case GenericARM: case GenericAArch64: @@ -209,7 +210,6 @@ public: // special alignment and could therefore also return false. case GenericItanium: case iOS: - case iOS64: case WatchOS: case Microsoft: case XL: @@ -277,9 +277,9 @@ public: /// done on a generic Itanium platform. bool canKeyFunctionBeInline() const { switch (getKind()) { + case AppleARM64: case Fuchsia: case GenericARM: - case iOS64: case WebAssembly: case WatchOS: return false; @@ -330,10 +330,10 @@ public: case XL: return UseTailPaddingUnlessPOD03; - // iOS on ARM64 and WebAssembly use the C++11 POD rules. They do not honor + // AppleARM64 and WebAssembly use the C++11 POD rules. They do not honor // the Itanium exception about classes with over-large bitfields. + case AppleARM64: case Fuchsia: - case iOS64: case WebAssembly: case WatchOS: return UseTailPaddingUnlessPOD11; diff --git a/clang/include/clang/Basic/TargetID.h b/clang/include/clang/Basic/TargetID.h index 95fd61d22eb1751f545c88f04519c190c66e6f5b..1a9785574d06984bdb318788d2d96d56d0ad2b9a 100644 --- a/clang/include/clang/Basic/TargetID.h +++ b/clang/include/clang/Basic/TargetID.h @@ -19,7 +19,7 @@ namespace clang { /// Get all feature strings that can be used in target ID for \p Processor. /// Target ID is a processor name with optional feature strings /// postfixed by a plus or minus sign delimited by colons, e.g. -/// gfx908:xnack+:sram-ecc-. Each processor have a limited +/// gfx908:xnack+:sramecc-. Each processor have a limited /// number of predefined features when showing up in a target ID. const llvm::SmallVector getAllPossibleTargetIDFeatures(const llvm::Triple &T, diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 698964b94ee24f5cdfe9b0b9064ae03356a7051e..de91ca2ee82efed4dbfa6e21dace0b0bb356744d 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1098,6 +1098,13 @@ public: /// either; the entire thing is pretty badly mangled. virtual bool hasProtectedVisibility() const { return true; } + /// Does this target aim for semantic compatibility with + /// Microsoft C++ code using dllimport/export attributes? + virtual bool shouldDLLImportComdatSymbols() const { + return getTriple().isWindowsMSVCEnvironment() || + getTriple().isWindowsItaniumEnvironment() || getTriple().isPS4CPU(); + } + /// An optional hook that targets can implement to perform semantic /// checking on attribute((section("foo"))) specifiers. /// diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 789fdfeb0b85cd30cb78aa921a13041417ced216..f2bb33cd3bfaee3cc796a338294ecff389f94aea 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -657,6 +657,7 @@ ALIAS("__volatile__" , volatile , KEYALL) // Type nullability. KEYWORD(_Nonnull , KEYALL) KEYWORD(_Nullable , KEYALL) +KEYWORD(_Nullable_result , KEYALL) KEYWORD(_Null_unspecified , KEYALL) // Microsoft extensions which should be disabled in strict conformance mode diff --git a/clang/include/clang/Basic/arm_neon.td b/clang/include/clang/Basic/arm_neon.td index feccf2e15dc0a02e36d296f46cf095532e736414..4d4e42dd514bf28b763a34fbe3c97e580cca2351 100644 --- a/clang/include/clang/Basic/arm_neon.td +++ b/clang/include/clang/Basic/arm_neon.td @@ -1902,22 +1902,34 @@ let ArchGuard = "defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC)" in { def VFMLALT_LANEQ_BF : SOpInst<"vbfmlalt_laneq", "..B(BQ)I", "Qf", OP_BFMLALT_LN>; } +multiclass VCMLA_ROTS { + foreach ROT = ["", "_rot90", "_rot180", "_rot270" ] in { + def : SInst<"vcmla" # ROT, "....", type # "Q" # type>; + } +} + // v8.3-A Vector complex addition intrinsics let ArchGuard = "defined(__ARM_FEATURE_COMPLEX) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in { def VCADD_ROT90_FP16 : SInst<"vcadd_rot90", "...", "h">; def VCADD_ROT270_FP16 : SInst<"vcadd_rot270", "...", "h">; def VCADDQ_ROT90_FP16 : SInst<"vcaddq_rot90", "QQQ", "h">; def VCADDQ_ROT270_FP16 : SInst<"vcaddq_rot270", "QQQ", "h">; + + defm VCMLA_FP16 : VCMLA_ROTS<"h", "uint32x2_t", "uint32x4_t">; } let ArchGuard = "defined(__ARM_FEATURE_COMPLEX)" in { def VCADD_ROT90 : SInst<"vcadd_rot90", "...", "f">; def VCADD_ROT270 : SInst<"vcadd_rot270", "...", "f">; def VCADDQ_ROT90 : SInst<"vcaddq_rot90", "QQQ", "f">; def VCADDQ_ROT270 : SInst<"vcaddq_rot270", "QQQ", "f">; + + defm VCMLA_F32 : VCMLA_ROTS<"f", "uint64x1_t", "uint64x2_t">; } let ArchGuard = "defined(__ARM_FEATURE_COMPLEX) && defined(__aarch64__)" in { def VCADDQ_ROT90_FP64 : SInst<"vcaddq_rot90", "QQQ", "d">; def VCADDQ_ROT270_FP64 : SInst<"vcaddq_rot270", "QQQ", "d">; + + defm VCMLA_FP64 : VCMLA_ROTS<"d", "uint64x2_t", "uint64x2_t">; } // V8.2-A BFloat intrinsics diff --git a/clang/include/clang/Config/config.h.cmake b/clang/include/clang/Config/config.h.cmake index 26e9d5c4eb4d39a34d90a13df846bff08b999760..a240862c528953c466347e8970145f50edfcabf1 100644 --- a/clang/include/clang/Config/config.h.cmake +++ b/clang/include/clang/Config/config.h.cmake @@ -75,9 +75,6 @@ /* enable x86 relax relocations by default */ #cmakedefine01 ENABLE_X86_RELAX_RELOCATIONS -/* Enable the experimental new pass manager by default */ -#cmakedefine01 ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER - /* Enable each functionality of modules */ #cmakedefine01 CLANG_ENABLE_ARCMT #cmakedefine01 CLANG_ENABLE_OBJC_REWRITER diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e0e45188d66abf7e62d95195dff89288bc2eb3f7..3aa862ba71b7bdf716300f896f38e573aeb48cd8 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -246,10 +246,11 @@ def clang_ignored_gcc_optimization_f_Group : OptionGroup< // This is useful if the option is usually disabled. multiclass OptInFFlag flags=[], code keypath="", - DefaultAnyOf defaults = DefaultAnyOf<[]>> { + list