diff --git a/.github/workflows/libclang-abi-tests.yml b/.github/workflows/libclang-abi-tests.yml index 90e816b0eaedd..8cc2f3a0fa3fa 100644 --- a/.github/workflows/libclang-abi-tests.yml +++ b/.github/workflows/libclang-abi-tests.yml @@ -124,12 +124,10 @@ jobs: - name: Dump ABI run: | parallel abi-dumper -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o {}-${{ matrix.ref }}.abi ./build/lib/{} ::: ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} - # Remove symbol versioning from dumps, so we can compare across major - # versions. We don't need to do this for libclang.so since its ABI - # is stable across major releases and the symbol versions don't change. - if [ -e libclang-cpp.so-${{ matrix.ref }}.abi ]; then - sed -i 's/LLVM_[0-9]\+/LLVM_NOVERSION/' libclang-cpp.so-${{ matrix.ref }}.abi - fi + for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do + # Remove symbol versioning from dumps, so we can compare across major versions. + sed -i 's/LLVM_[0-9]\+/LLVM_NOVERSION/' $lib-${{ matrix.ref }}.abi + done - name: Upload ABI file uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/llvm-project-tests.yml b/.github/workflows/llvm-project-tests.yml index 4910ddbe5cfd4..a32fe80ae11cc 100644 --- a/.github/workflows/llvm-project-tests.yml +++ b/.github/workflows/llvm-project-tests.yml @@ -39,15 +39,21 @@ jobs: - windows-2019 # We're using a specific version of macOS due to: # https://github.com/actions/virtual-environments/issues/5900 - # We need addtional testing to see if our workaround works for - # new macOS builds. - - macOS-10.15 + - macOS-11 steps: - name: Setup Windows if: startsWith(matrix.os, 'windows') uses: llvm/actions/setup-windows@main with: arch: amd64 + # On Windows, starting with win19/20220814.1, cmake choose the 32-bit + # python3.10.6 libraries instead of the 64-bit libraries when building + # lldb. Using this setup-python action to make 3.10 the default + # python fixes this. + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' - name: Install Ninja uses: llvm/actions/install-ninja@main # actions/checkout deletes any existing files in the new git directory, @@ -74,7 +80,7 @@ jobs: env: # Workaround for https://github.com/actions/virtual-environments/issues/5900. # This should be a no-op for non-mac OSes - PKG_CONFIG_PATH: /usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig//11 + PKG_CONFIG_PATH: /usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig//12 with: cmake_args: '-GNinja -DLLVM_ENABLE_PROJECTS="${{ inputs.projects }}" -DCMAKE_BUILD_TYPE=Release -DLLDB_INCLUDE_TESTS=OFF -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache' build_target: '${{ inputs.build_target }}' diff --git a/.github/workflows/release-tasks.yml b/.github/workflows/release-tasks.yml index a87805b878607..71de6b29b7756 100644 --- a/.github/workflows/release-tasks.yml +++ b/.github/workflows/release-tasks.yml @@ -15,7 +15,7 @@ jobs: - name: Validate Tag id: validate-tag run: | - test "${{ github.actor }}" = "tstellar" + test "${{ github.actor }}" = "tstellar" || test "${{ github.actor }}" = "tru" echo "${{ github.ref_name }}" | grep -e '^llvmorg-[0-9]\+\.[0-9]\+\.[0-9]\+\(-rc[0-9]\+\)\?$' release_version=`echo "${{ github.ref_name }}" | sed 's/llvmorg-//g'` echo "::set-output name=release-version::$release_version" diff --git a/.github/workflows/version-check.py b/.github/workflows/version-check.py index 74c061ee9e95f..d052bd3a5686b 100755 --- a/.github/workflows/version-check.py +++ b/.github/workflows/version-check.py @@ -4,25 +4,29 @@ import re import sys + +def get_version_from_tag(tag): + m = re.match('llvmorg-([0-9]+)\.([0-9]+)\.([0-9]+)(-rc[0-9]+)?$', tag) + if m: + if m.lastindex == 4: + # We have an rc tag. + return m.group(1,2,3) + # We have a final release tag. + return (m.group(1), m.group(2), str(int(m.group(3)) + 1)) + + m = re.match('llvmorg-([0-9]+)-init', tag) + if m: + return (int(m.group(1)) + 1, 0, 0) + + raise Exception(f"error: Tag is not valid: {tag}") + + version = sys.argv[1] repo = Repo() tag = repo.git.describe(tags = True, abbrev=0) -m = re.match('llvmorg-([0-9]+)\.([0-9]+)\.([0-9]+)', tag) -if not m: - print("error: Tag is not valid: ", tag) - sys.exit(1) - -expected_major = m.group(1) -expected_minor = m.group(2) -expected_patch = int(m.group(3)) + 1 -expected_version = f"{expected_major}.{expected_minor}.{expected_patch}" - -m = re.match("[0-9]+\.[0-9]+\.[0-9]+", version) -if not m: - print("error: Version is not valid: ", version) - sys.exit(1) +expected_version = '.'.join(get_version_from_tag(tag)) if version != expected_version: print("error: Expected version", expected_version, "but found version", version) diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp index c963307960146..f0c59fb695239 100644 --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -1593,7 +1593,7 @@ void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower // .debug_line if (LineStrSection) { - LineStr = MCDwarfLineStr(*BC.Ctx); + LineStr.emplace(*BC.Ctx); parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC, Streamer); } diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt index 04172db29ea5e..de76b4b00c360 100644 --- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -3,12 +3,18 @@ set(LLVM_LINK_COMPONENTS Support ) -if(LLVM_USE_HOST_TOOLS) - build_native_tool(make-confusable-table make_confusable_table) +set(CLANG_TIDY_CONFUSABLE_CHARS_GEN "clang-tidy-confusable-chars-gen" CACHE + STRING "Host clang-tidy-confusable-chars-gen executable. Saves building if cross-compiling.") + +if(NOT CLANG_TIDY_CONFUSABLE_CHARS_GEN STREQUAL "clang-tidy-confusable-chars-gen") + set(make_confusable_table ${CLANG_TIDY_CONFUSABLE_CHARS_GEN}) + set(make_confusable_table_target ${CLANG_TIDY_CONFUSABLE_CHARS_GEN}) +elseif(LLVM_USE_HOST_TOOLS) + build_native_tool(clang-tidy-confusable-chars-gen make_confusable_table) set(make_confusable_table_target "${make_confusable_table}") else() - set(make_confusable_table $) - set(make_confusable_table_target make-confusable-table) + set(make_confusable_table $) + set(make_confusable_table_target clang-tidy-confusable-chars-gen) endif() add_subdirectory(ConfusableTable) diff --git a/clang-tools-extra/clang-tidy/misc/ConfusableTable/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/ConfusableTable/CMakeLists.txt index a35f206fbf783..f0ad2dbc0c578 100644 --- a/clang-tools-extra/clang-tidy/misc/ConfusableTable/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/ConfusableTable/CMakeLists.txt @@ -1,6 +1,6 @@ set(LLVM_LINK_COMPONENTS Support) list(REMOVE_ITEM LLVM_COMMON_DEPENDS clang-tablegen-targets) -add_llvm_executable(make-confusable-table +add_llvm_executable(clang-tidy-confusable-chars-gen BuildConfusableTable.cpp ) diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp index 83111a1c752b0..2ce1dc14c3b0d 100644 --- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp @@ -12,8 +12,6 @@ #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" -#include - using namespace clang::ast_matchers; namespace clang { @@ -132,6 +130,12 @@ void ConstCorrectnessCheck::check(const MatchFinder::MatchResult &Result) { VC = VariableCategory::Reference; if (Variable->getType()->isPointerType()) VC = VariableCategory::Pointer; + if (Variable->getType()->isArrayType()) { + if (const auto *ArrayT = dyn_cast(Variable->getType())) { + if (ArrayT->getElementType()->isPointerType()) + VC = VariableCategory::Pointer; + } + } // Each variable can only be in one category: Value, Pointer, Reference. // Analysis can be controlled for every category. diff --git a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp index 8ae990a929dfd..afb4a1044a79a 100644 --- a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp @@ -472,8 +472,8 @@ class SimplifyBooleanExprCheck::Visitor : public RecursiveASTVisitor { checkSingleStatement(If->getThen(), parseReturnLiteralBool); if (ThenReturnBool && ThenReturnBool.Bool != TrailingReturnBool.Bool) { - if (Check->ChainedConditionalReturn || - (!PrevIf && If->getElse() == nullptr)) { + if ((Check->ChainedConditionalReturn || !PrevIf) && + If->getElse() == nullptr) { Check->replaceCompoundReturnWithCondition( Context, cast(*Second), TrailingReturnBool.Bool, If, ThenReturnBool.Item); diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index 0cc3792a0fdd2..66bda05d00f71 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -26,6 +26,8 @@ #include "support/Trace.h" #include "clang/Tooling/Core/Replacement.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringRef.h" @@ -571,8 +573,12 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, {"referencesProvider", true}, {"astProvider", true}, // clangd extension {"typeHierarchyProvider", true}, - {"memoryUsageProvider", true}, // clangd extension - {"compilationDatabase", // clangd extension + // Unfortunately our extension made use of the same capability name as the + // standard. Advertise this capability to tell clients that implement our + // extension we really have support for the standardized one as well. + {"standardTypeHierarchyProvider", true}, // clangd extension + {"memoryUsageProvider", true}, // clangd extension + {"compilationDatabase", // clangd extension llvm::json::Object{{"automaticReload", true}}}, {"callHierarchyProvider", true}, {"clangdInlayHintsProvider", true}, @@ -1183,18 +1189,94 @@ void ClangdLSPServer::onHover(const TextDocumentPositionParams &Params, }); } -void ClangdLSPServer::onTypeHierarchy( - const TypeHierarchyParams &Params, - Callback> Reply) { +// Our extension has a different representation on the wire than the standard. +// https://clangd.llvm.org/extensions#type-hierarchy +llvm::json::Value serializeTHIForExtension(TypeHierarchyItem THI) { + llvm::json::Object Result{{ + {"name", std::move(THI.name)}, + {"kind", static_cast(THI.kind)}, + {"uri", std::move(THI.uri)}, + {"range", THI.range}, + {"selectionRange", THI.selectionRange}, + {"data", std::move(THI.data)}, + }}; + if (THI.deprecated) + Result["deprecated"] = THI.deprecated; + if (THI.detail) + Result["detail"] = std::move(*THI.detail); + + if (THI.parents) { + llvm::json::Array Parents; + for (auto &Parent : *THI.parents) + Parents.emplace_back(serializeTHIForExtension(std::move(Parent))); + Result["parents"] = std::move(Parents); + } + + if (THI.children) { + llvm::json::Array Children; + for (auto &child : *THI.children) + Children.emplace_back(serializeTHIForExtension(std::move(child))); + Result["children"] = std::move(Children); + } + return Result; +} + +void ClangdLSPServer::onTypeHierarchy(const TypeHierarchyPrepareParams &Params, + Callback Reply) { + auto Serialize = + [Reply = std::move(Reply)]( + llvm::Expected> Resp) mutable { + if (!Resp) { + Reply(Resp.takeError()); + return; + } + if (Resp->empty()) { + Reply(nullptr); + return; + } + Reply(serializeTHIForExtension(std::move(Resp->front()))); + }; Server->typeHierarchy(Params.textDocument.uri.file(), Params.position, - Params.resolve, Params.direction, std::move(Reply)); + Params.resolve, Params.direction, std::move(Serialize)); } void ClangdLSPServer::onResolveTypeHierarchy( const ResolveTypeHierarchyItemParams &Params, - Callback> Reply) { + Callback Reply) { + auto Serialize = + [Reply = std::move(Reply)]( + llvm::Expected> Resp) mutable { + if (!Resp) { + Reply(Resp.takeError()); + return; + } + if (!*Resp) { + Reply(std::move(*Resp)); + return; + } + Reply(serializeTHIForExtension(std::move(**Resp))); + }; Server->resolveTypeHierarchy(Params.item, Params.resolve, Params.direction, - std::move(Reply)); + std::move(Serialize)); +} + +void ClangdLSPServer::onPrepareTypeHierarchy( + const TypeHierarchyPrepareParams &Params, + Callback> Reply) { + Server->typeHierarchy(Params.textDocument.uri.file(), Params.position, + Params.resolve, Params.direction, std::move(Reply)); +} + +void ClangdLSPServer::onSuperTypes( + const ResolveTypeHierarchyItemParams &Params, + Callback>> Reply) { + Server->superTypes(Params.item, std::move(Reply)); +} + +void ClangdLSPServer::onSubTypes( + const ResolveTypeHierarchyItemParams &Params, + Callback> Reply) { + Server->subTypes(Params.item, std::move(Reply)); } void ClangdLSPServer::onPrepareCallHierarchy( @@ -1523,6 +1605,9 @@ void ClangdLSPServer::bindMethods(LSPBinder &Bind, Bind.method("textDocument/symbolInfo", this, &ClangdLSPServer::onSymbolInfo); Bind.method("textDocument/typeHierarchy", this, &ClangdLSPServer::onTypeHierarchy); Bind.method("typeHierarchy/resolve", this, &ClangdLSPServer::onResolveTypeHierarchy); + Bind.method("textDocument/prepareTypeHierarchy", this, &ClangdLSPServer::onPrepareTypeHierarchy); + Bind.method("typeHierarchy/supertypes", this, &ClangdLSPServer::onSuperTypes); + Bind.method("typeHierarchy/subtypes", this, &ClangdLSPServer::onSubTypes); Bind.method("textDocument/prepareCallHierarchy", this, &ClangdLSPServer::onPrepareCallHierarchy); Bind.method("callHierarchy/incomingCalls", this, &ClangdLSPServer::onCallHierarchyIncomingCalls); Bind.method("textDocument/selectionRange", this, &ClangdLSPServer::onSelectionRange); diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h index 562f8e060161f..351b3d0da0be7 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.h +++ b/clang-tools-extra/clangd/ClangdLSPServer.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace clang { namespace clangd { @@ -132,10 +133,16 @@ class ClangdLSPServer : private ClangdServer::Callbacks, void onRename(const RenameParams &, Callback); void onHover(const TextDocumentPositionParams &, Callback>); - void onTypeHierarchy(const TypeHierarchyParams &, - Callback>); + void onPrepareTypeHierarchy(const TypeHierarchyPrepareParams &, + Callback>); + void onSuperTypes(const ResolveTypeHierarchyItemParams &, + Callback>>); + void onSubTypes(const ResolveTypeHierarchyItemParams &, + Callback>); + void onTypeHierarchy(const TypeHierarchyPrepareParams &, + Callback); void onResolveTypeHierarchy(const ResolveTypeHierarchyItemParams &, - Callback>); + Callback); void onPrepareCallHierarchy(const CallHierarchyPrepareParams &, Callback>); void onCallHierarchyIncomingCalls( diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index c3e7242c19342..cca632a0c6b88 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -751,7 +751,7 @@ void ClangdServer::findHover(PathRef File, Position Pos, void ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve, TypeHierarchyDirection Direction, - Callback> CB) { + Callback> CB) { auto Action = [File = File.str(), Pos, Resolve, Direction, CB = std::move(CB), this](Expected InpAST) mutable { if (!InpAST) @@ -763,6 +763,22 @@ void ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve, WorkScheduler->runWithAST("TypeHierarchy", File, std::move(Action)); } +void ClangdServer::superTypes( + const TypeHierarchyItem &Item, + Callback>> CB) { + WorkScheduler->run("typeHierarchy/superTypes", /*Path=*/"", + [=, CB = std::move(CB)]() mutable { + CB(clangd::superTypes(Item, Index)); + }); +} + +void ClangdServer::subTypes(const TypeHierarchyItem &Item, + Callback> CB) { + WorkScheduler->run( + "typeHierarchy/subTypes", /*Path=*/"", + [=, CB = std::move(CB)]() mutable { CB(clangd::subTypes(Item, Index)); }); +} + void ClangdServer::resolveTypeHierarchy( TypeHierarchyItem Item, int Resolve, TypeHierarchyDirection Direction, Callback> CB) { diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h index dacb7b74af99d..5095c2e05c403 100644 --- a/clang-tools-extra/clangd/ClangdServer.h +++ b/clang-tools-extra/clangd/ClangdServer.h @@ -253,7 +253,13 @@ class ClangdServer { /// Get information about type hierarchy for a given position. void typeHierarchy(PathRef File, Position Pos, int Resolve, TypeHierarchyDirection Direction, - Callback> CB); + Callback> CB); + /// Get direct parents of a type hierarchy item. + void superTypes(const TypeHierarchyItem &Item, + Callback>> CB); + /// Get direct children of a type hierarchy item. + void subTypes(const TypeHierarchyItem &Item, + Callback> CB); /// Resolve type hierarchy item in the given direction. void resolveTypeHierarchy(TypeHierarchyItem Item, int Resolve, diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index edbb1722ae38e..55982f41250f5 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -486,6 +486,9 @@ struct CodeCompletionBuilder { // we need to complete 'forward<$1>($0)'. return "($0)"; + if (Snippet->empty()) + return ""; + bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function || Completion.Kind == CompletionItemKind::Method || Completion.Kind == CompletionItemKind::Constructor || @@ -524,8 +527,6 @@ struct CodeCompletionBuilder { return *Snippet; // Replace argument snippets with a simplified pattern. - if (Snippet->empty()) - return ""; if (MayHaveArgList) { // Functions snippets can be of 2 types: // - containing only function arguments, e.g. diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index 12aa9dacc2dfe..8db57f234591d 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -220,10 +220,13 @@ void CommandMangler::adjust(std::vector &Cmd, ArgList = OptTable.ParseArgs( llvm::makeArrayRef(OriginalArgs).drop_front(), IgnoredCount, IgnoredCount, /*FlagsToInclude=*/ - IsCLMode ? (driver::options::CLOption | driver::options::CoreOption) + IsCLMode ? (driver::options::CLOption | driver::options::CoreOption | + driver::options::CLDXCOption) : /*everything*/ 0, /*FlagsToExclude=*/driver::options::NoDriverOption | - (IsCLMode ? 0 : driver::options::CLOption)); + (IsCLMode + ? 0 + : (driver::options::CLOption | driver::options::CLDXCOption))); llvm::SmallVector IndicesToDrop; // Having multiple architecture options (e.g. when building fat binaries) diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index e70d45769fe46..031192f763e6e 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -918,9 +918,19 @@ llvm::Optional getDiagnosticDocURI(Diag::DiagSource Source, // information to be worth linking. // https://clang.llvm.org/docs/DiagnosticsReference.html break; - case Diag::ClangTidy: - return {("https://clang.llvm.org/extra/clang-tidy/checks/" + Name + ".html") - .str()}; + case Diag::ClangTidy: { + StringRef Module, Check; + // This won't correctly get the module for clang-analyzer checks, but as we + // don't link in the analyzer that shouldn't be an issue. + // This would also need updating if anyone decides to create a module with a + // '-' in the name. + std::tie(Module, Check) = Name.split('-'); + if (Module.empty() || Check.empty()) + return llvm::None; + return ("https://clang.llvm.org/extra/clang-tidy/checks/" + Module + "/" + + Check + ".html") + .str(); + } case Diag::Clangd: if (Name == "unused-includes") return {"https://clangd.llvm.org/guides/include-cleaner"}; diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp index cb7abac3e9f9e..af22a446b03ce 100644 --- a/clang-tools-extra/clangd/Headers.cpp +++ b/clang-tools-extra/clangd/Headers.cpp @@ -22,9 +22,17 @@ namespace clang { namespace clangd { -const char IWYUPragmaKeep[] = "// IWYU pragma: keep"; -const char IWYUPragmaExport[] = "// IWYU pragma: export"; -const char IWYUPragmaBeginExports[] = "// IWYU pragma: begin_exports"; +llvm::Optional parseIWYUPragma(const char *Text) { + // This gets called for every comment seen in the preamble, so it's quite hot. + constexpr llvm::StringLiteral IWYUPragma = "// IWYU pragma: "; + if (strncmp(Text, IWYUPragma.data(), IWYUPragma.size())) + return llvm::None; + Text += IWYUPragma.size(); + const char *End = Text; + while (*End != 0 && *End != '\n') + ++End; + return StringRef(Text, End - Text); +} class IncludeStructure::RecordHeaders : public PPCallbacks, public CommentHandler { @@ -129,10 +137,10 @@ class IncludeStructure::RecordHeaders : public PPCallbacks, } bool HandleComment(Preprocessor &PP, SourceRange Range) override { - bool Err = false; - llvm::StringRef Text = SM.getCharacterData(Range.getBegin(), &Err); - if (Err) + auto Pragma = parseIWYUPragma(SM.getCharacterData(Range.getBegin())); + if (!Pragma) return false; + if (inMainFile()) { // Given: // @@ -150,8 +158,7 @@ class IncludeStructure::RecordHeaders : public PPCallbacks, // will know that the next inclusion is behind the IWYU pragma. // FIXME: Support "IWYU pragma: begin_exports" and "IWYU pragma: // end_exports". - if (!Text.startswith(IWYUPragmaExport) && - !Text.startswith(IWYUPragmaKeep)) + if (!Pragma->startswith("export") && !Pragma->startswith("keep")) return false; unsigned Offset = SM.getFileOffset(Range.getBegin()); LastPragmaKeepInMainFileLine = @@ -161,8 +168,7 @@ class IncludeStructure::RecordHeaders : public PPCallbacks, // does not support them properly yet, so they will be not marked as // unused. // FIXME: Once IncludeCleaner supports export pragmas, remove this. - if (!Text.startswith(IWYUPragmaExport) && - !Text.startswith(IWYUPragmaBeginExports)) + if (!Pragma->startswith("export") && !Pragma->startswith("begin_exports")) return false; Out->HasIWYUExport.insert( *Out->getID(SM.getFileEntryForID(SM.getFileID(Range.getBegin())))); diff --git a/clang-tools-extra/clangd/Headers.h b/clang-tools-extra/clangd/Headers.h index ff3f063168325..ba72ad397bf8f 100644 --- a/clang-tools-extra/clangd/Headers.h +++ b/clang-tools-extra/clangd/Headers.h @@ -35,6 +35,12 @@ namespace clangd { /// Returns true if \p Include is literal include like "path" or . bool isLiteralInclude(llvm::StringRef Include); +/// If Text begins an Include-What-You-Use directive, returns it. +/// Given "// IWYU pragma: keep", returns "keep". +/// Input is a null-terminated char* as provided by SM.getCharacterData(). +/// (This should not be StringRef as we do *not* want to scan for its length). +llvm::Optional parseIWYUPragma(const char *Text); + /// Represents a header file to be #include'd. struct HeaderFile { std::string File; diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 9b3b2b1c53224..16c6b1cecc031 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -10,6 +10,7 @@ #include "Config.h" #include "HeuristicResolver.h" #include "ParsedAST.h" +#include "SourceCode.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExprCXX.h" @@ -141,8 +142,10 @@ void collectDesignators(const InitListExpr *Sem, Fields.next(); // Always advance to the next subobject name. Prefix.resize(Size); // Erase any designator we appended. }); - if (llvm::isa(Init)) - continue; // a "hole" for a subobject that was not explicitly initialized + // Skip for a broken initializer or if it is a "hole" in a subobject that + // was not explicitly initialized. + if (!Init || llvm::isa(Init)) + continue; const auto *BraceElidedSubobject = llvm::dyn_cast(Init); if (BraceElidedSubobject && @@ -190,8 +193,8 @@ class InlayHintVisitor : public RecursiveASTVisitor { public: InlayHintVisitor(std::vector &Results, ParsedAST &AST, const Config &Cfg, llvm::Optional RestrictRange) - : Results(Results), AST(AST.getASTContext()), Cfg(Cfg), - RestrictRange(std::move(RestrictRange)), + : Results(Results), AST(AST.getASTContext()), Tokens(AST.getTokens()), + Cfg(Cfg), RestrictRange(std::move(RestrictRange)), MainFileID(AST.getSourceManager().getMainFileID()), Resolver(AST.getHeuristicResolver()), TypeHintPolicy(this->AST.getPrintingPolicy()), @@ -225,8 +228,7 @@ class InlayHintVisitor : public RecursiveASTVisitor { return true; } - processCall(E->getParenOrBraceRange().getBegin(), E->getConstructor(), - {E->getArgs(), E->getNumArgs()}); + processCall(E->getConstructor(), {E->getArgs(), E->getNumArgs()}); return true; } @@ -252,7 +254,7 @@ class InlayHintVisitor : public RecursiveASTVisitor { if (!Callee) return true; - processCall(E->getRParenLoc(), Callee, {E->getArgs(), E->getNumArgs()}); + processCall(Callee, {E->getArgs(), E->getNumArgs()}); return true; } @@ -276,11 +278,11 @@ class InlayHintVisitor : public RecursiveASTVisitor { return true; } - void addReturnTypeHint(FunctionDecl *D, SourceLocation Loc) { + void addReturnTypeHint(FunctionDecl *D, SourceRange Range) { auto *AT = D->getReturnType()->getContainedAutoType(); if (!AT || AT->getDeducedType().isNull()) return; - addTypeHint(Loc, D->getReturnType(), /*Prefix=*/"-> "); + addTypeHint(Range, D->getReturnType(), /*Prefix=*/"-> "); } bool VisitVarDecl(VarDecl *D) { @@ -373,21 +375,11 @@ class InlayHintVisitor : public RecursiveASTVisitor { private: using NameVec = SmallVector; - // The purpose of Anchor is to deal with macros. It should be the call's - // opening or closing parenthesis or brace. (Always using the opening would - // make more sense but CallExpr only exposes the closing.) We heuristically - // assume that if this location does not come from a macro definition, then - // the entire argument list likely appears in the main file and can be hinted. - void processCall(SourceLocation Anchor, const FunctionDecl *Callee, + void processCall(const FunctionDecl *Callee, llvm::ArrayRef Args) { if (!Cfg.InlayHints.Parameters || Args.size() == 0 || !Callee) return; - // If the anchor location comes from a macro defintion, there's nowhere to - // put hints. - if (!AST.getSourceManager().getTopMacroCallerLoc(Anchor).isFileID()) - return; - // The parameter name of a move or copy constructor is not very interesting. if (auto *Ctor = dyn_cast(Callee)) if (Ctor->isCopyOrMoveConstructor()) @@ -635,25 +627,33 @@ class InlayHintVisitor : public RecursiveASTVisitor { #undef CHECK_KIND } - auto FileRange = - toHalfOpenFileRange(AST.getSourceManager(), AST.getLangOpts(), R); - if (!FileRange) + auto LSPRange = getHintRange(R); + if (!LSPRange) return; - Range LSPRange{ - sourceLocToPosition(AST.getSourceManager(), FileRange->getBegin()), - sourceLocToPosition(AST.getSourceManager(), FileRange->getEnd())}; - Position LSPPos = Side == HintSide::Left ? LSPRange.start : LSPRange.end; + Position LSPPos = Side == HintSide::Left ? LSPRange->start : LSPRange->end; if (RestrictRange && (LSPPos < RestrictRange->start || !(LSPPos < RestrictRange->end))) return; - // The hint may be in a file other than the main file (for example, a header - // file that was included after the preamble), do not show in that case. - if (!AST.getSourceManager().isWrittenInMainFile(FileRange->getBegin())) - return; bool PadLeft = Prefix.consume_front(" "); bool PadRight = Suffix.consume_back(" "); Results.push_back(InlayHint{LSPPos, (Prefix + Label + Suffix).str(), Kind, - PadLeft, PadRight, LSPRange}); + PadLeft, PadRight, *LSPRange}); + } + + // Get the range of the main file that *exactly* corresponds to R. + llvm::Optional getHintRange(SourceRange R) { + const auto &SM = AST.getSourceManager(); + auto Spelled = Tokens.spelledForExpanded(Tokens.expandedTokens(R)); + // TokenBuffer will return null if e.g. R corresponds to only part of a + // macro expansion. + if (!Spelled || Spelled->empty()) + return llvm::None; + // Hint must be within the main file, not e.g. a non-preamble include. + if (SM.getFileID(Spelled->front().location()) != SM.getMainFileID() || + SM.getFileID(Spelled->back().location()) != SM.getMainFileID()) + return llvm::None; + return Range{sourceLocToPosition(SM, Spelled->front().location()), + sourceLocToPosition(SM, Spelled->back().endLocation())}; } void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix) { @@ -678,6 +678,7 @@ class InlayHintVisitor : public RecursiveASTVisitor { std::vector &Results; ASTContext &AST; + const syntax::TokenBuffer &Tokens; const Config &Cfg; llvm::Optional RestrictRange; FileID MainFileID; diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index ab75faaf98586..0a8e6dec1ea59 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -1199,12 +1199,13 @@ bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out, return true; } -bool fromJSON(const llvm::json::Value &Params, TypeHierarchyParams &R, +bool fromJSON(const llvm::json::Value &Params, TypeHierarchyPrepareParams &R, llvm::json::Path P) { llvm::json::ObjectMapper O(Params, P); return O && O.map("textDocument", R.textDocument) && - O.map("position", R.position) && O.map("resolve", R.resolve) && - O.map("direction", R.direction); + O.map("position", R.position) && + mapOptOrNull(Params, "resolve", R.resolve, P) && + mapOptOrNull(Params, "direction", R.direction, P); } llvm::raw_ostream &operator<<(llvm::raw_ostream &O, @@ -1212,23 +1213,28 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &O, return O << I.name << " - " << toJSON(I); } +llvm::json::Value toJSON(const TypeHierarchyItem::ResolveParams &RP) { + llvm::json::Object Result{{"symbolID", RP.symbolID}}; + if (RP.parents) + Result["parents"] = RP.parents; + return std::move(Result); +} +bool fromJSON(const llvm::json::Value &Params, + TypeHierarchyItem::ResolveParams &RP, llvm::json::Path P) { + llvm::json::ObjectMapper O(Params, P); + return O && O.map("symbolID", RP.symbolID) && + mapOptOrNull(Params, "parents", RP.parents, P); +} + llvm::json::Value toJSON(const TypeHierarchyItem &I) { - llvm::json::Object Result{{"name", I.name}, - {"kind", static_cast(I.kind)}, - {"range", I.range}, - {"selectionRange", I.selectionRange}, - {"uri", I.uri}}; + llvm::json::Object Result{ + {"name", I.name}, {"kind", static_cast(I.kind)}, + {"range", I.range}, {"selectionRange", I.selectionRange}, + {"uri", I.uri}, {"data", I.data}, + }; if (I.detail) Result["detail"] = I.detail; - if (I.deprecated) - Result["deprecated"] = I.deprecated; - if (I.parents) - Result["parents"] = I.parents; - if (I.children) - Result["children"] = I.children; - if (I.data) - Result["data"] = I.data; return std::move(Result); } @@ -1250,8 +1256,9 @@ bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I, bool fromJSON(const llvm::json::Value &Params, ResolveTypeHierarchyItemParams &R, llvm::json::Path P) { llvm::json::ObjectMapper O(Params, P); - return O && O.map("item", R.item) && O.map("resolve", R.resolve) && - O.map("direction", R.direction); + return O && O.map("item", R.item) && + mapOptOrNull(Params, "resolve", R.resolve, P) && + mapOptOrNull(Params, "direction", R.direction, P); } bool fromJSON(const llvm::json::Value &Params, ReferenceContext &R, @@ -1498,5 +1505,22 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ASTNode &Root) { return OS; } +bool fromJSON(const llvm::json::Value &E, SymbolID &S, llvm::json::Path P) { + auto Str = E.getAsString(); + if (!Str) { + P.report("expected a string"); + return false; + } + auto ID = SymbolID::fromStr(*Str); + if (!ID) { + elog("Malformed symbolid: {0}", ID.takeError()); + P.report("malformed symbolid"); + return false; + } + S = *ID; + return true; +} +llvm::json::Value toJSON(const SymbolID &S) { return S.str(); } + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index 0087017efad4f..181e837770580 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -77,6 +77,9 @@ class LSPError : public llvm::ErrorInfo { } }; +bool fromJSON(const llvm::json::Value &, SymbolID &, llvm::json::Path); +llvm::json::Value toJSON(const SymbolID &); + // URI in "file" scheme for a file. struct URIForFile { URIForFile() = default; @@ -1375,58 +1378,66 @@ bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out, /// The type hierarchy params is an extension of the /// `TextDocumentPositionsParams` with optional properties which can be used to /// eagerly resolve the item when requesting from the server. -struct TypeHierarchyParams : public TextDocumentPositionParams { +struct TypeHierarchyPrepareParams : public TextDocumentPositionParams { /// The hierarchy levels to resolve. `0` indicates no level. + /// This is a clangd extension. int resolve = 0; /// The direction of the hierarchy levels to resolve. + /// This is a clangd extension. TypeHierarchyDirection direction = TypeHierarchyDirection::Parents; }; -bool fromJSON(const llvm::json::Value &, TypeHierarchyParams &, +bool fromJSON(const llvm::json::Value &, TypeHierarchyPrepareParams &, llvm::json::Path); struct TypeHierarchyItem { - /// The human readable name of the hierarchy item. + /// The name of this item. std::string name; - /// Optional detail for the hierarchy item. It can be, for instance, the - /// signature of a function or method. - llvm::Optional detail; - - /// The kind of the hierarchy item. For instance, class or interface. + /// The kind of this item. SymbolKind kind; - /// `true` if the hierarchy item is deprecated. Otherwise, `false`. - bool deprecated = false; + /// More detail for this item, e.g. the signature of a function. + llvm::Optional detail; - /// The URI of the text document where this type hierarchy item belongs to. + /// The resource identifier of this item. URIForFile uri; - /// The range enclosing this type hierarchy item not including - /// leading/trailing whitespace but everything else like comments. This - /// information is typically used to determine if the client's cursor is - /// inside the type hierarch item to reveal in the symbol in the UI. + /// The range enclosing this symbol not including leading/trailing whitespace + /// but everything else, e.g. comments and code. Range range; - /// The range that should be selected and revealed when this type hierarchy - /// item is being picked, e.g. the name of a function. Must be contained by - /// the `range`. + /// The range that should be selected and revealed when this symbol is being + /// picked, e.g. the name of a function. Must be contained by the `range`. Range selectionRange; - /// If this type hierarchy item is resolved, it contains the direct parents. - /// Could be empty if the item does not have direct parents. If not defined, - /// the parents have not been resolved yet. + /// Used to resolve a client provided item back. + struct ResolveParams { + SymbolID symbolID; + /// None means parents aren't resolved and empty is no parents. + llvm::Optional> parents; + }; + /// A data entry field that is preserved between a type hierarchy prepare and + /// supertypes or subtypes requests. It could also be used to identify the + /// type hierarchy in the server, helping improve the performance on resolving + /// supertypes and subtypes. + ResolveParams data; + + /// `true` if the hierarchy item is deprecated. Otherwise, `false`. + /// This is a clangd exntesion. + bool deprecated = false; + + /// This is a clangd exntesion. llvm::Optional> parents; /// If this type hierarchy item is resolved, it contains the direct children /// of the current item. Could be empty if the item does not have any /// descendants. If not defined, the children have not been resolved. + /// This is a clangd exntesion. llvm::Optional> children; - - /// An optional 'data' field, which can be used to identify a type hierarchy - /// item in a resolve request. - llvm::Optional data; }; +llvm::json::Value toJSON(const TypeHierarchyItem::ResolveParams &); +bool fromJSON(const TypeHierarchyItem::ResolveParams &); llvm::json::Value toJSON(const TypeHierarchyItem &); llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TypeHierarchyItem &); bool fromJSON(const llvm::json::Value &, TypeHierarchyItem &, llvm::json::Path); diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp index 32a4d6a306536..a0a37e86ba010 100644 --- a/clang-tools-extra/clangd/TidyProvider.cpp +++ b/clang-tools-extra/clangd/TidyProvider.cpp @@ -212,8 +212,14 @@ TidyProvider disableUnusableChecks(llvm::ArrayRef ExtraBadChecks) { // code, which is often the case when clangd // tries to build an AST. "-bugprone-use-after-move", - // Alias for bugprone-use-after-moe. - "-hicpp-invalid-access-moved"); + // Alias for bugprone-use-after-move. + "-hicpp-invalid-access-moved", + + // ----- Performance problems ----- + + // This check runs expensive analysis for each variable. + // It has been observed to increase reparse time by 10x. + "-misc-const-correctness"); size_t Size = BadChecks.size(); for (const std::string &Str : ExtraBadChecks) { diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 46827433e136d..1b56f6a516042 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -51,6 +51,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallSet.h" @@ -60,6 +61,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" +#include namespace clang { namespace clangd { @@ -879,7 +881,8 @@ class ReferenceFinder : public index::IndexDataConsumer { }; ReferenceFinder(const ParsedAST &AST, - const llvm::ArrayRef Targets, bool PerToken) + const llvm::ArrayRef Targets, + bool PerToken) : PerToken(PerToken), AST(AST) { for (const NamedDecl *ND : Targets) { const Decl *CD = ND->getCanonicalDecl(); @@ -952,7 +955,7 @@ class ReferenceFinder : public index::IndexDataConsumer { }; std::vector -findRefs(const llvm::ArrayRef TargetDecls, ParsedAST &AST, +findRefs(const llvm::ArrayRef TargetDecls, ParsedAST &AST, bool PerToken) { ReferenceFinder RefFinder(AST, TargetDecls, PerToken); index::IndexingOptions IndexOpts; @@ -1240,8 +1243,8 @@ std::vector findDocumentHighlights(ParsedAST &AST, if (const SelectionTree::Node *N = ST.commonAncestor()) { DeclRelationSet Relations = DeclRelation::TemplatePattern | DeclRelation::Alias; - auto TargetDecls= - targetDecl(N->ASTNode, Relations, AST.getHeuristicResolver()); + auto TargetDecls = + targetDecl(N->ASTNode, Relations, AST.getHeuristicResolver()); if (!TargetDecls.empty()) { // FIXME: we may get multiple DocumentHighlights with the same location // and different kinds, deduplicate them. @@ -1613,29 +1616,32 @@ static llvm::Optional declToHierarchyItem(const NamedDecl &ND) { HI.uri = URIForFile::canonicalize(*FilePath, *TUPath); - // Compute the SymbolID and store it in the 'data' field. - // This allows typeHierarchy/resolve to be used to - // resolve children of items returned in a previous request - // for parents. - if (auto ID = getSymbolID(&ND)) - HI.data = ID.str(); - return HI; } static llvm::Optional -declToTypeHierarchyItem(const NamedDecl &ND) { +declToTypeHierarchyItem(const NamedDecl &ND, llvm::StringRef TUPath) { auto Result = declToHierarchyItem(ND); - if (Result) + if (Result) { Result->deprecated = ND.isDeprecated(); + // Compute the SymbolID and store it in the 'data' field. + // This allows typeHierarchy/resolve to be used to + // resolve children of items returned in a previous request + // for parents. + Result->data.symbolID = getSymbolID(&ND); + } return Result; } static llvm::Optional declToCallHierarchyItem(const NamedDecl &ND) { auto Result = declToHierarchyItem(ND); - if (Result && ND.isDeprecated()) + if (!Result) + return Result; + if (ND.isDeprecated()) Result->tags.push_back(SymbolTag::Deprecated); + if (auto ID = getSymbolID(&ND)) + Result->data = ID.str(); return Result; } @@ -1655,10 +1661,6 @@ static llvm::Optional symbolToHierarchyItem(const Symbol &S, // (https://github.com/clangd/clangd/issues/59). HI.range = HI.selectionRange; HI.uri = Loc->uri; - // Store the SymbolID in the 'data' field. The client will - // send this back in requests to resolve additional levels - // of the hierarchy. - HI.data = S.ID.str(); return HI; } @@ -1666,15 +1668,20 @@ static llvm::Optional symbolToHierarchyItem(const Symbol &S, static llvm::Optional symbolToTypeHierarchyItem(const Symbol &S, PathRef TUPath) { auto Result = symbolToHierarchyItem(S, TUPath); - if (Result) + if (Result) { Result->deprecated = (S.Flags & Symbol::Deprecated); + Result->data.symbolID = S.ID; + } return Result; } static llvm::Optional symbolToCallHierarchyItem(const Symbol &S, PathRef TUPath) { auto Result = symbolToHierarchyItem(S, TUPath); - if (Result && (S.Flags & Symbol::Deprecated)) + if (!Result) + return Result; + Result->data = S.ID.str(); + if (S.Flags & Symbol::Deprecated) Result->tags.push_back(SymbolTag::Deprecated); return Result; } @@ -1699,9 +1706,12 @@ static void fillSubTypes(const SymbolID &ID, using RecursionProtectionSet = llvm::SmallSet; -static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, - std::vector &SuperTypes, +// Extracts parents from AST and populates the type hierarchy item. +static void fillSuperTypes(const CXXRecordDecl &CXXRD, llvm::StringRef TUPath, + TypeHierarchyItem &Item, RecursionProtectionSet &RPSet) { + Item.parents.emplace(); + Item.data.parents.emplace(); // typeParents() will replace dependent template specializations // with their class template, so to avoid infinite recursion for // certain types of hierarchies, keep the templates encountered @@ -1716,10 +1726,10 @@ static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) { if (Optional ParentSym = - declToTypeHierarchyItem(*ParentDecl)) { - ParentSym->parents.emplace(); - fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet); - SuperTypes.emplace_back(std::move(*ParentSym)); + declToTypeHierarchyItem(*ParentDecl, TUPath)) { + fillSuperTypes(*ParentDecl, TUPath, *ParentSym, RPSet); + Item.data.parents->emplace_back(ParentSym->data); + Item.parents->emplace_back(std::move(*ParentSym)); } } @@ -1728,11 +1738,12 @@ static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, } } -const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) { - auto RecordFromNode = - [&AST](const SelectionTree::Node *N) -> const CXXRecordDecl * { +std::vector findRecordTypeAt(ParsedAST &AST, + Position Pos) { + auto RecordFromNode = [&AST](const SelectionTree::Node *N) { + std::vector Records; if (!N) - return nullptr; + return Records; // Note: explicitReferenceTargets() will search for both template // instantiations and template patterns, and prefer the former if available @@ -1740,30 +1751,32 @@ const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) { // class template). auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Underlying, AST.getHeuristicResolver()); - if (Decls.empty()) - return nullptr; - - const NamedDecl *D = Decls[0]; + for (const NamedDecl *D : Decls) { - if (const VarDecl *VD = dyn_cast(D)) { - // If this is a variable, use the type of the variable. - return VD->getType().getTypePtr()->getAsCXXRecordDecl(); - } + if (const VarDecl *VD = dyn_cast(D)) { + // If this is a variable, use the type of the variable. + Records.push_back(VD->getType().getTypePtr()->getAsCXXRecordDecl()); + continue; + } - if (const CXXMethodDecl *Method = dyn_cast(D)) { - // If this is a method, use the type of the class. - return Method->getParent(); - } + if (const CXXMethodDecl *Method = dyn_cast(D)) { + // If this is a method, use the type of the class. + Records.push_back(Method->getParent()); + continue; + } - // We don't handle FieldDecl because it's not clear what behaviour - // the user would expect: the enclosing class type (as with a - // method), or the field's type (as with a variable). + // We don't handle FieldDecl because it's not clear what behaviour + // the user would expect: the enclosing class type (as with a + // method), or the field's type (as with a variable). - return dyn_cast(D); + if (auto *RD = dyn_cast(D)) + Records.push_back(RD); + } + return Records; }; const SourceManager &SM = AST.getSourceManager(); - const CXXRecordDecl *Result = nullptr; + std::vector Result; auto Offset = positionToOffset(SM.getBufferData(SM.getMainFileID()), Pos); if (!Offset) { llvm::consumeError(Offset.takeError()); @@ -1772,7 +1785,7 @@ const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) { SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), *Offset, *Offset, [&](SelectionTree ST) { Result = RecordFromNode(ST.commonAncestor()); - return Result != nullptr; + return !Result.empty(); }); return Result; } @@ -2016,52 +2029,79 @@ std::vector typeParents(const CXXRecordDecl *CXXRD) { return Result; } -llvm::Optional +std::vector getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index, PathRef TUPath) { - const CXXRecordDecl *CXXRD = findRecordTypeAt(AST, Pos); - if (!CXXRD) - return llvm::None; - - bool WantParents = Direction == TypeHierarchyDirection::Parents || - Direction == TypeHierarchyDirection::Both; - bool WantChildren = Direction == TypeHierarchyDirection::Children || - Direction == TypeHierarchyDirection::Both; + std::vector Results; + for (const auto *CXXRD : findRecordTypeAt(AST, Pos)) { + + bool WantChildren = Direction == TypeHierarchyDirection::Children || + Direction == TypeHierarchyDirection::Both; + + // If we're looking for children, we're doing the lookup in the index. + // The index does not store relationships between implicit + // specializations, so if we have one, use the template pattern instead. + // Note that this needs to be done before the declToTypeHierarchyItem(), + // otherwise the type hierarchy item would misleadingly contain the + // specialization parameters, while the children would involve classes + // that derive from other specializations of the template. + if (WantChildren) { + if (auto *CTSD = dyn_cast(CXXRD)) + CXXRD = CTSD->getTemplateInstantiationPattern(); + } - // If we're looking for children, we're doing the lookup in the index. - // The index does not store relationships between implicit - // specializations, so if we have one, use the template pattern instead. - // Note that this needs to be done before the declToTypeHierarchyItem(), - // otherwise the type hierarchy item would misleadingly contain the - // specialization parameters, while the children would involve classes - // that derive from other specializations of the template. - if (WantChildren) { - if (auto *CTSD = dyn_cast(CXXRD)) - CXXRD = CTSD->getTemplateInstantiationPattern(); - } + Optional Result = + declToTypeHierarchyItem(*CXXRD, TUPath); + if (!Result) + continue; - Optional Result = declToTypeHierarchyItem(*CXXRD); - if (!Result) - return Result; + RecursionProtectionSet RPSet; + fillSuperTypes(*CXXRD, TUPath, *Result, RPSet); - if (WantParents) { - Result->parents.emplace(); + if (WantChildren && ResolveLevels > 0) { + Result->children.emplace(); - RecursionProtectionSet RPSet; - fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet); + if (Index) { + if (auto ID = getSymbolID(CXXRD)) + fillSubTypes(ID, *Result->children, Index, ResolveLevels, TUPath); + } + } + Results.emplace_back(std::move(*Result)); } - if (WantChildren && ResolveLevels > 0) { - Result->children.emplace(); + return Results; +} - if (Index) { - if (auto ID = getSymbolID(CXXRD)) - fillSubTypes(ID, *Result->children, Index, ResolveLevels, TUPath); +llvm::Optional> +superTypes(const TypeHierarchyItem &Item, const SymbolIndex *Index) { + std::vector Results; + if (!Item.data.parents) + return llvm::None; + if (Item.data.parents->empty()) + return Results; + LookupRequest Req; + llvm::DenseMap IDToData; + for (const auto &Parent : *Item.data.parents) { + Req.IDs.insert(Parent.symbolID); + IDToData[Parent.symbolID] = &Parent; + } + Index->lookup(Req, [&Item, &Results, &IDToData](const Symbol &S) { + if (auto THI = symbolToTypeHierarchyItem(S, Item.uri.file())) { + THI->data = *IDToData.lookup(S.ID); + Results.emplace_back(std::move(*THI)); } - } + }); + return Results; +} - return Result; +std::vector subTypes(const TypeHierarchyItem &Item, + const SymbolIndex *Index) { + std::vector Results; + fillSubTypes(Item.data.symbolID, Results, Index, 1, Item.uri.file()); + for (auto &ChildSym : Results) + ChildSym.data.parents = {Item.data}; + return Results; } void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, @@ -2069,18 +2109,13 @@ void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, const SymbolIndex *Index) { // We only support typeHierarchy/resolve for children, because for parents // we ignore ResolveLevels and return all levels of parents eagerly. - if (Direction == TypeHierarchyDirection::Parents || ResolveLevels == 0) + if (!Index || Direction == TypeHierarchyDirection::Parents || + ResolveLevels == 0) return; Item.children.emplace(); - - if (Index && Item.data) { - // We store the item's SymbolID in the 'data' field, and the client - // passes it back to us in typeHierarchy/resolve. - if (Expected ID = SymbolID::fromStr(*Item.data)) { - fillSubTypes(*ID, *Item.children, Index, ResolveLevels, Item.uri.file()); - } - } + fillSubTypes(Item.data.symbolID, *Item.children, Index, ResolveLevels, + Item.uri.file()); } std::vector diff --git a/clang-tools-extra/clangd/XRefs.h b/clang-tools-extra/clangd/XRefs.h index 1fa21feae8d5b..bf97faa5c0efd 100644 --- a/clang-tools-extra/clangd/XRefs.h +++ b/clang-tools-extra/clangd/XRefs.h @@ -115,17 +115,26 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, /// Get info about symbols at \p Pos. std::vector getSymbolInfo(ParsedAST &AST, Position Pos); -/// Find the record type references at \p Pos. -const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos); +/// Find the record types referenced at \p Pos. +std::vector findRecordTypeAt(ParsedAST &AST, + Position Pos); /// Given a record type declaration, find its base (parent) types. std::vector typeParents(const CXXRecordDecl *CXXRD); /// Get type hierarchy information at \p Pos. -llvm::Optional getTypeHierarchy( +std::vector getTypeHierarchy( ParsedAST &AST, Position Pos, int Resolve, TypeHierarchyDirection Direction, const SymbolIndex *Index = nullptr, PathRef TUPath = PathRef{}); +/// Returns direct parents of a TypeHierarchyItem using SymbolIDs stored inside +/// the item. +llvm::Optional> +superTypes(const TypeHierarchyItem &Item, const SymbolIndex *Index); +/// Returns direct children of a TypeHierarchyItem. +std::vector subTypes(const TypeHierarchyItem &Item, + const SymbolIndex *Index); + void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index); diff --git a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp index 145d98d57ca83..bbc80e7e0d139 100644 --- a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp +++ b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp @@ -17,8 +17,6 @@ namespace clang { namespace clangd { namespace { -const char IWYUPragma[] = "// IWYU pragma: private, include "; - const std::pair IncludeMappings[] = { {"include/__stddef_max_align_t.h", ""}, {"include/__wmmintrin_aes.h", ""}, @@ -712,17 +710,17 @@ collectIWYUHeaderMaps(CanonicalIncludes *Includes) { PragmaCommentHandler(CanonicalIncludes *Includes) : Includes(Includes) {} bool HandleComment(Preprocessor &PP, SourceRange Range) override { - llvm::StringRef Text = - Lexer::getSourceText(CharSourceRange::getCharRange(Range), - PP.getSourceManager(), PP.getLangOpts()); - if (!Text.consume_front(IWYUPragma)) + auto Pragma = parseIWYUPragma( + PP.getSourceManager().getCharacterData(Range.getBegin())); + if (!Pragma || !Pragma->consume_front("private, include ")) return false; auto &SM = PP.getSourceManager(); // We always insert using the spelling from the pragma. if (auto *FE = SM.getFileEntryForID(SM.getFileID(Range.getBegin()))) - Includes->addMapping( - FE->getLastRef(), - isLiteralInclude(Text) ? Text.str() : ("\"" + Text + "\"").str()); + Includes->addMapping(FE->getLastRef(), + isLiteralInclude(*Pragma) + ? Pragma->str() + : ("\"" + *Pragma + "\"").str()); return false; } diff --git a/clang-tools-extra/clangd/test/diagnostics-tidy.test b/clang-tools-extra/clangd/test/diagnostics-tidy.test index c7e79b0c6d5f5..a100c9f4359d1 100644 --- a/clang-tools-extra/clangd/test/diagnostics-tidy.test +++ b/clang-tools-extra/clangd/test/diagnostics-tidy.test @@ -9,7 +9,7 @@ # CHECK-NEXT: { # CHECK-NEXT: "code": "bugprone-sizeof-expression", # CHECK-NEXT: "codeDescription": { -# CHECK-NEXT: "href": "https://clang.llvm.org/extra/clang-tidy/checks/bugprone-sizeof-expression.html" +# CHECK-NEXT: "href": "https://clang.llvm.org/extra/clang-tidy/checks/bugprone/sizeof-expression.html" # CHECK-NEXT: }, # CHECK-NEXT: "message": "Suspicious usage of 'sizeof(K)'; did you mean 'K'?", # CHECK-NEXT: "range": { diff --git a/clang-tools-extra/clangd/test/initialize-params.test b/clang-tools-extra/clangd/test/initialize-params.test index c795ab5940432..8387fb9b504be 100644 --- a/clang-tools-extra/clangd/test/initialize-params.test +++ b/clang-tools-extra/clangd/test/initialize-params.test @@ -88,6 +88,7 @@ # CHECK-NEXT: "," # CHECK-NEXT: ] # CHECK-NEXT: }, +# CHECK-NEXT: "standardTypeHierarchyProvider": true, # CHECK-NEXT: "textDocumentSync": { # CHECK-NEXT: "change": 2, # CHECK-NEXT: "openClose": true, diff --git a/clang-tools-extra/clangd/test/lit.site.cfg.py.in b/clang-tools-extra/clangd/test/lit.site.cfg.py.in index 20caa72af3da1..1fe7c8d0f3244 100644 --- a/clang-tools-extra/clangd/test/lit.site.cfg.py.in +++ b/clang-tools-extra/clangd/test/lit.site.cfg.py.in @@ -10,6 +10,7 @@ config.python_executable = "@Python3_EXECUTABLE@" config.clang_tools_dir = lit_config.substitute("@CURRENT_TOOLS_DIR@") config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@") config.llvm_libs_dir = lit_config.substitute("@LLVM_LIBS_DIR@") +config.llvm_shlib_dir = "@SHLIBDIR@" config.clangd_source_dir = "@CMAKE_CURRENT_SOURCE_DIR@/.." config.clangd_binary_dir = "@CMAKE_CURRENT_BINARY_DIR@/.." diff --git a/clang-tools-extra/clangd/test/type-hierarchy-ext.test b/clang-tools-extra/clangd/test/type-hierarchy-ext.test new file mode 100644 index 0000000000000..ddb9a014be0c7 --- /dev/null +++ b/clang-tools-extra/clangd/test/type-hierarchy-ext.test @@ -0,0 +1,211 @@ +# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} +--- +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct Parent {};\nstruct Child1 : Parent {};\nstruct Child2 : Child1 {};\nstruct Child3 : Child2 {};\nstruct Child4 : Child3 {};"}}} +--- +{"jsonrpc":"2.0","id":1,"method":"textDocument/typeHierarchy","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":11},"direction":2,"resolve":1}} +# CHECK: "id": 1 +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "children": [ +# CHECK-NEXT: { +# CHECK-NEXT: "data": { +# CHECK-NEXT: "symbolID": "A6576FE083F2949A" +# CHECK-NEXT: }, +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child3", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "data": { +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "parents": [], +# CHECK-NEXT: "symbolID": "FE546E7B648D69A7" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "symbolID": "ECDC0C46D75120F4" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "symbolID": "8A991335E4E67D08" +# CHECK-NEXT: }, +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child2", +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "data": { +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "parents": [], +# CHECK-NEXT: "symbolID": "FE546E7B648D69A7" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "symbolID": "ECDC0C46D75120F4" +# CHECK-NEXT: }, +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child1", +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "data": { +# CHECK-NEXT: "parents": [], +# CHECK-NEXT: "symbolID": "FE546E7B648D69A7" +# CHECK-NEXT: }, +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Parent", +# CHECK-NEXT: "parents": [], +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 16, +# CHECK-NEXT: "line": 0 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 0, +# CHECK-NEXT: "line": 0 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 0 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 0 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 25, +# CHECK-NEXT: "line": 1 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 0, +# CHECK-NEXT: "line": 1 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 1 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 1 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 25, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 0, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: } +--- +{"jsonrpc":"2.0","id":2,"method":"typeHierarchy/resolve","params":{"item":{"uri":"test:///main.cpp","data":{"symbolID":"A6576FE083F2949A"},"name":"Child3","kind":23,"range":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}},"selectionRange":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}}},"direction":0,"resolve":1}} +# CHECK: "id": 2 +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "children": [ +# CHECK-NEXT: { +# CHECK-NEXT: "data": { +# CHECK-NEXT: "symbolID": "5705B382DFC77CBC" +# CHECK-NEXT: }, +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child4", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 4 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 4 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 4 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 4 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "data": { +# CHECK-NEXT: "symbolID": "A6576FE083F2949A" +# CHECK-NEXT: }, +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child3", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: } +--- +{"jsonrpc":"2.0","id":3,"method":"shutdown"} +--- +{"jsonrpc":"2.0","method":"exit"} diff --git a/clang-tools-extra/clangd/test/type-hierarchy.test b/clang-tools-extra/clangd/test/type-hierarchy.test index cb38e49cf61e3..69751000a7c6c 100644 --- a/clang-tools-extra/clangd/test/type-hierarchy.test +++ b/clang-tools-extra/clangd/test/type-hierarchy.test @@ -3,178 +3,140 @@ --- {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct Parent {};\nstruct Child1 : Parent {};\nstruct Child2 : Child1 {};\nstruct Child3 : Child2 {};\nstruct Child4 : Child3 {};"}}} --- -{"jsonrpc":"2.0","id":1,"method":"textDocument/typeHierarchy","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":11},"direction":2,"resolve":1}} +{"jsonrpc":"2.0","id":1,"method":"textDocument/prepareTypeHierarchy","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":11},"direction":2,"resolve":1}} # CHECK: "id": 1 # CHECK-NEXT: "jsonrpc": "2.0", -# CHECK-NEXT: "result": { -# CHECK-NEXT: "children": [ -# CHECK-NEXT: { -# CHECK-NEXT: "data": "A6576FE083F2949A", -# CHECK-NEXT: "kind": 23, -# CHECK-NEXT: "name": "Child3", -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 13, -# CHECK-NEXT: "line": 3 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 7, -# CHECK-NEXT: "line": 3 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "selectionRange": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 13, -# CHECK-NEXT: "line": 3 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 7, -# CHECK-NEXT: "line": 3 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" -# CHECK-NEXT: } -# CHECK-NEXT: ], -# CHECK-NEXT: "data": "8A991335E4E67D08", -# CHECK-NEXT: "kind": 23, -# CHECK-NEXT: "name": "Child2", -# CHECK-NEXT: "parents": [ -# CHECK-NEXT: { -# CHECK-NEXT: "data": "ECDC0C46D75120F4", -# CHECK-NEXT: "kind": 23, -# CHECK-NEXT: "name": "Child1", -# CHECK-NEXT: "parents": [ +# CHECK-NEXT: "result": [ +# CHECK-NEXT: { +# CHECK-NEXT: "data": { +# CHECK-NEXT: "parents": [ # CHECK-NEXT: { -# CHECK-NEXT: "data": "FE546E7B648D69A7", -# CHECK-NEXT: "kind": 23, -# CHECK-NEXT: "name": "Parent", -# CHECK-NEXT: "parents": [], -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 16, -# CHECK-NEXT: "line": 0 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 0, -# CHECK-NEXT: "line": 0 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "selectionRange": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 13, -# CHECK-NEXT: "line": 0 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 7, -# CHECK-NEXT: "line": 0 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "parents": [], +# CHECK-NEXT: "symbolID": "FE546E7B648D69A7" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "symbolID": "ECDC0C46D75120F4" # CHECK-NEXT: } # CHECK-NEXT: ], -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 25, -# CHECK-NEXT: "line": 1 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 0, -# CHECK-NEXT: "line": 1 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "selectionRange": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 13, -# CHECK-NEXT: "line": 1 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 7, -# CHECK-NEXT: "line": 1 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" -# CHECK-NEXT: } -# CHECK-NEXT: ], -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 25, -# CHECK-NEXT: "line": 2 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 0, -# CHECK-NEXT: "line": 2 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "selectionRange": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 13, -# CHECK-NEXT: "line": 2 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 7, -# CHECK-NEXT: "line": 2 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" -# CHECK-NEXT: } +# CHECK-NEXT: "symbolID": "8A991335E4E67D08" +# CHECK-NEXT: }, +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child2", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 25, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 0, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: } +# CHECK-NEXT: ] --- -{"jsonrpc":"2.0","id":2,"method":"typeHierarchy/resolve","params":{"item":{"uri":"test:///main.cpp","data":"A6576FE083F2949A","name":"Child3","kind":23,"range":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}},"selectionRange":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}}},"direction":0,"resolve":1}} +{"jsonrpc":"2.0","id":2,"method":"typeHierarchy/supertypes","params":{"item":{"uri":"test:///main.cpp","data":{"parents":[{"parents":[{"parents":[],"symbolID":"FE546E7B648D69A7"}],"symbolID":"ECDC0C46D75120F4"}],"symbolID":"8A991335E4E67D08"},"name":"Child2","kind":23,"range":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}},"selectionRange":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}}}}} # CHECK: "id": 2 # CHECK-NEXT: "jsonrpc": "2.0", -# CHECK-NEXT: "result": { -# CHECK-NEXT: "children": [ -# CHECK-NEXT: { -# CHECK-NEXT: "data": "5705B382DFC77CBC", -# CHECK-NEXT: "kind": 23, -# CHECK-NEXT: "name": "Child4", -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 13, -# CHECK-NEXT: "line": 4 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 7, -# CHECK-NEXT: "line": 4 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "selectionRange": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 13, -# CHECK-NEXT: "line": 4 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 7, -# CHECK-NEXT: "line": 4 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" -# CHECK-NEXT: } -# CHECK-NEXT: ], -# CHECK-NEXT: "data": "A6576FE083F2949A", -# CHECK-NEXT: "kind": 23, -# CHECK-NEXT: "name": "Child3", -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 13, -# CHECK-NEXT: "line": 3 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 7, -# CHECK-NEXT: "line": 3 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "selectionRange": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 13, -# CHECK-NEXT: "line": 3 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 7, -# CHECK-NEXT: "line": 3 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" -# CHECK-NEXT: } +# CHECK-NEXT: "result": [ +# CHECK-NEXT: { +# CHECK-NEXT: "data": { +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "parents": [], +# CHECK-NEXT: "symbolID": "FE546E7B648D69A7" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "symbolID": "ECDC0C46D75120F4" +# CHECK-NEXT: }, +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child1", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 1 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 1 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 1 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 1 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: } +# CHECK-NEXT: ] +--- +{"jsonrpc":"2.0","id":2,"method":"typeHierarchy/subtypes","params":{"item":{"uri":"test:///main.cpp","data":{"parents":[{"parents":[{"parents":[],"symbolID":"FE546E7B648D69A7"}],"symbolID":"ECDC0C46D75120F4"}],"symbolID":"8A991335E4E67D08"},"name":"Child2","kind":23,"range":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}},"selectionRange":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}}}}} +# CHECK: "id": 2 +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": [ +# CHECK-NEXT: { +# CHECK-NEXT: "data": { +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "parents": [ +# CHECK-NEXT: { +# CHECK-NEXT: "parents": [], +# CHECK-NEXT: "symbolID": "FE546E7B648D69A7" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "symbolID": "ECDC0C46D75120F4" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "symbolID": "8A991335E4E67D08" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "symbolID": "A6576FE083F2949A" +# CHECK-NEXT: }, +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child3", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file://{{.*}}/clangd-test/main.cpp" +# CHECK-NEXT: } +# CHECK-NEXT: ] --- {"jsonrpc":"2.0","id":3,"method":"shutdown"} --- diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 5050ab203b8db..079a4ec70623c 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1014,6 +1014,23 @@ TEST(CodeCompleteTest, NoColonColonAtTheEnd) { EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::")))); } +TEST(CompletionTests, EmptySnippetDoesNotCrash) { + // See https://github.com/clangd/clangd/issues/1216 + auto Results = completions(R"cpp( + int main() { + auto w = [&](auto &&f) { return f(f); }; + auto f = w([&](auto &&f) { + return [&](auto &&n) { + if (n == 0) { + return 1; + } + return n * ^(f)(n - 1); + }; + })(10); + } + )cpp"); +} + TEST(CompletionTest, BacktrackCrashes) { // Sema calls code completion callbacks twice in these cases. auto Results = completions(R"cpp( diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp index e8cbaa2bba32d..28ae6ea01e87a 100644 --- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp +++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp @@ -415,6 +415,19 @@ TEST(CommandMangler, EmptyArgs) { // Make sure we don't crash. Mangler.adjust(Args, "foo.cc"); } + +TEST(CommandMangler, PathsAsPositional) { + const auto Mangler = CommandMangler::forTests(); + std::vector Args = { + "clang", + "--driver-mode=cl", + "-I", + "foo", + }; + // Make sure we don't crash. + Mangler.adjust(Args, "a.cc"); + EXPECT_THAT(Args, Contains("foo")); +} } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/clang-tools-extra/clangd/unittests/HeadersTests.cpp index 32e4aea15490b..324d4b58a1ef1 100644 --- a/clang-tools-extra/clangd/unittests/HeadersTests.cpp +++ b/clang-tools-extra/clangd/unittests/HeadersTests.cpp @@ -9,6 +9,7 @@ #include "Headers.h" #include "Compiler.h" +#include "Matchers.h" #include "TestFS.h" #include "TestTU.h" #include "clang/Basic/TokenKinds.h" @@ -30,6 +31,7 @@ namespace { using ::testing::AllOf; using ::testing::Contains; using ::testing::ElementsAre; +using ::testing::Eq; using ::testing::IsEmpty; using ::testing::Not; using ::testing::UnorderedElementsAre; @@ -445,6 +447,18 @@ TEST_F(HeadersTest, HasIWYUPragmas) { EXPECT_FALSE(Includes.hasIWYUExport(getID("none.h", Includes))); } +TEST(Headers, ParseIWYUPragma) { + EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep"), HasValue(Eq("keep"))); + EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep\netc"), + HasValue(Eq("keep"))); + EXPECT_EQ(parseIWYUPragma("/* IWYU pragma: keep"), llvm::None) + << "Only // comments supported!"; + EXPECT_EQ(parseIWYUPragma("// IWYU pragma: keep"), llvm::None) + << "Sensitive to whitespace"; + EXPECT_EQ(parseIWYUPragma("// IWYU pragma:keep"), llvm::None) + << "Sensitive to whitespace"; +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index 87bb0cfc01f60..7127f6cc54c53 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -820,6 +820,15 @@ TEST(ParameterHints, Macros) { } )cpp", ExpectedHint{"param: ", "param"}); + + // If the macro expands to multiple arguments, don't hint it. + assertParameterHints(R"cpp( + void foo(double x, double y); + #define CONSTANTS 3.14, 2.72 + void bar() { + foo(CONSTANTS); + } + )cpp"); } TEST(ParameterHints, ConstructorParens) { @@ -1417,6 +1426,17 @@ TEST(DesignatorHints, OnlyAggregateInit) { )cpp" /*no designator hints expected (but param hints!)*/); } +TEST(DesignatorHints, NoCrash) { + assertDesignatorHints(R"cpp( + /*error-ok*/ + struct A {}; + struct Foo {int a; int b;}; + void test() { + Foo f{A(), $b[[1]]}; + } + )cpp", ExpectedHint{".b=", "b"}); +} + TEST(InlayHints, RestrictRange) { Annotations Code(R"cpp( auto a = false; diff --git a/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp b/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp index 7cdb6dcc03b61..fba7f3ea2155f 100644 --- a/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp +++ b/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp @@ -5,6 +5,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +#include "AST.h" #include "Annotations.h" #include "Matchers.h" #include "ParsedAST.h" @@ -16,6 +17,7 @@ #include "llvm/Support/Path.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include namespace clang { namespace clangd { @@ -26,6 +28,7 @@ using ::testing::ElementsAre; using ::testing::Field; using ::testing::IsEmpty; using ::testing::Matcher; +using ::testing::SizeIs; using ::testing::UnorderedElementsAre; // GMock helpers for matching TypeHierarchyItem. @@ -45,6 +48,10 @@ ::testing::Matcher children(ChildMatchers... ChildrenM) { // Note: "not resolved" is different from "resolved but empty"! MATCHER(parentsNotResolved, "") { return !arg.parents; } MATCHER(childrenNotResolved, "") { return !arg.children; } +MATCHER_P(withResolveID, SID, "") { return arg.symbolID.str() == SID; } +MATCHER_P(withResolveParents, M, "") { + return testing::ExplainMatchResult(M, arg.data.parents, result_listener); +} TEST(FindRecordTypeAt, TypeOrVariable) { Annotations Source(R"cpp( @@ -64,8 +71,10 @@ int main() { auto AST = TU.build(); for (Position Pt : Source.points()) { - const CXXRecordDecl *RD = findRecordTypeAt(AST, Pt); - EXPECT_EQ(&findDecl(AST, "Child2"), static_cast(RD)); + auto Records = findRecordTypeAt(AST, Pt); + ASSERT_THAT(Records, SizeIs(1)); + EXPECT_EQ(&findDecl(AST, "Child2"), + static_cast(Records.front())); } } @@ -86,8 +95,10 @@ int main() { auto AST = TU.build(); for (Position Pt : Source.points()) { - const CXXRecordDecl *RD = findRecordTypeAt(AST, Pt); - EXPECT_EQ(&findDecl(AST, "Child2"), static_cast(RD)); + auto Records = findRecordTypeAt(AST, Pt); + ASSERT_THAT(Records, SizeIs(1)); + EXPECT_EQ(&findDecl(AST, "Child2"), + static_cast(Records.front())); } } @@ -107,11 +118,10 @@ int main() { auto AST = TU.build(); for (Position Pt : Source.points()) { - const CXXRecordDecl *RD = findRecordTypeAt(AST, Pt); // A field does not unambiguously specify a record type // (possible associated reocrd types could be the field's type, // or the type of the record that the field is a member of). - EXPECT_EQ(nullptr, RD); + EXPECT_THAT(findRecordTypeAt(AST, Pt), SizeIs(0)); } } @@ -359,11 +369,11 @@ int main() { for (Position Pt : Source.points()) { // Set ResolveLevels to 0 because it's only used for Children; // for Parents, getTypeHierarchy() always returns all levels. - llvm::Optional Result = getTypeHierarchy( - AST, Pt, /*ResolveLevels=*/0, TypeHierarchyDirection::Parents); - ASSERT_TRUE(bool(Result)); + auto Result = getTypeHierarchy(AST, Pt, /*ResolveLevels=*/0, + TypeHierarchyDirection::Parents); + ASSERT_THAT(Result, SizeIs(1)); EXPECT_THAT( - *Result, + Result.front(), AllOf( withName("Child"), withKind(SymbolKind::Struct), parents(AllOf(withName("Parent1"), withKind(SymbolKind::Struct), @@ -398,11 +408,11 @@ TEST(TypeHierarchy, RecursiveHierarchyUnbounded) { // The parent is reported as "S" because "S<0>" is an invalid instantiation. // We then iterate once more and find "S" again before detecting the // recursion. - llvm::Optional Result = getTypeHierarchy( - AST, Source.points()[0], 0, TypeHierarchyDirection::Parents); - ASSERT_TRUE(bool(Result)); + auto Result = getTypeHierarchy(AST, Source.points()[0], 0, + TypeHierarchyDirection::Parents); + ASSERT_THAT(Result, SizeIs(1)); EXPECT_THAT( - *Result, + Result.front(), AllOf(withName("S<0>"), withKind(SymbolKind::Struct), parents( AllOf(withName("S"), withKind(SymbolKind::Struct), @@ -432,11 +442,11 @@ TEST(TypeHierarchy, RecursiveHierarchyBounded) { // Make sure getTypeHierarchy() doesn't get into an infinite recursion // for either a concrete starting point or a dependent starting point. - llvm::Optional Result = getTypeHierarchy( - AST, Source.point("SRefConcrete"), 0, TypeHierarchyDirection::Parents); - ASSERT_TRUE(bool(Result)); + auto Result = getTypeHierarchy(AST, Source.point("SRefConcrete"), 0, + TypeHierarchyDirection::Parents); + ASSERT_THAT(Result, SizeIs(1)); EXPECT_THAT( - *Result, + Result.front(), AllOf(withName("S<2>"), withKind(SymbolKind::Struct), parents(AllOf( withName("S<1>"), withKind(SymbolKind::Struct), @@ -445,9 +455,9 @@ TEST(TypeHierarchy, RecursiveHierarchyBounded) { parents())))))); Result = getTypeHierarchy(AST, Source.point("SRefDependent"), 0, TypeHierarchyDirection::Parents); - ASSERT_TRUE(bool(Result)); + ASSERT_THAT(Result, SizeIs(1)); EXPECT_THAT( - *Result, + Result.front(), AllOf(withName("S"), withKind(SymbolKind::Struct), parents(AllOf(withName("S"), withKind(SymbolKind::Struct), selectionRangeIs(Source.range("SDef")), parents())))); @@ -469,11 +479,11 @@ TEST(TypeHierarchy, DeriveFromImplicitSpec) { auto AST = TU.build(); auto Index = TU.index(); - llvm::Optional Result = getTypeHierarchy( - AST, Source.points()[0], 2, TypeHierarchyDirection::Children, Index.get(), - testPath(TU.Filename)); - ASSERT_TRUE(bool(Result)); - EXPECT_THAT(*Result, + auto Result = getTypeHierarchy(AST, Source.points()[0], 2, + TypeHierarchyDirection::Children, Index.get(), + testPath(TU.Filename)); + ASSERT_THAT(Result, SizeIs(1)); + EXPECT_THAT(Result.front(), AllOf(withName("Parent"), withKind(SymbolKind::Struct), children(AllOf(withName("Child1"), withKind(SymbolKind::Struct), children()), @@ -495,12 +505,12 @@ TEST(TypeHierarchy, DeriveFromPartialSpec) { auto AST = TU.build(); auto Index = TU.index(); - llvm::Optional Result = getTypeHierarchy( - AST, Source.points()[0], 2, TypeHierarchyDirection::Children, Index.get(), - testPath(TU.Filename)); - ASSERT_TRUE(bool(Result)); - EXPECT_THAT(*Result, AllOf(withName("Parent"), withKind(SymbolKind::Struct), - children())); + auto Result = getTypeHierarchy(AST, Source.points()[0], 2, + TypeHierarchyDirection::Children, Index.get(), + testPath(TU.Filename)); + ASSERT_THAT(Result, SizeIs(1)); + EXPECT_THAT(Result.front(), AllOf(withName("Parent"), + withKind(SymbolKind::Struct), children())); } TEST(TypeHierarchy, DeriveFromTemplate) { @@ -521,11 +531,11 @@ TEST(TypeHierarchy, DeriveFromTemplate) { // FIXME: We'd like this to show the implicit specializations Parent // and Child, but currently libIndex does not expose relationships // between implicit specializations. - llvm::Optional Result = getTypeHierarchy( - AST, Source.points()[0], 2, TypeHierarchyDirection::Children, Index.get(), - testPath(TU.Filename)); - ASSERT_TRUE(bool(Result)); - EXPECT_THAT(*Result, + auto Result = getTypeHierarchy(AST, Source.points()[0], 2, + TypeHierarchyDirection::Children, Index.get(), + testPath(TU.Filename)); + ASSERT_THAT(Result, SizeIs(1)); + EXPECT_THAT(Result.front(), AllOf(withName("Parent"), withKind(SymbolKind::Struct), children(AllOf(withName("Child"), withKind(SymbolKind::Struct), children())))); @@ -546,12 +556,12 @@ struct [[Parent]] { TU.HeaderCode = HeaderInPreambleAnnotations.code().str(); auto AST = TU.build(); - llvm::Optional Result = getTypeHierarchy( + std::vector Result = getTypeHierarchy( AST, SourceAnnotations.point(), 1, TypeHierarchyDirection::Parents); - ASSERT_TRUE(Result); + ASSERT_THAT(Result, SizeIs(1)); EXPECT_THAT( - *Result, + Result.front(), AllOf(withName("Child"), parents(AllOf(withName("Parent"), selectionRangeIs(HeaderInPreambleAnnotations.range()), @@ -722,22 +732,21 @@ struct Child2b : Child1 {}; auto AST = TU.build(); auto Index = TU.index(); - llvm::Optional Result = getTypeHierarchy( - AST, Source.point(), /*ResolveLevels=*/1, - TypeHierarchyDirection::Children, Index.get(), testPath(TU.Filename)); - ASSERT_TRUE(bool(Result)); + auto Result = getTypeHierarchy(AST, Source.point(), /*ResolveLevels=*/1, + TypeHierarchyDirection::Children, Index.get(), + testPath(TU.Filename)); + ASSERT_THAT(Result, SizeIs(1)); EXPECT_THAT( - *Result, - AllOf(withName("Parent"), withKind(SymbolKind::Struct), - parentsNotResolved(), + Result.front(), + AllOf(withName("Parent"), withKind(SymbolKind::Struct), parents(), children(AllOf(withName("Child1"), withKind(SymbolKind::Struct), parentsNotResolved(), childrenNotResolved())))); - resolveTypeHierarchy((*Result->children)[0], /*ResolveLevels=*/1, + resolveTypeHierarchy((*Result.front().children)[0], /*ResolveLevels=*/1, TypeHierarchyDirection::Children, Index.get()); EXPECT_THAT( - (*Result->children)[0], + (*Result.front().children)[0], AllOf(withName("Child1"), withKind(SymbolKind::Struct), parentsNotResolved(), children(AllOf(withName("Child2a"), withKind(SymbolKind::Struct), @@ -746,6 +755,53 @@ struct Child2b : Child1 {}; parentsNotResolved(), childrenNotResolved())))); } +TEST(Standard, SubTypes) { + Annotations Source(R"cpp( +struct Pare^nt1 {}; +struct Parent2 {}; +struct Child : Parent1, Parent2 {}; +)cpp"); + + TestTU TU = TestTU::withCode(Source.code()); + auto AST = TU.build(); + auto Index = TU.index(); + + auto Result = getTypeHierarchy(AST, Source.point(), /*ResolveLevels=*/1, + TypeHierarchyDirection::Children, Index.get(), + testPath(TU.Filename)); + ASSERT_THAT(Result, SizeIs(1)); + auto Children = subTypes(Result.front(), Index.get()); + + // Make sure parents are populated when getting children. + // FIXME: This is partial. + EXPECT_THAT( + Children, + UnorderedElementsAre( + AllOf(withName("Child"), + withResolveParents(HasValue(UnorderedElementsAre(withResolveID( + getSymbolID(&findDecl(AST, "Parent1")).str()))))))); +} + +TEST(Standard, SuperTypes) { + Annotations Source(R"cpp( +struct Parent {}; +struct Chil^d : Parent {}; +)cpp"); + + TestTU TU = TestTU::withCode(Source.code()); + auto AST = TU.build(); + auto Index = TU.index(); + + auto Result = getTypeHierarchy(AST, Source.point(), /*ResolveLevels=*/1, + TypeHierarchyDirection::Children, Index.get(), + testPath(TU.Filename)); + ASSERT_THAT(Result, SizeIs(1)); + auto Parents = superTypes(Result.front(), Index.get()); + + EXPECT_THAT(Parents, HasValue(UnorderedElementsAre( + AllOf(withName("Parent"), + withResolveParents(HasValue(IsEmpty())))))); +} } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 08eacd321d5ea..182052785d1b0 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -8,13 +8,6 @@ Extra Clang Tools |release| |ReleaseNotesTitle| Written by the `LLVM Team `_ -.. only:: PreRelease - - .. warning:: - These are in-progress notes for the upcoming Extra Clang Tools |version| release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -51,34 +44,67 @@ Improvements to clangd Inlay hints ^^^^^^^^^^^ +- Provide hints for: + - Lambda return types. + - Forwarding functions using the underlying function call. +- Support for standard LSP 3.17 inlay hints protocol. +- Designator inlay hints are enabled by default. + Diagnostics ^^^^^^^^^^^ + - Improved Fix-its of some clang-tidy checks when applied with clangd. +- Clangd now produces diagnostics for forwarding functions like make_unique. +- Include cleaner analysis can be disabled with the ``Diagnostics.Includes.IgnoreHeader`` config option. +- Include cleaner doesn’t diagnose exporting headers. +- clang-tidy and include cleaner diagnostics have links to their documentation. Semantic Highlighting ^^^^^^^^^^^^^^^^^^^^^ -Compile flags -^^^^^^^^^^^^^ +- Semantic highlighting works for tokens that span multiple lines. +- Mutable reference parameters in function calls receive ``usedAsMutableReference`` modifier. Hover ^^^^^ +- Hover displays desugared types by default now. + Code completion ^^^^^^^^^^^^^^^ +- Improved ranking/filtering for ObjC method selectors. +- Support for C++20 concepts and requires expressions. + Signature help ^^^^^^^^^^^^^^ +- Signature help for function pointers. +- Provides hints using underlying functions in forwarded calls. + Cross-references ^^^^^^^^^^^^^^^^ -Objective-C -^^^^^^^^^^^ +Code Actions +^^^^^^^^^^^^ + +- New code action to generate ObjC initializers. +- New code action to generate move/copy constructors/assignments. +- Extract to function works for methods in addition to free functions. +- Related diagnostics are attached to code actions response, if any. +- Extract variable works in C and ObjC files. +- Fix to define outline when the parameter has a braced initializer. Miscellaneous ^^^^^^^^^^^^^ +- Include fixer supports symbols inside macro arguments. +- Dependent autos are now deduced when there’s a single instantiation. +- Support for symbols exported with using declarations in all features. +- Fixed background-indexing priority for M1 chips. +- Indexing for standard library symbols. +- ObjC framework includes are spelled properly during include insertion operations. + Improvements to clang-doc ------------------------- @@ -226,12 +252,12 @@ Changes in existing checks - Fixed a false positive in :doc:`misc-unused-parameters ` - where invalid parameters were implicitly being treated as being unused. + where invalid parameters were implicitly being treated as being unused. This fixes `Issue 56152 `_. - Fixed false positives in :doc:`misc-unused-using-decls ` where `using` statements bringing - operators into the scope where incorrectly marked as unused. + operators into the scope where incorrectly marked as unused. This fixes `issue 55095 `_. - Fixed a false positive in :doc:`modernize-deprecated-headers diff --git a/clang-tools-extra/docs/clang-tidy/checks/abseil/no-internal-dependencies.rst b/clang-tools-extra/docs/clang-tidy/checks/abseil/no-internal-dependencies.rst index 3ddb023db8baf..c06057b313da5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/abseil/no-internal-dependencies.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/abseil/no-internal-dependencies.rst @@ -1,4 +1,4 @@ -subl.. title:: clang-tidy - abseil-no-internal-dependencies +.. title:: clang-tidy - abseil-no-internal-dependencies abseil-no-internal-dependencies =============================== diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst index 852d9346576da..6efcd31d469d6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst @@ -4,12 +4,12 @@ misc-const-correctness ====================== This check implements detection of local variables which could be declared as -``const``, but are not. Declaring variables as ``const`` is required or recommended by many +``const`` but are not. Declaring variables as ``const`` is required or recommended by many coding guidelines, such as: `CppCoreGuidelines ES.25 `_ and `AUTOSAR C++14 Rule A7-1-1 (6.7.1 Specifiers) `_. -Please note that this analysis is type-based only. Variables that are not modified +Please note that this check's analysis is type-based only. Variables that are not modified but used to create a non-const handle that might escape the scope are not diagnosed as potential ``const``. @@ -18,25 +18,29 @@ as potential ``const``. // Declare a variable, which is not ``const`` ... int i = 42; // but use it as read-only. This means that `i` can be declared ``const``. - int result = i * i; + int result = i * i; // Before transformation + int const result = i * i; // After transformation -The check can analyzes values, pointers and references but not (yet) pointees: +The check can analyze values, pointers and references but not (yet) pointees: .. code-block:: c++ // Normal values like built-ins or objects. - int potential_const_int = 42; // 'const int potential_const_int = 42' suggestion. + int potential_const_int = 42; // Before transformation + int const potential_const_int = 42; // After transformation int copy_of_value = potential_const_int; - MyClass could_be_const; // 'const MyClass could_be_const' suggestion; + MyClass could_be_const; // Before transformation + MyClass const could_be_const; // After transformation could_be_const.const_qualified_method(); // References can be declared const as well. - int &reference_value = potential_const_int; // 'const int &reference_value' suggestion. + int &reference_value = potential_const_int; // Before transformation + int const& reference_value = potential_const_int; // After transformation int another_copy = reference_value; // The similar semantics of pointers are not (yet) analyzed. - int *pointer_variable = &potential_const_int; // Not 'const int *pointer_variable' suggestion. + int *pointer_variable = &potential_const_int; // _NO_ 'const int *pointer_variable' suggestion. int last_copy = *pointer_variable; The automatic code transformation is only applied to variables that are declared in single @@ -44,18 +48,20 @@ declarations. You may want to prepare your code base with `readability-isolate-declaration `_ first. Note that there is the check -`cppcoreguidelines-avoid-non-const-global-variables `_ +`cppcoreguidelines-avoid-non-const-global-variables <../cppcoreguidelines/avoid-non-const-global-variables.html>`_ to enforce ``const`` correctness on all globals. Known Limitations ----------------- +The check does not run on `C` code. + The check will not analyze templated variables or variables that are instantiation dependent. Different instantiations can result in different ``const`` correctness properties and in general it -is not possible to find all instantiations of a template. It might be used differently in an -independent translation unit. +is not possible to find all instantiations of a template. The template might be used differently in +an independent translation unit. -Pointees can not be analyzed for constness yet. The following code is shows this limitation. +Pointees can not be analyzed for constness yet. The following code shows this limitation. .. code-block:: c++ @@ -74,15 +80,35 @@ This limitation affects the capability to add ``const`` to methods which is not Options ------- -.. option:: AnalyzeValues (default = 1) +.. option:: AnalyzeValues (default = true) Enable or disable the analysis of ordinary value variables, like ``int i = 42;`` -.. option:: AnalyzeReferences (default = 1) + .. code-block:: c++ + + // Warning + int i = 42; + // No warning + int const i = 42; + + // Warning + int a[] = {42, 42, 42}; + // No warning + int const a[] = {42, 42, 42}; + +.. option:: AnalyzeReferences (default = true) Enable or disable the analysis of reference variables, like ``int &ref = i;`` -.. option:: WarnPointersAsValues (default = 0) + .. code-block:: c++ + + int i = 42; + // Warning + int& ref = i; + // No warning + int const& ref = i; + +.. option:: WarnPointersAsValues (default = false) This option enables the suggestion for ``const`` of the pointer itself. Pointer values have two possibilities to be ``const``, the pointer @@ -90,28 +116,36 @@ Options .. code-block:: c++ - const int value = 42; - const int * const pointer_variable = &value; + int value = 42; - // The following operations are forbidden for `pointer_variable`. - // *pointer_variable = 44; - // pointer_variable = nullptr; + // Warning + const int * pointer_variable = &value; + // No warning + const int *const pointer_variable = &value; -.. option:: TransformValues (default = 1) +.. option:: TransformValues (default = true) - Provides fixit-hints for value types that automatically adds ``const`` if its a single declaration. + Provides fixit-hints for value types that automatically add ``const`` if its a single declaration. .. code-block:: c++ - // Emits a hint for 'value' to become 'const int value = 42;'. + // Before int value = 42; + // After + int const value = 42; + + // Before + int a[] = {42, 42, 42}; + // After + int const a[] = {42, 42, 42}; + // Result is modified later in its life-time. No diagnostic and fixit hint will be emitted. int result = value * 3; result -= 10; -.. option:: TransformReferences (default = 1) +.. option:: TransformReferences (default = true) - Provides fixit-hints for reference types that automatically adds ``const`` if its a single + Provides fixit-hints for reference types that automatically add ``const`` if its a single declaration. .. code-block:: c++ @@ -120,31 +154,45 @@ Options // it, it can not be transformed (yet). int value = 42; // The reference 'ref_value' is not modified and can be made 'const int &ref_value = value;' + // Before int &ref_value = value; + // After + int const &ref_value = value; // Result is modified later in its life-time. No diagnostic and fixit hint will be emitted. int result = ref_value * 3; result -= 10; -.. option:: TransformPointersAsValues (default = 0) +.. option:: TransformPointersAsValues (default = false) Provides fixit-hints for pointers if their pointee is not changed. This does not analyze if the value-pointed-to is unchanged! - Requires 'WarnPointersAsValues' to be 1. + Requires 'WarnPointersAsValues' to be 'true'. .. code-block:: c++ int value = 42; - // Emits a hint that 'ptr_value' may become 'int *const ptr_value = &value' because its pointee - // is not changed. + + // Before + const int * pointer_variable = &value; + // After + const int *const pointer_variable = &value; + + // Before + const int * a[] = {&value, &value}; + // After + const int *const a[] = {&value, &value}; + + // Before int *ptr_value = &value; + // After + int *const ptr_value = &value; - int result = 100 * (*ptr_value); - // This modification of the pointee is still allowed and not analyzed/diagnosed. + int result = 100 * (*ptr_value); // Does not modify the pointer itself. + // This modification of the pointee is still allowed and not diagnosed. *ptr_value = 0; // The following pointer may not become a 'int *const'. int *changing_pointee = &value; changing_pointee = &result; - diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp index 8a267eb04a151..9a150e887234d 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-values.cpp @@ -10,4 +10,65 @@ void potential_const_pointer() { double *p_local0 = &np_local0[1]; // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'double *' can be declared 'const' // CHECK-FIXES: double *const p_local0 + + using doublePtr = double*; + using doubleArray = double[15]; + doubleArray np_local1; + doublePtr p_local1 = &np_local1[0]; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local1' of type 'doublePtr' (aka 'double *') can be declared 'const' + // CHECK-FIXES: doublePtr const p_local1 +} + +void range_for() { + int np_local0[2] = {1, 2}; + int *p_local0[2] = {&np_local0[0], &np_local0[1]}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int *[2]' can be declared 'const' + // CHECK-FIXES: int *const p_local0[2] + for (const int *p_local1 : p_local0) { + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: variable 'p_local1' of type 'const int *' can be declared 'const' + // CHECK-FIXES: for (const int *const p_local1 : p_local0) + } + + int *p_local2[2] = {nullptr, nullptr}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'int *[2]' can be declared 'const' + // CHECK-FIXES: int *const p_local2[2] + for (const auto *con_ptr : p_local2) { + } + +} + +template +struct SmallVectorBase { + T data[4]; + void push_back(const T &el) {} + int size() const { return 4; } + T *begin() { return data; } + const T *begin() const { return data; } + T *end() { return data + 4; } + const T *end() const { return data + 4; } +}; + +template +struct SmallVector : SmallVectorBase {}; + +template +void EmitProtocolMethodList(T &&Methods) { + // Note: If the template is uninstantiated the analysis does not figure out, + // that p_local0 could be const. Not sure why, but probably bails because + // some expressions are type-dependent. + SmallVector p_local0; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'SmallVector' can be declared 'const' + // CHECK-FIXES: SmallVector const p_local0 + SmallVector np_local0; + for (const auto *I : Methods) { + if (I == nullptr) + np_local0.push_back(I); + } + p_local0.size(); +} +void instantiate() { + int *p_local0[4] = {nullptr, nullptr, nullptr, nullptr}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int *[4]' can be declared 'const' + // CHECK-FIXES: int *const p_local0[4] + EmitProtocolMethodList(p_local0); } diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp index 8acb0bd6b42c4..f469bfd055c93 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp @@ -526,18 +526,13 @@ void range_for() { // CHECK-FIXES: int const p_local1[2] for (const int &const_ref : p_local1) { } +} - int *p_local2[2] = {&np_local0[0], &np_local0[1]}; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local2' of type 'int *[2]' can be declared 'const' - // CHECK-FIXES: int *const p_local2[2] - for (const int *con_ptr : p_local2) { - } - - int *p_local3[2] = {nullptr, nullptr}; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local3' of type 'int *[2]' can be declared 'const' - // CHECK-FIXES: int *const p_local3[2] - for (const auto *con_ptr : p_local3) { - } +void arrays_of_pointers_are_ignored() { + int *np_local0[2] = {nullptr, nullptr}; + + using intPtr = int*; + intPtr np_local1[2] = {nullptr, nullptr}; } inline void *operator new(decltype(sizeof(void *)), void *p) { return p; } @@ -908,41 +903,6 @@ void vlas() { sizeof(int[++N]); } -template -struct SmallVectorBase { - T data[4]; - void push_back(const T &el) {} - int size() const { return 4; } - T *begin() { return data; } - const T *begin() const { return data; } - T *end() { return data + 4; } - const T *end() const { return data + 4; } -}; - -template -struct SmallVector : SmallVectorBase {}; - -template -void EmitProtocolMethodList(T &&Methods) { - // Note: If the template is uninstantiated the analysis does not figure out, - // that p_local0 could be const. Not sure why, but probably bails because - // some expressions are type-dependent. - SmallVector p_local0; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'SmallVector' can be declared 'const' - // CHECK-FIXES: SmallVector const p_local0 - SmallVector np_local0; - for (const auto *I : Methods) { - if (I == nullptr) - np_local0.push_back(I); - } - p_local0.size(); -} -void instantiate() { - int *p_local0[4] = {nullptr, nullptr, nullptr, nullptr}; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int *[4]' can be declared 'const' - // CHECK-FIXES: int *const p_local0[4] - EmitProtocolMethodList(p_local0); -} struct base { int member; }; diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.cpp index 0d08edb3803ab..63bf34cfafe9e 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/unused-using-decls.cpp @@ -210,14 +210,3 @@ template class U> class Bar {}; // We used to report Q unsued, because we only checked the first template // argument. Bar *bar; - -namespace internal { - struct S {}; - int operator+(S s1, S s2); -} - -// Make sure this statement is not reported as unused. -using internal::operator+; -using internal::S; - -int j() { return S() + S(); } diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp index 7e97e9f717fbf..ff50528c215f4 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-bool-expr-chained-conditional-return.cpp @@ -92,3 +92,14 @@ bool complex_chained_if_return_return_negated(int i) { // CHECK-FIXES: {{^}} }{{$}} // CHECK-FIXES: {{^ return i <= 10;$}} // CHECK-FIXES: {{^}$}} + + +bool PR57819(int x) { + // False positive introduced in clang-tidy-15 + // Expect no warning here. + if (x > 0) + return false; + else { + } + return true; +} diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index c27beec313d78..e3bc4b468fb66 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -117,6 +117,7 @@ if(CLANG_BUILT_STANDALONE) include(TableGen) include(HandleLLVMOptions) include(VersionFromVCS) + include(CheckAtomic) include(GetErrcMessages) include(LLVMDistributionSupport) @@ -516,6 +517,12 @@ if(CLANG_ENABLE_ARCMT) set(CLANG_ENABLE_OBJC_REWRITER ON) endif() +# This option is a stop-gap, we should commit to removing this as +# soon as possible. See discussion: +# https://discourse.llvm.org/t/rationale-for-removing-versioned-libclang-middle-ground-to-keep-it-behind-option/ +option(CLANG_FORCE_MATCHING_LIBCLANG_SOVERSION + "Force the SOVERSION of libclang to be equal to CLANG_MAJOR" ON) + # Clang version information set(CLANG_EXECUTABLE_VERSION "${CLANG_VERSION_MAJOR}" CACHE STRING diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index 6d1b6000484ce..52eb375a7e14b 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -1675,7 +1675,7 @@ Prevent optimization remarks from being output if they do not have at least this .. option:: -fdiagnostics-misexpect-tolerance= -Prevent misexpect diagnostics from being output if the profile counts are within N% of the expected. +Prevent misexpect diagnostics from being output if the profile counts are within N% of the expected. .. option:: -fdiagnostics-show-hotness, -fno-diagnostics-show-hotness @@ -2578,7 +2578,6 @@ Perform ThinLTO importing using provided function summary index .. option:: -ftime-trace - Turn on time profiler. Generates JSON file based on output filename. Results can be analyzed with chrome://tracing or `Speedscope App `_ for flamegraph visualization. diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 1bac2aee84bd9..6e97193888f77 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -400,7 +400,7 @@ Builtin Macros Vectors and Extended Vectors ============================ -Supports the GCC, OpenCL, AltiVec and NEON vector extensions. +Supports the GCC, OpenCL, AltiVec, NEON and SVE vector extensions. OpenCL vector types are created using the ``ext_vector_type`` attribute. It supports the ``V.xyzw`` syntax and other tidbits as seen in OpenCL. An example @@ -532,6 +532,8 @@ number of literals can be specified. For example: vector int vi5 = (vector int)(1, 2, 3, 4); float4 vf = (float4)((float2)(1.0f, 2.0f), (float2)(3.0f, 4.0f)); +.. _Vector Operations: + Vector Operations ----------------- @@ -539,34 +541,36 @@ The table below shows the support for each operation by vector extension. A dash indicates that an operation is not accepted according to a corresponding specification. -============================== ======= ======= ============= ======= - Operator OpenCL AltiVec GCC NEON -============================== ======= ======= ============= ======= -[] yes yes yes -- -unary operators +, -- yes yes yes -- -++, -- -- yes yes yes -- -+,--,*,/,% yes yes yes -- -bitwise operators &,|,^,~ yes yes yes -- ->>,<< yes yes yes -- -!, &&, || yes -- yes -- -==, !=, >, <, >=, <= yes yes yes -- -= yes yes yes yes -?: [#]_ yes -- yes -- -sizeof yes yes yes yes -C-style cast yes yes yes no -reinterpret_cast yes no yes no -static_cast yes no yes no -const_cast no no no no -address &v[i] no no no [#]_ no -============================== ======= ======= ============= ======= +============================== ======= ======= ============= ======= ===== + Operator OpenCL AltiVec GCC NEON SVE +============================== ======= ======= ============= ======= ===== +[] yes yes yes yes yes +unary operators +, -- yes yes yes yes yes +++, -- -- yes yes yes no no ++,--,*,/,% yes yes yes yes yes +bitwise operators &,|,^,~ yes yes yes yes yes +>>,<< yes yes yes yes yes +!, &&, || yes -- yes yes yes +==, !=, >, <, >=, <= yes yes yes yes yes += yes yes yes yes yes +?: [#]_ yes -- yes yes yes +sizeof yes yes yes yes yes [#]_ +C-style cast yes yes yes no no +reinterpret_cast yes no yes no no +static_cast yes no yes no no +const_cast no no no no no +address &v[i] no no no [#]_ no no +============================== ======= ======= ============= ======= ===== See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`. .. [#] ternary operator(?:) has different behaviors depending on condition operand's vector type. If the condition is a GNU vector (i.e. __vector_size__), - it's only available in C++ and uses normal bool conversions (that is, != 0). + a NEON vector or an SVE vector, it's only available in C++ and uses normal bool + conversions (that is, != 0). If it's an extension (OpenCL) vector, it's only available in C and OpenCL C. And it selects base on signedness of the condition operands (OpenCL v1.1 s6.3.9). +.. [#] sizeof can only be used on vector length specific SVE types. .. [#] Clang does not allow the address of an element to be taken while GCC allows this. This is intentional for vectors with a boolean element type and not implemented otherwise. @@ -756,6 +760,10 @@ performing the operation, and then truncating to ``_Float16``. ``__bf16`` is purely a storage format; it is currently only supported on the following targets: * 32-bit ARM * 64-bit ARM (AArch64) +* X86 (see below) + +On X86 targets, ``__bf16`` is supported as long as SSE2 is available, which +includes all 64-bit and all recent 32-bit processors. The ``__bf16`` type is only available when supported in hardware. @@ -1369,7 +1377,7 @@ The following type trait primitives are supported by Clang. Those traits marked * ``__has_trivial_move_assign`` (GNU, Microsoft): Deprecated, use ``__is_trivially_assignable`` instead. * ``__has_trivial_copy`` (GNU, Microsoft): - Deprecated, use ``__is_trivially_constructible`` instead. + Deprecated, use ``__is_trivially_copyable`` instead. * ``__has_trivial_constructor`` (GNU, Microsoft): Deprecated, use ``__is_trivially_constructible`` instead. * ``__has_trivial_move_constructor`` (GNU, Microsoft): diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 84c74335ea5d1..13cca2ebbfb89 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -8,13 +8,6 @@ Clang |release| |ReleaseNotesTitle| Written by the `LLVM Team `_ -.. only:: PreRelease - - .. warning:: - These are in-progress notes for the upcoming Clang |version| release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -44,6 +37,22 @@ here. Generic improvements to Clang as a whole or to its underlying infrastructure are described first, followed by language-specific sections with improvements to Clang's support for those languages. +Potentially Breaking Changes +============================ +These changes are ones which we think may surprise users when upgrading to +Clang |release| because of the opportunity they pose for disruption to existing +code bases. + +- The ``-Wimplicit-function-declaration`` and ``-Wimplicit-int`` warning + diagnostics are now enabled by default in C99, C11, and C17. As of C2x, + support for implicit function declarations and implicit int has been removed, + and the warning options will have no effect. Specifying ``-Wimplicit-int`` in + C89 mode will now issue warnings instead of being a noop. + *NOTE* these warnings are expected to default to an error in Clang 16. We + recommend that projects using configure scripts verify the results do not + change before/after setting ``-Werror=implicit-function-declarations`` or + ``-Wimplicit-int`` to avoid incompatibility with Clang 16. + Major New Features ------------------ @@ -127,7 +136,7 @@ Bug Fixes This fixes Issue `Issue 53488 `_. - According to `CWG 1394 `_ and `C++20 [dcl.fct.def.general]p2 `_, - Clang should not diagnose incomplete types in function definitions if the function body is "= delete;". + Clang should not diagnose incomplete types in function definitions if the function body is ``= delete;``. This fixes Issue `Issue 52802 `_. - Unknown type attributes with a ``[[]]`` spelling are no longer diagnosed twice. This fixes Issue `Issue 54817 `_. @@ -163,7 +172,7 @@ Bug Fixes promise_type body for coroutines if there is any allocation function declaration in the scope of promise_type. Additionally, to implement CWG2585, a coroutine will no longer generate a call to a global allocation function - with the signature (std::size_t, p0, ..., pn). + with the signature ``(std::size_t, p0, ..., pn)``. This fixes Issue `Issue 54881 `_. - Implement `CWG 2394 `_: Const class members may be initialized with a defaulted default constructor under the same @@ -202,10 +211,26 @@ Bug Fixes considered to have one positive bit in order to represent the underlying value. This effects whether we consider the store of the value one to be well defined. -- An operator introduced to the scope via a `using` statement now correctly references this +- An operator introduced to the scope via a ``using`` statement now correctly references this statement in clangd (hover over the symbol, jump to definition) as well as in the AST dump. This also fixes `issue 55095 `_ as a side-effect. +- When including a PCH from a GCC style directory with multiple alternative PCH + files, Clang now requires all defines set on the command line while generating + the PCH and when including it to match. This matches GCC's behaviour. + Previously Clang would tolerate defines to be set when creating the PCH but + missing when used, or vice versa. This makes sure that Clang picks the + correct one, where it previously would consider multiple ones as potentially + acceptable (and erroneously use whichever one is tried first). +- Fix a crash when generating code coverage information for an + ``if consteval`` statement. This fixes + `Issue 57377 `_. +- Fix a crash when a ``btf_type_tag`` attribute is applied to the pointee of + a function pointer. +- Clang 14 predeclared some builtin POSIX library functions in ``gnu2x`` mode, + and Clang 15 accidentally stopped predeclaring those functions in that + language mode. Clang 16 now predeclares those functions again. This fixes + `Issue 56607 `_. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -242,18 +267,6 @@ Improvements to Clang's diagnostics without a prototype and with no arguments is an invalid redeclaration of a function with a prototype. e.g., ``void f(int); void f() {}`` is now properly diagnosed. -- The ``-Wimplicit-function-declaration`` warning diagnostic now defaults to - an error in C99 and later. Prior to C2x, it may be downgraded to a warning - with ``-Wno-error=implicit-function-declaration``, or disabled entirely with - ``-Wno-implicit-function-declaration``. As of C2x, support for implicit - function declarations has been removed, and the warning options will have no - effect. -- The ``-Wimplicit-int`` warning diagnostic now defaults to an error in C99 and - later. Prior to C2x, it may be downgraded to a warning with - ``-Wno-error=implicit-int``, or disabled entirely with ``-Wno-implicit-int``. - As of C2x, support for implicit int has been removed, and the warning options - will have no effect. Specifying ``-Wimplicit-int`` in C89 mode will now issue - warnings instead of being a noop. - No longer issue a "declaration specifiers missing, defaulting to int" diagnostic in C89 mode because it is not an extension in C89, it was valid code. The diagnostic has been removed entirely as it did not have a @@ -298,7 +311,7 @@ Improvements to Clang's diagnostics - When using class templates without arguments, clang now tells developers that template arguments are missing in certain contexts. This fixes `Issue 55962 `_. -- Printable Unicode characters within `static_assert` messages are no longer +- Printable Unicode characters within ``static_assert`` messages are no longer escaped. - The ``-Winfinite-recursion`` diagnostic no longer warns about unevaluated operands of a ``typeid`` expression, as they are now @@ -313,15 +326,20 @@ Improvements to Clang's diagnostics conversions now defaults to an error in all C language modes. It may be downgraded to a warning with ``-Wno-error=int-conversion``, or disabled entirely with ``-Wno-int-conversion``. +- Deprecated lax vector conversions for Altivec vectors. + The default behaviour with respect to these conversions + will switch to disable them in an upcoming release. +- On AIX, only emit XL compatibility warning when 16 byte aligned structs are + pass-by-value function arguments. Non-comprehensive list of changes in this release ------------------------------------------------- -- Improve __builtin_dump_struct: +- Improve ``__builtin_dump_struct``: - Support bitfields in struct and union. - - Improve the dump format, dump both bitwidth(if its a bitfield) and field + - Improve the dump format, dump both bitwidth (if its a bitfield) and field value. - Remove anonymous tag locations and flatten anonymous struct members. - Beautify dump format, add indent for struct members. @@ -334,8 +352,9 @@ Non-comprehensive list of changes in this release custom formatting for non-aggregate types. - Previously disabled sanitizer options now enabled by default: - - ASAN_OPTIONS=detect_stack_use_after_return=1 (only on Linux). - - MSAN_OPTIONS=poison_in_dtor=1. + + - ``ASAN_OPTIONS=detect_stack_use_after_return=1`` (only on Linux). + - ``MSAN_OPTIONS=poison_in_dtor=1``. - Some type-trait builtins, such as ``__has_trivial_assign``, have been documented as deprecated for a while because their semantics don't mix well with post-C++11 type-traits. @@ -439,9 +458,9 @@ Attribute Changes in Clang ``__attribute__((function_return("keep")))`` was added. This is intended to be used by the Linux kernel to mitigate RETBLEED. -- Ignore the `__preferred_name__` attribute when writing for C++20 module interfaces. +- Ignore the ``__preferred_name__`` attribute when writing for C++20 module interfaces. This is a short-term workaround intentionally since clang doesn't take care of the - serialization and deserialization of `__preferred_name__`. See + serialization and deserialization of ``__preferred_name__``. See https://github.com/llvm/llvm-project/issues/56490 for example. Windows Support @@ -503,8 +522,8 @@ C++ Language Changes in Clang unsigned character literals. This fixes `Issue 54886 `_. - Stopped allowing constraints on non-template functions to be compliant with dcl.decl.general p4. -- Improved ``copy elision`` optimization. It's possible to apply ``NRVO`` for an object if at the moment when - any return statement of this object is executed, the ``return slot`` won't be occupied by another object. +- Improved `copy elision` optimization. It's possible to apply `NRVO` for an object if at the moment when + any return statement of this object is executed, the `return slot` won't be occupied by another object. C++20 Feature Support @@ -536,6 +555,12 @@ C++20 Feature Support - As per "Conditionally Trivial Special Member Functions" (P0848), it is now possible to overload destructors using concepts. Note that the rest of the paper about other special member functions is not yet implemented. +- Skip rebuilding lambda expressions in arguments of immediate invocations. + This fixes `GH56183 `_, + `GH51695 `_, + `GH50455 `_, + `GH54872 `_, + `GH54587 `_. C++2b Feature Support ^^^^^^^^^^^^^^^^^^^^^ @@ -553,25 +578,28 @@ C++2b Feature Support CUDA/HIP Language Changes in Clang ---------------------------------- -- Added `__noinline__` as a keyword to avoid diagnostics due to usage of - `__attribute__((__noinline__))` in CUDA/HIP programs. +- Added ``__noinline__`` as a keyword to avoid diagnostics due to usage of + ``__attribute__((__noinline__))`` in CUDA/HIP programs. Objective-C Language Changes in Clang ------------------------------------- -OpenCL C Language Changes in Clang ----------------------------------- +OpenCL Kernel Language Changes in Clang +--------------------------------------- -... +- Improved/fixed misc issues in the builtin function support and diagnostics. +- Improved diagnostics for unknown extension pragma, subgroup functions and + implicit function prototype. +- Added ``-cl-ext`` flag to the Clang driver to toggle extensions/features + compiled for. +- Added ``cl_khr_subgroup_rotate`` extension. +- Removed some ``printf`` and ``hostcall`` related diagnostics when compiling + for AMDGPU. +- Fixed alignment of pointer types in kernel arguments. ABI Changes in Clang -------------------- -- GCC doesn't pack non-POD members in packed structs unless the packed - attribute is also specified on the member. Clang historically did perform - such packing. Clang now matches the gcc behavior (except on Darwin and PS4). - You can switch back to the old ABI behavior with the flag: - ``-fclang-abi-compat=14.0``. - When compiling C for ARM or AArch64, a zero-length bitfield in a ``struct`` (e.g. ``int : 0``) no longer prevents the structure from being considered a homogeneous floating-point or vector aggregate. The new behavior agrees with @@ -619,6 +647,19 @@ X86 Support in Clang will be used by Linux kernel mitigations for RETBLEED. The corresponding flag ``-mfunction-return=keep`` may be appended to disable the feature. +The ``_Float16`` type requires SSE2 feature and above due to the instruction +limitations. When using it on i386 targets, you need to specify ``-msse2`` +explicitly. + +For targets without F16C feature or above, please make sure: + +- Use GCC 12.0 and above if you are using libgcc. +- If you are using compiler-rt, use the same version with the compiler. + Early versions provided FP16 builtins in a different ABI. A workaround is to use + a small code snippet to check the ABI if you cannot make sure of it. +- If you are using downstream runtimes that provide FP16 conversions, update + them with the new ABI. + DWARF Support in Clang ---------------------- @@ -633,8 +674,34 @@ Arm and AArch64 Support in Clang -------------------------------- - clang now supports the Cortex-M85 CPU, which can be chosen with - `-mcpu=cortex-m85`. By default, this has PACBTI turned on, but it can be - disabled with `-mcpu=cortex-m85+nopacbti`. + ``-mcpu=cortex-m85``. By default, this has PACBTI turned on, but it can be + disabled with ``-mcpu=cortex-m85+nopacbti``. +- clang now supports using C/C++ operators on sizeless SVE vectors such as + ``svint32_t``. The set of supported operators is shown in the table Vector + Operations found in the :ref:`Clang Language Extensions ` + document. + +RISC-V Support in Clang +----------------------- + +- Updates to the RISC-V vector intrinsics to align with ongoing additions to + the RISC-V Vector intrinsics specification. Additionally, these intrinsics + are now generated lazily, resulting a substantial improvement in + compile-time for code including the vector intrinsics header. +- Intrinsics added for the RISC-V scalar crypto ('K') extensions. +- Intrinsics added for the RISC-V CLZ and CTZ instructions in the Zbb + extension. +- An ABI lowering bug (resulting in incorrect LLVM IR generation) was fixed. + The bug could be triggered in particular circumstances in C++ when passing a + data-only struct that inherits from another struct. + +SPIR-V Support in Clang +----------------------- + +- Added flag ``-fintegrated-objemitter`` to enable use of experimental + integrated LLVM backend when generating SPIR-V binary. +- The SPIR-V generator continues to produce typed pointers in this release + despite the general switch of LLVM to opaque pointers. Floating Point Support in Clang ------------------------------- @@ -692,8 +759,11 @@ clang-extdef-mapping libclang -------- -- The soversion for libclang will now change for each new LLVM major release. This matches - the behavior of clang <= 13. +- Introduce new option ``CLANG_FORCE_MATCHING_LIBCLANG_SOVERSION`` that defaults to ON. + This means that by default libclang's SOVERSION matches the major version of LLVM. + Setting this to OFF makes the SOVERSION be the ABI compatible version (currently 13). + See `discussion `_ + here. Static Analyzer --------------- @@ -706,8 +776,8 @@ Static Analyzer positives. - Added a new checker ``alpha.unix.cstring.UninitializedRead`` this will check for uninitialized reads - from common memory copy/manipulation functions such as ``memcpy``, ``mempcpy``, ``memmove``, ``memcmp``, ` - `strcmp``, ``strncmp``, ``strcpy``, ``strlen``, ``strsep`` and many more. Although + from common memory copy/manipulation functions such as ``memcpy``, ``mempcpy``, ``memmove``, ``memcmp``, + ``strcmp``, ``strncmp``, ``strcpy``, ``strlen``, ``strsep`` and many more. Although this checker currently is in list of alpha checkers due to a false positive. - Added a new checker ``alpha.unix.Errno``. This can find the first read @@ -756,5 +826,5 @@ this release by going into the "``clang/docs/``" directory in the Clang tree. If you have any questions or comments about Clang, please feel free to -contact us on the Discourse forums (Clang Frontend category) +contact us on the `Discourse forums (Clang Frontend category) `_. diff --git a/clang/docs/StandardCPlusPlusModules.rst b/clang/docs/StandardCPlusPlusModules.rst new file mode 100644 index 0000000000000..ae434b14ef50c --- /dev/null +++ b/clang/docs/StandardCPlusPlusModules.rst @@ -0,0 +1,876 @@ +==================== +Standard C++ Modules +==================== + +.. contents:: + :local: + +Introduction +============ + +The term ``modules`` has a lot of meanings. For the users of Clang, modules may +refer to ``Objective-C Modules``, ``Clang C++ Modules`` (or ``Clang Header Modules``, +etc.) or ``Standard C++ Modules``. The implementation of all these kinds of modules in Clang +has a lot of shared code, but from the perspective of users, their semantics and +command line interfaces are very different. This document focuses on +an introduction of how to use standard C++ modules in Clang. + +There is already a detailed document about `Clang modules `_, it +should be helpful to read `Clang modules `_ if you want to know +more about the general idea of modules. Since standard C++ modules have different semantics +(and work flows) from `Clang modules`, this page describes the background and use of +Clang with standard C++ modules. + +Modules exist in two forms in the C++ Language Specification. They can refer to +either "Named Modules" or to "Header Units". This document covers both forms. + +Standard C++ Named modules +========================== + +This document was intended to be a manual first and foremost, however, we consider it helpful to +introduce some language background here for readers who are not familiar with +the new language feature. This document is not intended to be a language +tutorial; it will only introduce necessary concepts about the +structure and building of the project. + +Background and terminology +-------------------------- + +Modules +~~~~~~~ + +In this document, the term ``Modules``/``modules`` refers to standard C++ modules +feature if it is not decorated by ``Clang``. + +Clang Modules +~~~~~~~~~~~~~ + +In this document, the term ``Clang Modules``/``Clang modules`` refer to Clang +c++ modules extension. These are also known as ``Clang header modules``, +``Clang module map modules`` or ``Clang c++ modules``. + +Module and module unit +~~~~~~~~~~~~~~~~~~~~~~ + +A module consists of one or more module units. A module unit is a special +translation unit. Every module unit must have a module declaration. The syntax +of the module declaration is: + +.. code-block:: c++ + + [export] module module_name[:partition_name]; + +Terms enclosed in ``[]`` are optional. The syntax of ``module_name`` and ``partition_name`` +in regex form corresponds to ``[a-zA-Z_][a-zA-Z_0-9\.]*``. In particular, a literal dot ``.`` +in the name has no semantic meaning (e.g. implying a hierarchy). + +In this document, module units are classified into: + +* Primary module interface unit. + +* Module implementation unit. + +* Module interface partition unit. + +* Internal module partition unit. + +A primary module interface unit is a module unit whose module declaration is +``export module module_name;``. The ``module_name`` here denotes the name of the +module. A module should have one and only one primary module interface unit. + +A module implementation unit is a module unit whose module declaration is +``module module_name;``. A module could have multiple module implementation +units with the same declaration. + +A module interface partition unit is a module unit whose module declaration is +``export module module_name:partition_name;``. The ``partition_name`` should be +unique within any given module. + +An internal module partition unit is a module unit whose module declaration +is ``module module_name:partition_name;``. The ``partition_name`` should be +unique within any given module. + +In this document, we use the following umbrella terms: + +* A ``module interface unit`` refers to either a ``primary module interface unit`` + or a ``module interface partition unit``. + +* An ``importable module unit`` refers to either a ``module interface unit`` + or a ``internal module partition unit``. + +* A ``module partition unit`` refers to either a ``module interface partition unit`` + or a ``internal module partition unit``. + +Built Module Interface file +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A ``Built Module Interface file`` stands for the precompiled result of an importable module unit. +It is also called the acronym ``BMI`` genrally. + +Global module fragment +~~~~~~~~~~~~~~~~~~~~~~ + +In a module unit, the section from ``module;`` to the module declaration is called the global module fragment. + + +How to build projects using modules +----------------------------------- + +Quick Start +~~~~~~~~~~~ + +Let's see a "hello world" example that uses modules. + +.. code-block:: c++ + + // Hello.cppm + module; + #include + export module Hello; + export void hello() { + std::cout << "Hello World!\n"; + } + + // use.cpp + import Hello; + int main() { + hello(); + return 0; + } + +Then we type: + +.. code-block:: console + + $ clang++ -std=c++20 Hello.cppm --precompile -o Hello.pcm + $ clang++ -std=c++20 use.cpp -fprebuilt-module-path=. Hello.pcm -o Hello.out + $ ./Hello.out + Hello World! + +In this example, we make and use a simple module ``Hello`` which contains only a +primary module interface unit ``Hello.cppm``. + +Then let's see a little bit more complex "hello world" example which uses the 4 kinds of module units. + +.. code-block:: c++ + + // M.cppm + export module M; + export import :interface_part; + import :impl_part; + export void Hello(); + + // interface_part.cppm + export module M:interface_part; + export void World(); + + // impl_part.cppm + module; + #include + #include + module M:impl_part; + import :interface_part; + + std::string W = "World."; + void World() { + std::cout << W << std::endl; + } + + // Impl.cpp + module; + #include + module M; + void Hello() { + std::cout << "Hello "; + } + + // User.cpp + import M; + int main() { + Hello(); + World(); + return 0; + } + +Then we are able to compile the example by the following command: + +.. code-block:: console + + # Precompiling the module + $ clang++ -std=c++20 interface_part.cppm --precompile -o M-interface_part.pcm + $ clang++ -std=c++20 impl_part.cppm --precompile -fprebuilt-module-path=. -o M-impl_part.pcm + $ clang++ -std=c++20 M.cppm --precompile -fprebuilt-module-path=. -o M.pcm + $ clang++ -std=c++20 Impl.cpp -fmodule-file=M.pcm -c -o Impl.o + + # Compiling the user + $ clang++ -std=c++20 User.cpp -fprebuilt-module-path=. -c -o User.o + + # Compiling the module and linking it together + $ clang++ -std=c++20 M-interface_part.pcm -c -o M-interface_part.o + $ clang++ -std=c++20 M-impl_part.pcm -c -o M-impl_part.o + $ clang++ -std=c++20 M.pcm -c -o M.o + $ clang++ User.o M-interface_part.o M-impl_part.o M.o Impl.o -o a.out + +We explain the options in the following sections. + +How to enable standard C++ modules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Currently, standard C++ modules are enabled automatically +if the language standard is ``-std=c++20`` or newer. +The ``-fmodules-ts`` option is deprecated and is planned to be removed. + +How to produce a BMI +~~~~~~~~~~~~~~~~~~~~ + +It is possible to generate a BMI for an importable module unit by specifying the ``--precompile`` option. + +File name requirement +~~~~~~~~~~~~~~~~~~~~~ + +The file name of an ``importable module unit`` should end with ``.cppm`` +(or ``.ccm``, ``.cxxm``, ``.c++m``). The file name of a ``module implementation unit`` +should end with ``.cpp`` (or ``.cc``, ``.cxx``, ``.c++``). + +The file name of BMIs should end with ``.pcm``. +The file name of the BMI of a ``primary module interface unit`` should be ``module_name.pcm``. +The file name of BMIs of ``module partition unit`` should be ``module_name-partition_name.pcm``. + +If the file names use different extensions, Clang may fail to build the module. +For example, if the filename of an ``importable module unit`` ends with ``.cpp`` instead of ``.cppm``, +then we can't generate a BMI for the ``importable module unit`` by ``--precompile`` option +since ``--precompile`` option now would only run preprocessor, which is equal to `-E` now. +If we want the filename of an ``importable module unit`` ends with other suffixes instead of ``.cppm``, +we could put ``-x c++-module`` in front of the file. For example, + +.. code-block:: c++ + + // Hello.cpp + module; + #include + export module Hello; + export void hello() { + std::cout << "Hello World!\n"; + } + + // use.cpp + import Hello; + int main() { + hello(); + return 0; + } + +Now the filename of the ``module interface`` ends with ``.cpp`` instead of ``.cppm``, +we can't compile them by the original command lines. But we are still able to do it by: + +.. code-block:: console + + $ clang++ -std=c++20 -x c++-module Hello.cpp --precompile -o Hello.pcm + $ clang++ -std=c++20 use.cpp -fprebuilt-module-path=. Hello.pcm -o Hello.out + $ ./Hello.out + Hello World! + +How to specify the dependent BMIs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The option ``-fprebuilt-module-path`` tells the compiler the path where to search for dependent BMIs. +It may be used multiple times just like ``-I`` for specifying paths for header files. The look up rule here is: + +* (1) When we import module M. The compiler would look up M.pcm in the directories specified + by ``-fprebuilt-module-path``. +* (2) When we import partition module unit M:P. The compiler would look up M-P.pcm in the + directories specified by ``-fprebuilt-module-path``. + +Another way to specify the dependent BMIs is to use ``-fmodule-file``. The main difference +is that ``-fprebuilt-module-path`` takes a directory, whereas ``-fmodule-file`` requires a +specific file. In case both the ``-fprebuilt-module-path`` and ``-fmodule-file`` exist, the +``-fmodule-file`` option takes higher precedence. In another word, if the compiler finds the wanted +BMI specified by ``-fmodule-file``, the compiler wouldn't look up again in the directories specified +by ``-fprebuilt-module-path``. + +When we compile a ``module implementation unit``, we must pass the BMI of the corresponding +``primary module interface unit`` by ``-fmodule-file`` +since the language specification says a module implementation unit implicitly imports +the primary module interface unit. + + [module.unit]p8 + + A module-declaration that contains neither an export-keyword nor a module-partition implicitly + imports the primary module interface unit of the module as if by a module-import-declaration. + +Again, the option ``-fmodule-file`` may occur multiple times. +For example, the command line to compile ``M.cppm`` in +the above example could be rewritten into: + +.. code-block:: console + + $ clang++ -std=c++20 M.cppm --precompile -fmodule-file=M-interface_part.pcm -fmodule-file=M-impl_part.pcm -o M.pcm + +``-fprebuilt-module-path`` is more convenient and ``-fmodule-file`` is faster since +it saves time for file lookup. + +Remember that module units still have an object counterpart to the BMI +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is easy to forget to compile BMIs at first since we may envision module interfaces like headers. +However, this is not true. +Module units are translation units. We need to compile them to object files +and link the object files like the example shows. + +For example, the traditional compilation processes for headers are like: + +.. code-block:: text + + src1.cpp -+> clang++ src1.cpp --> src1.o ---, + hdr1.h --' +-> clang++ src1.o src2.o -> executable + hdr2.h --, | + src2.cpp -+> clang++ src2.cpp --> src2.o ---' + +And the compilation process for module units are like: + +.. code-block:: text + + src1.cpp ----------------------------------------+> clang++ src1.cpp -------> src1.o -, + (header unit) hdr1.h -> clang++ hdr1.h ... -> hdr1.pcm --' +-> clang++ src1.o mod1.o src2.o -> executable + mod1.cppm -> clang++ mod1.cppm ... -> mod1.pcm --,--> clang++ mod1.pcm ... -> mod1.o -+ + src2.cpp ----------------------------------------+> clang++ src2.cpp -------> src2.o -' + +As the diagrams show, we need to compile the BMI from module units to object files and link the object files. +(But we can't do this for the BMI from header units. See the later section for the definition of header units) + +If we want to create a module library, we can't just ship the BMIs in an archive. +We must compile these BMIs(``*.pcm``) into object files(``*.o``) and add those object files to the archive instead. + +Consistency Requirement +~~~~~~~~~~~~~~~~~~~~~~~ + +If we envision modules as a cache to speed up compilation, then - as with other caching techniques - +it is important to keep cache consistency. +So **currently** Clang will do very strict check for consistency. + +Options consistency +^^^^^^^^^^^^^^^^^^^ + +The language option of module units and their non-module-unit users should be consistent. +The following example is not allowed: + +.. code-block:: c++ + + // M.cppm + export module M; + + // Use.cpp + import M; + +.. code-block:: console + + $ clang++ -std=c++20 M.cppm --precompile -o M.pcm + $ clang++ -std=c++2b Use.cpp -fprebuilt-module-path=. + +The compiler would reject the example due to the inconsistent language options. +Not all options are language options. +For example, the following example is allowed: + +.. code-block:: console + + $ clang++ -std=c++20 M.cppm --precompile -o M.pcm + # Inconsistent optimization level. + $ clang++ -std=c++20 -O3 Use.cpp -fprebuilt-module-path=. + # Inconsistent debugging level. + $ clang++ -std=c++20 -g Use.cpp -fprebuilt-module-path=. + +Although the two examples have inconsistent optimization and debugging level, both of them are accepted. + +Note that **currently** the compiler doesn't consider inconsistent macro definition a problem. For example: + +.. code-block:: console + + $ clang++ -std=c++20 M.cppm --precompile -o M.pcm + # Inconsistent optimization level. + $ clang++ -std=c++20 -O3 -DNDEBUG Use.cpp -fprebuilt-module-path=. + +Currently Clang would accept the above example. But it may produce surprising results if the +debugging code depends on consistent use of ``NDEBUG`` also in other translation units. + +Source content consistency +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When the compiler reads a BMI, the compiler will check the consistency of the corresponding +source files. For example: + +.. code-block:: c++ + + // M.cppm + export module M; + export template + T foo(T t) { + return t; + } + + // Use.cpp + import M; + void bar() { + foo(5); + } + +.. code-block:: console + + $ clang++ -std=c++20 M.cppm --precompile -o M.pcm + $ rm M.cppm + $ clang++ -std=c++20 Use.cpp -fmodule-file=M.pcm + +The compiler would reject the example since the compiler failed to find the source file to check the consistency. +So the following example would be rejected too. + +.. code-block:: console + + $ clang++ -std=c++20 M.cppm --precompile -o M.pcm + $ echo "int i=0;" >> M.cppm + $ clang++ -std=c++20 Use.cpp -fmodule-file=M.pcm + +The compiler would reject it too since the compiler detected the file was changed. + +But it is OK to move the BMI as long as the source files remain: + +.. code-block:: console + + $ clang++ -std=c++20 M.cppm --precompile -o M.pcm + $ mkdir -p tmp + $ mv M.pcm tmp/M.pcm + $ clang++ -std=c++20 Use.cpp -fmodule-file=tmp/M.pcm + +The above example would be accepted. + +If the user doesn't want to follow the consistency requirement due to some reasons (e.g., distributing BMI), +the user could try to use ``-Xclang -fmodules-embed-all-files`` when producing BMI. For example: + +.. code-block:: console + + $ clang++ -std=c++20 M.cppm --precompile -Xclang -fmodules-embed-all-files -o M.pcm + $ rm M.cppm + $ clang++ -std=c++20 Use.cpp -fmodule-file=M.pcm + +Now the compiler would accept the above example. +Important note: Xclang options are intended to be used by compiler internally and its semantics +are not guaranteed to be preserved in future versions. + +Also the compiler will record the path to the header files included in the global module fragment and compare the +headers when imported. For example, + +.. code-block:: c++ + + // foo.h + #include + void Hello() { + std::cout << "Hello World.\n"; + } + + // foo.cppm + module; + #include "foo.h" + export module foo; + export using ::Hello; + + // Use.cpp + import foo; + int main() { + Hello(); + } + +Then it is problematic if we remove ``foo.h`` before import `foo` module. + +.. code-block:: console + + clang++ -std=c++20 foo.cppm --precompile -o foo.pcm + mv foo.h foo.orig.h + # The following one is rejected + clang++ -std=c++20 Use.cpp -fmodule-file=foo.pcm -c + +The above case will rejected. And we're still able to workaround it by ``-Xclang -fmodules-embed-all-files`` option: + +.. code-block:: console + + clang++ -std=c++20 foo.cppm --precompile -Xclang -fmodules-embed-all-files -o foo.pcm + mv foo.h foo.orig.h + clang++ -std=c++20 Use.cpp -fmodule-file=foo.pcm -c -o Use.o + clang++ Use.o foo.pcm + +ABI Impacts +----------- + +The declarations in a module unit which are not in the global module fragment have new linkage names. + +For example, + +.. code-block:: c++ + + export module M; + namespace NS { + export int foo(); + } + +The linkage name of ``NS::foo()`` would be ``_ZN2NSW1M3fooEv``. +This couldn't be demangled by previous versions of the debugger or demangler. +As of LLVM 15.x, users can utilize ``llvm-cxxfilt`` to demangle this: + +.. code-block:: console + + $ llvm-cxxfilt _ZN2NSW1M3fooEv + +The result would be ``NS::foo@M()``, which reads as ``NS::foo()`` in module ``M``. + +The ABI implies that we can't declare something in a module unit and define it in a non-module unit (or vice-versa), +as this would result in linking errors. + +Known Problems +-------------- + +The following describes issues in the current implementation of modules. +Please see https://github.com/llvm/llvm-project/labels/clang%3Amodules for more issues +or file a new issue if you don't find an existing one. +If you're going to create a new issue for standard C++ modules, +please start the title with ``[C++20] [Modules]`` (or ``[C++2b] [Modules]``, etc) +and add the label ``clang:modules`` (if you have permissions for that). + +For higher level support for proposals, you could visit https://clang.llvm.org/cxx_status.html. + +Support for clang-scan-deps +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The support for clang-scan-deps may be the most urgent problem for modules now. +Without the support for clang-scan-deps, it's hard to involve build systems. +This means that users could only play with modules through makefiles or by writing a parser by hand. +It blocks more uses for modules, which will block more defect reports or requirements. + +This is tracked in: https://github.com/llvm/llvm-project/issues/51792. + +Ambiguous deduction guide +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Currently, when we call deduction guides in global module fragment, +we may get incorrect diagnosing message like: `ambiguous deduction`. + +So if we're using deduction guide from global module fragment, we probably need to write: + +.. code-block:: c++ + + std::lock_guard lk(mutex); + +instead of + +.. code-block:: c++ + + std::lock_guard lk(mutex); + +This is tracked in: https://github.com/llvm/llvm-project/issues/56916 + +Ignored PreferredName Attribute +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Due to a tricky problem, when Clang writes BMIs, Clang will ignore the ``preferred_name`` attribute, if any. +This implies that the ``preferred_name`` wouldn't show in debugger or dumping. + +This is tracked in: https://github.com/llvm/llvm-project/issues/56490 + +Don't emit macros about module declaration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is covered by P1857R3. We mention it again here since users may abuse it before we implement it. + +Someone may want to write code which could be compiled both by modules or non-modules. +A direct idea would be use macros like: + +.. code-block:: c++ + + MODULE + IMPORT header_name + EXPORT_MODULE MODULE_NAME; + IMPORT header_name + EXPORT ... + +So this file could be triggered like a module unit or a non-module unit depending on the definition +of some macros. +However, this kind of usage is forbidden by P1857R3 but we haven't implemented P1857R3 yet. +This means that is possible to write illegal modules code now, and obviously this will stop working +once P1857R3 is implemented. +A simple suggestion would be "Don't play macro tricks with module declarations". + +This is tracked in: https://github.com/llvm/llvm-project/issues/56917 + +In consistent filename suffix requirement for importable module units +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Currently, clang requires the file name of an ``importable module unit`` should end with ``.cppm`` +(or ``.ccm``, ``.cxxm``, ``.c++m``). However, the behavior is inconsistent with other compilers. + +This is tracked in: https://github.com/llvm/llvm-project/issues/57416 + +Header Units +============ + +How to build projects using header unit +--------------------------------------- + +Quick Start +~~~~~~~~~~~ + +For the following example, + +.. code-block:: c++ + + import ; + int main() { + std::cout << "Hello World.\n"; + } + +we could compile it as + +.. code-block:: console + + $ clang++ -std=c++20 -xc++-system-header --precompile iostream -o iostream.pcm + $ clang++ -std=c++20 -fmodule-file=iostream.pcm main.cpp + +How to produce BMIs +~~~~~~~~~~~~~~~~~~~ + +Similar to named modules, we could use ``--precompile`` to produce the BMI. +But we need to specify that the input file is a header by ``-xc++-system-header`` or ``-xc++-user-header``. + +Also we could use `-fmodule-header={user,system}` option to produce the BMI for header units +which has suffix like `.h` or `.hh`. +The value of `-fmodule-header` means the user search path or the system search path. +The default value for `-fmodule-header` is `user`. +For example, + +.. code-block:: c++ + + // foo.h + #include + void Hello() { + std::cout << "Hello World.\n"; + } + + // use.cpp + import "foo.h"; + int main() { + Hello(); + } + +We could compile it as: + +.. code-block:: console + + $ clang++ -std=c++20 -fmodule-header foo.h -o foo.pcm + $ clang++ -std=c++20 -fmodule-file=foo.pcm use.cpp + +For headers which don't have a suffix, we need to pass ``-xc++-header`` +(or ``-xc++-system-header`` or ``-xc++-user-header``) to mark it as a header. +For example, + +.. code-block:: c++ + + // use.cpp + import "foo.h"; + int main() { + Hello(); + } + +.. code-block:: console + + $ clang++ -std=c++20 -fmodule-header=system -xc++-header iostream -o iostream.pcm + $ clang++ -std=c++20 -fmodule-file=iostream.pcm use.cpp + +How to specify the dependent BMIs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We could use ``-fmodule-file`` to specify the BMIs, and this option may occur multiple times as well. + +With the existing implementation ``-fprebuilt-module-path`` cannot be used for header units +(since they are nominally anonymous). +For header units, use ``-fmodule-file`` to include the relevant PCM file for each header unit. + +This is expect to be solved in future editions of the compiler either by the tooling finding and specifying +the -fmodule-file or by the use of a module-mapper that understands how to map the header name to their PCMs. + +Don't compile the BMI +~~~~~~~~~~~~~~~~~~~~~ + +Another difference with modules is that we can't compile the BMI from a header unit. +For example: + +.. code-block:: console + + $ clang++ -std=c++20 -xc++-system-header --precompile iostream -o iostream.pcm + # This is not allowed! + $ clang++ iostream.pcm -c -o iostream.o + +It makes sense due to the semantics of header units, which are just like headers. + +Include translation +~~~~~~~~~~~~~~~~~~~ + +The C++ spec allows the vendors to convert ``#include header-name`` to ``import header-name;`` when possible. +Currently, Clang would do this translation for the ``#include`` in the global module fragment. + +For example, the following two examples are the same: + +.. code-block:: c++ + + module; + import ; + export module M; + export void Hello() { + std::cout << "Hello.\n"; + } + +with the following one: + +.. code-block:: c++ + + module; + #include + export module M; + export void Hello() { + std::cout << "Hello.\n"; + } + +.. code-block:: console + + $ clang++ -std=c++20 -xc++-system-header --precompile iostream -o iostream.pcm + $ clang++ -std=c++20 -fmodule-file=iostream.pcm --precompile M.cppm -o M.cpp + +In the latter example, the Clang could find the BMI for the ```` +so it would try to replace the ``#include `` to ``import ;`` automatically. + + +Relationships between Clang modules +----------------------------------- + +Header units have pretty similar semantics with Clang modules. +The semantics of both of them are like headers. + +In fact, we could even "mimic" the sytle of header units by Clang modules: + +.. code-block:: c++ + + module "iostream" { + export * + header "/path/to/libstdcxx/iostream" + } + +.. code-block:: console + + $ clang++ -std=c++20 -fimplicit-modules -fmodule-map-file=.modulemap main.cpp + +It would be simpler if we are using libcxx: + +.. code-block:: console + + $ clang++ -std=c++20 main.cpp -fimplicit-modules -fimplicit-module-maps + +Since there is already one +`module map `_ +in the source of libcxx. + +Then immediately leads to the question: why don't we implement header units through Clang header modules? + +The main reason for this is that Clang modules have more semantics like hierarchy or +wrapping multiple headers together as a big module. +However, these things are not part of Standard C++ Header units, +and we want to avoid the impression that these additional semantics get interpreted as Standard C++ behavior. + +Another reason is that there are proposals to introduce module mappers to the C++ standard +(for example, https://wg21.link/p1184r2). +If we decide to reuse Clang's modulemap, we may get in trouble once we need to introduce another module mapper. + +So the final answer for why we don't reuse the interface of Clang modules for header units is that +there are some differences between header units and Clang modules and that ignoring those +differences now would likely become a problem in the future. + +Possible Questions +================== + +How modules speed up compilation +-------------------------------- + +A classic theory for the reason why modules speed up the compilation is: +if there are ``n`` headers and ``m`` source files and each header is included by each source file, +then the complexity of the compilation is ``O(n*m)``; +But if there are ``n`` module interfaces and ``m`` source files, the complexity of the compilation is +``O(n+m)``. So, using modules would be a big win when scaling. +In a simpler word, we could get rid of many redundant compilations by using modules. + +Roughly, this theory is correct. But the problem is that it is too rough. +The behavior depends on the optimization level, as we will illustrate below. + +First is ``O0``. The compilation process is described in the following graph. + +.. code-block:: none + + ├-------------frontend----------┼-------------middle end----------------┼----backend----┤ + │ │ │ │ + └---parsing----sema----codegen--┴----- transformations ---- codegen ----┴---- codegen --┘ + + ┌---------------------------------------------------------------------------------------┐ + | │ + | source file │ + | │ + └---------------------------------------------------------------------------------------┘ + + ┌--------┐ + │ │ + │imported│ + │ │ + │ code │ + │ │ + └--------┘ + +Here we can see that the source file (could be a non-module unit or a module unit) would get processed by the +whole pipeline. +But the imported code would only get involved in semantic analysis, which is mainly about name lookup, +overload resolution and template instantiation. +All of these processes are fast relative to the whole compilation process. +More importantly, the imported code only needs to be processed once in frontend code generation, +as well as the whole middle end and backend. +So we could get a big win for the compilation time in O0. + +But with optimizations, things are different: + +(we omit ``code generation`` part for each end due to the limited space) + +.. code-block:: none + + ├-------- frontend ---------┼--------------- middle end --------------------┼------ backend ----┤ + │ │ │ │ + └--- parsing ---- sema -----┴--- optimizations --- IPO ---- optimizations---┴--- optimizations -┘ + + ┌-----------------------------------------------------------------------------------------------┐ + │ │ + │ source file │ + │ │ + └-----------------------------------------------------------------------------------------------┘ + ┌---------------------------------------┐ + │ │ + │ │ + │ imported code │ + │ │ + │ │ + └---------------------------------------┘ + +It would be very unfortunate if we end up with worse performance after using modules. +The main concern is that when we compile a source file, the compiler needs to see the function body +of imported module units so that it can perform IPO (InterProcedural Optimization, primarily inlining +in practice) to optimize functions in current source file with the help of the information provided by +the imported module units. +In other words, the imported code would be processed again and again in importee units +by optimizations (including IPO itself). +The optimizations before IPO and the IPO itself are the most time-consuming part in whole compilation process. +So from this perspective, we might not be able to get the improvements described in the theory. +But we could still save the time for optimizations after IPO and the whole backend. + +Overall, at ``O0`` the implementations of functions defined in a module will not impact module users, +but at higher optimization levels the definitions of such functions are provided to user compilations for the +purposes of optimization (but definitions of these functions are still not included in the use's object file)- +this means the build speedup at higher optimization levels may be lower than expected given ``O0`` experience, +but does provide by more optimization opportunities. + diff --git a/clang/docs/index.rst b/clang/docs/index.rst index 78a1ed12bcf3c..507ddc4660ca4 100644 --- a/clang/docs/index.rst +++ b/clang/docs/index.rst @@ -40,6 +40,7 @@ Using Clang as a Compiler SafeStack ShadowCallStack SourceBasedCodeCoverage + StandardCPlusPlusModules Modules MSVCCompatibility MisExpect diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 725bb0bced9c5..baed5ca22fa75 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -3287,8 +3287,12 @@ class ConceptDecl : public TemplateDecl, public Mergeable { return isa(getTemplateParameters()->getParam(0)); } - ConceptDecl *getCanonicalDecl() override { return getFirstDecl(); } - const ConceptDecl *getCanonicalDecl() const { return getFirstDecl(); } + ConceptDecl *getCanonicalDecl() override { + return cast(getPrimaryMergedDecl(this)); + } + const ConceptDecl *getCanonicalDecl() const { + return const_cast(this)->getCanonicalDecl(); + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6ff5b8de57fd0..cb460401eb47c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -419,7 +419,7 @@ def warn_implicit_function_decl : Warning< InGroup, DefaultIgnore; def ext_implicit_function_decl_c99 : ExtWarn< "call to undeclared function %0; ISO C99 and later do not support implicit " - "function declarations">, InGroup, DefaultError; + "function declarations">, InGroup; def note_function_suggestion : Note<"did you mean %0?">; def err_ellipsis_first_param : Error< @@ -705,7 +705,7 @@ def ext_implicit_lib_function_decl : ExtWarn< def ext_implicit_lib_function_decl_c99 : ExtWarn< "call to undeclared library function '%0' with type %1; ISO C99 and later " "do not support implicit function declarations">, - InGroup, DefaultError; + InGroup; def note_include_header_or_declare : Note< "include the header <%0> or explicitly provide a declaration for '%1'">; def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">; @@ -4359,7 +4359,7 @@ def err_ident_list_in_fn_declaration : Error< "a parameter list without types is only allowed in a function definition">; def ext_param_not_declared : ExtWarn< "parameter %0 was not declared, defaults to 'int'; ISO C99 and later do not " - "support implicit int">, InGroup, DefaultError; + "support implicit int">, InGroup; def err_param_default_argument : Error< "C does not support default arguments">; def err_param_default_argument_redefinition : Error< @@ -10029,7 +10029,7 @@ def warn_receiver_forward_class : Warning< def note_method_sent_forward_class : Note<"method %0 is used for the forward class">; def ext_missing_type_specifier : ExtWarn< "type specifier missing, defaults to 'int'; ISO C99 and later do not support " - "implicit int">, InGroup, DefaultError; + "implicit int">, InGroup; def err_missing_type_specifier : Error< "a type specifier is required for all declarations">; def err_decimal_unsupported : Error< diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index 47d736a3b4557..8ef1c5991c56e 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -525,6 +525,11 @@ class Module { Parent->SubModules.push_back(this); } + /// Is this module have similar semantics as headers. + bool isHeaderLikeModule() const { + return isModuleMapModule() || isHeaderUnit(); + } + /// Is this a module partition. bool isModulePartition() const { return Kind == ModulePartitionInterface || diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 79454b5addead..7c5df05069edd 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -178,6 +178,8 @@ class Preprocessor { IdentifierInfo *Ident__is_target_vendor; // __is_target_vendor IdentifierInfo *Ident__is_target_os; // __is_target_os IdentifierInfo *Ident__is_target_environment; // __is_target_environment + IdentifierInfo *Ident__is_target_variant_os; + IdentifierInfo *Ident__is_target_variant_environment; IdentifierInfo *Ident__FLT_EVAL_METHOD__; // __FLT_EVAL_METHOD // Weak, only valid (and set) while InMacroArgs is true. @@ -1353,6 +1355,11 @@ class Preprocessor { StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef Tokens) const; + /// Get the predefines for this processor. + /// Used by some third-party tools to inspect and add predefines (see + /// https://github.com/llvm/llvm-project/issues/57483). + const std::string &getPredefines() const { return Predefines; } + /// Set the predefines for this Preprocessor. /// /// These predefines are automatically injected when parsing the main file. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 06ea0b417cb3a..681a76dfa56a6 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4479,6 +4479,8 @@ class Sema final { bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old); bool CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old); bool CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old); + bool IsRedefinitionInModule(const NamedDecl *New, + const NamedDecl *Old) const; void DiagnoseAmbiguousLookup(LookupResult &Result); //@} diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index cc4ced02876ea..dee2744516d5d 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1738,7 +1738,8 @@ class ASTReader const LangOptions &LangOpts, const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts, - StringRef ExistingModuleCachePath); + StringRef ExistingModuleCachePath, + bool RequireStrictOptionMatches = false); /// Returns the suggested contents of the predefines buffer, /// which contains a (typically-empty) subset of the predefines diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index a22031142c7c7..d522c87388a5b 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -637,10 +637,10 @@ static bool TryPrintAsStringLiteral(raw_ostream &Out, return false; // Nothing we can do about a sequence that is not null-terminated - if (!Inits.back().getInt().isZero()) + if (!Inits.back().isInt() || !Inits.back().getInt().isZero()) return false; - else - Inits = Inits.drop_back(); + + Inits = Inits.drop_back(); llvm::SmallString<40> Buf; Buf.push_back('"'); @@ -655,6 +655,8 @@ static bool TryPrintAsStringLiteral(raw_ostream &Out, } for (auto &Val : Inits) { + if (!Val.isInt()) + return false; int64_t Char64 = Val.getInt().getExtValue(); if (!isASCII(Char64)) return false; // Bye bye, see you in integers. diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 6f3ede2ce42a7..5ddd95e2ecca6 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1889,12 +1889,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, UnfilledBitsInLastUnit = 0; LastBitfieldStorageUnitSize = 0; - llvm::Triple Target = Context.getTargetInfo().getTriple(); - bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() || - Context.getLangOpts().getClangABICompat() <= - LangOptions::ClangABI::Ver14 || - Target.isPS() || Target.isOSDarwin())) || - D->hasAttr(); + bool FieldPacked = Packed || D->hasAttr(); AlignRequirementKind AlignRequirement = AlignRequirementKind::None; CharUnits FieldSize; diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 8d778500d1033..625048c69a864 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1993,7 +1993,7 @@ void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { cast(DRE->getDecl())->getTemplateSpecializationArgs(); assert(Args); - if (Args->size() != 1) { + if (Args->size() != 1 || Args->get(0).getKind() != TemplateArgument::Pack) { const TemplateParameterList *TPL = nullptr; if (!DRE->hadMultipleCandidates()) if (const auto *TD = dyn_cast(DRE->getDecl())) diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt index 3e052c0cf9957..c38c9fddb4240 100644 --- a/clang/lib/Basic/CMakeLists.txt +++ b/clang/lib/Basic/CMakeLists.txt @@ -110,3 +110,7 @@ add_clang_library(clangBasic omp_gen ) +target_link_libraries(clangBasic + PRIVATE + ${LLVM_ATOMIC_LIB} +) diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 60ef52ac3f0dd..8d8972c1613a9 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -489,9 +489,12 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__FP_FAST_FMA", "1"); Builder.defineMacro("__FP_FAST_FMAF", "1"); + // C/C++ operators work on both VLS and VLA SVE types + if (FPU & SveMode) + Builder.defineMacro("__ARM_FEATURE_SVE_VECTOR_OPERATORS", "2"); + if (Opts.VScaleMin && Opts.VScaleMin == Opts.VScaleMax) { Builder.defineMacro("__ARM_FEATURE_SVE_BITS", Twine(Opts.VScaleMin * 128)); - Builder.defineMacro("__ARM_FEATURE_SVE_VECTOR_OPERATORS"); } } diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 69afdf8a3584c..0f5c366816df9 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -358,6 +358,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector &Features, HasFloat16 = SSELevel >= SSE2; + HasBFloat16 = SSELevel >= SSE2; + MMX3DNowEnum ThreeDNowLevel = llvm::StringSwitch(Feature) .Case("+3dnowa", AMD3DNowAthlon) .Case("+3dnow", AMD3DNow) diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 0affa58b2f4c0..ed0864aec6d2d 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -156,6 +156,8 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { public: X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &) : TargetInfo(Triple) { + BFloat16Width = BFloat16Align = 16; + BFloat16Format = &llvm::APFloat::BFloat(); LongDoubleFormat = &llvm::APFloat::x87DoubleExtended(); AddrSpaceMap = &X86AddrSpaceMap; HasStrictFP = true; @@ -396,6 +398,8 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { uint64_t getPointerAlignV(unsigned AddrSpace) const override { return getPointerWidthV(AddrSpace); } + + const char *getBFloat16Mangling() const override { return "u6__bf16"; }; }; // X86-32 generic target diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 949112c63cc9e..6915f950b6ce3 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -649,8 +649,8 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) { SmallVector ModuleInits; for (Module *M : AllImports) { - // No Itanium initializer in module map modules. - if (M->isModuleMapModule()) + // No Itanium initializer in header like modules. + if (M->isHeaderLikeModule()) continue; // TODO: warn of mixed use of module map modules and C++20? llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); SmallString<256> FnName; @@ -778,8 +778,8 @@ CodeGenModule::EmitCXXGlobalInitFunc() { SmallVector ModuleInits; if (CXX20ModuleInits) for (Module *M : ImportedModules) { - // No Itanium initializer in module map modules. - if (M->isModuleMapModule()) + // No Itanium initializer in header like modules. + if (M->isHeaderLikeModule()) continue; llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); SmallString<256> FnName; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 05ab16668743b..9935fcc0d3ea2 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1509,6 +1509,21 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S, llvm::ConstantInt *CaseVal = Builder.getInt(S.getLHS()->EvaluateKnownConstInt(getContext())); + + // Emit debuginfo for the case value if it is an enum value. + const ConstantExpr *CE; + if (auto ICE = dyn_cast(S.getLHS())) + CE = dyn_cast(ICE->getSubExpr()); + else + CE = dyn_cast(S.getLHS()); + if (CE) { + if (auto DE = dyn_cast(CE->getSubExpr())) + if (CGDebugInfo *Dbg = getDebugInfo()) + if (CGM.getCodeGenOpts().hasReducedDebugInfo()) + Dbg->EmitGlobalVariable(DE->getDecl(), + APValue(llvm::APSInt(CaseVal->getValue()))); + } + if (SwitchLikelihood) SwitchLikelihood->push_back(Stmt::getLikelihood(Attrs)); @@ -2343,6 +2358,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { std::vector ArgElemTypes; std::vector Args; llvm::BitVector ResultTypeRequiresCast; + llvm::BitVector ResultRegIsFlagReg; // Keep track of inout constraints. std::string InOutConstraints; @@ -2400,6 +2416,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { ResultRegQualTys.push_back(QTy); ResultRegDests.push_back(Dest); + bool IsFlagReg = llvm::StringRef(OutputConstraint).startswith("{@cc"); + ResultRegIsFlagReg.push_back(IsFlagReg); + llvm::Type *Ty = ConvertTypeForMem(QTy); const bool RequiresCast = Info.allowsRegister() && (getTargetHooks().isScalarizableAsmOperand(*this, Ty) || @@ -2717,10 +2736,21 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { // ResultRegDests can be also populated by addReturnRegisterOutputs() above, // in which case its size may grow. assert(ResultTypeRequiresCast.size() <= ResultRegDests.size()); + assert(ResultRegIsFlagReg.size() <= ResultRegDests.size()); for (unsigned i = 0, e = RegResults.size(); i != e; ++i) { llvm::Value *Tmp = RegResults[i]; llvm::Type *TruncTy = ResultTruncRegTypes[i]; + if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) { + // Target must guarantee the Value `Tmp` here is lowered to a boolean + // value. + llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2); + llvm::Value *IsBooleanValue = + Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two); + llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume); + Builder.CreateCall(FnAssume, IsBooleanValue); + } + // If the result type of the LLVM IR asm doesn't match the result type of // the expression, do the conversion. if (ResultRegTypes[i] != ResultTruncRegTypes[i]) { diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index aa55cdaca5dca..570424dae7fc8 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -2582,8 +2582,9 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd); emitPostUpdateForReductionClause(CGF, S, [](CodeGenFunction &) { return nullptr; }); + LoopScope.restoreMap(); + CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; }); } - CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; }); // Emit: if (PreCond) - end. if (ContBlock) { CGF.EmitBranch(ContBlock); @@ -3426,11 +3427,12 @@ bool CodeGenFunction::EmitOMPWorksharingLoop( EmitOMPLastprivateClauseFinal( S, isOpenMPSimdDirective(S.getDirectiveKind()), Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc()))); + LoopScope.restoreMap(); + EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) { + return CGF.Builder.CreateIsNotNull( + CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); + }); } - EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) { - return CGF.Builder.CreateIsNotNull( - CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); - }); DoacrossCleanupScope.ForceCleanup(); // We're now done with the loop, so jump to the continuation block. if (ContBlock) { @@ -7658,6 +7660,7 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) { CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false, (*LIP)->getType(), S.getBeginLoc()))); } + LoopScope.restoreMap(); CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) { return CGF.Builder.CreateIsNotNull( CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false, diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index fe0890f433e8c..672acd844525b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1094,7 +1094,7 @@ class CodeGenFunction : public CodeGenTypeCache { void ForceCleanup() { RunCleanupsScope::ForceCleanup(); - MappedVars.restore(CGF); + restoreMap(); } /// Exit scope - all the mapped variables are restored. @@ -1108,6 +1108,11 @@ class CodeGenFunction : public CodeGenTypeCache { VD = VD->getCanonicalDecl(); return !VD->isLocalVarDeclOrParm() && CGF.LocalDeclMap.count(VD) > 0; } + + /// Restore all mapped variables w/o clean up. This is usefully when we want + /// to reference the original variables but don't want the clean up because + /// that could emit lifetime end too early, causing backend issue #56913. + void restoreMap() { MappedVars.restore(CGF); } }; /// Save/restore original map of previously emitted local vars in case when we diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 4e8e120d89dff..d87692face2a9 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -521,7 +521,7 @@ static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO, void CodeGenModule::Release() { Module *Primary = getContext().getModuleForCodeGen(); - if (CXX20ModuleInits && Primary && !Primary->isModuleMapModule()) + if (CXX20ModuleInits && Primary && !Primary->isHeaderLikeModule()) EmitModuleInitializers(Primary); EmitDeferred(); DeferredDecls.insert(EmittedDeferredDecls.begin(), @@ -2521,21 +2521,23 @@ void CodeGenModule::EmitModuleInitializers(clang::Module *Primary) { // source, first Global Module Fragments, if present. if (auto GMF = Primary->getGlobalModuleFragment()) { for (Decl *D : getContext().getModuleInitializers(GMF)) { - assert(D->getKind() == Decl::Var && "GMF initializer decl is not a var?"); + if (isa(D)) + continue; + assert(isa(D) && "GMF initializer decl is not a var?"); EmitTopLevelDecl(D); } } // Second any associated with the module, itself. for (Decl *D : getContext().getModuleInitializers(Primary)) { // Skip import decls, the inits for those are called explicitly. - if (D->getKind() == Decl::Import) + if (isa(D)) continue; EmitTopLevelDecl(D); } // Third any associated with the Privat eMOdule Fragment, if present. if (auto PMF = Primary->getPrivateModuleFragment()) { for (Decl *D : getContext().getModuleInitializers(PMF)) { - assert(D->getKind() == Decl::Var && "PMF initializer decl is not a var?"); + assert(isa(D) && "PMF initializer decl is not a var?"); EmitTopLevelDecl(D); } } diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 0fe084b628dab..836aabf80179d 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1377,19 +1377,23 @@ struct CounterCoverageMappingBuilder // Extend into the condition before we propagate through it below - this is // needed to handle macros that generate the "if" but not the condition. - extendRegion(S->getCond()); + if (!S->isConsteval()) + extendRegion(S->getCond()); Counter ParentCount = getRegion().getCounter(); Counter ThenCount = getRegionCounter(S); - // Emitting a counter for the condition makes it easier to interpret the - // counter for the body when looking at the coverage. - propagateCounts(ParentCount, S->getCond()); + if (!S->isConsteval()) { + // Emitting a counter for the condition makes it easier to interpret the + // counter for the body when looking at the coverage. + propagateCounts(ParentCount, S->getCond()); - // The 'then' count applies to the area immediately after the condition. - auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen())); - if (Gap) - fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount); + // The 'then' count applies to the area immediately after the condition. + Optional Gap = + findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen())); + if (Gap) + fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount); + } extendRegion(S->getThen()); Counter OutCount = propagateCounts(ThenCount, S->getThen()); @@ -1398,9 +1402,9 @@ struct CounterCoverageMappingBuilder if (const Stmt *Else = S->getElse()) { bool ThenHasTerminateStmt = HasTerminateStmt; HasTerminateStmt = false; - // The 'else' count applies to the area immediately after the 'then'. - Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else)); + Optional Gap = + findGapAreaBetween(getEnd(S->getThen()), getStart(Else)); if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount); extendRegion(Else); @@ -1416,9 +1420,11 @@ struct CounterCoverageMappingBuilder GapRegionCounter = OutCount; } - // Create Branch Region around condition. - createBranchRegion(S->getCond(), ThenCount, - subtractCounters(ParentCount, ThenCount)); + if (!S->isConsteval()) { + // Create Branch Region around condition. + createBranchRegion(S->getCond(), ThenCount, + subtractCounters(ParentCount, ThenCount)); + } } void VisitCXXTryStmt(const CXXTryStmt *S) { diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index d1ee61eab9d66..44743fa0206f4 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -2871,7 +2871,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) { Current = Integer; } else if (k == BuiltinType::Float || k == BuiltinType::Double || - k == BuiltinType::Float16) { + k == BuiltinType::Float16 || k == BuiltinType::BFloat16) { Current = SSE; } else if (k == BuiltinType::LongDouble) { const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat(); @@ -3002,7 +3002,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, Current = Integer; else if (Size <= 128) Lo = Hi = Integer; - } else if (ET->isFloat16Type() || ET == getContext().FloatTy) { + } else if (ET->isFloat16Type() || ET == getContext().FloatTy || + ET->isBFloat16Type()) { Current = SSE; } else if (ET == getContext().DoubleTy) { Lo = Hi = SSE; @@ -3474,9 +3475,9 @@ GetSSETypeAtOffset(llvm::Type *IRType, unsigned IROffset, if (SourceSize > T0Size) T1 = getFPTypeAtOffset(IRType, IROffset + T0Size, TD); if (T1 == nullptr) { - // Check if IRType is a half + float. float type will be in IROffset+4 due + // Check if IRType is a half/bfloat + float. float type will be in IROffset+4 due // to its alignment. - if (T0->isHalfTy() && SourceSize > 4) + if (T0->is16bitFPTy() && SourceSize > 4) T1 = getFPTypeAtOffset(IRType, IROffset + 4, TD); // If we can't get a second FP type, return a simple half or float. // avx512fp16-abi.c:pr51813_2 shows it works to return float for @@ -3488,7 +3489,7 @@ GetSSETypeAtOffset(llvm::Type *IRType, unsigned IROffset, if (T0->isFloatTy() && T1->isFloatTy()) return llvm::FixedVectorType::get(T0, 2); - if (T0->isHalfTy() && T1->isHalfTy()) { + if (T0->is16bitFPTy() && T1->is16bitFPTy()) { llvm::Type *T2 = nullptr; if (SourceSize > 4) T2 = getFPTypeAtOffset(IRType, IROffset + 4, TD); @@ -3497,7 +3498,7 @@ GetSSETypeAtOffset(llvm::Type *IRType, unsigned IROffset, return llvm::FixedVectorType::get(T0, 4); } - if (T0->isHalfTy() || T1->isHalfTy()) + if (T0->is16bitFPTy() || T1->is16bitFPTy()) return llvm::FixedVectorType::get(llvm::Type::getHalfTy(getVMContext()), 4); return llvm::Type::getDoubleTy(getVMContext()); @@ -7046,10 +7047,10 @@ Address ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Empty records are ignored for parameter passing purposes. if (isEmptyRecord(getContext(), Ty, true)) { - Address Addr = Address(CGF.Builder.CreateLoad(VAListAddr), - getVAListElementType(CGF), SlotSize); - Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); - return Addr; + VAListAddr = CGF.Builder.CreateElementBitCast(VAListAddr, CGF.Int8PtrTy); + auto *Load = CGF.Builder.CreateLoad(VAListAddr); + Address Addr = Address(Load, CGF.Int8Ty, SlotSize); + return CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); } CharUnits TySize = getContext().getTypeSizeInChars(Ty); @@ -11001,9 +11002,22 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, // Unions aren't eligible unless they're empty (which is caught above). if (RD->isUnion()) return false; + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + // If this is a C++ record, check the bases first. + if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { + for (const CXXBaseSpecifier &B : CXXRD->bases()) { + const auto *BDecl = + cast(B.getType()->castAs()->getDecl()); + CharUnits BaseOff = Layout.getBaseClassOffset(BDecl); + bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff, + Field1Ty, Field1Off, Field2Ty, + Field2Off); + if (!Ret) + return false; + } + } int ZeroWidthBitFieldCount = 0; for (const FieldDecl *FD : RD->fields()) { - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); uint64_t FieldOffInBits = Layout.getFieldOffset(FD->getFieldIndex()); QualType QTy = FD->getType(); if (FD->isBitField()) { diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp index 70ba8eb2a7d0d..2c9d65e7714a2 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; @@ -113,6 +114,30 @@ sparc::FloatABI sparc::getSparcFloatABI(const Driver &D, return ABI; } +std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args, + const llvm::Triple &Triple) { + if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getSpelling() << Triple.getTriple(); + return ""; + } + + if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { + StringRef CPUName = A->getValue(); + if (CPUName == "native") { + std::string CPU = std::string(llvm::sys::getHostCPUName()); + if (!CPU.empty() && CPU != "generic") + return CPU; + return ""; + } + return std::string(CPUName); + } + + if (Triple.getArch() == llvm::Triple::sparc && Triple.isOSSolaris()) + return "v9"; + return ""; +} + void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, std::vector &Features) { sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.h b/clang/lib/Driver/ToolChains/Arch/Sparc.h index d12a9a70e264c..44658c4259c69 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.h +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.h @@ -28,6 +28,9 @@ enum class FloatABI { FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args); +std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); + void getSparcTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, std::vector &Features); const char *getSparcAsmModeForCPU(llvm::StringRef Name, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index b62a025c50729..3704ed8586682 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2205,6 +2205,18 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, CmdArgs.push_back("-mfloat-abi"); CmdArgs.push_back("hard"); } + + if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) { + StringRef Name = A->getValue(); + std::string TuneCPU; + if (Name == "native") + TuneCPU = std::string(llvm::sys::getHostCPUName()); + else + TuneCPU = std::string(Name); + + CmdArgs.push_back("-tune-cpu"); + CmdArgs.push_back(Args.MakeArgString(TuneCPU)); + } } void Clang::AddSystemZTargetArgs(const ArgList &Args, @@ -4610,8 +4622,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, TC.addClangWarningOptions(CmdArgs); // FIXME: Subclass ToolChain for SPIR and move this to addClangWarningOptions. - if (Triple.isSPIR() || Triple.isSPIRV()) + if (Triple.isSPIR() || Triple.isSPIRV()) { CmdArgs.push_back("-Wspir-compat"); + // SPIR-V support still needs pointer types in some cases as recovering + // type from pointer uses is not always possible e.g. for extern functions + // (see PR56660). + CmdArgs.push_back("-no-opaque-pointers"); + } // Select the appropriate action. RewriteKind rewriteKind = RK_None; @@ -6576,7 +6593,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // support by default, or just assume that all languages do. bool HaveModules = Std && (Std->containsValue("c++2a") || Std->containsValue("c++20") || - Std->containsValue("c++latest")); + Std->containsValue("c++2b") || Std->containsValue("c++latest")); RenderModulesOptions(C, D, Args, Input, Output, CmdArgs, HaveModules); if (Args.hasFlag(options::OPT_fpch_validate_input_files_content, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 1d2c085d683e1..443725f7d8a8d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -12,6 +12,7 @@ #include "Arch/M68k.h" #include "Arch/Mips.h" #include "Arch/PPC.h" +#include "Arch/Sparc.h" #include "Arch/SystemZ.h" #include "Arch/VE.h" #include "Arch/X86.h" @@ -431,15 +432,15 @@ std::string tools::getCPUName(const Driver &D, const ArgList &Args, case llvm::Triple::bpfel: case llvm::Triple::bpfeb: - case llvm::Triple::sparc: - case llvm::Triple::sparcel: - case llvm::Triple::sparcv9: if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) return A->getValue(); - if (T.getArch() == llvm::Triple::sparc && T.isOSSolaris()) - return "v9"; return ""; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + return sparc::getSparcTargetCPU(D, Args, T); + case llvm::Triple::x86: case llvm::Triple::x86_64: return x86::getX86TargetCPU(D, Args, T); diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 5e59677947e62..7ad990dda467e 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -693,8 +693,8 @@ CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple, std::string CudaToolChain::getInputFilename(const InputInfo &Input) const { // Only object files are changed, for example assembly files keep their .s - // extensions. - if (Input.getType() != types::TY_Object) + // extensions. If the user requested device-only compilation don't change it. + if (Input.getType() != types::TY_Object || getDriver().offloadDeviceOnly()) return ToolChain::getInputFilename(Input); // Replace extension for object files with cubin because nvlink relies on diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 34396b0b59c2b..665cdc3132fb8 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -631,6 +631,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddRunTimeLibs(ToolChain, D, CmdArgs, Args); + // LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so + // forcibly link with libatomic as a workaround. + // TODO: Issue #41880 and D118021. + if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) { + CmdArgs.push_back("--push-state"); + CmdArgs.push_back("--as-needed"); + CmdArgs.push_back("-latomic"); + CmdArgs.push_back("--pop-state"); + } + if (WantPthread && !isAndroid) CmdArgs.push_back("-lpthread"); @@ -2129,31 +2139,21 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( // and gcc-toolsets. if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux && D.getVFS().exists("/opt/rh")) { - // Find the directory in /opt/rh/ starting with gcc-toolset-* or - // devtoolset-* with the highest version number and add that - // one to our prefixes. - std::string ChosenToolsetDir; - unsigned ChosenToolsetVersion = 0; - std::error_code EC; - for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin("/opt/rh", EC), - LE; - !EC && LI != LE; LI = LI.increment(EC)) { - StringRef ToolsetDir = llvm::sys::path::filename(LI->path()); - unsigned ToolsetVersion; - if ((!ToolsetDir.startswith("gcc-toolset-") && - !ToolsetDir.startswith("devtoolset-")) || - ToolsetDir.substr(ToolsetDir.rfind('-') + 1) - .getAsInteger(10, ToolsetVersion)) - continue; - - if (ToolsetVersion > ChosenToolsetVersion) { - ChosenToolsetVersion = ToolsetVersion; - ChosenToolsetDir = "/opt/rh/" + ToolsetDir.str(); - } - } - - if (ChosenToolsetVersion > 0) - Prefixes.push_back(ChosenToolsetDir + "/root/usr"); + // TODO: We may want to remove this, since the functionality + // can be achieved using config files. + Prefixes.push_back("/opt/rh/gcc-toolset-12/root/usr"); + Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr"); + Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-12/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-11/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-10/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-9/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-8/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-7/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-6/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-4/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-3/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-2/root/usr"); } // Fall back to /usr which is used by most non-Solaris systems. diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 5991cf23d5dc7..cf6549e2a5bda 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2329,25 +2329,6 @@ class AnnotatingParser { !PrevToken->MatchingParen) return TT_PointerOrReference; - // For "} &&" - if (PrevToken->is(tok::r_brace) && Tok.is(tok::ampamp)) { - const FormatToken *MatchingLBrace = PrevToken->MatchingParen; - - // We check whether there is a TemplateCloser(">") to indicate it's a - // template or not. If it's not a template, "&&" is likely a reference - // operator. - // struct {} &&ref = {}; - if (!MatchingLBrace) - return TT_PointerOrReference; - FormatToken *BeforeLBrace = MatchingLBrace->getPreviousNonComment(); - if (!BeforeLBrace || BeforeLBrace->isNot(TT_TemplateCloser)) - return TT_PointerOrReference; - - // If it is a template, "&&" is a binary operator. - // enable_if<>{} && ... - return TT_BinaryOperator; - } - if (PrevToken->Tok.isLiteral() || PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true, tok::kw_false, tok::r_brace)) { diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 7b07ab948f643..53cb48d2de9e6 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -772,7 +772,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (ASTReader::isAcceptableASTFile( Dir->path(), FileMgr, CI.getPCHContainerReader(), CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(), - SpecificModuleCachePath)) { + SpecificModuleCachePath, /*RequireStrictOptionMatches=*/true)) { PPOpts.ImplicitPCHInclude = std::string(Dir->path()); Found = true; break; diff --git a/clang/lib/Headers/cpuid.h b/clang/lib/Headers/cpuid.h index 5d262a60735f2..caa0069c2e1fa 100644 --- a/clang/lib/Headers/cpuid.h +++ b/clang/lib/Headers/cpuid.h @@ -232,6 +232,7 @@ /* Features in %ebx for leaf 0x80000008 */ #define bit_CLZERO 0x00000001 +#define bit_RDPRU 0x00000010 #define bit_WBNOINVD 0x00000200 diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index f3be2107f985f..c56f41c4495e6 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -387,6 +387,10 @@ void Preprocessor::RegisterBuiltinMacros() { Ident__is_target_os = RegisterBuiltinMacro(*this, "__is_target_os"); Ident__is_target_environment = RegisterBuiltinMacro(*this, "__is_target_environment"); + Ident__is_target_variant_os = + RegisterBuiltinMacro(*this, "__is_target_variant_os"); + Ident__is_target_variant_environment = + RegisterBuiltinMacro(*this, "__is_target_variant_environment"); // Modules. Ident__building_module = RegisterBuiltinMacro(*this, "__building_module"); @@ -1431,6 +1435,39 @@ static bool isTargetEnvironment(const TargetInfo &TI, return TI.getTriple().getEnvironment() == Env.getEnvironment(); } +/// Implements the __is_target_variant_os builtin macro. +static bool isTargetVariantOS(const TargetInfo &TI, const IdentifierInfo *II) { + if (TI.getTriple().isOSDarwin()) { + const llvm::Triple *VariantTriple = TI.getDarwinTargetVariantTriple(); + if (!VariantTriple) + return false; + + std::string OSName = + (llvm::Twine("unknown-unknown-") + II->getName().lower()).str(); + llvm::Triple OS(OSName); + if (OS.getOS() == llvm::Triple::Darwin) { + // Darwin matches macos, ios, etc. + return VariantTriple->isOSDarwin(); + } + return VariantTriple->getOS() == OS.getOS(); + } + return false; +} + +/// Implements the __is_target_variant_environment builtin macro. +static bool isTargetVariantEnvironment(const TargetInfo &TI, + const IdentifierInfo *II) { + if (TI.getTriple().isOSDarwin()) { + const llvm::Triple *VariantTriple = TI.getDarwinTargetVariantTriple(); + if (!VariantTriple) + return false; + std::string EnvName = (llvm::Twine("---") + II->getName().lower()).str(); + llvm::Triple Env(EnvName); + return VariantTriple->getEnvironment() == Env.getEnvironment(); + } + return false; +} + /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. void Preprocessor::ExpandBuiltinMacro(Token &Tok) { @@ -1677,6 +1714,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { .Case("__is_target_vendor", true) .Case("__is_target_os", true) .Case("__is_target_environment", true) + .Case("__is_target_variant_os", true) + .Case("__is_target_variant_environment", true) .Default(false); } }); @@ -1877,6 +1916,22 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Tok, *this, diag::err_feature_check_malformed); return II && isTargetEnvironment(getTargetInfo(), II); }); + } else if (II == Ident__is_target_variant_os) { + EvaluateFeatureLikeBuiltinMacro( + OS, Tok, II, *this, false, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo( + Tok, *this, diag::err_feature_check_malformed); + return II && isTargetVariantOS(getTargetInfo(), II); + }); + } else if (II == Ident__is_target_variant_environment) { + EvaluateFeatureLikeBuiltinMacro( + OS, Tok, II, *this, false, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + IdentifierInfo *II = ExpectFeatureIdentifierInfo( + Tok, *this, diag::err_feature_check_malformed); + return II && isTargetVariantEnvironment(getTargetInfo(), II); + }); } else { llvm_unreachable("Unknown identifier!"); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 985005d0b79bc..75ffa8b0a90ab 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1711,6 +1711,80 @@ bool Sema::CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old) { return false; } +// Check the redefinition in C++20 Modules. +// +// [basic.def.odr]p14: +// For any definable item D with definitions in multiple translation units, +// - if D is a non-inline non-templated function or variable, or +// - if the definitions in different translation units do not satisfy the +// following requirements, +// the program is ill-formed; a diagnostic is required only if the definable +// item is attached to a named module and a prior definition is reachable at +// the point where a later definition occurs. +// - Each such definition shall not be attached to a named module +// ([module.unit]). +// - Each such definition shall consist of the same sequence of tokens, ... +// ... +// +// Return true if the redefinition is not allowed. Return false otherwise. +bool Sema::IsRedefinitionInModule(const NamedDecl *New, + const NamedDecl *Old) const { + assert(getASTContext().isSameEntity(New, Old) && + "New and Old are not the same definition, we should diagnostic it " + "immediately instead of checking it."); + assert(const_cast(this)->isReachable(New) && + const_cast(this)->isReachable(Old) && + "We shouldn't see unreachable definitions here."); + + Module *NewM = New->getOwningModule(); + Module *OldM = Old->getOwningModule(); + + // We only checks for named modules here. The header like modules is skipped. + // FIXME: This is not right if we import the header like modules in the module + // purview. + // + // For example, assuming "header.h" provides definition for `D`. + // ```C++ + // //--- M.cppm + // export module M; + // import "header.h"; // or #include "header.h" but import it by clang modules + // actually. + // + // //--- Use.cpp + // import M; + // import "header.h"; // or uses clang modules. + // ``` + // + // In this case, `D` has multiple definitions in multiple TU (M.cppm and + // Use.cpp) and `D` is attached to a named module `M`. The compiler should + // reject it. But the current implementation couldn't detect the case since we + // don't record the information about the importee modules. + // + // But this might not be painful in practice. Since the design of C++20 Named + // Modules suggests us to use headers in global module fragment instead of + // module purview. + if (NewM && NewM->isHeaderLikeModule()) + NewM = nullptr; + if (OldM && OldM->isHeaderLikeModule()) + OldM = nullptr; + + if (!NewM && !OldM) + return true; + + // [basic.def.odr]p14.3 + // Each such definition shall not be attached to a named module + // ([module.unit]). + if ((NewM && NewM->isModulePurview()) || (OldM && OldM->isModulePurview())) + return true; + + // Then New and Old lives in the same TU if their share one same module unit. + if (NewM) + NewM = NewM->getTopLevelModule(); + if (OldM) + OldM = OldM->getTopLevelModule(); + return OldM == NewM; +} + static bool isUsingDecl(NamedDecl *D) { return isa(D) || isa(D) || @@ -3960,7 +4034,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, // default argument promotion rules were already checked by // ASTContext::typesAreCompatible(). if (Old->hasPrototype() && !New->hasWrittenPrototype() && NewDeclIsDefn && - Old->getNumParams() != New->getNumParams()) { + Old->getNumParams() != New->getNumParams() && !Old->isImplicit()) { if (Old->hasInheritedPrototype()) Old = Old->getCanonicalDecl(); Diag(New->getLocation(), diag::err_conflicting_types) << New; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0f79978b0911c..83081bbf0aa0c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -15603,6 +15603,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, resultType->castAs()->getVectorKind() != VectorType::AltiVecBool)) break; + else if (resultType->isVLSTBuiltinType()) // SVE vectors allow + and - + break; else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6 Opc == UO_Plus && resultType->isPointerType()) @@ -17598,6 +17600,11 @@ static void RemoveNestedImmediateInvocation( DRSet.erase(E); return E; } + ExprResult TransformLambdaExpr(LambdaExpr *E) { + // Do not rebuild lambdas to avoid creating a new type. + // Lambdas have already been processed inside their eval context. + return E; + } bool AlwaysRebuild() { return false; } bool ReplacingOriginal() { return true; } bool AllowSkippingCXXConstructExpr() { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 5331193de863d..6f9e025283f51 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5412,6 +5412,8 @@ void DiagnoseBuiltinDeprecation(Sema& S, TypeTrait Kind, Replacement = BTT_IsTriviallyAssignable; break; case UTT_HasTrivialCopy: + Replacement = UTT_IsTriviallyCopyable; + break; case UTT_HasTrivialDefaultConstructor: case UTT_HasTrivialMoveConstructor: Replacement = TT_IsTriviallyConstructible; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index d3b454843234b..bf7ca718a36b2 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -695,10 +695,10 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, // member of reference type uninitialized, the program is // ill-formed. SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) - << Field->getType() - << ILE->getSyntacticForm()->getSourceRange(); - SemaRef.Diag(Field->getLocation(), - diag::note_uninit_reference_member); + << Field->getType() + << (ILE->isSyntacticForm() ? ILE : ILE->getSyntacticForm()) + ->getSourceRange(); + SemaRef.Diag(Field->getLocation(), diag::note_uninit_reference_member); } hadError = true; return; diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 68158ec977cfe..5d0d87fd2422d 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -939,11 +939,9 @@ bool Sema::LookupBuiltin(LookupResult &R) { // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) { - // In C++, C2x, and OpenCL (spec v1.2 s6.9.f), we don't have any - // predefined library functions like 'malloc'. Instead, we'll just - // error. - if ((getLangOpts().CPlusPlus || getLangOpts().OpenCL || - getLangOpts().C2x) && + // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined + // library functions like 'malloc'. Instead, we'll just error. + if ((getLangOpts().CPlusPlus || getLangOpts().OpenCL) && Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return false; diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index dc1470bf7a9d1..a92fec6a02323 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -2270,6 +2270,9 @@ bool Sema::isInOpenMPTargetExecutionDirective() const { } bool Sema::isOpenMPRebuildMemberExpr(ValueDecl *D) { + // Only rebuild for Field. + if (!dyn_cast(D)) + return false; DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( D, [](OpenMPClauseKind C, bool AppliedToPointee, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d72cc33ed0f56..5dc0aadb2d5f3 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -63,9 +63,8 @@ static ExprResult CreateFunctionRefExpr( // being used. if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc)) return ExprError(); - DeclRefExpr *DRE = - DeclRefExpr::Create(S.Context, Fn->getQualifierLoc(), SourceLocation(), - Fn, false, Loc, Fn->getType(), VK_LValue, FoundDecl); + DeclRefExpr *DRE = new (S.Context) + DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); if (HadMultipleCandidates) DRE->setHadMultipleCandidates(true); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1542a07713fb7..ecc9596a87f0f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8728,7 +8728,7 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl, if (Previous.empty()) return; - auto *OldConcept = dyn_cast(Previous.getRepresentativeDecl()); + auto *OldConcept = dyn_cast(Previous.getRepresentativeDecl()->getUnderlyingDecl()); if (!OldConcept) { auto *Old = Previous.getRepresentativeDecl(); Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind) @@ -8746,7 +8746,8 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl, AddToScope = false; return; } - if (hasReachableDefinition(OldConcept)) { + if (hasReachableDefinition(OldConcept) && + IsRedefinitionInModule(NewDecl, OldConcept)) { Diag(NewDecl->getLocation(), diag::err_redefinition) << NewDecl->getDeclName(); notePreviousDefinition(OldConcept, NewDecl->getLocation()); @@ -8758,7 +8759,8 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl, // Other decls (e.g. namespaces) also have this shortcoming. return; } - Context.setPrimaryMergedDecl(NewDecl, OldConcept); + // We unwrap canonical decl late to check for module visibility. + Context.setPrimaryMergedDecl(NewDecl, OldConcept->getCanonicalDecl()); } /// \brief Strips various properties off an implicit instantiation diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 3ab5d26a9a750..edcac4d2ee9a2 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -6443,6 +6443,9 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State, CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); } + while (BTFTagAttributedTypeLoc TL = CurrTL.getAs()) + CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + while (DependentAddressSpaceTypeLoc TL = CurrTL.getAs()) { fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs()); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 76281d26b2ae5..d1e47c1045de5 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -624,20 +624,28 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts, } } +enum OptionValidation { + OptionValidateNone, + OptionValidateContradictions, + OptionValidateStrictMatches, +}; + /// Check the preprocessor options deserialized from the control block /// against the preprocessor options in an existing preprocessor. /// /// \param Diags If non-null, produce diagnostics for any mismatches incurred. -/// \param Validate If true, validate preprocessor options. If false, allow -/// macros defined by \p ExistingPPOpts to override those defined by -/// \p PPOpts in SuggestedPredefines. -static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, - const PreprocessorOptions &ExistingPPOpts, - DiagnosticsEngine *Diags, - FileManager &FileMgr, - std::string &SuggestedPredefines, - const LangOptions &LangOpts, - bool Validate = true) { +/// \param Validation If set to OptionValidateNone, ignore differences in +/// preprocessor options. If set to OptionValidateContradictions, +/// require that options passed both in the AST file and on the command +/// line (-D or -U) match, but tolerate options missing in one or the +/// other. If set to OptionValidateContradictions, require that there +/// are no differences in the options between the two. +static bool checkPreprocessorOptions( + const PreprocessorOptions &PPOpts, + const PreprocessorOptions &ExistingPPOpts, DiagnosticsEngine *Diags, + FileManager &FileMgr, std::string &SuggestedPredefines, + const LangOptions &LangOpts, + OptionValidation Validation = OptionValidateContradictions) { // Check macro definitions. MacroDefinitionsMap ASTFileMacros; collectMacroDefinitions(PPOpts, ASTFileMacros); @@ -653,7 +661,15 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, // Check whether we know anything about this macro name or not. llvm::StringMap>::iterator Known = ASTFileMacros.find(MacroName); - if (!Validate || Known == ASTFileMacros.end()) { + if (Validation == OptionValidateNone || Known == ASTFileMacros.end()) { + if (Validation == OptionValidateStrictMatches) { + // If strict matches are requested, don't tolerate any extra defines on + // the command line that are missing in the AST file. + if (Diags) { + Diags->Report(diag::err_pch_macro_def_undef) << MacroName << true; + } + return true; + } // FIXME: Check whether this identifier was referenced anywhere in the // AST file. If so, we should reject the AST file. Unfortunately, this // information isn't in the control block. What shall we do about it? @@ -684,8 +700,10 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, // If the macro was #undef'd in both, or if the macro bodies are identical, // it's fine. - if (Existing.second || Existing.first == Known->second.first) + if (Existing.second || Existing.first == Known->second.first) { + ASTFileMacros.erase(Known); continue; + } // The macro bodies differ; complain. if (Diags) { @@ -694,9 +712,20 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, } return true; } + if (Validation == OptionValidateStrictMatches) { + // If strict matches are requested, don't tolerate any extra defines in + // the AST file that are missing on the command line. + for (const auto &MacroName : ASTFileMacros.keys()) { + if (Diags) { + Diags->Report(diag::err_pch_macro_def_undef) << MacroName << false; + } + return true; + } + } // Check whether we're using predefines. - if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines && Validate) { + if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines && + Validation != OptionValidateNone) { if (Diags) { Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines; } @@ -705,7 +734,8 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts, // Detailed record is important since it is used for the module cache hash. if (LangOpts.Modules && - PPOpts.DetailedRecord != ExistingPPOpts.DetailedRecord && Validate) { + PPOpts.DetailedRecord != ExistingPPOpts.DetailedRecord && + Validation != OptionValidateNone) { if (Diags) { Diags->Report(diag::err_pch_pp_detailed_record) << PPOpts.DetailedRecord; } @@ -766,13 +796,9 @@ bool SimpleASTReaderListener::ReadPreprocessorOptions( const PreprocessorOptions &PPOpts, bool Complain, std::string &SuggestedPredefines) { - return checkPreprocessorOptions(PPOpts, - PP.getPreprocessorOpts(), - nullptr, - PP.getFileManager(), - SuggestedPredefines, - PP.getLangOpts(), - false); + return checkPreprocessorOptions(PPOpts, PP.getPreprocessorOpts(), nullptr, + PP.getFileManager(), SuggestedPredefines, + PP.getLangOpts(), OptionValidateNone); } /// Check the header search options deserialized from the control block @@ -5138,16 +5164,19 @@ namespace { const PreprocessorOptions &ExistingPPOpts; std::string ExistingModuleCachePath; FileManager &FileMgr; + bool StrictOptionMatches; public: SimplePCHValidator(const LangOptions &ExistingLangOpts, const TargetOptions &ExistingTargetOpts, const PreprocessorOptions &ExistingPPOpts, - StringRef ExistingModuleCachePath, FileManager &FileMgr) + StringRef ExistingModuleCachePath, FileManager &FileMgr, + bool StrictOptionMatches) : ExistingLangOpts(ExistingLangOpts), ExistingTargetOpts(ExistingTargetOpts), ExistingPPOpts(ExistingPPOpts), - ExistingModuleCachePath(ExistingModuleCachePath), FileMgr(FileMgr) {} + ExistingModuleCachePath(ExistingModuleCachePath), FileMgr(FileMgr), + StrictOptionMatches(StrictOptionMatches) {} bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, bool AllowCompatibleDifferences) override { @@ -5172,9 +5201,11 @@ namespace { bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, std::string &SuggestedPredefines) override { - return checkPreprocessorOptions(PPOpts, ExistingPPOpts, /*Diags=*/nullptr, - FileMgr, SuggestedPredefines, - ExistingLangOpts); + return checkPreprocessorOptions( + PPOpts, ExistingPPOpts, /*Diags=*/nullptr, FileMgr, + SuggestedPredefines, ExistingLangOpts, + StrictOptionMatches ? OptionValidateStrictMatches + : OptionValidateContradictions); } }; @@ -5451,9 +5482,11 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, const LangOptions &LangOpts, const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts, - StringRef ExistingModuleCachePath) { + StringRef ExistingModuleCachePath, + bool RequireStrictOptionMatches) { SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, - ExistingModuleCachePath, FileMgr); + ExistingModuleCachePath, FileMgr, + RequireStrictOptionMatches); return !readASTFileControlBlock(Filename, FileMgr, PCHContainerRdr, /*FindModuleFileExtensions=*/false, validator, diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 19149d0798229..ab65612bce90e 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -2839,6 +2839,12 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, return; } + if (const auto *TPO = dyn_cast(D)) { + // FIXME: We should meaningfully implement this. + (void)TPO; + return; + } + llvm_unreachable("Support for this Decl not implemented."); } diff --git a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp index 0143b5f8df6b6..655be20572b66 100644 --- a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp +++ b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp @@ -165,8 +165,8 @@ struct TransferableCommand { const unsigned OldPos = Pos; std::unique_ptr Arg(OptTable.ParseOneArg( ArgList, Pos, - /* Include */ ClangCLMode ? CoreOption | CLOption : 0, - /* Exclude */ ClangCLMode ? 0 : CLOption)); + /* Include */ ClangCLMode ? CoreOption | CLOption | CLDXCOption : 0, + /* Exclude */ ClangCLMode ? 0 : CLOption | CLDXCOption)); if (!Arg) continue; diff --git a/clang/lib/Tooling/Syntax/Tokens.cpp b/clang/lib/Tooling/Syntax/Tokens.cpp index e2014f965c900..1fa73c667b7f2 100644 --- a/clang/lib/Tooling/Syntax/Tokens.cpp +++ b/clang/lib/Tooling/Syntax/Tokens.cpp @@ -55,45 +55,140 @@ getTokensCovering(llvm::ArrayRef Toks, SourceRange R, return {Begin, End}; } -// Finds the smallest expansion range that contains expanded tokens First and -// Last, e.g.: +// Finds the range within FID corresponding to expanded tokens [First, Last]. +// Prev precedes First and Next follows Last, these must *not* be included. +// If no range satisfies the criteria, returns an invalid range. +// // #define ID(x) x // ID(ID(ID(a1) a2)) // ~~ -> a1 // ~~ -> a2 // ~~~~~~~~~ -> a1 a2 -SourceRange findCommonRangeForMacroArgs(const syntax::Token &First, - const syntax::Token &Last, - const SourceManager &SM) { - SourceRange Res; - auto FirstLoc = First.location(), LastLoc = Last.location(); - // Keep traversing up the spelling chain as longs as tokens are part of the - // same expansion. - while (!FirstLoc.isFileID() && !LastLoc.isFileID()) { - auto ExpInfoFirst = SM.getSLocEntry(SM.getFileID(FirstLoc)).getExpansion(); - auto ExpInfoLast = SM.getSLocEntry(SM.getFileID(LastLoc)).getExpansion(); - // Stop if expansions have diverged. - if (ExpInfoFirst.getExpansionLocStart() != - ExpInfoLast.getExpansionLocStart()) +SourceRange spelledForExpandedSlow(SourceLocation First, SourceLocation Last, + SourceLocation Prev, SourceLocation Next, + FileID TargetFile, + const SourceManager &SM) { + // There are two main parts to this algorithm: + // - identifying which spelled range covers the expanded tokens + // - validating that this range doesn't cover any extra tokens (First/Last) + // + // We do these in order. However as we transform the expanded range into the + // spelled one, we adjust First/Last so the validation remains simple. + + assert(SM.getSLocEntry(TargetFile).isFile()); + // In most cases, to select First and Last we must return their expansion + // range, i.e. the whole of any macros they are included in. + // + // When First and Last are part of the *same macro arg* of a macro written + // in TargetFile, we that slice of the arg, i.e. their spelling range. + // + // Unwrap such macro calls. If the target file has A(B(C)), the + // SourceLocation stack of a token inside C shows us the expansion of A first, + // then B, then any macros inside C's body, then C itself. + // (This is the reverse of the order the PP applies the expansions in). + while (First.isMacroID() && Last.isMacroID()) { + auto DecFirst = SM.getDecomposedLoc(First); + auto DecLast = SM.getDecomposedLoc(Last); + auto &ExpFirst = SM.getSLocEntry(DecFirst.first).getExpansion(); + auto &ExpLast = SM.getSLocEntry(DecLast.first).getExpansion(); + + if (!ExpFirst.isMacroArgExpansion() || !ExpLast.isMacroArgExpansion()) + break; + // Locations are in the same macro arg if they expand to the same place. + // (They may still have different FileIDs - an arg can have >1 chunks!) + if (ExpFirst.getExpansionLocStart() != ExpLast.getExpansionLocStart()) break; - // Do not continue into macro bodies. - if (!ExpInfoFirst.isMacroArgExpansion() || - !ExpInfoLast.isMacroArgExpansion()) + // Careful, given: + // #define HIDE ID(ID(a)) + // ID(ID(HIDE)) + // The token `a` is wrapped in 4 arg-expansions, we only want to unwrap 2. + // We distinguish them by whether the macro expands into the target file. + // Fortunately, the target file ones will always appear first. + auto &ExpMacro = + SM.getSLocEntry(SM.getFileID(ExpFirst.getExpansionLocStart())) + .getExpansion(); + if (ExpMacro.getExpansionLocStart().isMacroID()) break; - FirstLoc = SM.getImmediateSpellingLoc(FirstLoc); - LastLoc = SM.getImmediateSpellingLoc(LastLoc); - // Update the result afterwards, as we want the tokens that triggered the - // expansion. - Res = {FirstLoc, LastLoc}; + // Replace each endpoint with its spelling inside the macro arg. + // (This is getImmediateSpellingLoc without repeating lookups). + First = ExpFirst.getSpellingLoc().getLocWithOffset(DecFirst.second); + Last = ExpLast.getSpellingLoc().getLocWithOffset(DecLast.second); + + // Now: how do we adjust the previous/next bounds? Three cases: + // A) If they are also part of the same macro arg, we translate them too. + // This will ensure that we don't select any macros nested within the + // macro arg that cover extra tokens. Critical case: + // #define ID(X) X + // ID(prev target) // selecting 'target' succeeds + // #define LARGE ID(prev target) + // LARGE // selecting 'target' fails. + // B) They are not in the macro at all, then their expansion range is a + // sibling to it, and we can safely substitute that. + // #define PREV prev + // #define ID(X) X + // PREV ID(target) // selecting 'target' succeeds. + // #define LARGE PREV ID(target) + // LARGE // selecting 'target' fails. + // C) They are in a different arg of this macro, or the macro body. + // Now selecting the whole macro arg is fine, but the whole macro is not. + // Model this by setting using the edge of the macro call as the bound. + // #define ID2(X, Y) X Y + // ID2(prev, target) // selecting 'target' succeeds + // #define LARGE ID2(prev, target) + // LARGE // selecting 'target' fails + auto AdjustBound = [&](SourceLocation &Bound) { + if (Bound.isInvalid() || !Bound.isMacroID()) // Non-macro must be case B. + return; + auto DecBound = SM.getDecomposedLoc(Bound); + auto &ExpBound = SM.getSLocEntry(DecBound.first).getExpansion(); + if (ExpBound.isMacroArgExpansion() && + ExpBound.getExpansionLocStart() == ExpFirst.getExpansionLocStart()) { + // Case A: translate to (spelling) loc within the macro arg. + Bound = ExpBound.getSpellingLoc().getLocWithOffset(DecBound.second); + return; + } + while (Bound.isMacroID()) { + SourceRange Exp = SM.getImmediateExpansionRange(Bound).getAsRange(); + if (Exp.getBegin() == ExpMacro.getExpansionLocStart()) { + // Case B: bounds become the macro call itself. + Bound = (&Bound == &Prev) ? Exp.getBegin() : Exp.getEnd(); + return; + } + // Either case C, or expansion location will later find case B. + // We choose the upper bound for Prev and the lower one for Next: + // ID(prev) target ID(next) + // ^ ^ + // new-prev new-next + Bound = (&Bound == &Prev) ? Exp.getEnd() : Exp.getBegin(); + } + }; + AdjustBound(Prev); + AdjustBound(Next); } - // Normally mapping back to expansion location here only changes FileID, as - // we've already found some tokens expanded from the same macro argument, and - // they should map to a consecutive subset of spelled tokens. Unfortunately - // SourceManager::isBeforeInTranslationUnit discriminates sourcelocations - // based on their FileID in addition to offsets. So even though we are - // referring to same tokens, SourceManager might tell us that one is before - // the other if they've got different FileIDs. - return SM.getExpansionRange(CharSourceRange(Res, true)).getAsRange(); + + // In all remaining cases we need the full containing macros. + // If this overlaps Prev or Next, then no range is possible. + SourceRange Candidate = + SM.getExpansionRange(SourceRange(First, Last)).getAsRange(); + auto DecFirst = SM.getDecomposedExpansionLoc(Candidate.getBegin()); + auto DecLast = SM.getDecomposedLoc(Candidate.getEnd()); + // Can end up in the wrong file due to bad input or token-pasting shenanigans. + if (Candidate.isInvalid() || DecFirst.first != TargetFile || DecLast.first != TargetFile) + return SourceRange(); + // Check bounds, which may still be inside macros. + if (Prev.isValid()) { + auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Prev).getBegin()); + if (Dec.first != DecFirst.first || Dec.second >= DecFirst.second) + return SourceRange(); + } + if (Next.isValid()) { + auto Dec = SM.getDecomposedLoc(SM.getExpansionRange(Next).getEnd()); + if (Dec.first != DecLast.first || Dec.second <= DecLast.second) + return SourceRange(); + } + // Now we know that Candidate is a file range that covers [First, Last] + // without encroaching on {Prev, Next}. Ship it! + return Candidate; } } // namespace @@ -363,51 +458,50 @@ TokenBuffer::spelledForExpanded(llvm::ArrayRef Expanded) const { // of the range, bail out in that case. if (Expanded.empty()) return llvm::None; - - const syntax::Token *BeginSpelled; - const Mapping *BeginMapping; - std::tie(BeginSpelled, BeginMapping) = - spelledForExpandedToken(&Expanded.front()); - - const syntax::Token *LastSpelled; - const Mapping *LastMapping; - std::tie(LastSpelled, LastMapping) = - spelledForExpandedToken(&Expanded.back()); - - FileID FID = SourceMgr->getFileID(BeginSpelled->location()); + const syntax::Token *First = &Expanded.front(); + const syntax::Token *Last = &Expanded.back(); + const syntax::Token *FirstSpelled, *LastSpelled; + const TokenBuffer::Mapping *FirstMapping, *LastMapping; + std::tie(FirstSpelled, FirstMapping) = spelledForExpandedToken(First); + std::tie(LastSpelled, LastMapping) = spelledForExpandedToken(Last); + + FileID FID = SourceMgr->getFileID(FirstSpelled->location()); // FIXME: Handle multi-file changes by trying to map onto a common root. if (FID != SourceMgr->getFileID(LastSpelled->location())) return llvm::None; const MarkedFile &File = Files.find(FID)->second; - // If both tokens are coming from a macro argument expansion, try and map to - // smallest part of the macro argument. BeginMapping && LastMapping check is - // only for performance, they are a prerequisite for Expanded.front() and - // Expanded.back() being part of a macro arg expansion. - if (BeginMapping && LastMapping && - SourceMgr->isMacroArgExpansion(Expanded.front().location()) && - SourceMgr->isMacroArgExpansion(Expanded.back().location())) { - auto CommonRange = findCommonRangeForMacroArgs(Expanded.front(), - Expanded.back(), *SourceMgr); - // It might be the case that tokens are arguments of different macro calls, - // in that case we should continue with the logic below instead of returning - // an empty range. - if (CommonRange.isValid()) - return getTokensCovering(File.SpelledTokens, CommonRange, *SourceMgr); + // If the range is within one macro argument, the result may be only part of a + // Mapping. We must use the general (SourceManager-based) algorithm. + if (FirstMapping && FirstMapping == LastMapping && + SourceMgr->isMacroArgExpansion(First->location()) && + SourceMgr->isMacroArgExpansion(Last->location())) { + // We use excluded Prev/Next token for bounds checking. + SourceLocation Prev = (First == &ExpandedTokens.front()) + ? SourceLocation() + : (First - 1)->location(); + SourceLocation Next = (Last == &ExpandedTokens.back()) + ? SourceLocation() + : (Last + 1)->location(); + SourceRange Range = spelledForExpandedSlow( + First->location(), Last->location(), Prev, Next, FID, *SourceMgr); + if (Range.isInvalid()) + return llvm::None; + return getTokensCovering(File.SpelledTokens, Range, *SourceMgr); } + // Otherwise, use the fast version based on Mappings. // Do not allow changes that doesn't cover full expansion. - unsigned BeginExpanded = Expanded.begin() - ExpandedTokens.data(); - unsigned EndExpanded = Expanded.end() - ExpandedTokens.data(); - if (BeginMapping && BeginExpanded != BeginMapping->BeginExpanded) + unsigned FirstExpanded = Expanded.begin() - ExpandedTokens.data(); + unsigned LastExpanded = Expanded.end() - ExpandedTokens.data(); + if (FirstMapping && FirstExpanded != FirstMapping->BeginExpanded) return llvm::None; - if (LastMapping && LastMapping->EndExpanded != EndExpanded) + if (LastMapping && LastMapping->EndExpanded != LastExpanded) return llvm::None; - // All is good, return the result. return llvm::makeArrayRef( - BeginMapping ? File.SpelledTokens.data() + BeginMapping->BeginSpelled - : BeginSpelled, + FirstMapping ? File.SpelledTokens.data() + FirstMapping->BeginSpelled + : FirstSpelled, LastMapping ? File.SpelledTokens.data() + LastMapping->EndSpelled : LastSpelled + 1); } diff --git a/clang/test/AST/ast-dump-overloaded-operators.cpp b/clang/test/AST/ast-dump-overloaded-operators.cpp index 0f89a42e852d4..639a0d9874eb0 100644 --- a/clang/test/AST/ast-dump-overloaded-operators.cpp +++ b/clang/test/AST/ast-dump-overloaded-operators.cpp @@ -24,44 +24,21 @@ void test() { // CHECK-NEXT: |-FunctionDecl {{.*}} col:6{{( imported)?}} used operator, 'void (E, E)' // CHECK-NEXT: | |-ParmVarDecl {{.*}} col:17{{( imported)?}} 'E' // CHECK-NEXT: | `-ParmVarDecl {{.*}} col:19{{( imported)?}} 'E' -// CHECK-NEXT: |-FunctionDecl {{.*}} line:14:6{{( imported)?}} test 'void ()' -// CHECK-NEXT: | `-CompoundStmt {{.*}} -// CHECK-NEXT: | |-DeclStmt {{.*}} -// CHECK-NEXT: | | `-VarDecl {{.*}} col:5{{( imported)?}} used e 'E' -// CHECK-NEXT: | |-CXXOperatorCallExpr {{.*}} 'void' '+' -// CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' -// CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator+' 'void (E, E)' -// CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'E' -// CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' -// CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'E' -// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' -// CHECK-NEXT: | `-CXXOperatorCallExpr {{.*}} 'void' ',' -// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' -// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator,' 'void (E, E)' -// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'E' -// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' -// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'E' -// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' - -namespace a { - void operator-(E, E); -} - -using a::operator-; - -void f() { - E() - E(); -} -// CHECK: |-NamespaceDecl {{.*}} line:46:11{{( imported )?}} a -// CHECK-NEXT: | `-FunctionDecl {{.*}} col:8{{( imported)?}} used operator- 'void (E, E)' -// CHECK-NEXT: | |-ParmVarDecl {{.*}} col:19{{( imported)?}} 'E' -// CHECK-NEXT: | `-ParmVarDecl {{.*}} col:22{{( imported)?}} 'E' -// CHECK-NEXT: |-UsingDecl {{.*}} col:10{{( imported)?}} a::operator- -// CHECK-NEXT: |-UsingShadowDecl {{.*}} col:10{{( imported)?}} implicit Function {{.*}} 'operator-' 'void (E, E)' -// CHECK-NEXT: `-FunctionDecl {{.*}} line:52:6{{( imported)?}} f 'void ()' -// CHECK-NEXT: `-CompoundStmt {{.*}} -// CHECK-NEXT: `-CXXOperatorCallExpr {{.*}} 'void' '-' -// CHECK-NEXT: |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' -// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator-' 'void (E, E)' (UsingShadow {{.*}} 'operator-') -// CHECK-NEXT: |-CXXScalarValueInitExpr {{.*}} 'E' -// CHECK-NEXT: `-CXXScalarValueInitExpr {{.*}} 'E' +// CHECK-NEXT: `-FunctionDecl {{.*}} line:14:6{{( imported)?}} test 'void ()' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: |-DeclStmt {{.*}} +// CHECK-NEXT: | `-VarDecl {{.*}} col:5{{( imported)?}} used e 'E' +// CHECK-NEXT: |-CXXOperatorCallExpr {{.*}} 'void' '+' +// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' +// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator+' 'void (E, E)' +// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'E' +// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' +// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'E' +// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' +// CHECK-NEXT: `-CXXOperatorCallExpr {{.*}} 'void' ',' +// CHECK-NEXT: |-ImplicitCastExpr {{.*}} 'void (*)(E, E)' +// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'void (E, E)' lvalue Function {{.*}} 'operator,' 'void (E, E)' +// CHECK-NEXT: |-ImplicitCastExpr {{.*}} 'E' +// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'E' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'E' lvalue Var {{.*}} 'e' 'E' diff --git a/clang/test/Analysis/template-param-objects.cpp b/clang/test/Analysis/template-param-objects.cpp new file mode 100644 index 0000000000000..dde95fa62cb65 --- /dev/null +++ b/clang/test/Analysis/template-param-objects.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false -std=c++20 -verify %s + +template void clang_analyzer_dump(T); +void clang_analyzer_eval(bool); + +struct Box { + int value; +}; +bool operator ==(Box lhs, Box rhs) { + return lhs.value == rhs.value; +} +template void dumps() { + clang_analyzer_dump(V); // expected-warning {{lazyCompoundVal}} + clang_analyzer_dump(&V); // expected-warning {{Unknown}} + clang_analyzer_dump(V.value); // expected-warning {{Unknown}} FIXME: It should be '6 S32b'. + clang_analyzer_dump(&V.value); // expected-warning {{Unknown}} +} +template void dumps(); + +// [temp.param].7.3.2: +// "All such template parameters in the program of the same type with the +// same value denote the same template parameter object." +template void stable_addresses() { + clang_analyzer_eval(&A1 == &A2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. + clang_analyzer_eval(&B1 == &B2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. + clang_analyzer_eval(&A1 == &B2); // expected-warning {{UNKNOWN}} FIXME: It should be FALSE. + + clang_analyzer_eval(A1 == A2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. + clang_analyzer_eval(B1 == B2); // expected-warning {{UNKNOWN}} FIXME: It should be TRUE. + clang_analyzer_eval(A1 == B2); // expected-warning {{UNKNOWN}} FIXME: It should be FALSE. +} +template void stable_addresses(); diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c index 183382406475c..3bfad3637d264 100644 --- a/clang/test/C/drs/dr0xx.c +++ b/clang/test/C/drs/dr0xx.c @@ -110,7 +110,7 @@ struct dr007_b; * of treated as declaring a parameter of type 'int (*)(dr009_t);' */ typedef int dr009_t; -void dr009_f((dr009_t)); /* c99untilc2x-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} +void dr009_f((dr009_t)); /* c99untilc2x-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} c2xandup-error {{a type specifier is required for all declarations}} */ /* WG14 DR010: diff --git a/clang/test/C/drs/dr1xx.c b/clang/test/C/drs/dr1xx.c index 70435b523765d..1e430c5fb3951 100644 --- a/clang/test/C/drs/dr1xx.c +++ b/clang/test/C/drs/dr1xx.c @@ -369,7 +369,7 @@ void dr163(void) { int i; i = undeclared; /* expected-error {{use of undeclared identifier 'undeclared'}} */ sdfsdfsf = 1; /* expected-error {{use of undeclared identifier 'sdfsdfsf'}} */ - i = also_undeclared(); /* c99untilc2x-error {{call to undeclared function 'also_undeclared'; ISO C99 and later do not support implicit function declarations}} + i = also_undeclared(); /* c99untilc2x-warning {{call to undeclared function 'also_undeclared'; ISO C99 and later do not support implicit function declarations}} c2xandup-error {{use of undeclared identifier 'also_undeclared'}} */ } diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-p8vector.c b/clang/test/CodeGen/PowerPC/builtins-ppc-p8vector.c index af3d5c7d066b0..54d2c70c0aa55 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-p8vector.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-p8vector.c @@ -143,7 +143,7 @@ void test1() { res_vui = vec_mergee(vui, vui); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm -// CHECK-PPC: error: call to undeclared function 'vec_mergee' +// CHECK-PPC: warning: call to undeclared function 'vec_mergee' res_vbll = vec_mergee(vbll, vbll); // CHECK: @llvm.ppc.altivec.vperm @@ -177,7 +177,7 @@ void test1() { res_vui = vec_mergeo(vui, vui); // CHECK: @llvm.ppc.altivec.vperm // CHECK-LE: @llvm.ppc.altivec.vperm -// CHECK-PPC: error: call to undeclared function 'vec_mergeo' +// CHECK-PPC: warning: call to undeclared function 'vec_mergeo' /* vec_cmpeq */ res_vbll = vec_cmpeq(vbll, vbll); @@ -403,7 +403,7 @@ void test1() { res_vsc = vec_cntlz(vsc); // CHECK: call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.+}}, i1 false) // CHECK-LE: call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.+}}, i1 false) -// CHECK-PPC: error: call to undeclared function 'vec_cntlz' +// CHECK-PPC: warning: call to undeclared function 'vec_cntlz' res_vuc = vec_cntlz(vuc); // CHECK: call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.+}}, i1 false) @@ -754,19 +754,19 @@ void test1() { res_vsi = vec_vpksdss(vsll, vsll); // CHECK: llvm.ppc.altivec.vpksdss // CHECK-LE: llvm.ppc.altivec.vpksdss -// CHECK-PPC: error: call to undeclared function 'vec_vpksdss' +// CHECK-PPC: warning: call to undeclared function 'vec_vpksdss' /* vec_vpksdus */ res_vui = vec_vpksdus(vsll, vsll); // CHECK: llvm.ppc.altivec.vpksdus // CHECK-LE: llvm.ppc.altivec.vpksdus -// CHECK-PPC: error: call to undeclared function 'vec_vpksdus' +// CHECK-PPC: warning: call to undeclared function 'vec_vpksdus' /* vec_vpkudum */ res_vsi = vec_vpkudum(vsll, vsll); // CHECK: vperm // CHECK-LE: vperm -// CHECK-PPC: error: call to undeclared function 'vec_vpkudum' +// CHECK-PPC: warning: call to undeclared function 'vec_vpkudum' res_vui = vec_vpkudum(vull, vull); // CHECK: vperm @@ -775,13 +775,13 @@ void test1() { res_vui = vec_vpkudus(vull, vull); // CHECK: llvm.ppc.altivec.vpkudus // CHECK-LE: llvm.ppc.altivec.vpkudus -// CHECK-PPC: error: call to undeclared function 'vec_vpkudus' +// CHECK-PPC: warning: call to undeclared function 'vec_vpkudus' /* vec_vupkhsw */ res_vsll = vec_vupkhsw(vsi); // CHECK: llvm.ppc.altivec.vupkhsw // CHECK-LE: llvm.ppc.altivec.vupklsw -// CHECK-PPC: error: call to undeclared function 'vec_vupkhsw' +// CHECK-PPC: warning: call to undeclared function 'vec_vupkhsw' res_vbll = vec_vupkhsw(vbi); // CHECK: llvm.ppc.altivec.vupkhsw @@ -791,7 +791,7 @@ void test1() { res_vsll = vec_vupklsw(vsi); // CHECK: llvm.ppc.altivec.vupklsw // CHECK-LE: llvm.ppc.altivec.vupkhsw -// CHECK-PPC: error: call to undeclared function 'vec_vupklsw' +// CHECK-PPC: warning: call to undeclared function 'vec_vupklsw' res_vbll = vec_vupklsw(vbi); // CHECK: llvm.ppc.altivec.vupklsw @@ -845,7 +845,7 @@ void test1() { // CHECK: xor <16 x i8> [[T1]], // CHECK-LE: [[T1:%.+]] = and <16 x i8> // CHECK-LE: xor <16 x i8> [[T1]], -// CHECK-PPC: error: call to undeclared function 'vec_nand' +// CHECK-PPC: warning: call to undeclared function 'vec_nand' res_vbc = vec_nand(vbc, vbc); // CHECK: [[T1:%.+]] = and <16 x i8> @@ -937,7 +937,7 @@ void test1() { // CHECK: or <16 x i8> {{%.+}}, [[T1]] // CHECK-LE: [[T1:%.+]] = xor <16 x i8> {{%.+}}, // CHECK-LE: or <16 x i8> {{%.+}}, [[T1]] -// CHECK-PPC: error: call to undeclared function 'vec_orc' +// CHECK-PPC: warning: call to undeclared function 'vec_orc' res_vsc = vec_orc(vsc, vbc); // CHECK: [[T1:%.+]] = xor <16 x i8> {{%.+}}, @@ -1166,7 +1166,7 @@ void test1() { res_vsll = vec_vbpermq(vuc, vuc); // CHECK: llvm.ppc.altivec.vbpermq // CHECK-LE: llvm.ppc.altivec.vbpermq -// CHECK-PPC: error: call to undeclared function 'vec_vbpermq' +// CHECK-PPC: warning: call to undeclared function 'vec_vbpermq' /* vec_vgbbd */ res_vsc = vec_vgbbd(vsc); @@ -1176,12 +1176,12 @@ void test1() { res_vuc = vec_vgbbd(vuc); // CHECK: llvm.ppc.altivec.vgbbd // CHECK-LE: llvm.ppc.altivec.vgbbd -// CHECK-PPC: error: call to undeclared function 'vec_vgbbd' +// CHECK-PPC: warning: call to undeclared function 'vec_vgbbd' res_vuc = vec_gb(vuc); // CHECK: llvm.ppc.altivec.vgbbd // CHECK-LE: llvm.ppc.altivec.vgbbd -// CHECK-PPC: error: call to undeclared function 'vec_gb' +// CHECK-PPC: warning: call to undeclared function 'vec_gb' res_vsll = vec_gbb(vsll); // CHECK: llvm.ppc.altivec.vgbbd diff --git a/clang/test/CodeGen/RISCV/riscv-abi.cpp b/clang/test/CodeGen/RISCV/riscv-abi.cpp new file mode 100644 index 0000000000000..7e34ffef14d30 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-abi.cpp @@ -0,0 +1,123 @@ +// RUN: %clang_cc1 -triple riscv32 -emit-llvm %s -o - \ +// RUN: | FileCheck -check-prefixes=ILP32,ILP32-ILP32F,ILP32-ILP32F-ILP32D %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ +// RUN: | FileCheck -check-prefixes=ILP32F,ILP32-ILP32F,ILP32F-ILP32D,ILP32-ILP32F-ILP32D %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \ +// RUN: | FileCheck -check-prefixes=ILP32D,ILP32F-ILP32D,ILP32-ILP32F-ILP32D %s + +// RUN: %clang_cc1 -triple riscv64 -emit-llvm %s -o - \ +// RUN: | FileCheck -check-prefixes=LP64,LP64-LP64F,LP64-LP64F-LP64D %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \ +// RUN: | FileCheck -check-prefixes=LP64F,LP64-LP64F,LP64F-LP64D,LP64-LP64F-LP64D %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - \ +// RUN: | FileCheck -check-prefixes=LP64D,LP64F-LP64D,LP64-LP64F-LP64D %s + +#include + +// Ensure that fields inherited from a parent struct are treated in the same +// way as fields directly in the child for the purposes of RISC-V ABI rules. + +struct parent1_int32_s { + int32_t i1; +}; + +struct child1_int32_s : parent1_int32_s { + int32_t i2; +}; + +// ILP32-ILP32F-ILP32D-LABEL: define{{.*}} [2 x i32] @_Z30int32_int32_struct_inheritance14child1_int32_s([2 x i32] %a.coerce) +// LP64-LP64F-LP64D-LABEL: define{{.*}} i64 @_Z30int32_int32_struct_inheritance14child1_int32_s(i64 %a.coerce) +struct child1_int32_s int32_int32_struct_inheritance(struct child1_int32_s a) { + return a; +} + +struct parent2_int32_s { + int32_t i1; +}; + +struct child2_float_s : parent2_int32_s { + float f1; +}; + +// ILP32: define{{.*}} [2 x i32] @_Z30int32_float_struct_inheritance14child2_float_s([2 x i32] %a.coerce) +// ILP32F-ILP32D: define{{.*}} { i32, float } @_Z30int32_float_struct_inheritance14child2_float_s(i32 %0, float %1) +// LP64: define{{.*}} i64 @_Z30int32_float_struct_inheritance14child2_float_s(i64 %a.coerce) +// LP64F-LP64D: define{{.*}} { i32, float } @_Z30int32_float_struct_inheritance14child2_float_s(i32 %0, float %1) +struct child2_float_s int32_float_struct_inheritance(struct child2_float_s a) { + return a; +} + +struct parent3_float_s { + float f1; +}; + +struct child3_int64_s : parent3_float_s { + int64_t i1; +}; + +// ILP32-ILP32F-ILP32D-LABEL: define{{.*}} void @_Z30float_int64_struct_inheritance14child3_int64_s(ptr noalias sret(%struct.child3_int64_s) +// LP64-LABEL: define{{.*}} [2 x i64] @_Z30float_int64_struct_inheritance14child3_int64_s([2 x i64] %a.coerce) +// LP64F-LP64D-LABEL: define{{.*}} { float, i64 } @_Z30float_int64_struct_inheritance14child3_int64_s(float %0, i64 %1) +struct child3_int64_s float_int64_struct_inheritance(struct child3_int64_s a) { + return a; +} + +struct parent4_double_s { + double d1; +}; + +struct child4_double_s : parent4_double_s { + double d1; +}; + +// ILP32-ILP32F-LABEL: define{{.*}} void @_Z32double_double_struct_inheritance15child4_double_s(ptr noalias sret(%struct.child4_double_s) +// ILP32D-LABEL: define{{.*}} { double, double } @_Z32double_double_struct_inheritance15child4_double_s(double %0, double %1) +// LP64-LP64F-LABEL: define{{.*}} [2 x i64] @_Z32double_double_struct_inheritance15child4_double_s([2 x i64] %a.coerce) +// LP64D-LABEL: define{{.*}} { double, double } @_Z32double_double_struct_inheritance15child4_double_s(double %0, double %1) +struct child4_double_s double_double_struct_inheritance(struct child4_double_s a) { + return a; +} + +// When virtual inheritance is used, the resulting struct isn't eligible for +// passing in registers. + +struct parent5_virtual_s { + int32_t i1; +}; + +struct child5_virtual_s : virtual parent5_virtual_s { + float f1; +}; + +// ILP32-ILP32F-ILP32D-LABEL: define{{.*}} void @_ZN16child5_virtual_sC1EOS_(ptr noundef nonnull align 4 dereferenceable(8) %this, ptr noundef nonnull align 4 dereferenceable(8) %0) +// LP64-LP64F-LP64D-LABEL: define{{.*}} void @_ZN16child5_virtual_sC1EOS_(ptr noundef nonnull align 8 dereferenceable(12) %this, ptr noundef nonnull align 8 dereferenceable(12) %0) +struct child5_virtual_s int32_float_virtual_struct_inheritance(struct child5_virtual_s a) { + return a; +} + +// Check for correct lowering in the presence of diamond inheritance. + +struct parent6_float_s { + float f1; +}; + +struct child6a_s : parent6_float_s { +}; + +struct child6b_s : parent6_float_s { +}; + +struct grandchild_6_s : child6a_s, child6b_s { +}; + +// ILP32: define{{.*}} [2 x i32] @_Z38float_float_diamond_struct_inheritance14grandchild_6_s([2 x i32] %a.coerce) +// ILP32F-ILP64D: define{{.*}} { float, float } @_Z38float_float_diamond_struct_inheritance14grandchild_6_s(float %0, float %1) +// LP64: define{{.*}} i64 @_Z38float_float_diamond_struct_inheritance14grandchild_6_s(i64 %a.coerce) +// LP64F-LP64D: define{{.*}} { float, float } @_Z38float_float_diamond_struct_inheritance14grandchild_6_s(float %0, float %1) +struct grandchild_6_s float_float_diamond_struct_inheritance(struct grandchild_6_s a) { + return a; +} + +// NOTE: These prefixes are unused. Do not add tests below this line: +// ILP32F: {{.*}} +// LP64F: {{.*}} diff --git a/clang/test/CodeGen/X86/bfloat-abi.c b/clang/test/CodeGen/X86/bfloat-abi.c new file mode 100644 index 0000000000000..42250791848ac --- /dev/null +++ b/clang/test/CodeGen/X86/bfloat-abi.c @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -target-feature +sse2 < %s | FileCheck %s --check-prefixes=CHECK + +struct bfloat1 { + __bf16 a; +}; + +struct bfloat1 h1(__bf16 a) { + // CHECK: define{{.*}}bfloat @ + struct bfloat1 x; + x.a = a; + return x; +} + +struct bfloat2 { + __bf16 a; + __bf16 b; +}; + +struct bfloat2 h2(__bf16 a, __bf16 b) { + // CHECK: define{{.*}}<2 x bfloat> @ + struct bfloat2 x; + x.a = a; + x.b = b; + return x; +} + +struct bfloat3 { + __bf16 a; + __bf16 b; + __bf16 c; +}; + +struct bfloat3 h3(__bf16 a, __bf16 b, __bf16 c) { + // CHECK: define{{.*}}<4 x bfloat> @ + struct bfloat3 x; + x.a = a; + x.b = b; + x.c = c; + return x; +} + +struct bfloat4 { + __bf16 a; + __bf16 b; + __bf16 c; + __bf16 d; +}; + +struct bfloat4 h4(__bf16 a, __bf16 b, __bf16 c, __bf16 d) { + // CHECK: define{{.*}}<4 x bfloat> @ + struct bfloat4 x; + x.a = a; + x.b = b; + x.c = c; + x.d = d; + return x; +} + +struct floatbfloat { + float a; + __bf16 b; +}; + +struct floatbfloat fh(float a, __bf16 b) { + // CHECK: define{{.*}}<4 x half> @ + struct floatbfloat x; + x.a = a; + x.b = b; + return x; +} + +struct floatbfloat2 { + float a; + __bf16 b; + __bf16 c; +}; + +struct floatbfloat2 fh2(float a, __bf16 b, __bf16 c) { + // CHECK: define{{.*}}<4 x half> @ + struct floatbfloat2 x; + x.a = a; + x.b = b; + x.c = c; + return x; +} + +struct bfloatfloat { + __bf16 a; + float b; +}; + +struct bfloatfloat hf(__bf16 a, float b) { + // CHECK: define{{.*}}<4 x half> @ + struct bfloatfloat x; + x.a = a; + x.b = b; + return x; +} + +struct bfloat2float { + __bf16 a; + __bf16 b; + float c; +}; + +struct bfloat2float h2f(__bf16 a, __bf16 b, float c) { + // CHECK: define{{.*}}<4 x bfloat> @ + struct bfloat2float x; + x.a = a; + x.b = b; + x.c = c; + return x; +} + +struct floatbfloat3 { + float a; + __bf16 b; + __bf16 c; + __bf16 d; +}; + +struct floatbfloat3 fh3(float a, __bf16 b, __bf16 c, __bf16 d) { + // CHECK: define{{.*}}{ <4 x half>, bfloat } @ + struct floatbfloat3 x; + x.a = a; + x.b = b; + x.c = c; + x.d = d; + return x; +} + +struct bfloat5 { + __bf16 a; + __bf16 b; + __bf16 c; + __bf16 d; + __bf16 e; +}; + +struct bfloat5 h5(__bf16 a, __bf16 b, __bf16 c, __bf16 d, __bf16 e) { + // CHECK: define{{.*}}{ <4 x bfloat>, bfloat } @ + struct bfloat5 x; + x.a = a; + x.b = b; + x.c = c; + x.d = d; + x.e = e; + return x; +} diff --git a/clang/test/CodeGen/X86/bfloat-half-abi.c b/clang/test/CodeGen/X86/bfloat-half-abi.c new file mode 100644 index 0000000000000..42250791848ac --- /dev/null +++ b/clang/test/CodeGen/X86/bfloat-half-abi.c @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -target-feature +sse2 < %s | FileCheck %s --check-prefixes=CHECK + +struct bfloat1 { + __bf16 a; +}; + +struct bfloat1 h1(__bf16 a) { + // CHECK: define{{.*}}bfloat @ + struct bfloat1 x; + x.a = a; + return x; +} + +struct bfloat2 { + __bf16 a; + __bf16 b; +}; + +struct bfloat2 h2(__bf16 a, __bf16 b) { + // CHECK: define{{.*}}<2 x bfloat> @ + struct bfloat2 x; + x.a = a; + x.b = b; + return x; +} + +struct bfloat3 { + __bf16 a; + __bf16 b; + __bf16 c; +}; + +struct bfloat3 h3(__bf16 a, __bf16 b, __bf16 c) { + // CHECK: define{{.*}}<4 x bfloat> @ + struct bfloat3 x; + x.a = a; + x.b = b; + x.c = c; + return x; +} + +struct bfloat4 { + __bf16 a; + __bf16 b; + __bf16 c; + __bf16 d; +}; + +struct bfloat4 h4(__bf16 a, __bf16 b, __bf16 c, __bf16 d) { + // CHECK: define{{.*}}<4 x bfloat> @ + struct bfloat4 x; + x.a = a; + x.b = b; + x.c = c; + x.d = d; + return x; +} + +struct floatbfloat { + float a; + __bf16 b; +}; + +struct floatbfloat fh(float a, __bf16 b) { + // CHECK: define{{.*}}<4 x half> @ + struct floatbfloat x; + x.a = a; + x.b = b; + return x; +} + +struct floatbfloat2 { + float a; + __bf16 b; + __bf16 c; +}; + +struct floatbfloat2 fh2(float a, __bf16 b, __bf16 c) { + // CHECK: define{{.*}}<4 x half> @ + struct floatbfloat2 x; + x.a = a; + x.b = b; + x.c = c; + return x; +} + +struct bfloatfloat { + __bf16 a; + float b; +}; + +struct bfloatfloat hf(__bf16 a, float b) { + // CHECK: define{{.*}}<4 x half> @ + struct bfloatfloat x; + x.a = a; + x.b = b; + return x; +} + +struct bfloat2float { + __bf16 a; + __bf16 b; + float c; +}; + +struct bfloat2float h2f(__bf16 a, __bf16 b, float c) { + // CHECK: define{{.*}}<4 x bfloat> @ + struct bfloat2float x; + x.a = a; + x.b = b; + x.c = c; + return x; +} + +struct floatbfloat3 { + float a; + __bf16 b; + __bf16 c; + __bf16 d; +}; + +struct floatbfloat3 fh3(float a, __bf16 b, __bf16 c, __bf16 d) { + // CHECK: define{{.*}}{ <4 x half>, bfloat } @ + struct floatbfloat3 x; + x.a = a; + x.b = b; + x.c = c; + x.d = d; + return x; +} + +struct bfloat5 { + __bf16 a; + __bf16 b; + __bf16 c; + __bf16 d; + __bf16 e; +}; + +struct bfloat5 h5(__bf16 a, __bf16 b, __bf16 c, __bf16 d, __bf16 e) { + // CHECK: define{{.*}}{ <4 x bfloat>, bfloat } @ + struct bfloat5 x; + x.a = a; + x.b = b; + x.c = c; + x.d = d; + x.e = e; + return x; +} diff --git a/clang/test/CodeGen/X86/bfloat-mangle.cpp b/clang/test/CodeGen/X86/bfloat-mangle.cpp new file mode 100644 index 0000000000000..2892a76d8d910 --- /dev/null +++ b/clang/test/CodeGen/X86/bfloat-mangle.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -target-feature +sse2 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +sse2 -emit-llvm -o - %s | FileCheck %s + +// CHECK: define {{.*}}void @_Z3foou6__bf16(bfloat noundef %b) +void foo(__bf16 b) {} diff --git a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c b/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c index c57c476032025..d7c79d7a44220 100644 --- a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c +++ b/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c @@ -1650,3 +1650,143 @@ svuint32_t rem_scalar_u32(svuint32_t a, uint32_t b) { svuint64_t rem_scalar_u64(svuint64_t a, uint64_t b) { return a % b; } + +// UNARY PROMOTION + +// CHECK-LABEL: @prom_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret [[A:%.*]] +// +svint8_t prom_i8(svint8_t a) { + return +a; +} + +// CHECK-LABEL: @prom_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret [[A:%.*]] +// +svint16_t prom_i16(svint16_t a) { + return +a; +} + +// CHECK-LABEL: @prom_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret [[A:%.*]] +// +svint32_t prom_i32(svint32_t a) { + return +a; +} + +// CHECK-LABEL: @prom_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret [[A:%.*]] +// +svint64_t prom_i64(svint64_t a) { + return +a; +} + +// CHECK-LABEL: @prom_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret [[A:%.*]] +// +svuint8_t prom_u8(svuint8_t a) { + return +a; +} + +// CHECK-LABEL: @prom_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret [[A:%.*]] +// +svuint16_t prom_u16(svuint16_t a) { + return +a; +} + +// CHECK-LABEL: @prom_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret [[A:%.*]] +// +svuint32_t prom_u32(svuint32_t a) { + return +a; +} + +// CHECK-LABEL: @prom_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret [[A:%.*]] +// +svuint64_t prom_u64(svuint64_t a) { + return +a; +} + +// UNARY NEGATION + +// CHECK-LABEL: @neg_i8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = sub zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svint8_t neg_i8(svint8_t a) { + return -a; +} + +// CHECK-LABEL: @neg_i16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = sub zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svint16_t neg_i16(svint16_t a) { + return -a; +} + +// CHECK-LABEL: @neg_i32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = sub zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svint32_t neg_i32(svint32_t a) { + return -a; +} + +// CHECK-LABEL: @neg_i64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = sub zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svint64_t neg_i64(svint64_t a) { + return -a; +} + +// CHECK-LABEL: @neg_u8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = sub zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svuint8_t neg_u8(svuint8_t a) { + return -a; +} + +// CHECK-LABEL: @neg_u16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = sub zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svuint16_t neg_u16(svuint16_t a) { + return -a; +} + +// CHECK-LABEL: @neg_u32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = sub zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svuint32_t neg_u32(svuint32_t a) { + return -a; +} + +// CHECK-LABEL: @neg_u64( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[SUB:%.*]] = sub zeroinitializer, [[A:%.*]] +// CHECK-NEXT: ret [[SUB]] +// +svuint64_t neg_u64(svuint64_t a) { + return -a; +} diff --git a/clang/test/CodeGen/arm-vaarg.c b/clang/test/CodeGen/arm-vaarg.c new file mode 100644 index 0000000000000..4dab397a20de4 --- /dev/null +++ b/clang/test/CodeGen/arm-vaarg.c @@ -0,0 +1,23 @@ +// RUN: %clang -Xclang -no-opaque-pointers -mfloat-abi=soft -target arm-linux-gnu -emit-llvm -S -o - %s | FileCheck %s + +struct Empty {}; + +struct Empty emptyvar; + +void take_args(int a, ...) { +// CHECK: [[ALLOCA_VA_LIST:%[a-zA-Z0-9._]+]] = alloca %struct.__va_list, align 4 +// CHECK: call void @llvm.va_start +// CHECK-NEXT: [[AP_ADDR:%[a-zA-Z0-9._]+]] = bitcast %struct.__va_list* [[ALLOCA_VA_LIST]] to i8** +// CHECK-NEXT: [[LOAD_AP:%[a-zA-Z0-9._]+]] = load i8*, i8** [[AP_ADDR]], align 4 +// CHECK-NEXT: [[EMPTY_PTR:%[a-zA-Z0-9._]+]] = bitcast i8* [[LOAD_AP]] to %struct.Empty* + + // It's conceivable that EMPTY_PTR may not actually be a valid pointer + // (e.g. it's at the very bottom of the stack and the next page is + // invalid). This doesn't matter provided it's never loaded (there's no + // well-defined way to tell), but it becomes a problem if we do try to use it. +// CHECK-NOT: load %struct.Empty, %struct.Empty* [[EMPTY_PTR]] + __builtin_va_list l; + __builtin_va_start(l, a); + emptyvar = __builtin_va_arg(l, struct Empty); + __builtin_va_end(l); +} diff --git a/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c b/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c new file mode 100644 index 0000000000000..29ca5f58e4b81 --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s + +struct t { + int (__attribute__((btf_type_tag("rcu"))) *f)(); + int a; +}; +int foo(struct t *arg) { + return arg->a; +} + +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f" +// CHECK-SAME: baseType: ![[L18:[0-9]+]] +// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L21:[0-9]+]]) +// CHECK: ![[L21]] = !{![[L22:[0-9]+]]} +// CHECK: ![[L22]] = !{!"btf_type_tag", !"rcu"} diff --git a/clang/test/CodeGen/builtins-arm-msvc-compat-only.c b/clang/test/CodeGen/builtins-arm-msvc-compat-only.c index 42cc9d70a1427..c2b021b31174b 100644 --- a/clang/test/CodeGen/builtins-arm-msvc-compat-only.c +++ b/clang/test/CodeGen/builtins-arm-msvc-compat-only.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple thumbv7-windows -fms-extensions -emit-llvm -o - %s \ // RUN: | FileCheck %s -check-prefix CHECK-MSVC -// RUN: not %clang_cc1 -triple armv7-eabi -emit-llvm %s -o /dev/null 2>&1 \ +// RUN: %clang_cc1 -triple armv7-eabi -emit-llvm %s -o /dev/null 2>&1 \ // RUN: | FileCheck %s -check-prefix CHECK-EABI // REQUIRES: arm-registered-target @@ -9,7 +9,7 @@ void emit() { } // CHECK-MSVC: call void asm sideeffect ".inst.n 0xDEFE", ""() -// CHECK-EABI: error: call to undeclared function '__emit' +// CHECK-EABI: warning: call to undeclared function '__emit' void emit_truncated() { __emit(0x11110000); // movs r0, r0 diff --git a/clang/test/CodeGen/debug-info-enum-case-val.c b/clang/test/CodeGen/debug-info-enum-case-val.c new file mode 100644 index 0000000000000..f39de0d732375 --- /dev/null +++ b/clang/test/CodeGen/debug-info-enum-case-val.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s + +enum { A = 1 }; +int func1(int a) { + switch(a) { + case A: return 10; + default: break; + } + return 0; +} +// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type +// CHECK-SAME: elements: [[TEST1_ENUMS:![0-9]*]] +// CHECK: [[TEST1_ENUMS]] = !{[[TEST1_E:![0-9]*]]} +// CHECK: [[TEST1_E]] = !DIEnumerator(name: "A", value: 1) + +// Test ImplicitCast of switch case enum value +enum { B = 2 }; +typedef unsigned long long __t1; +typedef __t1 __t2; +int func2(__t2 a) { + switch(a) { + case B: return 10; + default: break; + } + return 0; +} +// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type +// CHECK-SAME: elements: [[TEST2_ENUMS:![0-9]*]] +// CHECK: [[TEST2_ENUMS]] = !{[[TEST2_E:![0-9]*]]} +// CHECK: [[TEST2_E]] = !DIEnumerator(name: "B", value: 2) diff --git a/clang/test/CodeGen/inline-asm-x86-flag-output.c b/clang/test/CodeGen/inline-asm-x86-flag-output.c index 4c7e750e6d939..732714388c195 100644 --- a/clang/test/CodeGen/inline-asm-x86-flag-output.c +++ b/clang/test/CodeGen/inline-asm-x86-flag-output.c @@ -374,3 +374,22 @@ _Bool check_no_clobber_conflicts(void) { : "cx"); return b; } + +int test_assume_boolean_flag(long nr, volatile long *addr) { + //CHECK-LABEL: @test_assume_boolean_flag + //CHECK: %0 = tail call { i32, i32 } asm "cmp $2,$1", "={@cca},={@ccae},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* elementtype(i64) %addr, i64 %nr) + //CHECK: [[RES1:%.*]] = extractvalue { i32, i32 } %0, 0 + //CHECK: [[RES2:%.*]] = extractvalue { i32, i32 } %0, 1 + //CHECK: %1 = icmp ult i32 [[RES1]], 2 + //CHECK: tail call void @llvm.assume(i1 %1) + //CHECK: %2 = icmp ult i32 [[RES2]], 2 + //CHECK: tail call void @llvm.assume(i1 %2) + int x,y; + asm("cmp %2,%1" + : "=@cca"(x), "=@ccae"(y), "=m"(*(volatile long *)(addr)) + : "r"(nr) + : "cc"); + if (x) + return 0; + return 1; +} diff --git a/clang/test/CodeGen/neon-crypto.c b/clang/test/CodeGen/neon-crypto.c index 9168865744161..1b29b1a530965 100644 --- a/clang/test/CodeGen/neon-crypto.c +++ b/clang/test/CodeGen/neon-crypto.c @@ -14,7 +14,7 @@ uint8x16_t test_vaeseq_u8(uint8x16_t data, uint8x16_t key) { // CHECK-LABEL: @test_vaeseq_u8 - // CHECK-NO-CRYPTO: error: call to undeclared function 'vaeseq_u8' + // CHECK-NO-CRYPTO: warning: call to undeclared function 'vaeseq_u8' return vaeseq_u8(data, key); // CHECK: call <16 x i8> @llvm.{{arm.neon|aarch64.crypto}}.aese(<16 x i8> %data, <16 x i8> %key) } diff --git a/clang/test/CodeGenCXX/module-initializer-header.cppm b/clang/test/CodeGenCXX/module-initializer-header.cppm new file mode 100644 index 0000000000000..253f096845b92 --- /dev/null +++ b/clang/test/CodeGenCXX/module-initializer-header.cppm @@ -0,0 +1,31 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: rm -rf %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -xc++-user-header -emit-header-unit %t/header.h -o %t/header.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=%t/header.pcm %t/M.cppm -S -emit-llvm -o - | FileCheck %t/M.cppm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=%t/header.pcm %t/Use.cpp -S -emit-llvm -o - | FileCheck %t/Use.cpp +// +//--- header.h +int foo(); +int i = foo(); + +//--- M.cppm +module; +import "header.h"; +export module M; + +// CHECK: @i = {{.*}}global i32 0 +// CHECK: void @__cxx_global_var_init() +// CHECK-NEXT: entry: +// CHECK-NEXT: %call = call noundef{{.*}} i32 @_Z3foov() +// CHECK-NEXT: store i32 %call, ptr @i + +//--- Use.cpp +import "header.h"; + +// CHECK: @i = {{.*}}global i32 0 +// CHECK: void @__cxx_global_var_init() +// CHECK-NEXT: entry: +// CHECK-NEXT: %call = call noundef{{.*}} i32 @_Z3foov() +// CHECK-NEXT: store i32 %call, ptr @i diff --git a/clang/test/CoverageMapping/if.cpp b/clang/test/CoverageMapping/if.cpp index 5b705cd46ab72..de3554c100b96 100644 --- a/clang/test/CoverageMapping/if.cpp +++ b/clang/test/CoverageMapping/if.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++1z -triple %itanium_abi_triple -main-file-name if.cpp %s | FileCheck %s +// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++2b -triple %itanium_abi_triple -main-file-name if.cpp %s | FileCheck %s int nop() { return 0; } @@ -13,6 +13,22 @@ void foo() { // CHECK-NEXT: Gap,File 0, [[@LINE+1]]:21 -> [[@ ++j; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:8 = #1, (#0 - #1) } // CHECK-NEXT: [[@LINE-2]]:9 -> [[@LINE-1]]:5 = #1 // CHECK-NEXT: [[@LINE-2]]:5 -> [[@LINE-2]]:8 = #1 + +// FIXME: Do not generate coverage for discarded branches in if consteval and if constexpr statements +constexpr int check_consteval(int i) { + if consteval { + i++; + } + if !consteval { + i++; + } + if consteval { + return 42; + } else { + return i; + } +} + // CHECK-LABEL: main: int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = #0 int i = 0; @@ -50,6 +66,10 @@ int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = // CHECK-NEXT: File 0, [[@LINE+1]]:14 -> [[@LINE+1]]:20 = #6 i = i == 0?i + 12:i + 10; // CHECK-NEXT: File 0, [[@LINE]]:21 -> [[@LINE]]:27 = (#0 - #6) + // GH-57377 + constexpr int c_i = check_consteval(0); + check_consteval(i); + return 0; } diff --git a/clang/test/Driver/cuda-bindings.cu b/clang/test/Driver/cuda-bindings.cu index 6cc21251bfdd3..7115117e79ce5 100644 --- a/clang/test/Driver/cuda-bindings.cu +++ b/clang/test/Driver/cuda-bindings.cu @@ -135,3 +135,14 @@ // RUN: | FileCheck -check-prefix=DASM2 %s // DASM2: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_30.s" // DASM2: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_35.s" + +// +// Ensure we output the user's specified name in device-only mode. +// +// RUN: %clang -target powerpc64le-ibm-linux-gnu -### \ +// RUN: --cuda-gpu-arch=sm_52 --cuda-device-only -c -o foo.o %s 2>&1 \ +// RUN: | FileCheck -check-prefix=D_ONLY %s +// RUN: %clang -target powerpc64le-ibm-linux-gnu -### --offload-new-driver \ +// RUN: --cuda-gpu-arch=sm_52 --cuda-device-only -c -o foo.o %s 2>&1 \ +// RUN: | FileCheck -check-prefix=D_ONLY %s +// D_ONLY: "foo.o" diff --git a/clang/test/Driver/cxx_for_opencl.clcpp b/clang/test/Driver/cxx_for_opencl.clcpp index fc2fc621791d9..e3e89c53b8886 100644 --- a/clang/test/Driver/cxx_for_opencl.clcpp +++ b/clang/test/Driver/cxx_for_opencl.clcpp @@ -13,6 +13,6 @@ kernel void k(){ auto a = get_local_id(1); #ifndef __OPENCL_CPP_VERSION__ //expected-error@-2{{OpenCL C version 2.0 does not support the 'auto' storage class specifier}} -//expected-error@-3{{type specifier missing, defaults to 'int'}} +//expected-warning@-3{{type specifier missing, defaults to 'int'}} #endif } diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index d7c58431fa76f..e76b35d6137c7 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -1007,6 +1007,7 @@ // CHECK-SPARCV8: "{{.*}}ld{{(.exe)?}}" // CHECK-SPARCV8: "-m" "elf32_sparc" // CHECK-SPARCV8: "-dynamic-linker" "{{(/usr/sparc-unknown-linux-gnu)?}}/lib/ld-linux.so.2" +// CHECK-SPARCV8: "--push-state" "--as-needed" "-latomic" "--pop-state" // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=sparcel-unknown-linux-gnu \ @@ -1021,6 +1022,7 @@ // CHECK-SPARCV9: "{{.*}}ld{{(.exe)?}}" // CHECK-SPARCV9: "-m" "elf64_sparc" // CHECK-SPARCV9: "-dynamic-linker" "{{(/usr/sparcv9-unknown-linux-gnu)?}}/lib{{(64)?}}/ld-linux.so.2" +// CHECK-SPARCV9-NOT: "-latomic" // Test linker invocation on Android. // RUN: %clang -### %s -no-pie 2>&1 \ diff --git a/clang/test/Driver/modules-fprebuilt-mdoule-path.cpp b/clang/test/Driver/modules-fprebuilt-mdoule-path.cpp new file mode 100644 index 0000000000000..a2c830bfda00b --- /dev/null +++ b/clang/test/Driver/modules-fprebuilt-mdoule-path.cpp @@ -0,0 +1,7 @@ +// RUN: %clang -std=c++2a -fprebuilt-module-path=. -### -c %s 2>&1 | FileCheck %s +// RUN: %clang -std=c++20 -fprebuilt-module-path=. -### -c %s 2>&1 | FileCheck %s +// RUN: %clang -std=c++2b -fprebuilt-module-path=. -### -c %s 2>&1 | FileCheck %s +// RUN: %clang -std=c++latest -fprebuilt-module-path=. -### -c %s 2>&1 | FileCheck %s +// +// CHECK-NOT: warning: argument unused during compilation +// CHECK: -fprebuilt-module-path=. diff --git a/clang/test/Driver/sparc-march.c b/clang/test/Driver/sparc-march.c new file mode 100644 index 0000000000000..9adde8bfd6c56 --- /dev/null +++ b/clang/test/Driver/sparc-march.c @@ -0,0 +1,4 @@ +// RUN: %clang -target sparcv9 -march=v9 -### -c %s 2>&1 | FileCheck %s +// RUN: %clang -target sparc64 -march=v9 -### -c %s 2>&1 | FileCheck %s +// RUN: %clang -target sparc -march=v9 -### -c %s 2>&1 | FileCheck %s +// CHECK: error: unsupported option '-march=' for target diff --git a/clang/test/Driver/sparc-mcpu.c b/clang/test/Driver/sparc-mcpu.c new file mode 100644 index 0000000000000..92421f16e997d --- /dev/null +++ b/clang/test/Driver/sparc-mcpu.c @@ -0,0 +1,21 @@ +// RUN: %clang -target sparcv9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9 %s +// SPARCV9: "-cc1"{{.*}} "-triple" "sparcv9" + +// RUN: %clang -target sparc64 -### -c %s 2>&1 | FileCheck -check-prefix=SPARC64 %s +// SPARC64: "-cc1"{{.*}} "-triple" "sparc64" + +// RUN: %clang -target sparcv9 -mcpu=v9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9_V9 %s +// SPARCV9_V9: "-cc1"{{.*}} "-triple" "sparcv9"{{.*}} "-target-cpu" "v9" + +// RUN: %clang -target sparcv9 -mcpu=ultrasparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9_US %s +// SPARCV9_US: "-cc1"{{.*}} "-triple" "sparcv9"{{.*}} "-target-cpu" "ultrasparc" + +// RUN: %clang -target sparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARC %s +// SPARC: "-cc1"{{.*}} "-triple" "sparc" + +// RUN: %clang -target sparc -mcpu=v9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARC_V9 %s +// SPARC_V9: "-cc1"{{.*}} "-triple" "sparc"{{.*}} "-target-cpu" "v9" + +// RUN: %clang -target sparc -mcpu=ultrasparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARC_US %s +// SPARC_US: "-cc1"{{.*}} "-triple" "sparc"{{.*}} "-target-cpu" "ultrasparc" + diff --git a/clang/test/Driver/sparc-mtune.c b/clang/test/Driver/sparc-mtune.c new file mode 100644 index 0000000000000..94eb05b54f4f9 --- /dev/null +++ b/clang/test/Driver/sparc-mtune.c @@ -0,0 +1,21 @@ +// RUN: %clang -target sparcv9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9 %s +// SPARCV9: "-cc1"{{.*}} "-triple" "sparcv9" + +// RUN: %clang -target sparc64 -### -c %s 2>&1 | FileCheck -check-prefix=SPARC64 %s +// SPARC64: "-cc1"{{.*}} "-triple" "sparc64" + +// RUN: %clang -target sparcv9 -mtune=v9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9_V9 %s +// SPARCV9_V9: "-cc1"{{.*}} "-triple" "sparcv9"{{.*}} "-tune-cpu" "v9" + +// RUN: %clang -target sparcv9 -mtune=ultrasparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARCV9_US %s +// SPARCV9_US: "-cc1"{{.*}} "-triple" "sparcv9"{{.*}} "-tune-cpu" "ultrasparc" + +// RUN: %clang -target sparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARC %s +// SPARC: "-cc1"{{.*}} "-triple" "sparc" + +// RUN: %clang -target sparc -mtune=v9 -### -c %s 2>&1 | FileCheck -check-prefix=SPARC_V9 %s +// SPARC_V9: "-cc1"{{.*}} "-triple" "sparc"{{.*}} "-tune-cpu" "v9" + +// RUN: %clang -target sparc -mtune=ultrasparc -### -c %s 2>&1 | FileCheck -check-prefix=SPARC_US %s +// SPARC_US: "-cc1"{{.*}} "-triple" "sparc"{{.*}} "-tune-cpu" "ultrasparc" + diff --git a/clang/test/Driver/spirv-toolchain.cl b/clang/test/Driver/spirv-toolchain.cl index db3ee4d3fe02f..8bec46b44044b 100644 --- a/clang/test/Driver/spirv-toolchain.cl +++ b/clang/test/Driver/spirv-toolchain.cl @@ -6,6 +6,7 @@ // RUN: %clang -### --target=spirv64 -x c -c %s 2>&1 | FileCheck --check-prefix=SPV64 %s // SPV64: "-cc1" "-triple" "spirv64" +// SPV64-SAME: "-no-opaque-pointers" // SPV64-SAME: "-o" [[BC:".*bc"]] // SPV64: {{llvm-spirv.*"}} [[BC]] "-o" {{".*o"}} @@ -16,6 +17,7 @@ // RUN: %clang -### --target=spirv32 -x c -c %s 2>&1 | FileCheck --check-prefix=SPV32 %s // SPV32: "-cc1" "-triple" "spirv32" +// SPV32-SAME: "-no-opaque-pointers" // SPV32-SAME: "-o" [[BC:".*bc"]] // SPV32: {{llvm-spirv.*"}} [[BC]] "-o" {{".*o"}} diff --git a/clang/test/FixIt/fixit.c b/clang/test/FixIt/fixit.c index eda00c35ccbb2..c929b5abc5ee8 100644 --- a/clang/test/FixIt/fixit.c +++ b/clang/test/FixIt/fixit.c @@ -29,7 +29,7 @@ int array0[5] = { [3] 3 }; // expected-warning {{GNU 'missing ='}} // CHECK: int x // CHECK: int y -void f1(x, y) // expected-error 2{{was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}} +void f1(x, y) // expected-warning 2{{was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}} { } diff --git a/clang/test/Frontend/fixed_point_errors.c b/clang/test/Frontend/fixed_point_errors.c index 6a711936f2397..2d12a1ebb10b9 100644 --- a/clang/test/Frontend/fixed_point_errors.c +++ b/clang/test/Frontend/fixed_point_errors.c @@ -228,9 +228,9 @@ void CheckSuffixOnIntegerLiterals(void) { // Using auto auto auto_fract = 0r; // expected-error{{invalid suffix 'r' on integer constant}} - // expected-error@-1{{type specifier missing, defaults to 'int'}} + // expected-warning@-1{{type specifier missing, defaults to 'int'}} auto auto_accum = 0k; // expected-error{{invalid suffix 'k' on integer constant}} - // expected-error@-1{{type specifier missing, defaults to 'int'}} + // expected-warning@-1{{type specifier missing, defaults to 'int'}} } // Ok conversions diff --git a/clang/test/Frontend/fixed_point_not_enabled.c b/clang/test/Frontend/fixed_point_not_enabled.c index a1a60c5a6fa80..e7522213f98d6 100644 --- a/clang/test/Frontend/fixed_point_not_enabled.c +++ b/clang/test/Frontend/fixed_point_not_enabled.c @@ -11,7 +11,7 @@ unsigned long _Accum u_long_accum; // expected-error{{compile with '-ffixed-p // Aliased fixed point types short _Accum short_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} _Accum accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} - // expected-error@-1{{type specifier missing, defaults to 'int'}} + // expected-warning@-1{{type specifier missing, defaults to 'int'}} long _Accum long_accum; // expected-error{{compile with '-ffixed-point' to enable fixed point types}} // Cannot use fixed point suffixes diff --git a/clang/test/Frontend/system-header-line-directive.c b/clang/test/Frontend/system-header-line-directive.c index d5705e028daa5..0de69196d76e2 100644 --- a/clang/test/Frontend/system-header-line-directive.c +++ b/clang/test/Frontend/system-header-line-directive.c @@ -3,7 +3,7 @@ #include #include -// expected-error@line-directive.h:* {{type specifier missing, defaults to 'int'}} +// expected-warning@line-directive.h:* {{type specifier missing, defaults to 'int'}} #include "line-directive.h" // This tests that "#line" directives in system headers preserve system diff --git a/clang/test/Headers/arm-cmse-header-ns.c b/clang/test/Headers/arm-cmse-header-ns.c index dfbef2c002917..b4112a4fc79a3 100644 --- a/clang/test/Headers/arm-cmse-header-ns.c +++ b/clang/test/Headers/arm-cmse-header-ns.c @@ -1,4 +1,4 @@ -// RUN: not %clang_cc1 -triple thumbv8m.base-eabi -fsyntax-only %s 2>&1 | FileCheck --check-prefix=CHECK-c %s +// RUN: %clang_cc1 -triple thumbv8m.base-eabi -fsyntax-only %s 2>&1 | FileCheck --check-prefix=CHECK-c %s // RUN: not %clang_cc1 -triple thumbv8m.base-eabi -fsyntax-only -x c++ %s 2>&1 | FileCheck --check-prefix=CHECK-cpp %s #include @@ -16,10 +16,10 @@ void func(callback_t fptr, void *p) cmse_TTAT(p); cmse_TTA_fptr(fptr); cmse_TTAT_fptr(fptr); -// CHECK-c: error: call to undeclared function 'cmse_TTA' -// CHECK-c: error: call to undeclared function 'cmse_TTAT' -// CHECK-c: error: call to undeclared function 'cmse_TTA_fptr' -// CHECK-c: error: call to undeclared function 'cmse_TTAT_fptr' +// CHECK-c: warning: call to undeclared function 'cmse_TTA' +// CHECK-c: warning: call to undeclared function 'cmse_TTAT' +// CHECK-c: warning: call to undeclared function 'cmse_TTA_fptr' +// CHECK-c: warning: call to undeclared function 'cmse_TTAT_fptr' // CHECK-cpp: error: use of undeclared identifier 'cmse_TTA' // CHECK-cpp: error: use of undeclared identifier 'cmse_TTAT' // CHECK-cpp: error: use of undeclared identifier 'cmse_TTA_fptr' diff --git a/clang/test/Index/annotate-operator-call-expr.cpp b/clang/test/Index/annotate-operator-call-expr.cpp index 3da2ec7eaca6b..facb841ce33fc 100644 --- a/clang/test/Index/annotate-operator-call-expr.cpp +++ b/clang/test/Index/annotate-operator-call-expr.cpp @@ -17,68 +17,68 @@ void testFoo(Foo foo, int index) { // RUN: c-index-test -test-annotate-tokens=%s:7:1:7:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK1 // CHECK1: Identifier: "foo" [7:3 - 7:6] DeclRefExpr=foo:6:18 -// CHECK1: Punctuation: "(" [7:6 - 7:7] CallExpr=operator():3:7 -// CHECK1: Punctuation: ")" [7:7 - 7:8] CallExpr=operator():3:7 +// CHECK1: Punctuation: "(" [7:6 - 7:7] DeclRefExpr=operator():3:7 RefName=[7:6 - 7:7] RefName=[7:7 - 7:8] +// CHECK1: Punctuation: ")" [7:7 - 7:8] DeclRefExpr=operator():3:7 RefName=[7:6 - 7:7] RefName=[7:7 - 7:8] // CHECK1: Punctuation: ";" [7:8 - 7:9] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:8:1:8:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK2 -// CHECK2: Punctuation: "(" [8:6 - 8:7] CallExpr=operator():3:7 +// CHECK2: Punctuation: "(" [8:6 - 8:7] DeclRefExpr=operator():3:7 RefName=[8:6 - 8:7] RefName=[8:12 - 8:13] // CHECK2: Identifier: "index" [8:7 - 8:12] DeclRefExpr=index:6:27 -// CHECK2: Punctuation: ")" [8:12 - 8:13] CallExpr=operator():3:7 +// CHECK2: Punctuation: ")" [8:12 - 8:13] DeclRefExpr=operator():3:7 RefName=[8:6 - 8:7] RefName=[8:12 - 8:13] // CHECK2: Punctuation: ";" [8:13 - 8:14] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:10:1:10:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK3 // CHECK3: Identifier: "foo" [10:3 - 10:6] DeclRefExpr=foo:6:18 -// CHECK3: Punctuation: "[" [10:6 - 10:7] CallExpr=operator[]:2:7 +// CHECK3: Punctuation: "[" [10:6 - 10:7] DeclRefExpr=operator[]:2:7 RefName=[10:6 - 10:7] RefName=[10:12 - 10:13] // CHECK3: Identifier: "index" [10:7 - 10:12] DeclRefExpr=index:6:27 -// CHECK3: Punctuation: "]" [10:12 - 10:13] CallExpr=operator[]:2:7 +// CHECK3: Punctuation: "]" [10:12 - 10:13] DeclRefExpr=operator[]:2:7 RefName=[10:6 - 10:7] RefName=[10:12 - 10:13] // CHECK3: Punctuation: ";" [10:13 - 10:14] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:11:1:11:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK4 // CHECK4: Identifier: "foo" [11:3 - 11:6] DeclRefExpr=foo:6:18 -// CHECK4: Punctuation: "[" [11:6 - 11:7] CallExpr=operator[]:2:7 +// CHECK4: Punctuation: "[" [11:6 - 11:7] DeclRefExpr=operator[]:2:7 RefName=[11:6 - 11:7] RefName=[11:20 - 11:21] // CHECK4: Identifier: "index" [11:7 - 11:12] DeclRefExpr=index:6:27 // CHECK4: Punctuation: "+" [11:13 - 11:14] BinaryOperator= // CHECK4: Identifier: "index" [11:15 - 11:20] DeclRefExpr=index:6:27 -// CHECK4: Punctuation: "]" [11:20 - 11:21] CallExpr=operator[]:2:7 +// CHECK4: Punctuation: "]" [11:20 - 11:21] DeclRefExpr=operator[]:2:7 RefName=[11:6 - 11:7] RefName=[11:20 - 11:21] // CHECK4: Punctuation: ";" [11:21 - 11:22] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:13:1:13:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK5 // CHECK5: Identifier: "foo" [13:3 - 13:6] DeclRefExpr=foo:6:18 -// CHECK5: Punctuation: "[" [13:6 - 13:7] CallExpr=operator[]:2:7 +// CHECK5: Punctuation: "[" [13:6 - 13:7] DeclRefExpr=operator[]:2:7 RefName=[13:6 - 13:7] RefName=[13:17 - 13:18] // CHECK5: Identifier: "foo" [13:7 - 13:10] DeclRefExpr=foo:6:18 -// CHECK5: Punctuation: "[" [13:10 - 13:11] CallExpr=operator[]:2:7 +// CHECK5: Punctuation: "[" [13:10 - 13:11] DeclRefExpr=operator[]:2:7 RefName=[13:10 - 13:11] RefName=[13:16 - 13:17] // CHECK5: Identifier: "index" [13:11 - 13:16] DeclRefExpr=index:6:27 -// CHECK5: Punctuation: "]" [13:16 - 13:17] CallExpr=operator[]:2:7 -// CHECK5: Punctuation: "]" [13:17 - 13:18] CallExpr=operator[]:2:7 +// CHECK5: Punctuation: "]" [13:16 - 13:17] DeclRefExpr=operator[]:2:7 RefName=[13:10 - 13:11] RefName=[13:16 - 13:17] +// CHECK5: Punctuation: "]" [13:17 - 13:18] DeclRefExpr=operator[]:2:7 RefName=[13:6 - 13:7] RefName=[13:17 - 13:18] // CHECK5: Punctuation: ";" [13:18 - 13:19] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:14:1:14:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK6 // CHECK6: Identifier: "foo" [14:3 - 14:6] DeclRefExpr=foo:6:18 -// CHECK6: Punctuation: "[" [14:6 - 14:7] CallExpr=operator[]:2:7 +// CHECK6: Punctuation: "[" [14:6 - 14:7] DeclRefExpr=operator[]:2:7 RefName=[14:6 - 14:7] RefName=[14:25 - 14:26] // CHECK6: Identifier: "foo" [14:7 - 14:10] DeclRefExpr=foo:6:18 -// CHECK6: Punctuation: "(" [14:10 - 14:11] CallExpr=operator():3:7 -// CHECK6: Punctuation: ")" [14:11 - 14:12] CallExpr=operator():3:7 +// CHECK6: Punctuation: "(" [14:10 - 14:11] DeclRefExpr=operator():3:7 RefName=[14:10 - 14:11] RefName=[14:11 - 14:12] +// CHECK6: Punctuation: ")" [14:11 - 14:12] DeclRefExpr=operator():3:7 RefName=[14:10 - 14:11] RefName=[14:11 - 14:12] // CHECK6: Punctuation: "+" [14:13 - 14:14] BinaryOperator= // CHECK6: Identifier: "foo" [14:15 - 14:18] DeclRefExpr=foo:6:18 -// CHECK6: Punctuation: "[" [14:18 - 14:19] CallExpr=operator[]:2:7 -// CHECK6: Identifier: "index" [14:19 - 14:24] DeclRefExpr=index:6:27 -// CHECK6: Punctuation: "]" [14:24 - 14:25] CallExpr=operator[]:2:7 -// CHECK6: Punctuation: "]" [14:25 - 14:26] CallExpr=operator[]:2:7 +// CHECK6: Punctuation: "[" [14:18 - 14:19] DeclRefExpr=operator[]:2:7 RefName=[14:18 - 14:19] RefName=[14:24 - 14:25] +// CHECK6: Identifier: "index" [14:19 - 14:24] DeclRefExpr=operator[]:2:7 RefName=[14:6 - 14:7] RefName=[14:25 - 14:26] +// CHECK6: Punctuation: "]" [14:24 - 14:25] DeclRefExpr=operator[]:2:7 RefName=[14:18 - 14:19] RefName=[14:24 - 14:25] +// CHECK6: Punctuation: "]" [14:25 - 14:26] DeclRefExpr=operator[]:2:7 RefName=[14:6 - 14:7] RefName=[14:25 - 14:26] // CHECK6: Punctuation: ";" [14:26 - 14:27] CompoundStmt= // RUN: c-index-test -test-annotate-tokens=%s:15:1:15:100 %s -std=c++11 -Wno-unused-value | FileCheck %s -check-prefix=CHECK7 // CHECK7: Identifier: "foo" [15:3 - 15:6] DeclRefExpr=foo:6:18 -// CHECK7: Punctuation: "[" [15:6 - 15:7] CallExpr=operator[]:2:7 +// CHECK7: Punctuation: "[" [15:6 - 15:7] DeclRefExpr=operator[]:2:7 RefName=[15:6 - 15:7] RefName=[15:30 - 15:31] // CHECK7: Identifier: "foo" [15:7 - 15:10] DeclRefExpr=foo:6:18 -// CHECK7: Punctuation: "(" [15:10 - 15:11] CallExpr=operator():3:7 +// CHECK7: Punctuation: "(" [15:10 - 15:11] DeclRefExpr=operator():3:7 RefName=[15:10 - 15:11] RefName=[15:16 - 15:17] // CHECK7: Identifier: "index" [15:11 - 15:16] DeclRefExpr=index:6:27 -// CHECK7: Punctuation: ")" [15:16 - 15:17] CallExpr=operator():3:7 +// CHECK7: Punctuation: ")" [15:16 - 15:17] DeclRefExpr=operator():3:7 RefName=[15:10 - 15:11] RefName=[15:16 - 15:17] // CHECK7: Punctuation: "+" [15:18 - 15:19] BinaryOperator= // CHECK7: Identifier: "foo" [15:20 - 15:23] DeclRefExpr=foo:6:18 -// CHECK7: Punctuation: "[" [15:23 - 15:24] CallExpr=operator[]:2:7 +// CHECK7: Punctuation: "[" [15:23 - 15:24] DeclRefExpr=operator[]:2:7 RefName=[15:23 - 15:24] RefName=[15:29 - 15:30] // CHECK7: Identifier: "index" [15:24 - 15:29] DeclRefExpr=index:6:27 -// CHECK7: Punctuation: "]" [15:29 - 15:30] CallExpr=operator[]:2:7 -// CHECK7: Punctuation: "]" [15:30 - 15:31] CallExpr=operator[]:2:7 +// CHECK7: Punctuation: "]" [15:29 - 15:30] DeclRefExpr=operator[]:2:7 RefName=[15:23 - 15:24] RefName=[15:29 - 15:30] +// CHECK7: Punctuation: "]" [15:30 - 15:31] DeclRefExpr=operator[]:2:7 RefName=[15:6 - 15:7] RefName=[15:30 - 15:31] // CHECK7: Punctuation: ";" [15:31 - 15:32] CompoundStmt= diff --git a/clang/test/Index/cursor-ref-names.cpp b/clang/test/Index/cursor-ref-names.cpp index e34c65eefd254..26174bca1afaf 100644 --- a/clang/test/Index/cursor-ref-names.cpp +++ b/clang/test/Index/cursor-ref-names.cpp @@ -33,9 +33,9 @@ int main() // CHECK: cursor-ref-names.cpp:18:5: CallExpr=func:8:10 Extent=[18:5 - 18:16] // CHECK: cursor-ref-names.cpp:18:10: MemberRefExpr=func:8:10 SingleRefName=[18:10 - 18:14] RefName=[18:10 - 18:14] Extent=[18:5 - 18:14] // CHECK: cursor-ref-names.cpp:18:5: DeclRefExpr=inst:17:9 Extent=[18:5 - 18:9] -// CHECK: cursor-ref-names.cpp:19:5: CallExpr=operator[]:4:9 Extent=[19:5 - 19:12] +// CHECK: cursor-ref-names.cpp:19:5: CallExpr=operator[]:4:9 SingleRefName=[19:9 - 19:12] RefName=[19:9 - 19:10] RefName=[19:11 - 19:12] Extent=[19:5 - 19:12] // CHECK: cursor-ref-names.cpp:19:5: DeclRefExpr=inst:17:9 Extent=[19:5 - 19:9] -// CHECK: cursor-ref-names.cpp:19:9: DeclRefExpr=operator[]:4:9 Extent=[19:9 - 19:10] +// CHECK: cursor-ref-names.cpp:19:9: DeclRefExpr=operator[]:4:9 RefName=[19:9 - 19:10] RefName=[19:11 - 19:12] Extent=[19:9 - 19:12] // CHECK: cursor-ref-names.cpp:20:5: CallExpr=operator[]:4:9 Extent=[20:5 - 20:23] // CHECK: cursor-ref-names.cpp:20:10: MemberRefExpr=operator[]:4:9 SingleRefName=[20:10 - 20:20] RefName=[20:10 - 20:18] RefName=[20:18 - 20:19] RefName=[20:19 - 20:20] Extent=[20:5 - 20:20] // CHECK: cursor-ref-names.cpp:20:5: DeclRefExpr=inst:17:9 Extent=[20:5 - 20:9] diff --git a/clang/test/Modules/config_macros.m b/clang/test/Modules/config_macros.m index dd071993809be..68ef6508afe65 100644 --- a/clang/test/Modules/config_macros.m +++ b/clang/test/Modules/config_macros.m @@ -5,7 +5,7 @@ } char *test_bar(void) { - return bar(); // expected-error{{call to undeclared function 'bar'; ISO C99 and later do not support implicit function declarations}} \ + return bar(); // expected-warning{{call to undeclared function 'bar'; ISO C99 and later do not support implicit function declarations}} \ // expected-error{{incompatible integer to pointer conversion}} } diff --git a/clang/test/Modules/malformed-overload.m b/clang/test/Modules/malformed-overload.m index fd5d2f4f696b4..369de580c9d74 100644 --- a/clang/test/Modules/malformed-overload.m +++ b/clang/test/Modules/malformed-overload.m @@ -1,6 +1,6 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -fsyntax-only -I%S/Inputs/malformed-overload -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Wno-strict-prototypes -verify %s -NSLog(@"%@", path); // expected-error {{expected parameter declarator}} expected-error {{expected ')'}} expected-error {{type specifier missing}} expected-warning {{incompatible redeclaration}} expected-note {{to match this '('}} expected-note {{'NSLog' is a builtin with type}} +NSLog(@"%@", path); // expected-error {{expected parameter declarator}} expected-error {{expected ')'}} expected-warning {{type specifier missing}} expected-warning {{incompatible redeclaration}} expected-note {{to match this '('}} expected-note {{'NSLog' is a builtin with type}} #import "X.h" @class NSString; diff --git a/clang/test/Modules/merge-concepts.cpp b/clang/test/Modules/merge-concepts.cpp index 9242f27633795..c774157dd85b4 100644 --- a/clang/test/Modules/merge-concepts.cpp +++ b/clang/test/Modules/merge-concepts.cpp @@ -28,6 +28,10 @@ module "library" { export * header "concepts.h" } + module "compare" { + export * + header "compare.h" + } module "format" { export * header "format.h" @@ -47,19 +51,34 @@ module "library" { #define SAME_AS_H template -concept same_as = __is_same(T, U); +concept same_as_impl = __is_same(T, U); +template +concept same_as = same_as_impl && same_as_impl; #endif // SAME_AS_H + +//--- compare.h +#ifndef COMPARE_H +#define COMPARE_H + +#include "same_as.h" +#include "concepts.h" + +template void foo() + requires same_as +{} +#endif // COMPARE_H + //--- format.h #ifndef FORMAT_H #define FORMAT_H -#include "concepts.h" #include "same_as.h" +#include "concepts.h" -template void foo() +template void bar() requires same_as {} -#endif // FORMAT_H \ No newline at end of file +#endif // FORMAT_H diff --git a/clang/test/Modules/merge-concepts.cppm b/clang/test/Modules/merge-concepts.cppm new file mode 100644 index 0000000000000..ca4877bfd7949 --- /dev/null +++ b/clang/test/Modules/merge-concepts.cppm @@ -0,0 +1,185 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -emit-module-interface -I%t %t/A.cppm -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface -I%t %t/B.cppm -o %t/B.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use2.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use3.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use4.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/C.cppm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -I%t %t/D.cppm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -I%t %t/E.cppm -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -I%t %t/F.cppm -verify -fsyntax-only +// +// Testing header units for coverity. +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/foo.h -o %t/foo.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -fmodule-file=%t/foo.pcm %t/Use5.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -fmodule-file=%t/foo.pcm %t/Use6.cpp -verify -fsyntax-only +// +// Testing with module map modules. It is unclear about the relation ship between Clang modules and +// C++20 Named Modules. Will they coexist? Or will they be mutually exclusive? +// The test here is for primarily coverity. +// +// RUN: rm -f %t/foo.pcm +// RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -fprebuilt-module-path=%t \ +// RUN: -fmodule-map-file=%t/module.map %t/Use7.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -fprebuilt-module-path=%t \ +// RUN: -fmodule-map-file=%t/module.map %t/Use7.cpp -verify -fsyntax-only +// Testing module map modules with named modules. +// RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%t/module.map \ +// RUN: %t/A.cppm -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -fprebuilt-module-path=%t \ +// RUN: -fmodule-map-file=%t/module.map %t/Use7.cpp -verify -fsyntax-only +// RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -fprebuilt-module-path=%t \ +// RUN: -fmodule-map-file=%t/module.map %t/Use7.cpp -verify -fsyntax-only + +// +//--- foo.h +#ifndef FOO_H +#define FOO_H +template +concept same_as = __is_same(T, U); +#endif + +// The compiler would warn if we include foo_h twice without guard. +//--- redecl.h +#ifndef REDECL_H +#define REDECL_H +template +concept same_as = __is_same(T, U); +#endif + +//--- A.cppm +module; +#include "foo.h" +export module A; +export using ::same_as; + +//--- B.cppm +module; +#include "foo.h" +export module B; +export using ::same_as; + +//--- Use.cpp +// expected-no-diagnostics +import A; +import B; + +template void foo() + requires same_as +{} + +//--- Use2.cpp +// expected-no-diagnostics +#include "foo.h" +import A; + +template void foo() + requires same_as +{} + +//--- Use3.cpp +// expected-no-diagnostics +import A; +#include "foo.h" + +template void foo() + requires same_as +{} + +//--- Use4.cpp +// expected-no-diagnostics +import A; +import B; +#include "foo.h" + +template void foo() + requires same_as +{} + +//--- C.cppm +// expected-no-diagnostics +module; +#include "foo.h" +export module C; +import A; +import B; + +template void foo() + requires same_as +{} + +//--- D.cppm +module; +#include "foo.h" +#include "redecl.h" +export module D; +export using ::same_as; + +// expected-error@* {{redefinition of 'same_as'}} +// expected-note@* 1+{{previous definition is here}} + +//--- E.cppm +module; +#include "foo.h" +export module E; +export template +concept same_as = __is_same(T, U); + +// expected-error@* {{redefinition of 'same_as'}} +// expected-note@* 1+{{previous definition is here}} + +//--- F.cppm +export module F; +template +concept same_as = __is_same(T, U); +template +concept same_as = __is_same(T, U); + +// expected-error@* {{redefinition of 'same_as'}} +// expected-note@* 1+{{previous definition is here}} + +//--- Use5.cpp +// expected-no-diagnostics +import "foo.h"; +import A; + +template void foo() + requires same_as +{} + +//--- Use6.cpp +// expected-no-diagnostics +import A; +import "foo.h"; + +template void foo() + requires same_as +{} + +//--- module.map +module "foo" { + export * + header "foo.h" +} + +//--- Use7.cpp +// expected-no-diagnostics +#include "foo.h" +import A; + +template void foo() + requires same_as +{} + +//--- Use8.cpp +// expected-no-diagnostics +import A; +#include "foo.h" + +template void foo() + requires same_as +{} diff --git a/clang/test/Modules/modulemap-locations.m b/clang/test/Modules/modulemap-locations.m index e5738e105263a..08e06f47f5c8e 100644 --- a/clang/test/Modules/modulemap-locations.m +++ b/clang/test/Modules/modulemap-locations.m @@ -12,9 +12,7 @@ void test(void) { will_be_found1(); - wont_be_found1(); // expected-error{{call to undeclared function 'wont_be_found1'; ISO C99 and later do not support implicit function declarations}} \ - expected-note {{did you mean 'will_be_found1'?}} \ - expected-note@Inputs/ModuleMapLocations/Module_ModuleMap/a.h:1 {{'will_be_found1' declared here}} + wont_be_found1(); // expected-warning{{call to undeclared function 'wont_be_found1'; ISO C99 and later do not support implicit function declarations}} will_be_found2(); - wont_be_found2(); // expected-error{{call to undeclared function 'wont_be_found2'; ISO C99 and later do not support implicit function declarations}} + wont_be_found2(); // expected-warning{{call to undeclared function 'wont_be_found2'; ISO C99 and later do not support implicit function declarations}} } diff --git a/clang/test/OpenMP/bug56913.c b/clang/test/OpenMP/bug56913.c new file mode 100644 index 0000000000000..cc7231626878c --- /dev/null +++ b/clang/test/OpenMP/bug56913.c @@ -0,0 +1,32 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs --prefix-filecheck-ir-name _ +// RUN: %clang_cc1 -fopenmp-simd -O1 -x c -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK + +int j; +int *u; + +void loop(int n) { + int i; +#pragma omp parallel master taskloop simd linear(j) + for (i = 0; i < n; ++i) { + ++j; + u = &j; + } +} +// CHECK-LABEL: define {{[^@]+}}@loop +// CHECK-SAME: (i32 noundef [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[J:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N]], 0 +// CHECK-NEXT: br i1 [[CMP]], label [[SIMD_IF_THEN:%.*]], label [[SIMD_IF_END:%.*]] +// CHECK: simd.if.then: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @j, align 4, !tbaa [[TBAA2:![0-9]+]] +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[J]]) #[[ATTR2:[0-9]+]] +// CHECK-NEXT: store ptr [[J]], ptr @u, align 8, !tbaa [[TBAA6:![0-9]+]], !llvm.access.group [[ACC_GRP8:![0-9]+]] +// CHECK-NEXT: [[INC_LE:%.*]] = add i32 [[TMP0]], [[N]] +// CHECK-NEXT: store i32 [[INC_LE]], ptr [[J]], align 4, !tbaa [[TBAA2]] +// CHECK-NEXT: store i32 [[INC_LE]], ptr @j, align 4, !tbaa [[TBAA2]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[J]]) #[[ATTR2]] +// CHECK-NEXT: br label [[SIMD_IF_END]] +// CHECK: simd.if.end: +// CHECK-NEXT: ret void +// diff --git a/clang/test/OpenMP/declare_mapper_messages.c b/clang/test/OpenMP/declare_mapper_messages.c index ae95dc81caef6..ab9e63ede4506 100644 --- a/clang/test/OpenMP/declare_mapper_messages.c +++ b/clang/test/OpenMP/declare_mapper_messages.c @@ -42,9 +42,9 @@ int fun(int arg) { {} #pragma omp target map(mapper:vv) // expected-error {{expected '(' after 'mapper'}} {} -#pragma omp target map(mapper( :vv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-error {{call to undeclared function 'mapper'}} expected-note {{to match this '('}} +#pragma omp target map(mapper( :vv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-warning {{call to undeclared function 'mapper'}} expected-note {{to match this '('}} {} -#pragma omp target map(mapper(aa :vv) // expected-error {{use of undeclared identifier 'aa'}} expected-error {{expected ')'}} expected-error {{call to undeclared function 'mapper'}} expected-note {{to match this '('}} +#pragma omp target map(mapper(aa :vv) // expected-error {{use of undeclared identifier 'aa'}} expected-error {{expected ')'}} expected-warning {{call to undeclared function 'mapper'}} expected-note {{to match this '('}} {} #pragma omp target map(mapper(ab) :vv) // expected-error {{missing map type}} expected-error {{cannot find a valid user-defined mapper for type 'struct vec' with name 'ab'}} {} diff --git a/clang/test/OpenMP/for_linear_codegen.cpp b/clang/test/OpenMP/for_linear_codegen.cpp index 05ccf94e4fd43..c7c9324dc1b66 100644 --- a/clang/test/OpenMP/for_linear_codegen.cpp +++ b/clang/test/OpenMP/for_linear_codegen.cpp @@ -322,18 +322,18 @@ int main() { // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: // CHECK1-NEXT: call void @__kmpc_for_static_fini(%struct.ident_t* @[[GLOB2]], i32 [[TMP5]]) -// CHECK1-NEXT: [[TMP19:%.*]] = bitcast i64* [[DOTLVAR__ADDR]] to i8* -// CHECK1-NEXT: call void @__kmpc_free(i32 [[TMP5]], i8* [[TMP19]], i8* inttoptr (i64 5 to i8*)) -// CHECK1-NEXT: [[TMP20:%.*]] = load i32, i32* [[DOTOMP_IS_LAST]], align 4 -// CHECK1-NEXT: [[TMP21:%.*]] = icmp ne i32 [[TMP20]], 0 -// CHECK1-NEXT: br i1 [[TMP21]], label [[DOTOMP_LINEAR_PU:%.*]], label [[DOTOMP_LINEAR_PU_DONE:%.*]] +// CHECK1-NEXT: [[TMP19:%.*]] = load i32, i32* [[DOTOMP_IS_LAST]], align 4 +// CHECK1-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 +// CHECK1-NEXT: br i1 [[TMP20]], label [[DOTOMP_LINEAR_PU:%.*]], label [[DOTOMP_LINEAR_PU_DONE:%.*]] // CHECK1: .omp.linear.pu: -// CHECK1-NEXT: [[TMP22:%.*]] = load float*, float** [[PVAR2]], align 8 -// CHECK1-NEXT: store float* [[TMP22]], float** [[TMP0]], align 8 -// CHECK1-NEXT: [[TMP23:%.*]] = load i64, i64* [[DOTLVAR__ADDR]], align 8 -// CHECK1-NEXT: store i64 [[TMP23]], i64* [[TMP1]], align 8 +// CHECK1-NEXT: [[TMP21:%.*]] = load float*, float** [[PVAR2]], align 8 +// CHECK1-NEXT: store float* [[TMP21]], float** [[TMP0]], align 8 +// CHECK1-NEXT: [[TMP22:%.*]] = load i64, i64* [[DOTLVAR__ADDR]], align 8 +// CHECK1-NEXT: store i64 [[TMP22]], i64* [[TMP1]], align 8 // CHECK1-NEXT: br label [[DOTOMP_LINEAR_PU_DONE]] // CHECK1: .omp.linear.pu.done: +// CHECK1-NEXT: [[TMP23:%.*]] = bitcast i64* [[DOTLVAR__ADDR]] to i8* +// CHECK1-NEXT: call void @__kmpc_free(i32 [[TMP5]], i8* [[TMP23]], i8* inttoptr (i64 5 to i8*)) // CHECK1-NEXT: call void @__kmpc_barrier(%struct.ident_t* @[[GLOB1]], i32 [[TMP5]]) // CHECK1-NEXT: ret void // diff --git a/clang/test/OpenMP/parallel_default_messages.cpp b/clang/test/OpenMP/parallel_default_messages.cpp index 7db15d7267317..65e0d92c32fc2 100644 --- a/clang/test/OpenMP/parallel_default_messages.cpp +++ b/clang/test/OpenMP/parallel_default_messages.cpp @@ -49,3 +49,10 @@ int main(int argc, char **argv) { return 0; } + +class A{ + void a() { + #pragma omp parallel + a(b); // expected-error {{use of undeclared identifier 'b'}} + } +}; diff --git a/clang/test/OpenMP/parallel_master_taskloop_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/parallel_master_taskloop_simd_lastprivate_codegen.cpp index ef015914d6710..ffda7d2ad8019 100644 --- a/clang/test/OpenMP/parallel_master_taskloop_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/parallel_master_taskloop_simd_lastprivate_codegen.cpp @@ -1847,8 +1847,12 @@ void loop() { // CHECK6-NEXT: [[TMP38:%.*]] = icmp ne i32 [[TMP37]], 0 // CHECK6-NEXT: br i1 [[TMP38]], label [[DOTOMP_LINEAR_PU_I:%.*]], label [[DOTOMP_OUTLINED__1_EXIT:%.*]] // CHECK6: .omp.linear.pu.i: -// CHECK6-NEXT: [[TMP39:%.*]] = load i32, i32* [[J_I]], align 4, !noalias !14 -// CHECK6-NEXT: store i32 [[TMP39]], i32* [[J_I]], align 4, !noalias !14 +// CHECK6-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[TMP20]], i32 0, i32 0 +// CHECK6-NEXT: [[TMP40:%.*]] = load i32*, i32** [[TMP39]], align 8 +// CHECK6-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[TMP20]], i32 0, i32 1 +// CHECK6-NEXT: [[TMP42:%.*]] = load i32*, i32** [[TMP41]], align 8 +// CHECK6-NEXT: [[TMP43:%.*]] = load i32, i32* [[J_I]], align 4, !noalias !14 +// CHECK6-NEXT: store i32 [[TMP43]], i32* [[TMP42]], align 4 // CHECK6-NEXT: br label [[DOTOMP_OUTLINED__1_EXIT]] // CHECK6: .omp_outlined..1.exit: // CHECK6-NEXT: ret i32 0 diff --git a/clang/test/PCH/chain-macro-override.c b/clang/test/PCH/chain-macro-override.c index 26abae1cb9d55..62b05324ed44b 100644 --- a/clang/test/PCH/chain-macro-override.c +++ b/clang/test/PCH/chain-macro-override.c @@ -10,7 +10,7 @@ int foo(void) { f(); g(); h(); - h2(); // expected-error {{call to undeclared function 'h2'; ISO C99 and later do not support implicit function declarations}} + h2(); // expected-warning {{call to undeclared function 'h2'; ISO C99 and later do not support implicit function declarations}} h3(); return x; } diff --git a/clang/test/PCH/pch-dir.c b/clang/test/PCH/pch-dir.c index f8b8c05878f45..afdd7b1f4f307 100644 --- a/clang/test/PCH/pch-dir.c +++ b/clang/test/PCH/pch-dir.c @@ -6,7 +6,7 @@ // RUN: %clang -x c++-header -std=c++98 %S/pch-dir.h -o %t.h.gch/cpp.gch // RUN: %clang -include %t.h -DFOO=foo -fsyntax-only %s -Xclang -print-stats 2> %t.clog // RUN: FileCheck -check-prefix=CHECK-C %s < %t.clog -// RUN: %clang -include %t.h -DFOO=bar -DBAR=bar -fsyntax-only %s -Xclang -ast-print > %t.cbarlog +// RUN: %clang -include %t.h -DFOO=bar -fsyntax-only %s -Xclang -ast-print > %t.cbarlog // RUN: FileCheck -check-prefix=CHECK-CBAR %s < %t.cbarlog // RUN: %clang -x c++ -include %t.h -std=c++98 -fsyntax-only %s -Xclang -print-stats 2> %t.cpplog // RUN: FileCheck -check-prefix=CHECK-CPP %s < %t.cpplog @@ -14,6 +14,11 @@ // RUN: not %clang -x c++ -std=c++11 -include %t.h -fsyntax-only %s 2> %t.cpp11log // RUN: FileCheck -check-prefix=CHECK-NO-SUITABLE %s < %t.cpp11log +// RUN: not %clang -include %t.h -fsyntax-only %s 2> %t.missinglog2 +// RUN: FileCheck -check-prefix=CHECK-NO-SUITABLE %s < %t.missinglog2 +// RUN: not %clang -include %t.h -DFOO=foo -DBAR=bar -fsyntax-only %s 2> %t.missinglog2 +// RUN: FileCheck -check-prefix=CHECK-NO-SUITABLE %s < %t.missinglog2 + // Don't crash if the precompiled header file is missing. // RUN: not %clang_cc1 -include-pch %t.h.gch -DFOO=baz -fsyntax-only %s -print-stats 2> %t.missinglog // RUN: FileCheck -check-prefix=CHECK-NO-SUITABLE %s < %t.missinglog diff --git a/clang/test/Parser/altivec.c b/clang/test/Parser/altivec.c index 66d2ca33ed91e..3f344e9c5a13c 100644 --- a/clang/test/Parser/altivec.c +++ b/clang/test/Parser/altivec.c @@ -97,8 +97,8 @@ vector unsigned long int v_uli; // nonaix-warning {{Use of 'long' with '__ve // These should have warnings. __vector long double vv_ld; // expected-error {{cannot use 'long double' with '__vector'}} vector long double v_ld; // expected-error {{cannot use 'long double' with '__vector'}} -vector bool v_b; // expected-error {{type specifier missing, defaults to 'int'}} -vector __bool v___b; // expected-error {{type specifier missing, defaults to 'int'}} +vector bool v_b; // expected-warning {{type specifier missing, defaults to 'int'}} +vector __bool v___b; // expected-warning {{type specifier missing, defaults to 'int'}} // These should have errors. #ifndef __VSX__ diff --git a/clang/test/Parser/attributes.c b/clang/test/Parser/attributes.c index fe22c7e98a537..3375c4bc37410 100644 --- a/clang/test/Parser/attributes.c +++ b/clang/test/Parser/attributes.c @@ -7,7 +7,7 @@ foo(void) { } -__attribute__(()) y; // expected-error {{type specifier missing, defaults to 'int'}} +__attribute__(()) y; // expected-warning {{type specifier missing, defaults to 'int'}} // PR2796 int (__attribute__(()) *z)(long y); @@ -19,8 +19,8 @@ int f2(y, __attribute__(()) x); // expected-error {{expected identifier}} // This is parsed as a normal argument list (with two args that are implicit // int) because the __attribute__ is a declspec. -void f3(__attribute__(()) x, // expected-error {{type specifier missing, defaults to 'int'}} - y); // expected-error {{type specifier missing, defaults to 'int'}} +void f3(__attribute__(()) x, // expected-warning {{type specifier missing, defaults to 'int'}} + y); // expected-warning {{type specifier missing, defaults to 'int'}} void f4(__attribute__(())); // expected-error {{expected parameter declarator}} @@ -30,14 +30,14 @@ int baz(int (__attribute__(()) *x)(long y)); void g1(void (*f1)(__attribute__(()) int x)); void g2(int (*f2)(y, __attribute__(()) x)); // expected-error {{expected identifier}} -void g3(void (*f3)(__attribute__(()) x, int y)); // expected-error {{type specifier missing, defaults to 'int'}} +void g3(void (*f3)(__attribute__(()) x, int y)); // expected-warning {{type specifier missing, defaults to 'int'}} void g4(void (*f4)(__attribute__(()))); // expected-error {{expected parameter declarator}} void (*h1)(void (*f1)(__attribute__(()) int x)); void (*h2)(int (*f2)(y, __attribute__(()) x)); // expected-error {{expected identifier}} -void (*h3)(void (*f3)(__attribute__(()) x)); // expected-error {{type specifier missing, defaults to 'int'}} +void (*h3)(void (*f3)(__attribute__(()) x)); // expected-warning {{type specifier missing, defaults to 'int'}} void (*h4)(void (*f4)(__attribute__(()))); // expected-error {{expected parameter declarator}} diff --git a/clang/test/Parser/declarators.c b/clang/test/Parser/declarators.c index c294bd085366e..92cba09cdbbf6 100644 --- a/clang/test/Parser/declarators.c +++ b/clang/test/Parser/declarators.c @@ -6,7 +6,7 @@ void f0(); /* expected-warning {{a function declaration without a prototype is d void f1(int [*]); void f2(int [const *]); void f3(int [volatile const*]); -int f4(*XX)(void); /* expected-error {{cannot return}} expected-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} */ +int f4(*XX)(void); /* expected-error {{cannot return}} expected-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} */ int f5(int [static]); /* expected-error {{'static' may not be used without an array size}} */ char ((((*X)))); @@ -64,9 +64,9 @@ struct xyz test8(void) { return a; } // a should be be marked invalid, no diag. // Verify that implicit int still works. -static f; // expected-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} -static g = 4; // expected-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} -static h // expected-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} +static f; // expected-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} +static g = 4; // expected-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} +static h // expected-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} __asm__("foo"); diff --git a/clang/test/Parser/objc-forcollection-neg-2.m b/clang/test/Parser/objc-forcollection-neg-2.m index e28b74f3f4424..f95dd1356bc3e 100644 --- a/clang/test/Parser/objc-forcollection-neg-2.m +++ b/clang/test/Parser/objc-forcollection-neg-2.m @@ -24,7 +24,7 @@ - (void)compilerTestAgainst; @implementation MyList (BasicTest) - (void)compilerTestAgainst { - static i;// expected-error {{type specifier missing, defaults to 'int'}} + static i;// expected-warning {{type specifier missing, defaults to 'int'}} for (id el, elem in self) // expected-error {{only one element declaration is allowed}} ++i; for (id el in self) diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 6e495a0ae96e7..2d4ec2bbcae92 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -150,6 +150,7 @@ // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE %s // CHECK-SVE: __ARM_FEATURE_SVE 1 +// CHECK-SVE: __ARM_FEATURE_SVE_VECTOR_OPERATORS 2 // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve+bf16 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE-BF16 %s // CHECK-SVE-BF16: __ARM_FEATURE_BF16_SCALAR_ARITHMETIC 1 @@ -512,9 +513,7 @@ // RUN: %clang -target aarch64-arm-none-eabi -march=armv8-a+sve -msve-vector-bits=2048 -x c -E -dM %s -o - 2>&1 | FileCheck -check-prefix=CHECK-SVE-VECTOR-BITS -D#VBITS=2048 %s // RUN: %clang -target aarch64-arm-none-eabi -march=armv8-a+sve -msve-vector-bits=512+ -x c -E -dM %s -o - 2>&1 | FileCheck -check-prefix=CHECK-NO-SVE-VECTOR-BITS %s // CHECK-SVE-VECTOR-BITS: __ARM_FEATURE_SVE_BITS [[#VBITS:]] -// CHECK-SVE-VECTOR-BITS: __ARM_FEATURE_SVE_VECTOR_OPERATORS 1 // CHECK-NO-SVE-VECTOR-BITS-NOT: __ARM_FEATURE_SVE_BITS -// CHECK-NO-SVE-VECTOR-BITS-NOT: __ARM_FEATURE_SVE_VECTOR_OPERATORS // ================== Check Large System Extensions (LSE) // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+lse -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-LSE %s diff --git a/clang/test/Preprocessor/is_target_unknown.c b/clang/test/Preprocessor/is_target_unknown.c index d81afcbd22410..b61538fb39154 100644 --- a/clang/test/Preprocessor/is_target_unknown.c +++ b/clang/test/Preprocessor/is_target_unknown.c @@ -20,3 +20,13 @@ #if !__is_target_environment(unknown) #error "mismatching environment" #endif + +// Unknown variant OS is not allowed. +#if __is_target_variant_os(unknown) + #error "mismatching OS" +#endif + +// Unknown variant environment is not allowed. +#if __is_target_variant_environment(unknown) + #error "mismatching environment" +#endif diff --git a/clang/test/Preprocessor/is_target_variant.c b/clang/test/Preprocessor/is_target_variant.c new file mode 100644 index 0000000000000..8d374f878416c --- /dev/null +++ b/clang/test/Preprocessor/is_target_variant.c @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -fsyntax-only -triple arm64-apple-macos -DMAC -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple arm64-apple-ios13.1 -DIOS -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple arm64-apple-ios13.1-macabi -DCATALYST -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple arm64-apple-macos12 -darwin-target-variant-triple arm64-apple-ios-macabi -DZIPPERED -verify %s +// expected-no-diagnostics + +#if !__has_builtin(__is_target_variant_os) || !__has_builtin(__is_target_variant_environment) + #error "has builtin doesn't work" +#endif + +#ifdef ZIPPERED + + // Target variant is a darwin. + #if !__is_target_variant_os(darwin) + #error "mismatching variant os" + #endif + + // Target variant is not macOS... + #if __is_target_variant_os(macos) + #error "mismatching variant os" + #endif + + // ...but iOS. + #if !__is_target_variant_os(ios) + #error "mismatching variant os" + #endif + + // Zippered builds also set the target variant environment to macabi. + // At the moment, only zippered builds set __is_target_variant_os(ios), + // so checking __is_target_variant_environment() is currently redundant + // with checking the former. + #if !__is_target_variant_environment(macabi) + #error "mismatching variant environment" + #endif + +#else + + // In non-zippered builds, even for catalyst, no target variant is set. + // So these are all false. + + #if __is_target_variant_os(darwin) + #error "mismatching variant os" + #endif + + #if __is_target_variant_os(macos) + #error "mismatching variant os" + #endif + + #if __is_target_variant_os(ios) + #error "mismatching variant os" + #endif + + #if __is_target_variant_environment(macabi) + #error "mismatching variant environment" + #endif + +#endif + +// The target environment in zippered builds is _not_ macabi. +// The target environment is macabi only in catalyst builds. +#ifdef CATALYST + #if !__is_target_environment(macabi) + #error "mismatching environment" + #endif + #if !__is_target_os(ios) + #error "mismatching os" + #endif +#else + #if __is_target_environment(macabi) + #error "mismatching environment" + #endif +#endif diff --git a/clang/test/Preprocessor/macro_paste_msextensions.c b/clang/test/Preprocessor/macro_paste_msextensions.c index 1549ff5e55620..dcc5336b91c14 100644 --- a/clang/test/Preprocessor/macro_paste_msextensions.c +++ b/clang/test/Preprocessor/macro_paste_msextensions.c @@ -32,7 +32,7 @@ nested(baz) rise of the dead tokens // rdar://8197149 - VC++ allows invalid token pastes: (##baz #define foo(x) abc(x) #define bar(y) foo(##baz(y)) -bar(q) // expected-error {{type specifier missing}} expected-error {{invalid preprocessing token}} expected-error {{parameter list without types}} +bar(q) // expected-warning {{type specifier missing}} expected-error {{invalid preprocessing token}} expected-error {{parameter list without types}} // CHECK: abc(baz(q)) diff --git a/clang/test/Preprocessor/predefined-arch-macros.c b/clang/test/Preprocessor/predefined-arch-macros.c index 6384b139c4054..0ffa2739e5df4 100644 --- a/clang/test/Preprocessor/predefined-arch-macros.c +++ b/clang/test/Preprocessor/predefined-arch-macros.c @@ -3216,6 +3216,7 @@ // CHECK_ZNVER2_M32: #define __POPCNT__ 1 // CHECK_ZNVER2_M32: #define __PRFCHW__ 1 // CHECK_ZNVER2_M32: #define __RDPID__ 1 +// CHECK_ZNVER2_M32: #define __RDPRU__ 1 // CHECK_ZNVER2_M32: #define __RDRND__ 1 // CHECK_ZNVER2_M32: #define __RDSEED__ 1 // CHECK_ZNVER2_M32: #define __SHA__ 1 @@ -3266,6 +3267,7 @@ // CHECK_ZNVER2_M64: #define __POPCNT__ 1 // CHECK_ZNVER2_M64: #define __PRFCHW__ 1 // CHECK_ZNVER2_M64: #define __RDPID__ 1 +// CHECK_ZNVER2_M64: #define __RDPRU__ 1 // CHECK_ZNVER2_M64: #define __RDRND__ 1 // CHECK_ZNVER2_M64: #define __RDSEED__ 1 // CHECK_ZNVER2_M64: #define __SHA__ 1 @@ -3318,6 +3320,7 @@ // CHECK_ZNVER3_M32: #define __POPCNT__ 1 // CHECK_ZNVER3_M32: #define __PRFCHW__ 1 // CHECK_ZNVER3_M32: #define __RDPID__ 1 +// CHECK_ZNVER3_M32: #define __RDPRU__ 1 // CHECK_ZNVER3_M32: #define __RDRND__ 1 // CHECK_ZNVER3_M32: #define __RDSEED__ 1 // CHECK_ZNVER3_M32: #define __SHA__ 1 @@ -3368,6 +3371,7 @@ // CHECK_ZNVER3_M64: #define __POPCNT__ 1 // CHECK_ZNVER3_M64: #define __PRFCHW__ 1 // CHECK_ZNVER3_M64: #define __RDPID__ 1 +// CHECK_ZNVER3_M64: #define __RDPRU__ 1 // CHECK_ZNVER3_M64: #define __RDRND__ 1 // CHECK_ZNVER3_M64: #define __RDSEED__ 1 // CHECK_ZNVER3_M64: #define __SHA__ 1 diff --git a/clang/test/Sema/__try.c b/clang/test/Sema/__try.c index 9bfd914c013c1..d0b2164198a2e 100644 --- a/clang/test/Sema/__try.c +++ b/clang/test/Sema/__try.c @@ -50,7 +50,7 @@ void TEST(void) { } // expected-error{{expected '__except' or '__finally' block}} void TEST(void) { - __except (FilterExpression()) { // expected-error{{call to undeclared function '__except'; ISO C99 and later do not support implicit function declarations}} \ + __except (FilterExpression()) { // expected-warning{{call to undeclared function '__except'; ISO C99 and later do not support implicit function declarations}} \ // expected-error{{too few arguments to function call, expected 1, have 0}} \ // expected-error{{expected ';' after expression}} } diff --git a/clang/test/Sema/aarch64-tme-errors.c b/clang/test/Sema/aarch64-tme-errors.c index 26e931b62bcb7..63ce87f3dc6b9 100644 --- a/clang/test/Sema/aarch64-tme-errors.c +++ b/clang/test/Sema/aarch64-tme-errors.c @@ -3,6 +3,6 @@ #include "arm_acle.h" void test_no_tme_funcs(void) { - __tstart(); // expected-error{{call to undeclared function '__tstart'; ISO C99 and later do not support implicit function declarations}} + __tstart(); // expected-warning{{call to undeclared function '__tstart'; ISO C99 and later do not support implicit function declarations}} __builtin_tstart(); // expected-error{{use of unknown builtin '__builtin_tstart'}} } diff --git a/clang/test/Sema/address_spaces.c b/clang/test/Sema/address_spaces.c index ff7a134e04ebf..085bef9b72d31 100644 --- a/clang/test/Sema/address_spaces.c +++ b/clang/test/Sema/address_spaces.c @@ -9,7 +9,7 @@ void bar(_AS2 int a); // expected-error {{parameter may not be qualified with an void foo(_AS3 float *a, _AS1 float b) // expected-error {{parameter may not be qualified with an address space}} { - _AS2 *x;// expected-error {{type specifier missing, defaults to 'int'}} + _AS2 *x;// expected-warning {{type specifier missing, defaults to 'int'}} _AS1 float * _AS2 *B; int _AS1 _AS2 *Y; // expected-error {{multiple address spaces specified for type}} diff --git a/clang/test/Sema/auto-type.c b/clang/test/Sema/auto-type.c index 1170c687c96aa..bc845e37c2aed 100644 --- a/clang/test/Sema/auto-type.c +++ b/clang/test/Sema/auto-type.c @@ -37,7 +37,7 @@ void Issue53652(void) { // GCC does not accept this either, for the same reason. _Atomic(__auto_type) aat2 = a; // expected-error {{'__auto_type' not allowed here}} \ - // expected-error {{type specifier missing, defaults to 'int'}} + // expected-warning {{type specifier missing, defaults to 'int'}} // Ensure the types are what we expect them to be, regardless of order we // pass the types. diff --git a/clang/test/Sema/bitfield.c b/clang/test/Sema/bitfield.c index 468fe93485cc0..b2982515da4d6 100644 --- a/clang/test/Sema/bitfield.c +++ b/clang/test/Sema/bitfield.c @@ -84,5 +84,5 @@ struct Test6 { }; struct PR36157 { - int n : 1 ? 1 : implicitly_declare_function(); // expected-error {{call to undeclared function 'implicitly_declare_function'; ISO C99 and later do not support implicit function declarations}} + int n : 1 ? 1 : implicitly_declare_function(); // expected-warning {{call to undeclared function 'implicitly_declare_function'; ISO C99 and later do not support implicit function declarations}} }; diff --git a/clang/test/Sema/block-args.c b/clang/test/Sema/block-args.c index 1e000abf4b361..245b2c02b8067 100644 --- a/clang/test/Sema/block-args.c +++ b/clang/test/Sema/block-args.c @@ -37,7 +37,7 @@ void f0(void) { // rdar://problem/8962770 void test4(void) { - int (^f)(void) = ^((x)) { }; // expected-error {{type specifier missing}} expected-error {{type-id cannot have a name}} + int (^f)(void) = ^((x)) { }; // expected-warning {{type specifier missing}} expected-error {{type-id cannot have a name}} } // rdar://problem/9170609 diff --git a/clang/test/Sema/block-literal.c b/clang/test/Sema/block-literal.c index b760c647f0d19..4cb96fb490926 100644 --- a/clang/test/Sema/block-literal.c +++ b/clang/test/Sema/block-literal.c @@ -41,7 +41,7 @@ void test2(void) { foo: takeblock(^{ x = 4; }); // expected-error {{variable is not assignable (missing __block type specifier)}} - __block y = 7; // expected-error {{type specifier missing, defaults to 'int'}} + __block y = 7; // expected-warning {{type specifier missing, defaults to 'int'}} takeblock(^{ y = 8; }); } diff --git a/clang/test/Sema/builtin-setjmp.c b/clang/test/Sema/builtin-setjmp.c index 5092d1665c193..94cd2652d0ab5 100644 --- a/clang/test/Sema/builtin-setjmp.c +++ b/clang/test/Sema/builtin-setjmp.c @@ -35,10 +35,10 @@ void use(void) { setjmp(0); #if NO_SETJMP // cxx-error@-2 {{undeclared identifier 'setjmp'}} - // c-error@-3 {{call to undeclared function 'setjmp'; ISO C99 and later do not support implicit function declarations}} + // c-warning@-3 {{call to undeclared function 'setjmp'; ISO C99 and later do not support implicit function declarations}} #elif ONLY_JMP_BUF // cxx-error@-5 {{undeclared identifier 'setjmp'}} - // c-error@-6 {{call to undeclared library function 'setjmp' with type 'int (jmp_buf)' (aka 'int (int *)'); ISO C99 and later do not support implicit function declarations}} + // c-warning@-6 {{call to undeclared library function 'setjmp' with type 'int (jmp_buf)' (aka 'int (int *)'); ISO C99 and later do not support implicit function declarations}} // c-note@-7 {{include the header or explicitly provide a declaration for 'setjmp'}} #else // cxx-no-diagnostics diff --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c index 702b40c63767f..b3ef004bec0f4 100644 --- a/clang/test/Sema/builtins.c +++ b/clang/test/Sema/builtins.c @@ -206,9 +206,9 @@ void test18(void) { } void no_ms_builtins(void) { - __assume(1); // expected-error {{call to undeclared function '__assume'; ISO C99 and later do not support implicit function declarations}} - __noop(1); // expected-error {{call to undeclared function '__noop'; ISO C99 and later do not support implicit function declarations}} - __debugbreak(); // expected-error {{call to undeclared function '__debugbreak'; ISO C99 and later do not support implicit function declarations}} + __assume(1); // expected-warning {{call to undeclared function '__assume'; ISO C99 and later do not support implicit function declarations}} + __noop(1); // expected-warning {{call to undeclared function '__noop'; ISO C99 and later do not support implicit function declarations}} + __debugbreak(); // expected-warning {{call to undeclared function '__debugbreak'; ISO C99 and later do not support implicit function declarations}} } void unavailable(void) { diff --git a/clang/test/Sema/crash-invalid-builtin.c b/clang/test/Sema/crash-invalid-builtin.c index 26e5888a9e30e..8f749f7b32bb5 100644 --- a/clang/test/Sema/crash-invalid-builtin.c +++ b/clang/test/Sema/crash-invalid-builtin.c @@ -1,4 +1,4 @@ // RUN: %clang_cc1 -triple=x86_64-apple-darwin -fsyntax-only -verify %s // PR23086 -__builtin_isinf(...); // expected-error {{type specifier missing, defaults to 'int'}} expected-error {{ISO C requires a named parameter before '...'}} // expected-error {{cannot redeclare builtin function '__builtin_isinf'}} // expected-note {{'__builtin_isinf' is a builtin with type 'int ()'}} +__builtin_isinf(...); // expected-warning {{type specifier missing, defaults to 'int'}} expected-error {{ISO C requires a named parameter before '...'}} // expected-error {{cannot redeclare builtin function '__builtin_isinf'}} // expected-note {{'__builtin_isinf' is a builtin with type 'int ()'}} diff --git a/clang/test/Sema/cxx-as-c.c b/clang/test/Sema/cxx-as-c.c index a5d1a4944c956..41d7350d1f15e 100644 --- a/clang/test/Sema/cxx-as-c.c +++ b/clang/test/Sema/cxx-as-c.c @@ -2,7 +2,7 @@ // PR36157 struct Foo { - Foo(int n) : n_(n) {} // expected-error 1+{{}} + Foo(int n) : n_(n) {} // expected-error 1+{{}} expected-warning 1+{{}} private: int n; }; diff --git a/clang/test/Sema/function.c b/clang/test/Sema/function.c index 1143fe8f50d53..43c8a6c8662b3 100644 --- a/clang/test/Sema/function.c +++ b/clang/test/Sema/function.c @@ -18,7 +18,7 @@ void h (const char *fmt, ...) {} // expected-error{{conflicting types for 'h'}} // PR1965 int t5(b); // expected-error {{parameter list without types}} -int t6(int x, g); // expected-error {{type specifier missing, defaults to 'int'}} +int t6(int x, g); // expected-warning {{type specifier missing, defaults to 'int'}} int t7(, ); // expected-error {{expected parameter declarator}} expected-error {{expected parameter declarator}} int t8(, int a); // expected-error {{expected parameter declarator}} @@ -41,8 +41,8 @@ int t14() { } // -y(y) { return y; } // expected-error{{parameter 'y' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}} \ - // expected-error{{type specifier missing, defaults to 'int'}} +y(y) { return y; } // expected-warning{{parameter 'y' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}} \ + // expected-warning{{type specifier missing, defaults to 'int'}} // PR3137, diff --git a/clang/test/Sema/gnu-builtins.c b/clang/test/Sema/gnu-builtins.c new file mode 100644 index 0000000000000..c4da8b39363cd --- /dev/null +++ b/clang/test/Sema/gnu-builtins.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify=gnu -std=gnu17 %s +// RUN: %clang_cc1 -fsyntax-only -verify=gnu -std=gnu2x %s +// RUN: %clang_cc1 -fsyntax-only -verify=std -std=c17 %s +// RUN: %clang_cc1 -fsyntax-only -verify=std -std=c2x %s + +// std-no-diagnostics + +// 'index' is a builtin library function, but only in GNU mode. So this should +// give an error in GNU modes but be okay in non-GNU mode. +// FIXME: the error is correct, but these notes are pretty awful. +int index; // gnu-error {{redefinition of 'index' as different kind of symbol}} \ + gnu-note {{unguarded header; consider using #ifdef guards or #pragma once}} \ + gnu-note {{previous definition is here}} diff --git a/clang/test/Sema/implicit-builtin-decl.c b/clang/test/Sema/implicit-builtin-decl.c index 055ba7e70eb12..a54e652556c36 100644 --- a/clang/test/Sema/implicit-builtin-decl.c +++ b/clang/test/Sema/implicit-builtin-decl.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -Wno-strict-prototypes -verify %s void f() { - int *ptr = malloc(sizeof(int) * 10); // expected-error{{call to undeclared library function 'malloc' with type}} \ + int *ptr = malloc(sizeof(int) * 10); // expected-warning{{call to undeclared library function 'malloc' with type}} \ // expected-note{{include the header or explicitly provide a declaration for 'malloc'}} \ // expected-note{{'malloc' is a builtin with type 'void *}} } @@ -24,7 +24,7 @@ void h() { void f2() { fprintf(0, "foo"); // expected-warning{{declaration of built-in function 'fprintf' requires inclusion of the header }} \ - expected-error {{call to undeclared function 'fprintf'; ISO C99 and later do not support implicit function declarations}} + expected-warning {{call to undeclared function 'fprintf'; ISO C99 and later do not support implicit function declarations}} } // PR2892 diff --git a/clang/test/Sema/implicit-decl.c b/clang/test/Sema/implicit-decl.c index 351f70ea33665..ce26dcd3a122f 100644 --- a/clang/test/Sema/implicit-decl.c +++ b/clang/test/Sema/implicit-decl.c @@ -1,55 +1,60 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only -Werror=implicit-function-declaration -std=c99 -// RUN: %clang_cc1 %s -verify -fsyntax-only -std=c11 +// RUN: %clang_cc1 %s -verify=werror,both -fsyntax-only -Werror=implicit-function-declaration -std=c99 +// RUN: %clang_cc1 %s -verify=expected,both -fsyntax-only -std=c11 // RUN: %clang_cc1 %s -verify=c2x -fsyntax-only -std=c2x /// -Werror-implicit-function-declaration is a deprecated alias used by many projects. -// RUN: %clang_cc1 %s -verify -fsyntax-only -Werror-implicit-function-declaration +// RUN: %clang_cc1 %s -verify=werror,both -fsyntax-only -Werror-implicit-function-declaration // c2x-note@*:* {{'__builtin_va_list' declared here}} typedef int int32_t; typedef unsigned char Boolean; -extern int printf(__const char *__restrict __format, ...); // expected-note{{'printf' declared here}} \ +extern int printf(__const char *__restrict __format, ...); // werror-note{{'printf' declared here}} \ c2x-note {{'printf' declared here}} void func(void) { int32_t *vector[16]; const char compDesc[16 + 1]; int32_t compCount = 0; - if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-error {{call to undeclared function '_CFCalendarDecomposeAbsoluteTimeV'; ISO C99 and later do not support implicit function declarations}} \ - expected-note {{previous implicit declaration}} \ + if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // werror-error {{call to undeclared function '_CFCalendarDecomposeAbsoluteTimeV'; ISO C99 and later do not support implicit function declarations}} \ + both-note {{previous implicit declaration}} \ + expected-warning {{call to undeclared function '_CFCalendarDecomposeAbsoluteTimeV'; ISO C99 and later do not support implicit function declarations}} \ c2x-error {{use of undeclared identifier '_CFCalendarDecomposeAbsoluteTimeV'}} } - printg("Hello, World!\n"); // expected-error{{call to undeclared function 'printg'; ISO C99 and later do not support implicit function declarations}} \ - expected-note{{did you mean 'printf'?}} \ + printg("Hello, World!\n"); // werror-error{{call to undeclared function 'printg'; ISO C99 and later do not support implicit function declarations}} \ + werror-note{{did you mean 'printf'?}} \ + expected-warning{{call to undeclared function 'printg'; ISO C99 and later do not support implicit function declarations}} \ c2x-error {{use of undeclared identifier 'printg'; did you mean 'printf'?}} - __builtin_is_les(1, 3); // expected-error{{use of unknown builtin '__builtin_is_les'}} \ + __builtin_is_les(1, 3); // both-error{{use of unknown builtin '__builtin_is_les'}} \ c2x-error {{unknown type name '__builtin_is_les'; did you mean '__builtin_va_list'?}} \ c2x-error {{expected identifier or '('}} \ c2x-error {{expected ')'}} \ c2x-note {{to match this '('}} } -Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) { // expected-error {{conflicting types}} +Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) { // both-error {{conflicting types}} return 0; } // Test the typo-correction callback in Sema::ImplicitlyDefineFunction -extern int sformatf(char *str, __const char *__restrict __format, ...); // expected-note{{'sformatf' declared here}} +extern int sformatf(char *str, __const char *__restrict __format, ...); // werror-note{{'sformatf' declared here}} void test_implicit(void) { int formats = 0; // c2x-note {{'formats' declared here}} - formatd("Hello, World!\n"); // expected-error{{call to undeclared function 'formatd'; ISO C99 and later do not support implicit function declarations}} \ - expected-note{{did you mean 'sformatf'?}} \ + formatd("Hello, World!\n"); // werror-error{{call to undeclared function 'formatd'; ISO C99 and later do not support implicit function declarations}} \ + werror-note{{did you mean 'sformatf'?}} \ + expected-warning{{call to undeclared function 'formatd'; ISO C99 and later do not support implicit function declarations}} \ c2x-error {{use of undeclared identifier 'formatd'; did you mean 'formats'?}} \ c2x-error {{called object type 'int' is not a function or function pointer}} } void test_suggestion(void) { - bark(); // expected-error {{call to undeclared function 'bark'; ISO C99 and later do not support implicit function declarations}} \ + bark(); // werror-error {{call to undeclared function 'bark'; ISO C99 and later do not support implicit function declarations}} \ + expected-warning {{call to undeclared function 'bark'; ISO C99 and later do not support implicit function declarations}} \ c2x-error {{use of undeclared identifier 'bark'}} - bork(); // expected-error {{call to undeclared function 'bork'; ISO C99 and later do not support implicit function declarations}} \ + bork(); // werror-error {{call to undeclared function 'bork'; ISO C99 and later do not support implicit function declarations}} \ + expected-warning {{call to undeclared function 'bork'; ISO C99 and later do not support implicit function declarations}} \ c2x-error {{use of undeclared identifier 'bork'}} } diff --git a/clang/test/Sema/implicit-int.c b/clang/test/Sema/implicit-int.c index 477cd6977375b..a5578cd0f65b3 100644 --- a/clang/test/Sema/implicit-int.c +++ b/clang/test/Sema/implicit-int.c @@ -4,18 +4,18 @@ */ foo(void) { /* expected-warning {{type specifier missing, defaults to 'int'}} \ - ext-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ + ext-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ unsupported-error {{a type specifier is required for all declarations}} */ return 0; } y; /* expected-warning {{type specifier missing, defaults to 'int'}} \ - ext-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ + ext-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ unsupported-error {{a type specifier is required for all declarations}} */ /* rdar://6131634 */ void f((x)); /* expected-warning {{type specifier missing, defaults to 'int'}} \ - ext-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ + ext-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ unsupported-error {{a type specifier is required for all declarations}} */ /* PR3702 */ @@ -26,18 +26,18 @@ void f((x)); /* expected-warning {{type specifier missing, defaults to 'int'}} #define ILPAD() PAD((NROW - tt.tt_row) * 10) /* 1 ms per char */ void -h19_insline(n) /* ext-error {{parameter 'n' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}} \ +h19_insline(n) /* ext-warning {{parameter 'n' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}} \ unsupported-error {{unknown type name 'n'}} */ { ILPAD(); /* expected-warning {{type specifier missing, defaults to 'int'}} \ - ext-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ + ext-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ unsupported-error {{a type specifier is required for all declarations}} */ } struct foo { __extension__ __attribute__((packed)) x : 4; /* expected-warning {{type specifier missing, defaults to 'int'}} \ - ext-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ + ext-warning {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \ unsupported-error {{unknown type name 'x'}} */ }; diff --git a/clang/test/Sema/implicit-intel-builtin-decl.c b/clang/test/Sema/implicit-intel-builtin-decl.c index e7d17d9f19b9f..1015d9bfe0265 100644 --- a/clang/test/Sema/implicit-intel-builtin-decl.c +++ b/clang/test/Sema/implicit-intel-builtin-decl.c @@ -3,26 +3,26 @@ void f(void) { (void)_mm_getcsr(); // cxx-warning{{implicitly declaring library function '_mm_getcsr'}} \ - c-error{{call to undeclared library function '_mm_getcsr'}} \ + c-warning{{call to undeclared library function '_mm_getcsr'}} \ expected-note{{include the header or explicitly provide a declaration for '_mm_getcsr'}} _mm_setcsr(1); // cxx-warning{{implicitly declaring library function '_mm_setcsr'}} \ - c-error{{call to undeclared library function '_mm_setcsr'}} \ + c-warning{{call to undeclared library function '_mm_setcsr'}} \ expected-note{{include the header or explicitly provide a declaration for '_mm_setcsr'}} _mm_sfence(); // cxx-warning{{implicitly declaring library function '_mm_sfence'}} \ - c-error{{call to undeclared library function '_mm_sfence'}} \ + c-warning{{call to undeclared library function '_mm_sfence'}} \ expected-note{{include the header or explicitly provide a declaration for '_mm_sfence'}} _mm_clflush((void*)0); // cxx-warning{{implicitly declaring library function '_mm_clflush'}} \ - c-error{{call to undeclared library function '_mm_clflush'}} \ + c-warning{{call to undeclared library function '_mm_clflush'}} \ expected-note{{include the header or explicitly provide a declaration for '_mm_clflush'}} _mm_lfence(); // cxx-warning{{implicitly declaring library function '_mm_lfence'}} \ - c-error{{call to undeclared library function '_mm_lfence'}} \ + c-warning{{call to undeclared library function '_mm_lfence'}} \ expected-note{{include the header or explicitly provide a declaration for '_mm_lfence'}} _mm_mfence(); // cxx-warning{{implicitly declaring library function '_mm_mfence'}} \ - c-error{{call to undeclared library function '_mm_mfence'}} \ + c-warning{{call to undeclared library function '_mm_mfence'}} \ expected-note{{include the header or explicitly provide a declaration for '_mm_mfence'}} _mm_pause(); // cxx-warning{{implicitly declaring library function '_mm_pause'}} \ - c-error{{call to undeclared library function '_mm_pause'}} \ + c-warning{{call to undeclared library function '_mm_pause'}} \ expected-note{{include the header or explicitly provide a declaration for '_mm_pause'}} } diff --git a/clang/test/Sema/implicit-ms-builtin-decl.c b/clang/test/Sema/implicit-ms-builtin-decl.c index 1294bb6aa9aab..6bb2f6e3b8e24 100644 --- a/clang/test/Sema/implicit-ms-builtin-decl.c +++ b/clang/test/Sema/implicit-ms-builtin-decl.c @@ -2,9 +2,9 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown -fsyntax-only -verify %s -fms-extensions void f(void) { - (void)_byteswap_ushort(42); // expected-error{{call to undeclared library function '_byteswap_ushort'}} \ + (void)_byteswap_ushort(42); // expected-warning{{call to undeclared library function '_byteswap_ushort'}} \ // expected-note{{include the header or explicitly provide a declaration for '_byteswap_ushort'}} - (void)_byteswap_uint64(42LL); // expected-error{{call to undeclared library function '_byteswap_uint64'}} \ + (void)_byteswap_uint64(42LL); // expected-warning{{call to undeclared library function '_byteswap_uint64'}} \ // expected-note{{include the header or explicitly provide a declaration for '_byteswap_uint64'}} } @@ -21,9 +21,9 @@ void g(void) { #if defined(__x86_64__) void h(void) { - (void)__mulh(21, 2); // expected-error{{call to undeclared library function '__mulh'}} \ + (void)__mulh(21, 2); // expected-warning{{call to undeclared library function '__mulh'}} \ // expected-note{{include the header or explicitly provide a declaration for '__mulh'}} - (void)__umulh(21, 2); // expected-error{{call to undeclared library function '__umulh'}} \ + (void)__umulh(21, 2); // expected-warning{{call to undeclared library function '__umulh'}} \ // expected-note{{include the header or explicitly provide a declaration for '__umulh'}} } @@ -38,7 +38,7 @@ void i(void) { #if defined(i386) void h(void) { - (void)__mulh(21LL, 2LL); // expected-error{{call to undeclared function '__mulh'; ISO C99 and later do not support implicit function declarations}} - (void)__umulh(21ULL, 2ULL); // expected-error{{call to undeclared function '__umulh'; ISO C99 and later do not support implicit function declarations}} + (void)__mulh(21LL, 2LL); // expected-warning{{call to undeclared function '__mulh'; ISO C99 and later do not support implicit function declarations}} + (void)__umulh(21ULL, 2ULL); // expected-warning{{call to undeclared function '__umulh'; ISO C99 and later do not support implicit function declarations}} } #endif diff --git a/clang/test/Sema/invalid-decl.c b/clang/test/Sema/invalid-decl.c index 4f2680074dcd0..ca5fa124e8023 100644 --- a/clang/test/Sema/invalid-decl.c +++ b/clang/test/Sema/invalid-decl.c @@ -6,7 +6,7 @@ void test(void) { // PR2400 -typedef xtype (*x)(void* handle); // expected-error {{function cannot return function type}} expected-error 2{{type specifier missing, defaults to 'int'}} +typedef xtype (*x)(void* handle); // expected-error {{function cannot return function type}} expected-warning 2{{type specifier missing, defaults to 'int'}} typedef void ytype(); diff --git a/clang/test/Sema/invalid-struct-init.c b/clang/test/Sema/invalid-struct-init.c index 72f6bbae12abd..0dd00b55ea21f 100644 --- a/clang/test/Sema/invalid-struct-init.c +++ b/clang/test/Sema/invalid-struct-init.c @@ -3,7 +3,7 @@ typedef struct _zend_module_entry zend_module_entry; struct _zend_module_entry { _efree((p)); // expected-error{{type name requires a specifier or qualifier}} \ - expected-error {{type specifier missing, defaults to 'int'}} + expected-warning {{type specifier missing, defaults to 'int'}} }; typedef struct _zend_function_entry { } zend_function_entry; diff --git a/clang/test/Sema/prototype-redecls.c b/clang/test/Sema/prototype-redecls.c index ed569b5223ce2..49305db10d240 100644 --- a/clang/test/Sema/prototype-redecls.c +++ b/clang/test/Sema/prototype-redecls.c @@ -29,7 +29,7 @@ void garp(x) int x; {} // Ensure redeclarations that conflict with a builtin use a note which makes it // clear that the previous declaration was a builtin. -float rintf() { // expected-error {{conflicting types for 'rintf'}} \ +float rintf() { // expected-warning {{incompatible redeclaration of library function 'rintf'}} \ expected-note {{'rintf' is a builtin with type 'float (float)'}} return 1.0f; } diff --git a/clang/test/Sema/redefinition.c b/clang/test/Sema/redefinition.c index 7e690e1a917d5..28f7f02bb251d 100644 --- a/clang/test/Sema/redefinition.c +++ b/clang/test/Sema/redefinition.c @@ -4,7 +4,7 @@ int f(int); int f(int a) { return 0; } // expected-error {{redefinition of 'f'}} // -int foo(x) { // expected-error {{parameter 'x' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}} +int foo(x) { // expected-warning {{parameter 'x' was not declared, defaults to 'int'; ISO C99 and later do not support implicit int}} return 0; } int x = 1; diff --git a/clang/test/Sema/sizeless-1.c b/clang/test/Sema/sizeless-1.c index 5e7e3be772e8c..64af214d206b9 100644 --- a/clang/test/Sema/sizeless-1.c +++ b/clang/test/Sema/sizeless-1.c @@ -187,10 +187,8 @@ void func(int sel) { global_int8_ptr -= 1; // expected-error {{arithmetic on a pointer to sizeless type}} global_int8_ptr - global_int8_ptr; // expected-error {{arithmetic on a pointer to sizeless type}} - +init_int8; // expected-error {{invalid argument type 'svint8_t'}} ++init_int8; // expected-error {{cannot increment value of type 'svint8_t'}} init_int8++; // expected-error {{cannot increment value of type 'svint8_t'}} - -init_int8; // expected-error {{invalid argument type 'svint8_t'}} --init_int8; // expected-error {{cannot decrement value of type 'svint8_t'}} init_int8--; // expected-error {{cannot decrement value of type 'svint8_t'}} !init_int8; // expected-error {{invalid argument type 'svint8_t'}} diff --git a/clang/test/Sema/typo-correction.c b/clang/test/Sema/typo-correction.c index ceab0e2634c5c..4048488528d43 100644 --- a/clang/test/Sema/typo-correction.c +++ b/clang/test/Sema/typo-correction.c @@ -10,11 +10,11 @@ void PR21656(void) { x = (float)arst; // expected-error-re {{use of undeclared identifier 'arst'{{$}}}} } -a = b ? : 0; // expected-error {{type specifier missing, defaults to 'int'}} \ +a = b ? : 0; // expected-warning {{type specifier missing, defaults to 'int'}} \ // expected-error {{use of undeclared identifier 'b'}} int foobar; // expected-note {{'foobar' declared here}} -new_a = goobar ?: 4; // expected-error {{type specifier missing, defaults to 'int'}} \ +new_a = goobar ?: 4; // expected-warning {{type specifier missing, defaults to 'int'}} \ // expected-error {{use of undeclared identifier 'goobar'; did you mean 'foobar'?}} \ // expected-error {{initializer element is not a compile-time constant}} @@ -37,7 +37,7 @@ int c11Generic(int arg) { typedef long long __m128i __attribute__((__vector_size__(16))); int PR23101(__m128i __x) { - return foo((__v2di)__x); // expected-error {{call to undeclared function 'foo'; ISO C99 and later do not support implicit function declarations}} \ + return foo((__v2di)__x); // expected-warning {{call to undeclared function 'foo'; ISO C99 and later do not support implicit function declarations}} \ // expected-error {{use of undeclared identifier '__v2di'}} } diff --git a/clang/test/Sema/varargs.c b/clang/test/Sema/varargs.c index 2cb7270f604a0..ebab2c9cd8b50 100644 --- a/clang/test/Sema/varargs.c +++ b/clang/test/Sema/varargs.c @@ -114,7 +114,7 @@ void f13(enum E1 e, ...) { } void f14(int e, ...) { - // expected-error@+3 {{call to undeclared library function 'va_start'}} + // expected-warning@+3 {{call to undeclared library function 'va_start'}} // expected-note@+2 {{include the header }} // expected-error@+1 {{too few arguments to function call}} va_start(); diff --git a/clang/test/Sema/vector-decl-crash.c b/clang/test/Sema/vector-decl-crash.c index 5e4b098fee2d3..fafe34133de43 100644 --- a/clang/test/Sema/vector-decl-crash.c +++ b/clang/test/Sema/vector-decl-crash.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fsyntax-only -verify -triple x86_64-unknown-unknown +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple riscv64-unknown-unknown // GH50171 // This would previously crash when __bf16 was not a supported type. diff --git a/clang/test/Sema/vla.c b/clang/test/Sema/vla.c index c6d61aac4515f..73e24e90beea1 100644 --- a/clang/test/Sema/vla.c +++ b/clang/test/Sema/vla.c @@ -72,7 +72,7 @@ int TransformBug(int a) { // PR36157 struct { int a[ // expected-error {{variable length array in struct}} - implicitly_declared() // expected-error {{call to undeclared function 'implicitly_declared'; ISO C99 and later do not support implicit function declarations}} + implicitly_declared() // expected-warning {{call to undeclared function 'implicitly_declared'; ISO C99 and later do not support implicit function declarations}} ]; }; int (*use_implicitly_declared)(void) = implicitly_declared; // ok, was implicitly declared at file scope diff --git a/clang/test/SemaCXX/class-layout.cpp b/clang/test/SemaCXX/class-layout.cpp index f81e526d0e2ad..5403bd6e6a6f6 100644 --- a/clang/test/SemaCXX/class-layout.cpp +++ b/clang/test/SemaCXX/class-layout.cpp @@ -1,10 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base // RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=14 -// RUN: %clang_cc1 -triple x86_64-scei-ps4 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6 -// RUN: %clang_cc1 -triple x86_64-sie-ps5 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6 // RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6 -// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14 // expected-no-diagnostics #define SA(n, p) int a##n[(p) ? 1 : -1] @@ -608,37 +604,3 @@ namespace PR37275 { #endif #pragma pack(pop) } - -namespace non_pod { -struct t1 { -protected: - int a; -}; -// GCC prints warning: ignoring packed attribute because of unpacked non-POD field 't1 t2::v1'` -struct t2 { - char c1; - short s1; - char c2; - t1 v1; -} __attribute__((packed)); -#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 14 -_Static_assert(_Alignof(t1) == 4, ""); -_Static_assert(_Alignof(t2) == 1, ""); -#else -_Static_assert(_Alignof(t1) == 4, ""); -_Static_assert(_Alignof(t2) == 4, ""); -#endif -_Static_assert(sizeof(t2) == 8, ""); // it's still packing the rest of the struct -} // namespace non_pod - -namespace non_pod_packed { -struct t1 { -protected: - int a; -} __attribute__((packed)); -struct t2 { - t1 v1; -} __attribute__((packed)); -_Static_assert(_Alignof(t1) == 1, ""); -_Static_assert(_Alignof(t2) == 1, ""); -} // namespace non_pod_packed diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index df2a9925c0154..c6f3e27346a10 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -766,3 +766,72 @@ void test() { static_assert(c == 8); } } + +// https://github.com/llvm/llvm-project/issues/51695 +namespace GH51695 { +// Original ======================================== +template +struct type_t {}; + +template +struct list_t {}; + +template +consteval auto pop_front(list_t) -> auto { + return list_t{}; +} + +template +consteval auto apply(list_t, F fn) -> auto { + return fn(type_t{}...); +} + +void test1() { + constexpr auto x = apply(pop_front(list_t{}), + [](type_t...) { return 42; }); + static_assert(x == 42); +} +// Reduced 1 ======================================== +consteval bool zero() { return false; } + +template +consteval bool foo(bool, F f) { + return f(); +} + +void test2() { + constexpr auto x = foo(zero(), []() { return true; }); + static_assert(x); +} + +// Reduced 2 ======================================== +template +consteval auto bar(F f) { return f;} + +void test3() { + constexpr auto t1 = bar(bar(bar(bar([]() { return true; }))))(); + static_assert(t1); + + int a = 1; // expected-note {{declared here}} + auto t2 = bar(bar(bar(bar([=]() { return a; }))))(); // expected-error-re {{call to consteval function 'GH51695::bar<(lambda at {{.*}})>' is not a constant expression}} + // expected-note@-1 {{read of non-const variable 'a' is not allowed in a constant expression}} + + constexpr auto t3 = bar(bar([x=bar(42)]() { return x; }))(); + static_assert(t3==42); + constexpr auto t4 = bar(bar([x=bar(42)]() consteval { return x; }))(); + static_assert(t4==42); +} + +} // namespace GH51695 + +// https://github.com/llvm/llvm-project/issues/50455 +namespace GH50455 { +void f() { + []() consteval { int i{}; }(); + []() consteval { int i{}; ++i; }(); +} +void g() { + (void)[](int i) consteval { return i; }(0); + (void)[](int i) consteval { return i; }(0); +} +} // namespace GH50455 diff --git a/clang/test/SemaCXX/deprecated-builtins.cpp b/clang/test/SemaCXX/deprecated-builtins.cpp index 2bb687c1ef129..849b9b014fff2 100644 --- a/clang/test/SemaCXX/deprecated-builtins.cpp +++ b/clang/test/SemaCXX/deprecated-builtins.cpp @@ -11,7 +11,7 @@ void f() { a = __has_nothrow_constructor(A); // expected-warning-re {{__has_nothrow_constructor {{.*}} use __is_nothrow_constructible}} a = __has_trivial_assign(A); // expected-warning-re {{__has_trivial_assign {{.*}} use __is_trivially_assignable}} a = __has_trivial_move_assign(A); // expected-warning-re {{__has_trivial_move_assign {{.*}} use __is_trivially_assignable}} - a = __has_trivial_copy(A); // expected-warning-re {{__has_trivial_copy {{.*}} use __is_trivially_constructible}} + a = __has_trivial_copy(A); // expected-warning-re {{__has_trivial_copy {{.*}} use __is_trivially_copyable}} a = __has_trivial_constructor(A); // expected-warning-re {{__has_trivial_constructor {{.*}} use __is_trivially_constructible}} a = __has_trivial_move_constructor(A); // expected-warning-re {{__has_trivial_move_constructor {{.*}} use __is_trivially_constructible}} a = __has_trivial_destructor(A); // expected-warning-re {{__has_trivial_destructor {{.*}} use __is_trivially_destructible}} diff --git a/clang/test/SemaCXX/sizeless-1.cpp b/clang/test/SemaCXX/sizeless-1.cpp index 80e74db49c0f4..6c8c873f494f7 100644 --- a/clang/test/SemaCXX/sizeless-1.cpp +++ b/clang/test/SemaCXX/sizeless-1.cpp @@ -199,10 +199,8 @@ void func(int sel) { global_int8_ptr -= 1; // expected-error {{arithmetic on a pointer to sizeless type}} global_int8_ptr - global_int8_ptr; // expected-error {{arithmetic on a pointer to sizeless type}} - +init_int8; // expected-error {{invalid argument type 'svint8_t'}} ++init_int8; // expected-error {{cannot increment value of type 'svint8_t'}} init_int8++; // expected-error {{cannot increment value of type 'svint8_t'}} - -init_int8; // expected-error {{invalid argument type 'svint8_t'}} --init_int8; // expected-error {{cannot decrement value of type 'svint8_t'}} init_int8--; // expected-error {{cannot decrement value of type 'svint8_t'}} !init_int8; // expected-error {{invalid argument type 'svint8_t'}} diff --git a/clang/test/SemaCXX/specialization-diagnose-crash.cpp b/clang/test/SemaCXX/specialization-diagnose-crash.cpp new file mode 100644 index 0000000000000..5fd387cab19d9 --- /dev/null +++ b/clang/test/SemaCXX/specialization-diagnose-crash.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only %s --std=c++17 -verify +// This is a reduction of GH57370 and GH58028, originally appearing +// in libstdc++'s variant code. + +struct V1 {}; +struct V2 : V1 { + int &a; +}; + +template using void_t = void; + +template struct X { T x; }; + +template struct Variant { + Variant() = delete; // expected-note {{deleted here}} +}; + +template +struct Variant{T1()})>> {}; + +void f() { + Variant(); + Variant(); // expected-error {{call to deleted constructor}} +} diff --git a/clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp b/clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp new file mode 100644 index 0000000000000..6d1b29e785c31 --- /dev/null +++ b/clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify +// expected-no-diagnostics + +// Reported by: https://github.com/llvm/llvm-project/issues/57013 +// The following code should not crash clang +struct X { + char arr[2]; + constexpr X() {} + constexpr void modify() { + arr[0] = 0; + } +}; +constexpr X f(X t) { + t.modify(); + return t; +} +auto x = f(X()); diff --git a/clang/test/SemaObjC/builtin_objc_lib_functions.m b/clang/test/SemaObjC/builtin_objc_lib_functions.m index 211c472464608..bda2f62678c06 100644 --- a/clang/test/SemaObjC/builtin_objc_lib_functions.m +++ b/clang/test/SemaObjC/builtin_objc_lib_functions.m @@ -1,29 +1,29 @@ // RUN: %clang_cc1 -x objective-c %s -fsyntax-only -verify // rdar://8592641 -Class f0(void) { return objc_getClass("a"); } // expected-error {{call to undeclared library function 'objc_getClass' with type 'id (const char *)'}} \ +Class f0(void) { return objc_getClass("a"); } // expected-warning {{call to undeclared library function 'objc_getClass' with type 'id (const char *)'}} \ // expected-note {{include the header or explicitly provide a declaration for 'objc_getClass'}} // rdar://8735023 -Class f1(void) { return objc_getMetaClass("a"); } // expected-error {{call to undeclared library function 'objc_getMetaClass' with type 'id (const char *)'}} \ +Class f1(void) { return objc_getMetaClass("a"); } // expected-warning {{call to undeclared library function 'objc_getMetaClass' with type 'id (const char *)'}} \ // expected-note {{include the header or explicitly provide a declaration for 'objc_getMetaClass'}} -void f2(id val) { objc_enumerationMutation(val); } // expected-error {{call to undeclared library function 'objc_enumerationMutation' with type 'void (id)'}} \ +void f2(id val) { objc_enumerationMutation(val); } // expected-warning {{call to undeclared library function 'objc_enumerationMutation' with type 'void (id)'}} \ // expected-note {{include the header or explicitly provide a declaration for 'objc_enumerationMutation'}} -long double f3(id self, SEL op) { return objc_msgSend_fpret(self, op); } // expected-error {{call to undeclared library function 'objc_msgSend_fpret' with type 'long double (id, SEL, ...)'}} \ +long double f3(id self, SEL op) { return objc_msgSend_fpret(self, op); } // expected-warning {{call to undeclared library function 'objc_msgSend_fpret' with type 'long double (id, SEL, ...)'}} \ // expected-note {{include the header or explicitly provide a declaration for 'objc_msgSend_fpret'}} id f4(struct objc_super *super, SEL op) { // expected-warning {{declaration of 'struct objc_super' will not be visible outside of this function}} - return objc_msgSendSuper(super, op); // expected-error {{call to undeclared library function 'objc_msgSendSuper' with type 'id (struct objc_super *, SEL, ...)'}} \ + return objc_msgSendSuper(super, op); // expected-warning {{call to undeclared library function 'objc_msgSendSuper' with type 'id (struct objc_super *, SEL, ...)'}} \ // expected-note {{include the header or explicitly provide a declaration for 'objc_msgSendSuper'}} } id f5(id val, id *dest) { - return objc_assign_strongCast(val, dest); // expected-error {{call to undeclared library function 'objc_assign_strongCast' with type 'id (id, id *)'}} \ + return objc_assign_strongCast(val, dest); // expected-warning {{call to undeclared library function 'objc_assign_strongCast' with type 'id (id, id *)'}} \ // expected-note {{include the header or explicitly provide a declaration for 'objc_assign_strongCast'}} } int f6(Class exceptionClass, id exception) { - return objc_exception_match(exceptionClass, exception); // expected-error {{call to undeclared library function 'objc_exception_match' with type 'int (id, id)'}} \ + return objc_exception_match(exceptionClass, exception); // expected-warning {{call to undeclared library function 'objc_exception_match' with type 'int (id, id)'}} \ // expected-note {{include the header or explicitly provide a declaration for 'objc_exception_match'}} } diff --git a/clang/test/SemaObjC/builtin_objc_nslog.m b/clang/test/SemaObjC/builtin_objc_nslog.m index 3c35a02d9b8a3..ad7873fe1d47d 100644 --- a/clang/test/SemaObjC/builtin_objc_nslog.m +++ b/clang/test/SemaObjC/builtin_objc_nslog.m @@ -3,11 +3,11 @@ #include void f1(id arg) { - NSLog(@"%@", arg); // expected-error {{call to undeclared library function 'NSLog' with type 'void (id, ...)'}} \ + NSLog(@"%@", arg); // expected-warning {{call to undeclared library function 'NSLog' with type 'void (id, ...)'}} \ // expected-note {{include the header or explicitly provide a declaration for 'NSLog'}} } void f2(id str, va_list args) { - NSLogv(@"%@", args); // expected-error {{call to undeclared library function 'NSLogv' with type }} \ + NSLogv(@"%@", args); // expected-warning {{call to undeclared library function 'NSLogv' with type }} \ // expected-note {{include the header or explicitly provide a declaration for 'NSLogv'}} } diff --git a/clang/test/SemaObjC/ivar-lookup-resolution-builtin.m b/clang/test/SemaObjC/ivar-lookup-resolution-builtin.m index 09d69aca9f93b..bbb1b4f6a168a 100644 --- a/clang/test/SemaObjC/ivar-lookup-resolution-builtin.m +++ b/clang/test/SemaObjC/ivar-lookup-resolution-builtin.m @@ -28,7 +28,7 @@ + (int) ClassMethod; @implementation Test1 - (int) InstMethod { - return index; // expected-error {{call to undeclared library function 'index'}} \ + return index; // expected-warning {{call to undeclared library function 'index'}} \ // expected-note {{include the header or explicitly provide a declaration for 'index'}} \ // expected-error {{incompatible pointer to integer conversion returning}} } diff --git a/clang/test/SemaObjC/protocols.m b/clang/test/SemaObjC/protocols.m index ebb9b634b4b61..eb27341007691 100644 --- a/clang/test/SemaObjC/protocols.m +++ b/clang/test/SemaObjC/protocols.m @@ -62,6 +62,6 @@ @protocol B < A > // expected-error{{protocol has circular dependency}} @end @protocol P -- (int)test:(int)param, ..; // expected-error{{type specifier missing}} \ +- (int)test:(int)param, ..; // expected-warning{{type specifier missing}} \ // expected-error{{expected ';' after method prototype}} @end diff --git a/clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl b/clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl index 2ea6d3bc4862d..9e2869af87b4e 100644 --- a/clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl +++ b/clang/test/SemaOpenCL/invalid-pipes-cl1.2.cl @@ -10,7 +10,7 @@ void foo(read_only pipe int p); // expected-error@-5 {{C++ for OpenCL version 2021 does not support the 'pipe' type qualifier}} // expected-error@-6 {{access qualifier can only be used for pipe and image type}} #else -// expected-error@-8 {{type specifier missing, defaults to 'int'}} +// expected-warning@-8 {{type specifier missing, defaults to 'int'}} // expected-error@-9 {{access qualifier can only be used for pipe and image type}} // expected-error@-10 {{expected ')'}} expected-note@-10 {{to match this '('}} #endif diff --git a/clang/test/Unit/lit.cfg.py b/clang/test/Unit/lit.cfg.py index 1aa3abc13d7d1..39d78af19cac0 100644 --- a/clang/test/Unit/lit.cfg.py +++ b/clang/test/Unit/lit.cfg.py @@ -45,7 +45,7 @@ config.environment[var] = os.environ[var] def find_shlibpath_var(): - if platform.system() in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS']: + if platform.system() in ['Linux', 'FreeBSD', 'NetBSD', 'OpenBSD', 'SunOS']: yield 'LD_LIBRARY_PATH' elif platform.system() == 'Darwin': yield 'DYLD_LIBRARY_PATH' diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt index 8d95d0900e8c4..c6b3b44a76334 100644 --- a/clang/tools/libclang/CMakeLists.txt +++ b/clang/tools/libclang/CMakeLists.txt @@ -1,3 +1,25 @@ +# The SOVERSION should be updated only if a change is made to the libclang +# ABI, and when it is updated, it should be updated to the current +# LLVM_VERSION_MAJOR. +# Please also see clang/tools/libclang/libclang.map + +# This option defaults to CLANG_FORCE_MATCHING_LIBCLANG_SOVERSION +# to ON - which means that it by default matches CLANG_VERSION_MAJOR +# +# TODO: This should probably not be a option going forward but we +# we should commit to a way to do it. But due to getting this out +# in LLVM 15.x we opted for a option. +if(NOT CLANG_FORCE_MATCHING_LIBCLANG_SOVERSION) + set(LIBCLANG_SOVERSION 13) +else() + set(LIBCLANG_SOVERSION ${CLANG_VERSION_MAJOR}) +endif() + +# TODO: harmonize usage of LIBCLANG_SOVERSION / LIBCLANG_LIBARY_VERSION +# below; this was added under time-pressure to avoid reverting the +# better default from LLVM 14 for LLVM 15.0.0-rc3, hence no time +# to clean up previous inconsistencies. + set(SOURCES ARCMigrate.cpp BuildSystem.cpp @@ -64,7 +86,8 @@ endif () option(LIBCLANG_BUILD_STATIC "Build libclang as a static library (in addition to a shared one)" OFF) -set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/libclang.exports) +set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_BINARY_DIR}/libclang-generic.exports) +set(LIBCLANG_VERSION_SCRIPT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/libclang.map) if(MSVC) # Avoid LNK4197 by not specifying libclang.exports here. @@ -73,6 +96,20 @@ if(MSVC) set(LLVM_EXPORTED_SYMBOL_FILE) endif() +if (UNIX AND NOT APPLE) + set(LLVM_EXPORTED_SYMBOL_FILE) + set(USE_VERSION_SCRIPT ${LLVM_HAVE_LINK_VERSION_SCRIPT}) +endif() + +if (LLVM_EXPORTED_SYMBOL_FILE) + add_custom_command(OUTPUT ${LLVM_EXPORTED_SYMBOL_FILE} + COMMAND "${Python3_EXECUTABLE}" + ARGS ${CMAKE_CURRENT_SOURCE_DIR}/linker-script-to-export-list.py + ${LIBCLANG_VERSION_SCRIPT_FILE} + ${LLVM_EXPORTED_SYMBOL_FILE} + DEPENDS ${LIBCLANG_VERSION_SCRIPT_FILE}) +endif() + if(LLVM_ENABLE_PIC OR (WIN32 AND NOT LIBCLANG_BUILD_STATIC)) set(ENABLE_SHARED SHARED) endif() @@ -145,6 +182,21 @@ if(ENABLE_SHARED) ) endif() endif() + if (USE_VERSION_SCRIPT) + target_link_options(libclang PRIVATE "-Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/libclang.map") + # The Solaris 11.4 linker supports a subset of GNU ld version scripts, + # but requires a special option to enable it. + if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + target_link_options(libclang PRIVATE "-Wl,-z,gnu-version-script-compat") + endif() + # Ensure that libclang.so gets rebuilt when the linker script changes. + set_property(SOURCE ARCMigrate.cpp APPEND PROPERTY + OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libclang.map) + + set_target_properties(libclang PROPERTIES + VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}${LLVM_VERSION_SUFFIX} + SOVERSION ${LIBCLANG_SOVERSION}) + endif() endif() if(INTERNAL_INSTALL_PREFIX) diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports deleted file mode 100644 index 639d13d21d6d3..0000000000000 --- a/clang/tools/libclang/libclang.exports +++ /dev/null @@ -1,395 +0,0 @@ -clang_BlockCommandComment_getArgText -clang_BlockCommandComment_getCommandName -clang_BlockCommandComment_getNumArgs -clang_BlockCommandComment_getParagraph -clang_CXCursorSet_contains -clang_CXCursorSet_insert -clang_CXIndex_getGlobalOptions -clang_CXIndex_setGlobalOptions -clang_CXIndex_setInvocationEmissionPathOption -clang_CXRewriter_create -clang_CXRewriter_dispose -clang_CXRewriter_insertTextBefore -clang_CXRewriter_overwriteChangedFiles -clang_CXRewriter_removeText -clang_CXRewriter_replaceText -clang_CXRewriter_writeMainFileToStdOut -clang_CXXConstructor_isConvertingConstructor -clang_CXXConstructor_isCopyConstructor -clang_CXXConstructor_isDefaultConstructor -clang_CXXConstructor_isMoveConstructor -clang_CXXField_isMutable -clang_CXXMethod_isConst -clang_CXXMethod_isDefaulted -clang_CXXMethod_isPureVirtual -clang_CXXMethod_isStatic -clang_CXXMethod_isVirtual -clang_CXXRecord_isAbstract -clang_Comment_getChild -clang_Comment_getKind -clang_Comment_getNumChildren -clang_Comment_isWhitespace -clang_CompilationDatabase_dispose -clang_CompilationDatabase_fromDirectory -clang_CompilationDatabase_getAllCompileCommands -clang_CompilationDatabase_getCompileCommands -clang_CompileCommand_getArg -clang_CompileCommand_getDirectory -clang_CompileCommand_getFilename -clang_CompileCommand_getMappedSourceContent -clang_CompileCommand_getMappedSourcePath -clang_CompileCommand_getNumArgs -clang_CompileCommand_getNumMappedSources -clang_CompileCommands_dispose -clang_CompileCommands_getCommand -clang_CompileCommands_getSize -clang_Cursor_Evaluate -clang_Cursor_getArgument -clang_Cursor_getBriefCommentText -clang_Cursor_getCXXManglings -clang_Cursor_getCommentRange -clang_Cursor_getMangling -clang_Cursor_getModule -clang_Cursor_getNumArguments -clang_Cursor_getNumTemplateArguments -clang_Cursor_getObjCDeclQualifiers -clang_Cursor_getObjCManglings -clang_Cursor_getObjCPropertyAttributes -clang_Cursor_getObjCPropertyGetterName -clang_Cursor_getObjCPropertySetterName -clang_Cursor_getObjCSelectorIndex -clang_Cursor_getOffsetOfField -clang_Cursor_getParsedComment -clang_Cursor_getRawCommentText -clang_Cursor_getReceiverType -clang_Cursor_getSpellingNameRange -clang_Cursor_getStorageClass -clang_Cursor_getTemplateArgumentKind -clang_Cursor_getTemplateArgumentType -clang_Cursor_getTemplateArgumentUnsignedValue -clang_Cursor_getTemplateArgumentValue -clang_Cursor_getTranslationUnit -clang_Cursor_getVarDeclInitializer -clang_Cursor_hasAttrs -clang_Cursor_hasVarDeclExternalStorage -clang_Cursor_hasVarDeclGlobalStorage -clang_Cursor_isAnonymous -clang_Cursor_isAnonymousRecordDecl -clang_Cursor_isBitField -clang_Cursor_isDynamicCall -clang_Cursor_isExternalSymbol -clang_Cursor_isFunctionInlined -clang_Cursor_isInlineNamespace -clang_Cursor_isMacroBuiltin -clang_Cursor_isMacroFunctionLike -clang_Cursor_isNull -clang_Cursor_isObjCOptional -clang_Cursor_isVariadic -clang_EnumDecl_isScoped -clang_EvalResult_dispose -clang_EvalResult_getAsDouble -clang_EvalResult_getAsInt -clang_EvalResult_getAsLongLong -clang_EvalResult_getAsStr -clang_EvalResult_getAsUnsigned -clang_EvalResult_getKind -clang_EvalResult_isUnsignedInt -clang_File_isEqual -clang_File_tryGetRealPathName -clang_FullComment_getAsHTML -clang_FullComment_getAsXML -clang_HTMLStartTagComment_isSelfClosing -clang_HTMLStartTag_getAttrName -clang_HTMLStartTag_getAttrValue -clang_HTMLStartTag_getNumAttrs -clang_HTMLTagComment_getAsString -clang_HTMLTagComment_getTagName -clang_IndexAction_create -clang_IndexAction_dispose -clang_InlineCommandComment_getArgText -clang_InlineCommandComment_getCommandName -clang_InlineCommandComment_getNumArgs -clang_InlineCommandComment_getRenderKind -clang_InlineContentComment_hasTrailingNewline -clang_Location_isFromMainFile -clang_Location_isInSystemHeader -clang_ModuleMapDescriptor_create -clang_ModuleMapDescriptor_dispose -clang_ModuleMapDescriptor_setFrameworkModuleName -clang_ModuleMapDescriptor_setUmbrellaHeader -clang_ModuleMapDescriptor_writeToBuffer -clang_Module_getASTFile -clang_Module_getFullName -clang_Module_getName -clang_Module_getNumTopLevelHeaders -clang_Module_getParent -clang_Module_getTopLevelHeader -clang_Module_isSystem -clang_ParamCommandComment_getDirection -clang_ParamCommandComment_getParamIndex -clang_ParamCommandComment_getParamName -clang_ParamCommandComment_isDirectionExplicit -clang_ParamCommandComment_isParamIndexValid -clang_PrintingPolicy_dispose -clang_PrintingPolicy_getProperty -clang_PrintingPolicy_setProperty -clang_Range_isNull -clang_TParamCommandComment_getDepth -clang_TParamCommandComment_getIndex -clang_TParamCommandComment_getParamName -clang_TParamCommandComment_isParamPositionValid -clang_TargetInfo_dispose -clang_TargetInfo_getPointerWidth -clang_TargetInfo_getTriple -clang_TextComment_getText -clang_Type_getAlignOf -clang_Type_getCXXRefQualifier -clang_Type_getClassType -clang_Type_getModifiedType -clang_Type_getNamedType -clang_Type_getNullability -clang_Type_getNumObjCProtocolRefs -clang_Type_getNumObjCTypeArgs -clang_Type_getNumTemplateArguments -clang_Type_getObjCEncoding -clang_Type_getObjCObjectBaseType -clang_Type_getObjCProtocolDecl -clang_Type_getObjCTypeArg -clang_Type_getOffsetOf -clang_Type_getSizeOf -clang_Type_getTemplateArgumentAsType -clang_Type_getValueType -clang_Type_isTransparentTagTypedef -clang_Type_visitFields -clang_VerbatimBlockLineComment_getText -clang_VerbatimLineComment_getText -clang_VirtualFileOverlay_addFileMapping -clang_VirtualFileOverlay_create -clang_VirtualFileOverlay_dispose -clang_VirtualFileOverlay_setCaseSensitivity -clang_VirtualFileOverlay_writeToBuffer -clang_annotateTokens -clang_codeCompleteAt -clang_codeCompleteGetContainerKind -clang_codeCompleteGetContainerUSR -clang_codeCompleteGetContexts -clang_codeCompleteGetDiagnostic -clang_codeCompleteGetNumDiagnostics -clang_codeCompleteGetObjCSelector -clang_constructUSR_ObjCCategory -clang_constructUSR_ObjCClass -clang_constructUSR_ObjCIvar -clang_constructUSR_ObjCMethod -clang_constructUSR_ObjCProperty -clang_constructUSR_ObjCProtocol -clang_createCXCursorSet -clang_createIndex -clang_createTranslationUnit -clang_createTranslationUnit2 -clang_createTranslationUnitFromSourceFile -clang_defaultCodeCompleteOptions -clang_defaultDiagnosticDisplayOptions -clang_defaultEditingTranslationUnitOptions -clang_defaultReparseOptions -clang_defaultSaveOptions -clang_disposeCXCursorSet -clang_disposeCXPlatformAvailability -clang_disposeCXTUResourceUsage -clang_disposeCodeCompleteResults -clang_disposeDiagnostic -clang_disposeDiagnosticSet -clang_disposeIndex -clang_disposeOverriddenCursors -clang_disposeSourceRangeList -clang_disposeString -clang_disposeStringSet -clang_disposeTokens -clang_disposeTranslationUnit -clang_enableStackTraces -clang_equalCursors -clang_equalLocations -clang_equalRanges -clang_equalTypes -clang_executeOnThread -clang_findIncludesInFile -clang_findIncludesInFileWithBlock -clang_findReferencesInFile -clang_findReferencesInFileWithBlock -clang_formatDiagnostic -clang_free -clang_getAddressSpace -clang_getAllSkippedRanges -clang_getArgType -clang_getArrayElementType -clang_getArraySize -clang_getBuildSessionTimestamp -clang_getCString -clang_getCXTUResourceUsage -clang_getCXXAccessSpecifier -clang_getCanonicalCursor -clang_getCanonicalType -clang_getChildDiagnostics -clang_getClangVersion -clang_getCompletionAnnotation -clang_getCompletionAvailability -clang_getCompletionBriefComment -clang_getCompletionChunkCompletionString -clang_getCompletionChunkKind -clang_getCompletionChunkText -clang_getCompletionFixIt -clang_getCompletionNumAnnotations -clang_getCompletionNumFixIts -clang_getCompletionParent -clang_getCompletionPriority -clang_getCursor -clang_getCursorAvailability -clang_getCursorCompletionString -clang_getCursorDefinition -clang_getCursorDisplayName -clang_getCursorExceptionSpecificationType -clang_getCursorExtent -clang_getCursorKind -clang_getCursorKindSpelling -clang_getCursorLanguage -clang_getCursorLexicalParent -clang_getCursorLinkage -clang_getCursorLocation -clang_getCursorPlatformAvailability -clang_getCursorPrettyPrinted -clang_getCursorPrintingPolicy -clang_getCursorReferenceNameRange -clang_getCursorReferenced -clang_getCursorResultType -clang_getCursorSemanticParent -clang_getCursorSpelling -clang_getCursorTLSKind -clang_getCursorType -clang_getCursorUSR -clang_getCursorVisibility -clang_getDeclObjCTypeEncoding -clang_getDefinitionSpellingAndExtent -clang_getDiagnostic -clang_getDiagnosticCategory -clang_getDiagnosticCategoryName -clang_getDiagnosticCategoryText -clang_getDiagnosticFixIt -clang_getDiagnosticInSet -clang_getDiagnosticLocation -clang_getDiagnosticNumFixIts -clang_getDiagnosticNumRanges -clang_getDiagnosticOption -clang_getDiagnosticRange -clang_getDiagnosticSetFromTU -clang_getDiagnosticSeverity -clang_getDiagnosticSpelling -clang_getElementType -clang_getEnumConstantDeclUnsignedValue -clang_getEnumConstantDeclValue -clang_getEnumDeclIntegerType -clang_getExceptionSpecificationType -clang_getExpansionLocation -clang_getFieldDeclBitWidth -clang_getFile -clang_getFileContents -clang_getFileLocation -clang_getFileName -clang_getFileTime -clang_getFileUniqueID -clang_getFunctionTypeCallingConv -clang_getIBOutletCollectionType -clang_getIncludedFile -clang_getInclusions -clang_getInstantiationLocation -clang_getLocation -clang_getLocationForOffset -clang_getModuleForFile -clang_getNullCursor -clang_getNullLocation -clang_getNullRange -clang_getNumArgTypes -clang_getNumCompletionChunks -clang_getNumDiagnostics -clang_getNumDiagnosticsInSet -clang_getNumElements -clang_getNumOverloadedDecls -clang_getOverloadedDecl -clang_getOverriddenCursors -clang_getPointeeType -clang_getPresumedLocation -clang_getRange -clang_getRangeEnd -clang_getRangeStart -clang_getRemappings -clang_getRemappingsFromFileList -clang_getResultType -clang_getSkippedRanges -clang_getSpecializedCursorTemplate -clang_getSpellingLocation -clang_getTUResourceUsageName -clang_getTemplateCursorKind -clang_getToken -clang_getTokenExtent -clang_getTokenKind -clang_getTokenLocation -clang_getTokenSpelling -clang_getTranslationUnitCursor -clang_getTranslationUnitSpelling -clang_getTranslationUnitTargetInfo -clang_getTypeDeclaration -clang_getTypeKindSpelling -clang_getTypeSpelling -clang_getTypedefDeclUnderlyingType -clang_getTypedefName -clang_hashCursor -clang_indexLoc_getCXSourceLocation -clang_indexLoc_getFileLocation -clang_indexSourceFile -clang_indexSourceFileFullArgv -clang_indexTranslationUnit -clang_index_getCXXClassDeclInfo -clang_index_getClientContainer -clang_index_getClientEntity -clang_index_getIBOutletCollectionAttrInfo -clang_index_getObjCCategoryDeclInfo -clang_index_getObjCContainerDeclInfo -clang_index_getObjCInterfaceDeclInfo -clang_index_getObjCPropertyDeclInfo -clang_index_getObjCProtocolRefListInfo -clang_index_isEntityObjCContainerKind -clang_index_setClientContainer -clang_index_setClientEntity -clang_install_aborting_llvm_fatal_error_handler -clang_isAttribute -clang_isConstQualifiedType -clang_isCursorDefinition -clang_isDeclaration -clang_isExpression -clang_isFileMultipleIncludeGuarded -clang_isFunctionTypeVariadic -clang_isInvalid -clang_isInvalidDeclaration -clang_isPODType -clang_isPreprocessing -clang_isReference -clang_isRestrictQualifiedType -clang_isStatement -clang_isTranslationUnit -clang_isUnexposed -clang_isVirtualBase -clang_isVolatileQualifiedType -clang_loadDiagnostics -clang_parseTranslationUnit -clang_parseTranslationUnit2 -clang_parseTranslationUnit2FullArgv -clang_remap_dispose -clang_remap_getFilenames -clang_remap_getNumFiles -clang_reparseTranslationUnit -clang_saveTranslationUnit -clang_sortCodeCompletionResults -clang_suspendTranslationUnit -clang_toggleCrashRecovery -clang_tokenize -clang_uninstall_llvm_fatal_error_handler -clang_visitChildren -clang_visitChildrenWithBlock diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map new file mode 100644 index 0000000000000..716e2474966d5 --- /dev/null +++ b/clang/tools/libclang/libclang.map @@ -0,0 +1,413 @@ +# If you add a symbol to this file, make sure to add it with the correct +# version. For example, if the LLVM main branch is LLVM 14.0.0, add new +# symbols with the version LLVM_14. +# On platforms where versions scripts are not used, this file will be used to +# generate a list of exports for libclang.so + +LLVM_13 { + global: + clang_BlockCommandComment_getArgText; + clang_BlockCommandComment_getCommandName; + clang_BlockCommandComment_getNumArgs; + clang_BlockCommandComment_getParagraph; + clang_CXCursorSet_contains; + clang_CXCursorSet_insert; + clang_CXIndex_getGlobalOptions; + clang_CXIndex_setGlobalOptions; + clang_CXIndex_setInvocationEmissionPathOption; + clang_CXRewriter_create; + clang_CXRewriter_dispose; + clang_CXRewriter_insertTextBefore; + clang_CXRewriter_overwriteChangedFiles; + clang_CXRewriter_removeText; + clang_CXRewriter_replaceText; + clang_CXRewriter_writeMainFileToStdOut; + clang_CXXConstructor_isConvertingConstructor; + clang_CXXConstructor_isCopyConstructor; + clang_CXXConstructor_isDefaultConstructor; + clang_CXXConstructor_isMoveConstructor; + clang_CXXField_isMutable; + clang_CXXMethod_isConst; + clang_CXXMethod_isDefaulted; + clang_CXXMethod_isPureVirtual; + clang_CXXMethod_isStatic; + clang_CXXMethod_isVirtual; + clang_CXXRecord_isAbstract; + clang_Comment_getChild; + clang_Comment_getKind; + clang_Comment_getNumChildren; + clang_Comment_isWhitespace; + clang_CompilationDatabase_dispose; + clang_CompilationDatabase_fromDirectory; + clang_CompilationDatabase_getAllCompileCommands; + clang_CompilationDatabase_getCompileCommands; + clang_CompileCommand_getArg; + clang_CompileCommand_getDirectory; + clang_CompileCommand_getFilename; + clang_CompileCommand_getMappedSourceContent; + clang_CompileCommand_getMappedSourcePath; + clang_CompileCommand_getNumArgs; + clang_CompileCommand_getNumMappedSources; + clang_CompileCommands_dispose; + clang_CompileCommands_getCommand; + clang_CompileCommands_getSize; + clang_Cursor_Evaluate; + clang_Cursor_getArgument; + clang_Cursor_getBriefCommentText; + clang_Cursor_getCXXManglings; + clang_Cursor_getCommentRange; + clang_Cursor_getMangling; + clang_Cursor_getModule; + clang_Cursor_getNumArguments; + clang_Cursor_getNumTemplateArguments; + clang_Cursor_getObjCDeclQualifiers; + clang_Cursor_getObjCManglings; + clang_Cursor_getObjCPropertyAttributes; + clang_Cursor_getObjCPropertyGetterName; + clang_Cursor_getObjCPropertySetterName; + clang_Cursor_getObjCSelectorIndex; + clang_Cursor_getOffsetOfField; + clang_Cursor_getParsedComment; + clang_Cursor_getRawCommentText; + clang_Cursor_getReceiverType; + clang_Cursor_getSpellingNameRange; + clang_Cursor_getStorageClass; + clang_Cursor_getTemplateArgumentKind; + clang_Cursor_getTemplateArgumentType; + clang_Cursor_getTemplateArgumentUnsignedValue; + clang_Cursor_getTemplateArgumentValue; + clang_Cursor_getTranslationUnit; + clang_Cursor_getVarDeclInitializer; + clang_Cursor_hasAttrs; + clang_Cursor_hasVarDeclExternalStorage; + clang_Cursor_hasVarDeclGlobalStorage; + clang_Cursor_isAnonymous; + clang_Cursor_isAnonymousRecordDecl; + clang_Cursor_isBitField; + clang_Cursor_isDynamicCall; + clang_Cursor_isExternalSymbol; + clang_Cursor_isFunctionInlined; + clang_Cursor_isInlineNamespace; + clang_Cursor_isMacroBuiltin; + clang_Cursor_isMacroFunctionLike; + clang_Cursor_isNull; + clang_Cursor_isObjCOptional; + clang_Cursor_isVariadic; + clang_EnumDecl_isScoped; + clang_EvalResult_dispose; + clang_EvalResult_getAsDouble; + clang_EvalResult_getAsInt; + clang_EvalResult_getAsLongLong; + clang_EvalResult_getAsStr; + clang_EvalResult_getAsUnsigned; + clang_EvalResult_getKind; + clang_EvalResult_isUnsignedInt; + clang_File_isEqual; + clang_File_tryGetRealPathName; + clang_FullComment_getAsHTML; + clang_FullComment_getAsXML; + clang_HTMLStartTagComment_isSelfClosing; + clang_HTMLStartTag_getAttrName; + clang_HTMLStartTag_getAttrValue; + clang_HTMLStartTag_getNumAttrs; + clang_HTMLTagComment_getAsString; + clang_HTMLTagComment_getTagName; + clang_IndexAction_create; + clang_IndexAction_dispose; + clang_InlineCommandComment_getArgText; + clang_InlineCommandComment_getCommandName; + clang_InlineCommandComment_getNumArgs; + clang_InlineCommandComment_getRenderKind; + clang_InlineContentComment_hasTrailingNewline; + clang_Location_isFromMainFile; + clang_Location_isInSystemHeader; + clang_ModuleMapDescriptor_create; + clang_ModuleMapDescriptor_dispose; + clang_ModuleMapDescriptor_setFrameworkModuleName; + clang_ModuleMapDescriptor_setUmbrellaHeader; + clang_ModuleMapDescriptor_writeToBuffer; + clang_Module_getASTFile; + clang_Module_getFullName; + clang_Module_getName; + clang_Module_getNumTopLevelHeaders; + clang_Module_getParent; + clang_Module_getTopLevelHeader; + clang_Module_isSystem; + clang_ParamCommandComment_getDirection; + clang_ParamCommandComment_getParamIndex; + clang_ParamCommandComment_getParamName; + clang_ParamCommandComment_isDirectionExplicit; + clang_ParamCommandComment_isParamIndexValid; + clang_PrintingPolicy_dispose; + clang_PrintingPolicy_getProperty; + clang_PrintingPolicy_setProperty; + clang_Range_isNull; + clang_TParamCommandComment_getDepth; + clang_TParamCommandComment_getIndex; + clang_TParamCommandComment_getParamName; + clang_TParamCommandComment_isParamPositionValid; + clang_TargetInfo_dispose; + clang_TargetInfo_getPointerWidth; + clang_TargetInfo_getTriple; + clang_TextComment_getText; + clang_Type_getAlignOf; + clang_Type_getCXXRefQualifier; + clang_Type_getClassType; + clang_Type_getModifiedType; + clang_Type_getNamedType; + clang_Type_getNullability; + clang_Type_getNumObjCProtocolRefs; + clang_Type_getNumObjCTypeArgs; + clang_Type_getNumTemplateArguments; + clang_Type_getObjCEncoding; + clang_Type_getObjCObjectBaseType; + clang_Type_getObjCProtocolDecl; + clang_Type_getObjCTypeArg; + clang_Type_getOffsetOf; + clang_Type_getSizeOf; + clang_Type_getTemplateArgumentAsType; + clang_Type_getValueType; + clang_Type_isTransparentTagTypedef; + clang_Type_visitFields; + clang_VerbatimBlockLineComment_getText; + clang_VerbatimLineComment_getText; + clang_VirtualFileOverlay_addFileMapping; + clang_VirtualFileOverlay_create; + clang_VirtualFileOverlay_dispose; + clang_VirtualFileOverlay_setCaseSensitivity; + clang_VirtualFileOverlay_writeToBuffer; + clang_annotateTokens; + clang_codeCompleteAt; + clang_codeCompleteGetContainerKind; + clang_codeCompleteGetContainerUSR; + clang_codeCompleteGetContexts; + clang_codeCompleteGetDiagnostic; + clang_codeCompleteGetNumDiagnostics; + clang_codeCompleteGetObjCSelector; + clang_constructUSR_ObjCCategory; + clang_constructUSR_ObjCClass; + clang_constructUSR_ObjCIvar; + clang_constructUSR_ObjCMethod; + clang_constructUSR_ObjCProperty; + clang_constructUSR_ObjCProtocol; + clang_createCXCursorSet; + clang_createIndex; + clang_createTranslationUnit; + clang_createTranslationUnit2; + clang_createTranslationUnitFromSourceFile; + clang_defaultCodeCompleteOptions; + clang_defaultDiagnosticDisplayOptions; + clang_defaultEditingTranslationUnitOptions; + clang_defaultReparseOptions; + clang_defaultSaveOptions; + clang_disposeCXCursorSet; + clang_disposeCXPlatformAvailability; + clang_disposeCXTUResourceUsage; + clang_disposeCodeCompleteResults; + clang_disposeDiagnostic; + clang_disposeDiagnosticSet; + clang_disposeIndex; + clang_disposeOverriddenCursors; + clang_disposeSourceRangeList; + clang_disposeString; + clang_disposeStringSet; + clang_disposeTokens; + clang_disposeTranslationUnit; + clang_enableStackTraces; + clang_equalCursors; + clang_equalLocations; + clang_equalRanges; + clang_equalTypes; + clang_executeOnThread; + clang_findIncludesInFile; + clang_findIncludesInFileWithBlock; + clang_findReferencesInFile; + clang_findReferencesInFileWithBlock; + clang_formatDiagnostic; + clang_free; + clang_getAddressSpace; + clang_getAllSkippedRanges; + clang_getArgType; + clang_getArrayElementType; + clang_getArraySize; + clang_getBuildSessionTimestamp; + clang_getCString; + clang_getCXTUResourceUsage; + clang_getCXXAccessSpecifier; + clang_getCanonicalCursor; + clang_getCanonicalType; + clang_getChildDiagnostics; + clang_getClangVersion; + clang_getCompletionAnnotation; + clang_getCompletionAvailability; + clang_getCompletionBriefComment; + clang_getCompletionChunkCompletionString; + clang_getCompletionChunkKind; + clang_getCompletionChunkText; + clang_getCompletionFixIt; + clang_getCompletionNumAnnotations; + clang_getCompletionNumFixIts; + clang_getCompletionParent; + clang_getCompletionPriority; + clang_getCursor; + clang_getCursorAvailability; + clang_getCursorCompletionString; + clang_getCursorDefinition; + clang_getCursorDisplayName; + clang_getCursorExceptionSpecificationType; + clang_getCursorExtent; + clang_getCursorKind; + clang_getCursorKindSpelling; + clang_getCursorLanguage; + clang_getCursorLexicalParent; + clang_getCursorLinkage; + clang_getCursorLocation; + clang_getCursorPlatformAvailability; + clang_getCursorPrettyPrinted; + clang_getCursorPrintingPolicy; + clang_getCursorReferenceNameRange; + clang_getCursorReferenced; + clang_getCursorResultType; + clang_getCursorSemanticParent; + clang_getCursorSpelling; + clang_getCursorTLSKind; + clang_getCursorType; + clang_getCursorUSR; + clang_getCursorVisibility; + clang_getDeclObjCTypeEncoding; + clang_getDefinitionSpellingAndExtent; + clang_getDiagnostic; + clang_getDiagnosticCategory; + clang_getDiagnosticCategoryName; + clang_getDiagnosticCategoryText; + clang_getDiagnosticFixIt; + clang_getDiagnosticInSet; + clang_getDiagnosticLocation; + clang_getDiagnosticNumFixIts; + clang_getDiagnosticNumRanges; + clang_getDiagnosticOption; + clang_getDiagnosticRange; + clang_getDiagnosticSetFromTU; + clang_getDiagnosticSeverity; + clang_getDiagnosticSpelling; + clang_getElementType; + clang_getEnumConstantDeclUnsignedValue; + clang_getEnumConstantDeclValue; + clang_getEnumDeclIntegerType; + clang_getExceptionSpecificationType; + clang_getExpansionLocation; + clang_getFieldDeclBitWidth; + clang_getFile; + clang_getFileContents; + clang_getFileLocation; + clang_getFileName; + clang_getFileTime; + clang_getFileUniqueID; + clang_getFunctionTypeCallingConv; + clang_getIBOutletCollectionType; + clang_getIncludedFile; + clang_getInclusions; + clang_getInstantiationLocation; + clang_getLocation; + clang_getLocationForOffset; + clang_getModuleForFile; + clang_getNullCursor; + clang_getNullLocation; + clang_getNullRange; + clang_getNumArgTypes; + clang_getNumCompletionChunks; + clang_getNumDiagnostics; + clang_getNumDiagnosticsInSet; + clang_getNumElements; + clang_getNumOverloadedDecls; + clang_getOverloadedDecl; + clang_getOverriddenCursors; + clang_getPointeeType; + clang_getPresumedLocation; + clang_getRange; + clang_getRangeEnd; + clang_getRangeStart; + clang_getRemappings; + clang_getRemappingsFromFileList; + clang_getResultType; + clang_getSkippedRanges; + clang_getSpecializedCursorTemplate; + clang_getSpellingLocation; + clang_getTUResourceUsageName; + clang_getTemplateCursorKind; + clang_getToken; + clang_getTokenExtent; + clang_getTokenKind; + clang_getTokenLocation; + clang_getTokenSpelling; + clang_getTranslationUnitCursor; + clang_getTranslationUnitSpelling; + clang_getTranslationUnitTargetInfo; + clang_getTypeDeclaration; + clang_getTypeKindSpelling; + clang_getTypeSpelling; + clang_getTypedefDeclUnderlyingType; + clang_getTypedefName; + clang_hashCursor; + clang_indexLoc_getCXSourceLocation; + clang_indexLoc_getFileLocation; + clang_indexSourceFile; + clang_indexSourceFileFullArgv; + clang_indexTranslationUnit; + clang_index_getCXXClassDeclInfo; + clang_index_getClientContainer; + clang_index_getClientEntity; + clang_index_getIBOutletCollectionAttrInfo; + clang_index_getObjCCategoryDeclInfo; + clang_index_getObjCContainerDeclInfo; + clang_index_getObjCInterfaceDeclInfo; + clang_index_getObjCPropertyDeclInfo; + clang_index_getObjCProtocolRefListInfo; + clang_index_isEntityObjCContainerKind; + clang_index_setClientContainer; + clang_index_setClientEntity; + clang_install_aborting_llvm_fatal_error_handler; + clang_isAttribute; + clang_isConstQualifiedType; + clang_isCursorDefinition; + clang_isDeclaration; + clang_isExpression; + clang_isFileMultipleIncludeGuarded; + clang_isFunctionTypeVariadic; + clang_isInvalid; + clang_isInvalidDeclaration; + clang_isPODType; + clang_isPreprocessing; + clang_isReference; + clang_isRestrictQualifiedType; + clang_isStatement; + clang_isTranslationUnit; + clang_isUnexposed; + clang_isVirtualBase; + clang_isVolatileQualifiedType; + clang_loadDiagnostics; + clang_parseTranslationUnit; + clang_parseTranslationUnit2; + clang_parseTranslationUnit2FullArgv; + clang_remap_dispose; + clang_remap_getFilenames; + clang_remap_getNumFiles; + clang_reparseTranslationUnit; + clang_saveTranslationUnit; + clang_sortCodeCompletionResults; + clang_suspendTranslationUnit; + clang_toggleCrashRecovery; + clang_tokenize; + clang_uninstall_llvm_fatal_error_handler; + clang_visitChildren; + clang_visitChildrenWithBlock; + + local: *; +}; + +# Example of how to add a new symbol version entry. If you do add a new symbol +# version, please update the example to depend on the version you added. +# LLVM_X { +# global: +# clang_newsymbol; +# }; diff --git a/clang/tools/libclang/linker-script-to-export-list.py b/clang/tools/libclang/linker-script-to-export-list.py new file mode 100644 index 0000000000000..37fb172b9a0a2 --- /dev/null +++ b/clang/tools/libclang/linker-script-to-export-list.py @@ -0,0 +1,11 @@ +import re +import os +import sys + +input_file = open(sys.argv[1]) +output_file = open(sys.argv[2], 'w') + +for line in input_file: + m = re.search('^\s+(clang_[^;]+)', line) + if m: + output_file.write(m.group(1) + "\n") diff --git a/clang/unittests/AST/StmtPrinterTest.cpp b/clang/unittests/AST/StmtPrinterTest.cpp index f3ea74d65696f..ef80812886aef 100644 --- a/clang/unittests/AST/StmtPrinterTest.cpp +++ b/clang/unittests/AST/StmtPrinterTest.cpp @@ -31,7 +31,7 @@ using namespace tooling; namespace { -enum class StdVer { CXX98, CXX11, CXX14, CXX17, CXX2a }; +enum class StdVer { CXX98, CXX11, CXX14, CXX17, CXX20 }; DeclarationMatcher FunctionBodyMatcher(StringRef ContainingFunction) { return functionDecl(hasName(ContainingFunction), @@ -67,7 +67,9 @@ PrintedStmtCXXMatches(StdVer Standard, StringRef Code, const T &NodeMatch, case StdVer::CXX11: StdOpt = "-std=c++11"; break; case StdVer::CXX14: StdOpt = "-std=c++14"; break; case StdVer::CXX17: StdOpt = "-std=c++17"; break; - case StdVer::CXX2a: StdOpt = "-std=c++2a"; break; + case StdVer::CXX20: + StdOpt = "-std=c++20"; + break; } std::vector Args = { @@ -146,6 +148,35 @@ TEST(StmtPrinter, TestFloatingPointLiteral) { // Should be: with semicolon } +TEST(StmtPrinter, TestStringLiteralOperatorTemplate_Pack) { + ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11, + R"cpp( + template constexpr double operator""_c() { return 42; } + void A() { + constexpr auto waldo = 42_c; + } +)cpp", + FunctionBodyMatcher("A"), + "constexpr auto waldo = 42_c;\n")); +} + +TEST(StmtPrinter, TestStringLiteralOperatorTemplate_Class) { + ASSERT_TRUE( + PrintedStmtCXXMatches(StdVer::CXX20, + R"cpp( + struct C { + template constexpr C(const char (&)[N]) : n(N) {} + unsigned n; + }; + template constexpr auto operator""_c() { return c.n; } + void A() { + constexpr auto waldo = "abc"_c; + } +)cpp", + FunctionBodyMatcher("A"), + "constexpr auto waldo = operator\"\"_c<{4}>();\n")); +} + TEST(StmtPrinter, TestCXXConversionDeclImplicit) { ASSERT_TRUE(PrintedStmtCXXMatches( StdVer::CXX98, @@ -201,15 +232,17 @@ TEST(StmtPrinter, TestCXXLamda) { "[](auto a, int b, auto c, int, auto) {\n" "}")); - ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX2a, - "void A() {" - " auto l = [] class T3>" - " (int a, auto, int, auto d) { };" - "}", - lambdaExpr(anything()).bind("id"), - "[] class T3>(int a, auto, int, auto d) {\n" - "}")); + ASSERT_TRUE( + PrintedStmtCXXMatches(StdVer::CXX20, + "void A() {" + " auto l = [] class T3>" + " (int a, auto, int, auto d) { };" + "}", + lambdaExpr(anything()).bind("id"), + "[] class T3>(int a, auto, int, auto d) {\n" + "}")); } TEST(StmtPrinter, TestNoImplicitBases) { diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index e5a9447f01a99..8b3881adc4ce0 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -4675,9 +4675,6 @@ TEST(UsingDeclaration, ThroughUsingDeclaration) { EXPECT_TRUE(notMatches( "namespace a { void f(); } using a::f; void g() { a::f(); }", declRefExpr(throughUsingDecl(anything())))); - EXPECT_TRUE(matches("struct S {}; namespace a { int operator+(S s1, S s2); } " - "using a::operator+; int g() { return S() + S(); }", - declRefExpr(throughUsingDecl(anything())))); } TEST(SingleDecl, IsSingleDecl) { diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp index 64bc616523f05..c434dfcb3e86c 100644 --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -18,7 +18,6 @@ #include "clang/Driver/Driver.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/MC/TargetRegistry.h" -#include "llvm/Support/Host.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" @@ -570,95 +569,4 @@ TEST(DxcModeTest, ValidatorVersionValidation) { Diags.Clear(); DiagConsumer->clear(); } - -TEST(ToolChainTest, Toolsets) { - // Ignore this test on Windows hosts. - llvm::Triple Host(llvm::sys::getProcessTriple()); - if (Host.isOSWindows()) - GTEST_SKIP(); - - IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); - IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - - // Check (newer) GCC toolset installation. - { - IntrusiveRefCntPtr InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); - - // These should be ignored. - InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-2", 0, - llvm::MemoryBuffer::getMemBuffer("\n")); - InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-", 0, - llvm::MemoryBuffer::getMemBuffer("\n")); - InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--", 0, - llvm::MemoryBuffer::getMemBuffer("\n")); - InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--1", 0, - llvm::MemoryBuffer::getMemBuffer("\n")); - - // File needed for GCC installation detection. - InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-12/root/usr/lib/gcc/" - "x86_64-redhat-linux/11/crtbegin.o", - 0, llvm::MemoryBuffer::getMemBuffer("\n")); - - DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); - Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, - "clang LLVM compiler", InMemoryFileSystem); - std::unique_ptr C( - TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); - ASSERT_TRUE(C); - std::string S; - { - llvm::raw_string_ostream OS(S); - C->getDefaultToolChain().printVerboseInfo(OS); - } - EXPECT_EQ("Found candidate GCC installation: " - "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" - "Selected GCC installation: " - "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" - "Candidate multilib: .;@m64\n" - "Selected multilib: .;@m64\n", - S); - } - - // And older devtoolset. - { - IntrusiveRefCntPtr InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); - - // These should be ignored. - InMemoryFileSystem->addFile("/opt/rh/devtoolset-2", 0, - llvm::MemoryBuffer::getMemBuffer("\n")); - InMemoryFileSystem->addFile("/opt/rh/devtoolset-", 0, - llvm::MemoryBuffer::getMemBuffer("\n")); - InMemoryFileSystem->addFile("/opt/rh/devtoolset--", 0, - llvm::MemoryBuffer::getMemBuffer("\n")); - InMemoryFileSystem->addFile("/opt/rh/devtoolset--1", 0, - llvm::MemoryBuffer::getMemBuffer("\n")); - - // File needed for GCC installation detection. - InMemoryFileSystem->addFile("/opt/rh/devtoolset-12/root/usr/lib/gcc/" - "x86_64-redhat-linux/11/crtbegin.o", - 0, llvm::MemoryBuffer::getMemBuffer("\n")); - - DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer); - Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags, - "clang LLVM compiler", InMemoryFileSystem); - std::unique_ptr C( - TheDriver.BuildCompilation({"clang", "--gcc-toolchain="})); - ASSERT_TRUE(C); - std::string S; - { - llvm::raw_string_ostream OS(S); - C->getDefaultToolChain().printVerboseInfo(OS); - } - EXPECT_EQ("Found candidate GCC installation: " - "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" - "Selected GCC installation: " - "/opt/rh/devtoolset-12/root/usr/lib/gcc/x86_64-redhat-linux/11\n" - "Candidate multilib: .;@m64\n" - "Selected multilib: .;@m64\n", - S); - } -} - } // end anonymous namespace. diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index e26cfb0ee88a0..fdc7c4a0c2fe2 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -10474,6 +10474,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { verifyFormat("class {\n" "}&& ptr = {};", Style); + verifyFormat("bool b = 3 == int{3} && true;"); Style.PointerAlignment = FormatStyle::PAS_Middle; verifyFormat("struct {\n" diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 4b2622522e0f8..ad8ba76bdcca0 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -86,6 +86,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { EXPECT_EQ(Tokens.size(), 5u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::amp, TT_UnaryOperator); + Tokens = annotate("bool b = 3 == int{3} && true;\n"); + EXPECT_EQ(Tokens.size(), 13u) << Tokens; + EXPECT_TOKEN(Tokens[9], tok::ampamp, TT_BinaryOperator); + Tokens = annotate("struct {\n" "} *ptr;"); EXPECT_EQ(Tokens.size(), 7u) << Tokens; diff --git a/clang/unittests/Tooling/Syntax/TokensTest.cpp b/clang/unittests/Tooling/Syntax/TokensTest.cpp index 77f719ce28cd0..85fc837fbe2be 100644 --- a/clang/unittests/Tooling/Syntax/TokensTest.cpp +++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp @@ -743,6 +743,62 @@ TEST_F(TokenBufferTest, SpelledByExpanded) { ValueIs(SameRange(findSpelled("ID2 ( a4 , a5 a6 a7 )")))); // Should fail, spans multiple invocations. EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("a1 a2 a3 a4")), llvm::None); + + // https://github.com/clangd/clangd/issues/1289 + recordTokens(R"cpp( + #define FOO(X) foo(X) + #define INDIRECT FOO(y) + INDIRECT // expands to foo(y) + )cpp"); + EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("y")), llvm::None); + + recordTokens(R"cpp( + #define FOO(X) a X b + FOO(y) + )cpp"); + EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("y")), + ValueIs(SameRange(findSpelled("y")))); + + recordTokens(R"cpp( + #define ID(X) X + #define BAR ID(1) + BAR + )cpp"); + EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("1")), + ValueIs(SameRange(findSpelled(") BAR").drop_front()))); + + // Critical cases for mapping of Prev/Next in spelledForExpandedSlow. + recordTokens(R"cpp( + #define ID(X) X + ID(prev ID(good)) + #define LARGE ID(prev ID(bad)) + LARGE + )cpp"); + EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")), + ValueIs(SameRange(findSpelled("good")))); + EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None); + + recordTokens(R"cpp( + #define PREV prev + #define ID(X) X + PREV ID(good) + #define LARGE PREV ID(bad) + LARGE + )cpp"); + EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")), + ValueIs(SameRange(findSpelled("good")))); + EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None); + + recordTokens(R"cpp( + #define ID(X) X + #define ID2(X, Y) X Y + ID2(prev, ID(good)) + #define LARGE ID2(prev, bad) + LARGE + )cpp"); + EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")), + ValueIs(SameRange(findSpelled("good")))); + EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None); } TEST_F(TokenBufferTest, ExpandedTokensForRange) { diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp index b2f6ede56522a..e1e1c078ccbf5 100644 --- a/clang/utils/TableGen/SveEmitter.cpp +++ b/clang/utils/TableGen/SveEmitter.cpp @@ -1282,6 +1282,8 @@ void SVEEmitter::createHeader(raw_ostream &OS) { OS << "#ifdef __cplusplus\n"; OS << "} // extern \"C\"\n"; OS << "#endif\n\n"; + OS << "#undef __ai\n\n"; + OS << "#undef __aio\n\n"; OS << "#endif /*__ARM_FEATURE_SVE */\n\n"; OS << "#endif /* __ARM_SVE_H */\n"; } diff --git a/cmake/Modules/FindLibEdit.cmake b/cmake/Modules/FindLibEdit.cmake index 7e62d4d839ae1..de8f5a2e71013 100644 --- a/cmake/Modules/FindLibEdit.cmake +++ b/cmake/Modules/FindLibEdit.cmake @@ -21,6 +21,7 @@ find_library(LibEdit_LIBRARIES NAMES edit HINTS ${PC_LIBEDIT_LIBRARY_DIRS}) include(CheckIncludeFile) if(LibEdit_INCLUDE_DIRS AND EXISTS "${LibEdit_INCLUDE_DIRS}/histedit.h") + include(CMakePushCheckState) cmake_push_check_state() list(APPEND CMAKE_REQUIRED_INCLUDES ${LibEdit_INCLUDE_DIRS}) list(APPEND CMAKE_REQUIRED_LIBRARIES ${LibEdit_LIBRARIES}) diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 4a572bc005fe8..62737735695f2 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -479,6 +479,12 @@ append_list_if(MINGW -fms-extensions SANITIZER_COMMON_CFLAGS) append_list_if(C_SUPPORTS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS) append_list_if(COMPILER_RT_HAS_Z_TEXT -Wl,-z,text SANITIZER_COMMON_LINK_FLAGS) +# Only necessary for 32-bit SPARC. Solaris 11.2+ ld uses -z ignore/-z record +# natively, but supports --as-needed/--no-as-needed for GNU ld compatibility. +if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "sparc") + list(APPEND SANITIZER_COMMON_LINK_LIBS -Wl,--as-needed atomic -Wl,--no-as-needed) +endif() + if (COMPILER_RT_USE_BUILTINS_LIBRARY) string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") else() diff --git a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake index 2c9983c6a1ae3..640c7e7124c99 100644 --- a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake @@ -116,7 +116,7 @@ function(darwin_test_archs os valid_archs) if(NOT TEST_COMPILE_ONLY) message(STATUS "Finding valid architectures for ${os}...") set(SIMPLE_C ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.c) - file(WRITE ${SIMPLE_C} "#include \nint main() { printf(__FILE__); return 0; }\n") + file(WRITE ${SIMPLE_C} "#include \nint main(void) { printf(__FILE__); return 0; }\n") set(os_linker_flags) foreach(flag ${DARWIN_${os}_LINK_FLAGS}) diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake index 9b5e03a6607ba..e322af89a0427 100644 --- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake @@ -484,6 +484,10 @@ function(get_compiler_rt_target arch variable) set(target "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}") elseif(ANDROID AND ${arch} STREQUAL "i386") set(target "i686${triple_suffix}") + elseif(${arch} STREQUAL "amd64") + set(target "x86_64${triple_suffix}") + elseif(${arch} STREQUAL "sparc64") + set(target "sparcv9${triple_suffix}") else() set(target "${arch}${triple_suffix}") endif() diff --git a/compiler-rt/cmake/builtin-config-ix.cmake b/compiler-rt/cmake/builtin-config-ix.cmake index 9cbadf33e2574..439abc713bad9 100644 --- a/compiler-rt/cmake/builtin-config-ix.cmake +++ b/compiler-rt/cmake/builtin-config-ix.cmake @@ -30,6 +30,14 @@ _Float16 foo(_Float16 x) { " ) +builtin_check_c_compiler_source(COMPILER_RT_HAS_BFLOAT16 +" +__bf16 foo(__bf16 x) { + return x; +} +" +) + builtin_check_c_compiler_source(COMPILER_RT_HAS_ASM_LSE " asm(\".arch armv8-a+lse\"); diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index cd45176cf2ba7..9077e8f9ffe04 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -209,7 +209,7 @@ set(COMPILER_RT_SUPPORTED_ARCH) # runtime libraries supported by our current compilers cross-compiling # abilities. set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc) -file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main() { printf(\"hello, world\"); }\n") +file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main(void) { printf(\"hello, world\"); }\n") # Detect whether the current target platform is 32-bit or 64-bit, and setup # the correct commandline flags needed to attempt to target 32-bit and 64-bit. diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 0b91b4ce79933..df02682ae00f9 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -165,10 +165,8 @@ set(GENERIC_SOURCES subvsi3.c subvti3.c trampoline_setup.c - truncdfbf2.c truncdfhf2.c truncdfsf2.c - truncsfbf2.c truncsfhf2.c ucmpdi2.c ucmpti2.c @@ -183,6 +181,15 @@ set(GENERIC_SOURCES umodti3.c ) +# Build BF16 files only when "__bf16" is available. +if(COMPILER_RT_HAS_BFLOAT16 AND NOT APPLE) + set(GENERIC_SOURCES + ${GENERIC_SOURCES} + truncdfbf2.c + truncsfbf2.c + ) +endif() + # TODO: Several "tf" files (and divtc3.c, but not multc3.c) are in # GENERIC_SOURCES instead of here. set(GENERIC_TF_SOURCES @@ -621,9 +628,11 @@ set(mips64_SOURCES ${GENERIC_TF_SOURCES} set(mips64el_SOURCES ${GENERIC_TF_SOURCES} ${mips_SOURCES}) +set(powerpc_SOURCES ${GENERIC_SOURCES}) + set(powerpcspe_SOURCES ${GENERIC_SOURCES}) -set(powerpc_SOURCES +set(powerpc64_SOURCES ppc/divtc3.c ppc/fixtfdi.c ppc/fixunstfdi.c @@ -638,15 +647,14 @@ set(powerpc_SOURCES ) # These routines require __int128, which isn't supported on AIX. if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") - set(powerpc_SOURCES + set(powerpc64_SOURCES ppc/floattitf.c ppc/fixtfti.c ppc/fixunstfti.c - ${powerpc_SOURCES} + ${powerpc64_SOURCES} ) endif() -set(powerpc64le_SOURCES ${powerpc_SOURCES}) -set(powerpc64_SOURCES ${powerpc_SOURCES}) +set(powerpc64le_SOURCES ${powerpc64_SOURCES}) set(riscv_SOURCES riscv/save.S @@ -737,7 +745,7 @@ else () SOURCE "#if !(__ARM_FP & 0x8) #error No double-precision support! #endif - int main() { return 0; }") + int main(void) { return 0; }") if(NOT COMPILER_RT_HAS_${arch}_VFP_DP) list(REMOVE_ITEM ${arch}_SOURCES ${arm_Thumb1_VFPv2_DP_SOURCES}) endif() @@ -753,8 +761,9 @@ else () list(APPEND BUILTIN_CFLAGS_${arch} -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET) endif() - # For some arches, force enable int128 for compiling long double routines. - if("${arch}" STREQUAL "powerpc" OR "${arch}" STREQUAL "riscv32") + # For RISCV32, we must force enable int128 for compiling long + # double routines. + if("${arch}" STREQUAL "riscv32") list(APPEND BUILTIN_CFLAGS_${arch} -fforce-enable-int128) endif() diff --git a/compiler-rt/lib/builtins/fp_trunc.h b/compiler-rt/lib/builtins/fp_trunc.h index 7a54564a3520a..91f614528ab3f 100644 --- a/compiler-rt/lib/builtins/fp_trunc.h +++ b/compiler-rt/lib/builtins/fp_trunc.h @@ -60,7 +60,7 @@ typedef uint16_t dst_rep_t; static const int dstSigBits = 10; #elif defined DST_BFLOAT -typedef uint16_t dst_t; +typedef __bf16 dst_t; typedef uint16_t dst_rep_t; #define DST_REP_C UINT16_C static const int dstSigBits = 7; diff --git a/compiler-rt/lib/builtins/int_types.h b/compiler-rt/lib/builtins/int_types.h index 9ee5a327b28a4..7a72de4806764 100644 --- a/compiler-rt/lib/builtins/int_types.h +++ b/compiler-rt/lib/builtins/int_types.h @@ -64,7 +64,7 @@ typedef union { } udwords; #if defined(__LP64__) || defined(__wasm__) || defined(__mips64) || \ - defined(__riscv) || defined(_WIN64) || defined(__powerpc__) + defined(__riscv) || defined(_WIN64) #define CRT_HAS_128BIT #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 9af296b1853a9..b29665a633907 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -6703,7 +6703,7 @@ INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) { COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value); // Workaround a bug in glibc's "old" semaphore implementation by // zero-initializing the sem_t contents. This has to be done here because - // interceptors bind to the lowest symbols version by default, hitting the + // interceptors bind to the lowest version before glibc 2.36, hitting the // buggy code path while the non-sanitized build of the same code works fine. REAL(memset)(s, 0, sizeof(*s)); int res = REAL(sem_init)(s, pshared, value); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index ea4e5b015d116..32005eef08cd5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -90,7 +90,7 @@ # else # define SANITIZER_IOSSIM 0 # endif -# if TARGET_OS_DRIVERKIT +# if defined(TARGET_OS_DRIVERKIT) && TARGET_OS_DRIVERKIT # define SANITIZER_DRIVERKIT 1 # else # define SANITIZER_DRIVERKIT 0 diff --git a/compiler-rt/lib/scudo/standalone/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/CMakeLists.txt index f439f6f9d2d6f..4b586bc662b45 100644 --- a/compiler-rt/lib/scudo/standalone/CMakeLists.txt +++ b/compiler-rt/lib/scudo/standalone/CMakeLists.txt @@ -135,7 +135,7 @@ if (COMPILER_RT_HAS_GWP_ASAN) endif() -set(SCUDO_LINK_LIBS) +set(SCUDO_LINK_LIBS ${COMPILER_RT_UNWINDER_LINK_LIBS}) append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread SCUDO_LINK_FLAGS) diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index c5a8420da14ff..3dd258283e5ce 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -540,9 +540,12 @@ def is_binutils_lto_supported(): # We require both ld.bfd and ld.gold exist and support plugins. They are in # the same repository 'binutils-gdb' and usually built together. for exe in (config.gnu_ld_executable, config.gold_executable): - ld_cmd = subprocess.Popen([exe, '--help'], stdout=subprocess.PIPE, env={'LANG': 'C'}) - ld_out = ld_cmd.stdout.read().decode() - ld_cmd.wait() + try: + ld_cmd = subprocess.Popen([exe, '--help'], stdout=subprocess.PIPE, env={'LANG': 'C'}) + ld_out = ld_cmd.stdout.read().decode() + ld_cmd.wait() + except OSError: + return False if not '-plugin' in ld_out: return False diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp index d623ccabb5b55..234c5019f6920 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/sem_init_glibc.cpp @@ -1,39 +1,36 @@ // RUN: %clangxx -O0 -g %s -lutil -o %t && %run %t // This test depends on the glibc layout of struct sem_t and checks that we // don't leave sem_t::private uninitialized. -// UNSUPPORTED: android, lsan-x86, ubsan, target-is-mips64, target-is-mips64el +// UNSUPPORTED: android, lsan-x86, ubsan #include #include #include #include #include -// On powerpc64be semval_t must be 64 bits even with "old" versions of glibc. -#if __PPC64__ && __BIG_ENDIAN__ -typedef uint64_t semval_t; - -// This condition needs to correspond to __HAVE_64B_ATOMICS macro in glibc. -#elif (defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \ - defined(__s390x__) || defined(__sparc64__) || defined(__alpha__) || \ - defined(__ia64__) || defined(__m68k__)) && __GLIBC_PREREQ(2, 21) -typedef uint64_t semval_t; -#else +// musl and glibc's __HAVE_64B_ATOMICS==0 ports (e.g. arm, i386) use 32-bit sem +// values. 64-bit glibc ports defining sem_init@GLIBC_2.0 (mips64) use 32-bit as +// well, if the sem_init interceptor picks the oldest versioned symbol +// (glibc<2.36, see https://sourceware.org/PR14932). +#if !defined(__GLIBC__) || defined(__ILP32__) || \ + !__GLIBC_PREREQ(2, 36) && defined(__mips64__) typedef unsigned semval_t; +#else +typedef uint64_t semval_t; #endif -// glibc 2.21 has introduced some changes in the way the semaphore value is -// handled for 32-bit platforms, but since these changes are not ABI-breaking -// they are not versioned. On newer platforms such as ARM, there is only one -// version of the symbol, so it's enough to check the glibc version. However, -// for old platforms such as i386, glibc contains two or even three versions of -// the sem_init symbol, and the sanitizers always pick the oldest one. -// Therefore, it is not enough to rely on the __GLIBC_PREREQ macro - we should -// instead check the platform as well to make sure we only expect the new -// behavior on platforms where the older symbols do not exist. -#if defined(__arm__) && __GLIBC_PREREQ(2, 21) -#define GET_SEM_VALUE(V) ((V) >> 1) +// glibc __HAVE_64B_ATOMICS==0 ports define a sem_init which shifts the value by +// 1 (https://sourceware.org/PR12674 glibc 2.21). The version is picked if +// either glibc>=2.36 or sem_init@GLIBC_2.0 is absent (arm and newer ports). +// +// The __GLIBC_PREREQ check is brittle in that it requires matched +// __GLIBC_PREREQ values for build time and run time. +#if defined(__GLIBC__) && defined(__ILP32__) && \ + (__GLIBC_PREREQ(2, 36) || (__GLIBC_PREREQ(2, 21) && !defined(__i386__) && \ + !defined(__mips__) && !defined(__powerpc__))) +# define GET_SEM_VALUE(V) ((V) >> 1) #else -#define GET_SEM_VALUE(V) (V) +# define GET_SEM_VALUE(V) (V) #endif void my_sem_init(bool priv, int value, semval_t *a, unsigned char *b) { diff --git a/flang/cmake/modules/AddFlang.cmake b/flang/cmake/modules/AddFlang.cmake index 7c71d2b7b044c..d516ca31b51fa 100644 --- a/flang/cmake/modules/AddFlang.cmake +++ b/flang/cmake/modules/AddFlang.cmake @@ -18,7 +18,7 @@ endmacro() macro(add_flang_library name) cmake_parse_arguments(ARG - "SHARED;STATIC" + "SHARED;STATIC;INSTALL_WITH_TOOLCHAIN" "" "ADDITIONAL_HEADERS" ${ARGN}) @@ -65,7 +65,8 @@ macro(add_flang_library name) if (TARGET ${name}) - if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "libflang") + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "libflang" + OR ARG_INSTALL_WITH_TOOLCHAIN) get_target_export_arg(${name} Flang export_to_flangtargets UMBRELLA flang-libraries) install(TARGETS ${name} COMPONENT ${name} diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md index 38d5c3f0706dc..d206ff45a7b55 100644 --- a/flang/docs/ReleaseNotes.md +++ b/flang/docs/ReleaseNotes.md @@ -1,10 +1,4 @@ -# Flang 15.0.0 (In-Progress) Release Notes - -> **warning** -> -> These are in-progress notes for the upcoming LLVM 15.0.0 release. -> Release notes for previous releases can be found on [the Download -> Page](https://releases.llvm.org/download.html). +# Flang 15.0.0 Release Notes ## Introduction diff --git a/flang/lib/Decimal/CMakeLists.txt b/flang/lib/Decimal/CMakeLists.txt index 18655f096f0d9..3430fa5913819 100644 --- a/flang/lib/Decimal/CMakeLists.txt +++ b/flang/lib/Decimal/CMakeLists.txt @@ -1,5 +1,5 @@ -add_flang_library(FortranDecimal +add_flang_library(FortranDecimal INSTALL_WITH_TOOLCHAIN binary-to-decimal.cpp decimal-to-binary.cpp ) diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp index 9ec2f04489aee..5295420ae9a85 100644 --- a/flang/lib/Optimizer/CodeGen/Target.cpp +++ b/flang/lib/Optimizer/CodeGen/Target.cpp @@ -268,6 +268,7 @@ fir::CodeGenSpecifics::get(mlir::MLIRContext *ctx, llvm::Triple &&trp, case llvm::Triple::OSType::Linux: case llvm::Triple::OSType::Darwin: case llvm::Triple::OSType::MacOSX: + case llvm::Triple::OSType::Solaris: case llvm::Triple::OSType::Win32: return std::make_unique(ctx, std::move(trp), std::move(kindMap)); @@ -280,6 +281,7 @@ fir::CodeGenSpecifics::get(mlir::MLIRContext *ctx, llvm::Triple &&trp, case llvm::Triple::OSType::Linux: case llvm::Triple::OSType::Darwin: case llvm::Triple::OSType::MacOSX: + case llvm::Triple::OSType::Solaris: case llvm::Triple::OSType::Win32: return std::make_unique(ctx, std::move(trp), std::move(kindMap)); diff --git a/flang/runtime/CMakeLists.txt b/flang/runtime/CMakeLists.txt index ce8a615642341..5c61cebf3c709 100644 --- a/flang/runtime/CMakeLists.txt +++ b/flang/runtime/CMakeLists.txt @@ -88,4 +88,6 @@ add_flang_library(FortranRuntime LINK_LIBS FortranDecimal + + INSTALL_WITH_TOOLCHAIN ) diff --git a/flang/runtime/FortranMain/CMakeLists.txt b/flang/runtime/FortranMain/CMakeLists.txt index 1d840ee5d1a38..fe0d607c3f1a9 100644 --- a/flang/runtime/FortranMain/CMakeLists.txt +++ b/flang/runtime/FortranMain/CMakeLists.txt @@ -1,3 +1,3 @@ -add_flang_library(Fortran_main STATIC +add_flang_library(Fortran_main STATIC INSTALL_WITH_TOOLCHAIN Fortran_main.c ) diff --git a/flang/test/Driver/linker-flags.f90 b/flang/test/Driver/linker-flags.f90 index ae0f5b3c8f825..90c4a940c6d5f 100644 --- a/flang/test/Driver/linker-flags.f90 +++ b/flang/test/Driver/linker-flags.f90 @@ -36,8 +36,11 @@ ! MINGW-SAME: -lFortranRuntime ! MINGW-SAME: -lFortranDecimal -! NOTE: This check should also match if the default linker is lld-link.exe -! MSVC-LABEL: link.exe +! NOTE: This also matches lld-link (when CLANG_DEFAULT_LINKER=lld) and +! any .exe suffix that is added when resolving to the full path of +! (lld-)link.exe on Windows platforms. The suffix may not be added +! when the executable is not found or on non-Windows platforms. +! MSVC-LABEL: link ! MSVC-SAME: Fortran_main.lib ! MSVC-SAME: FortranRuntime.lib ! MSVC-SAME: FortranDecimal.lib diff --git a/libcxx/.clang-format b/libcxx/.clang-format index 8d8eff5905afb..acc6773c16ded 100644 --- a/libcxx/.clang-format +++ b/libcxx/.clang-format @@ -68,7 +68,7 @@ MaxEmptyLinesToKeep: 1 NamespaceIndentation: Inner PackConstructorInitializers: NextLine -PenaltyIndentedWhitespace: 61 +PenaltyIndentedWhitespace: 2 Language: Cpp Standard: c++20 diff --git a/libcxx/cmake/Modules/DefineLinkerScript.cmake b/libcxx/cmake/Modules/DefineLinkerScript.cmake deleted file mode 100644 index 71a43086727c7..0000000000000 --- a/libcxx/cmake/Modules/DefineLinkerScript.cmake +++ /dev/null @@ -1,56 +0,0 @@ -# This function defines a linker script in place of the symlink traditionally -# created for shared libraries. -# -# More specifically, this function goes through the PUBLIC and INTERFACE -# library dependencies of and gathers them into a linker script, -# such that those libraries are linked against when the shared library for -# is linked against. -# -# Arguments: -# : A target representing a shared library. A linker script will be -# created in place of that target's TARGET_LINKER_FILE, which is -# the symlink pointing to the actual shared library (usually -# libFoo.so pointing to libFoo.so.1, which itself points to -# libFoo.so.1.0). - -function(define_linker_script target) - if (NOT TARGET "${target}") - message(FATAL_ERROR "The provided target '${target}' is not actually a target.") - endif() - - get_target_property(target_type "${target}" TYPE) - if (NOT "${target_type}" STREQUAL "SHARED_LIBRARY") - message(FATAL_ERROR "The provided target '${target}' is not a shared library (its type is '${target_type}').") - endif() - - set(symlink "$") - set(soname "$") - - get_target_property(interface_libs "${target}" INTERFACE_LINK_LIBRARIES) - - set(link_libraries) - if (interface_libs) - foreach(lib IN LISTS interface_libs) - if ("${lib}" MATCHES "cxx-headers|ParallelSTL") - continue() - endif() - # If ${lib} is not a target, we use a dummy target which we know will - # have an OUTPUT_NAME property so that CMake doesn't fail when evaluating - # the non-selected branch of the `IF`. It doesn't matter what it evaluates - # to because it's not selected, but it must not cause an error. - # See https://gitlab.kitware.com/cmake/cmake/-/issues/21045. - set(output_name_tgt "$,${lib},${target}>") - set(libname "$,$,${lib}>") - list(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}${libname}") - endforeach() - endif() - string(REPLACE ";" " " link_libraries "${link_libraries}") - - set(linker_script "INPUT(${soname} ${link_libraries})") - add_custom_command(TARGET "${target}" POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E remove "${symlink}" - COMMAND "${CMAKE_COMMAND}" -E echo "${linker_script}" > "${symlink}" - COMMENT "Generating linker script: '${linker_script}' as file ${symlink}" - VERBATIM - ) -endfunction() diff --git a/libcxx/cmake/config-ix.cmake b/libcxx/cmake/config-ix.cmake index 209e6214a4718..e65d320728528 100644 --- a/libcxx/cmake/config-ix.cmake +++ b/libcxx/cmake/config-ix.cmake @@ -94,7 +94,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unknown-pragmas") check_c_source_compiles(" #pragma comment(lib, \"c\") -int main() { return 0; } +int main(void) { return 0; } " C_SUPPORTS_COMMENT_LIB_PRAGMA) cmake_pop_check_state() endif() diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 7ab2d6c0c6cbc..b1bf86942e690 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -262,7 +262,7 @@ Status ------------------------------------------------- ----------------- ``__cpp_lib_polymorphic_allocator`` *unimplemented* ------------------------------------------------- ----------------- - ``__cpp_lib_ranges`` *unimplemented* + ``__cpp_lib_ranges`` ``201811L`` ------------------------------------------------- ----------------- ``__cpp_lib_remove_cvref`` ``201711L`` ------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index 96e98fd5c9ab3..0409866f999aa 100644 --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -1,5 +1,5 @@ ========================================= -Libc++ 15.0.0 (In-Progress) Release Notes +Libc++ 15.0.0 Release Notes ========================================= .. contents:: @@ -8,12 +8,6 @@ Libc++ 15.0.0 (In-Progress) Release Notes Written by the `Libc++ Team `_ -.. warning:: - - These are in-progress notes for the upcoming libc++ 15 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -50,6 +44,7 @@ almost complete. The ``ranges`` library is considered experimental. Implemented Papers ------------------ +- P1004R2 - Making ``std::vector`` constexpr - P0627R6 - Function to mark unreachable code - P1165R1 - Make stateful allocator propagation more consistent for ``operator+(basic_string)`` - P0674R1 - Support arrays in ``make_shared`` and ``allocate_shared`` @@ -62,6 +57,7 @@ Implemented Papers - P2418R2 - Add support for ``std::generator``-like types to ``std::format`` - LWG3659 - Consider ``ATOMIC_FLAG_INIT`` undeprecation - P1423R3 - ``char8_t`` backward compatibility remediation +- P2508R1 - Exposing ``std::basic-format-string`` - Marked the following papers as "Complete" (note that some of those might have been implemented in a previous release but not marked as such): @@ -145,11 +141,11 @@ Deprecations and Removals or upgrade to C++11 or later. It is possible to re-enable ``std::function`` in C++03 by defining ``_LIBCPP_ENABLE_CXX03_FUNCTION``. This option will be removed in LLVM 16. -- ``unary_function`` and ``binary_function`` are no longer available in C++17 and C++20. - They can be re-enabled by defining ``_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION``. - They are also marked as ``[[deprecated]]`` in C++11 and later. To disable deprecation warnings - you have to define ``_LIBCPP_DISABLE_DEPRECATION_WARNINGS``. Note that this disables - all deprecation warnings. +- ``unary_function`` and ``binary_function`` are now marked as ``[[deprecated]]`` in C++11 and later. + Deprecation warnings can be disabled by defining ``_LIBCPP_DISABLE_DEPRECATION_WARNINGS``, however + this disables all deprecation warnings, not only those for ``unary_function`` and ``binary_function``. + Also note that starting in LLVM 16, ``unary_function`` and ``binary_function`` will be removed entirely + (not only deprecated) in C++17 and above, as mandated by the Standard. - The contents of ````, ``wstring_convert`` and ``wbuffer_convert`` have been marked as deprecated. To disable deprecation warnings you have to define ``_LIBCPP_DISABLE_DEPRECATION_WARNINGS``. Note that this @@ -198,6 +194,14 @@ Upcoming Deprecations and Removals ABI Affecting Changes --------------------- +- In freestanding mode, ``atomic`` does not contain a lock byte anymore if the platform + can implement lockfree atomics for that size. More specifically, in LLVM <= 11.0.1, an ``atomic`` + would not contain a lock byte. This was broken in LLVM >= 12.0.0, where it started including a lock byte despite + the platform supporting lockfree atomics for that size. Starting in LLVM 15.0.1, the ABI for these types has been + restored to what it used to be (no lock byte), which is the most efficient implementation. + + This ABI break only affects users that compile with ``-ffreestanding``, and only for ``atomic`` where ``T`` + is a non-builtin type that could be lockfree on the platform. See https://llvm.org/D133377 for more details. - The ``_LIBCPP_ABI_USE_CXX03_NULLPTR_EMULATION`` macro controlling whether we use an emulation for ``std::nullptr_t`` in C++03 mode has been removed. After this change, @@ -237,11 +241,6 @@ Build System Changes use the ``CMAKE_CXX_COMPILER_TARGET``, ``CMAKE_SYSROOT`` and ``CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN`` variables provided by CMake. -- When building for Windows, vendors who want to avoid dll-exporting symbols from the static libc++abi - library should set ``LIBCXXABI_HERMETIC_STATIC_LIBRARY=ON`` when configuring CMake. The current - behavior, which tries to guess the correct dll-export semantics based on whether we're building - the libc++ shared library, will be removed in LLVM 16. - - Previously, the C++ ABI library headers would be installed inside ``/include/c++/v1`` alongside the libc++ headers as part of building libc++. This is not the case anymore -- the ABI library is expected to install its headers where it wants them as part of its own build. diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv index e62ba746eac75..1cdbeac9a4634 100644 --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -146,13 +146,13 @@ "`2899 `__","``is_(nothrow_)move_constructible``\ and ``tuple``\ , ``optional``\ and ``unique_ptr``\ ","Cologne","","" "`3055 `__","``path::operator+=(*single-character*)``\ misspecified","Cologne","|Complete|","7.0" "`3158 `__","``tuple(allocator_arg_t, const Alloc&)``\ should be conditionally explicit","Cologne","|Complete|","10.0" -"`3169 `__","``ranges``\ permutation generators discard useful information","Cologne","","","|ranges|" +"`3169 `__","``ranges``\ permutation generators discard useful information","Cologne","|Complete|","15.0","|ranges|" "`3183 `__","Normative permission to specialize Ranges variable templates","Cologne","|Nothing To Do|","","|ranges|" "`3184 `__","Inconsistencies in ``bind_front``\ wording","Cologne","|Complete|","13.0" "`3185 `__","Uses-allocator construction functions missing ``constexpr``\ and ``noexcept``\ ","Cologne","","" -"`3186 `__","``ranges``\ removal, partition, and ``partial_sort_copy``\ algorithms discard useful information","Cologne","","","|ranges|" +"`3186 `__","``ranges``\ removal, partition, and ``partial_sort_copy``\ algorithms discard useful information","Cologne","|Complete|","15.0","|ranges|" "`3187 `__","`P0591R4 `__ reverted DR 2586 fixes to ``scoped_allocator_adaptor::construct()``\ ","Cologne","","" -"`3191 `__","``std::ranges::shuffle``\ synopsis does not match algorithm definition","Cologne","","","|ranges|" +"`3191 `__","``std::ranges::shuffle``\ synopsis does not match algorithm definition","Cologne","|Complete|","15.0","|ranges|" "`3196 `__","``std::optional``\ is ill-formed is ``T``\ is an array","Cologne","|Complete|","" "`3198 `__","Bad constraint on ``std::span::span()``\ ","Cologne","|Complete|","" "`3199 `__","``istream >> bitset<0>``\ fails","Cologne","","" @@ -220,7 +220,7 @@ "`3280 `__","View converting constructors can cause constraint recursion and are unneeded","Prague","|Complete|","15.0","|ranges|" "`3281 `__","Conversion from ``*pair-like*``\ types to ``subrange``\ is a silent semantic promotion","Prague","|Complete|","15.0","|ranges|" "`3282 `__","``subrange``\ converting constructor should disallow derived to base conversions","Prague","|Complete|","15.0","|ranges|" -"`3284 `__","``random_access_iterator``\ semantic constraints accidentally promote difference type using unary negate","Prague","|Nothing To Do|","","|ranges|" +"`3284 `__","``random_access_iterator``\ semantic constraints accidentally promote difference type using unary negate","Prague","|Nothing To Do|","","|ranges|" "`3285 `__","The type of a customization point object shall satisfy ``semiregular``\ ","Prague","|Nothing To Do|","","|ranges|" "`3286 `__","``ranges::size``\ is not required to be valid after a call to ``ranges::begin``\ on an input range","Prague","|Complete|","15.0","|ranges|" "`3291 `__","``iota_view::iterator``\ has the wrong ``iterator_category``\ ","Prague","|Complete|","15.0","|ranges|" diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv index 703c4a54c27e9..7d39424a6e6ef 100644 --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -61,7 +61,7 @@ "`P0608R3 `__","LWG","A sane variant converting constructor","San Diego","|Complete|","9.0" "`P0655R1 `__","LWG","visit: Explicit Return Type for visit","San Diego","|Complete|","12.0" "`P0771R1 `__","LWG","std::function move constructor should be noexcept","San Diego","|Complete|","6.0" -"`P0896R4 `__","LWG","The One Ranges Proposal","San Diego","|In Progress|","" +"`P0896R4 `__","LWG","The One Ranges Proposal","San Diego","|Complete|","15.0" "`P0899R1 `__","LWG","P0899R1 - LWG 3016 is not a defect","San Diego","|Nothing To Do|","" "`P0919R3 `__","LWG","Heterogeneous lookup for unordered containers","San Diego","|Complete|","12.0" "`P0972R0 `__","LWG"," ``zero()``\ , ``min()``\ , and ``max()``\ should be noexcept","San Diego","|Complete|","8.0" @@ -89,7 +89,7 @@ "`P1024R3 `__","LWG","Usability Enhancements for std::span","Kona","|Complete|","9.0" "`P1164R1 `__","LWG","Make create_directory() Intuitive","Kona","|Complete|","12.0" "`P1227R2 `__","LWG","Signed ssize() functions, unsigned size() functions","Kona","|Complete|","9.0" -"`P1252R2 `__","LWG","Ranges Design Cleanup","Kona","","" +"`P1252R2 `__","LWG","Ranges Design Cleanup","Kona","|Complete|","15.0" "`P1286R2 `__","CWG","Contra CWG DR1778","Kona","","" "`P1357R1 `__","LWG","Traits for [Un]bounded Arrays","Kona","|Complete|","9.0" "`P1458R1 `__","LWG","Mandating the Standard Library: Clause 16 - Language support library","Kona","|Complete|","9.0" @@ -107,7 +107,7 @@ "`P0660R10 `__","LWG","Stop Token and Joining Thread, Rev 10","Cologne","","" "`P0784R7 `__","CWG","More constexpr containers","Cologne","|Complete|","12.0" "`P0980R1 `__","LWG","Making std::string constexpr","Cologne","|Complete|","15.0" -"`P1004R2 `__","LWG","Making std::vector constexpr","Cologne","","" +"`P1004R2 `__","LWG","Making std::vector constexpr","Cologne","|Complete|","15.0" "`P1035R7 `__","LWG","Input Range Adaptors","Cologne","","" "`P1065R2 `__","LWG","Constexpr INVOKE","Cologne","|Complete|","12.0" "`P1135R6 `__","LWG","The C++20 Synchronization Library","Cologne","|Complete|","11.0" @@ -141,7 +141,7 @@ "`P1645R1 `__","LWG","constexpr for numeric algorithms","Belfast","|Complete|","12.0" "`P1686R2 `__","LWG","Mandating the Standard Library: Clause 27 - Time library","Belfast","* *","" "`P1690R1 `__","LWG","Refinement Proposal for P0919 Heterogeneous lookup for unordered containers","Belfast","|Complete|","12.0" -"`P1716R3 `__","LWG","ranges compare algorithm are over-constrained","Belfast","* *","" +"`P1716R3 `__","LWG","ranges compare algorithm are over-constrained","Belfast","|Complete|","15.0" "`P1718R2 `__","LWG","Mandating the Standard Library: Clause 25 - Algorithms library","Belfast","* *","" "`P1719R2 `__","LWG","Mandating the Standard Library: Clause 26 - Numerics library","Belfast","* *","" "`P1720R2 `__","LWG","Mandating the Standard Library: Clause 28 - Localization library","Belfast","* *","" @@ -153,7 +153,7 @@ "`P1865R1 `__","LWG","Add max() to latch and barrier","Belfast","|Complete|","11.0" "`P1869R1 `__","LWG","Rename 'condition_variable_any' interruptible wait methods","Belfast","* *","" "`P1870R1 `__","LWG","forwarding-range is too subtle","Belfast","|Complete|","15.0" -"`P1871R1 `__","LWG","Should concepts be enabled or disabled?","Belfast","|Complete|","14.0" +"`P1871R1 `__","LWG","Concept traits should be named after concepts","Belfast","|Complete|","14.0" "`P1872R0 `__","LWG","span should have size_type, not index_type","Belfast","|Complete|","10.0" "`P1878R1 `__","LWG","Constraining Readable Types","Belfast","|Complete|","15.0" "`P1892R1 `__","LWG","Extended locale-specific presentation specifiers for std::format","Belfast","|Complete|","14.0" @@ -166,7 +166,7 @@ "`P0586R2 `__","LWG","Safe integral comparisons","Prague","|Complete|","13.0" "`P0593R6 `__","CWG","Implicit creation of objects for low-level object manipulation","Prague","* *","" "`P1115R3 `__","LWG","Improving the Return Value of Erase-Like Algorithms II: Free erase/erase if","Prague","|Complete|","11.0" -"`P1243R4 `__","LWG","Rangify New Algorithms","Prague","* *","" +"`P1243R4 `__","LWG","Rangify New Algorithms","Prague","|Complete|","15.0" "`P1460R1 `__","LWG","Mandating the Standard Library: Clause 20 - Utilities library","Prague","* *","" "`P1739R4 `__","LWG","Avoid template bloat for safe_ranges in combination with ""subrange-y"" view adaptors","Prague","|Complete|","15.0" "`P1831R1 `__","LWG","Deprecating volatile: library","Prague","* *","" @@ -190,7 +190,7 @@ "`P2091R0 `__","LWG","Issues with range access CPOs","Prague","|Complete|","15.0" "`P2101R0 `__","LWG","'Models' subsumes 'satisfies' (Wording for US298 and US300)","Prague","* *","" "`P2102R0 `__","LWG","Make 'implicit expression variations' more explicit (Wording for US185)","Prague","* *","" -"`P2106R0 `__","LWG","Alternative wording for GB315 and GB316","Prague","* *","" +"`P2106R0 `__","LWG","Alternative wording for GB315 and GB316","Prague","|Complete|","15.0" "`P2116R0 `__","LWG","Remove tuple-like protocol support from fixed-extent span","Prague","|Complete|","11.0" "","","","","","" "`P2231R1 `__","LWG","Missing constexpr in std::optional and std::variant","June 2021","|Partial| [#note-P2231]_","13.0" diff --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv index af62c1f92f7f0..361e76657b51a 100644 --- a/libcxx/docs/Status/Cxx2bIssues.csv +++ b/libcxx/docs/Status/Cxx2bIssues.csv @@ -159,8 +159,33 @@ "`3660 `__","``iterator_traits::pointer`` should conform to §[iterator.traits]","February 2022","|Complete|","14.0" "`3661 `__","``constinit atomic> a(nullptr);`` should work","February 2022","","" "","","","","" +"`3564 `__","``transform_view::iterator::value_type`` and ``iterator_category`` should use ``const F&``","July 2022","","","|ranges|" +"`3617 `__","``function``/``packaged_task`` deduction guides and deducing ``this``","July 2022","","" +"`3656 `__","Inconsistent bit operations returning a count","July 2022","|Complete|","15.0","" +"`3659 `__","Consider ``ATOMIC_FLAG_INIT`` undeprecation","July 2022","|Complete|","15.0" +"`3670 `__","``Cpp17InputIterators`` don't have integer-class difference types","July 2022","","","|ranges|" +"`3671 `__","``atomic_fetch_xor`` missing from ``stdatomic.h``","July 2022","","" +"`3672 `__","``common_iterator::operator->()`` should return by value","July 2022","","","|ranges|" +"`3683 `__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","July 2022","","" +"`3687 `__","``expected`` move constructor should move","July 2022","","" +"`3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","July 2022","","","|spaceship|" +"`3701 `__","Make ``formatter, charT>`` requirement explicit","July 2022","","","|format|" +"`3702 `__","Should ``zip_transform_view::iterator`` remove ``operator<``","July 2022","","" +"`3703 `__","Missing requirements for ``expected`` requires ``is_void``","July 2022","","" +"`3704 `__","LWG 2059 added overloads that might be ill-formed for sets","July 2022","","" +"`3705 `__","Hashability shouldn't depend on basic_string's allocator","July 2022","","" +"`3707 `__","chunk_view::outer-iterator::value_type::size should return unsigned type","July 2022","","","|ranges|" +"`3708 `__","``take_while_view::sentinel``'s conversion constructor should move","July 2022","","","|ranges|" +"`3709 `__","LWG-3703 was underly ambitious","July 2022","","" +"`3710 `__","The ``end`` of ``chunk_view`` for input ranges can be ``const``","July 2022","","","|ranges|" +"`3711 `__","Missing preconditions for slide_view constructor","July 2022","","","|ranges|" +"`3712 `__","``chunk_view`` and ``slide_view`` should not be ``default_initializable``","July 2022","","","|ranges|" +"`3713 `__","Sorted with respect to comparator (only)","July 2022","","" +"`3715 `__","``view_interface::empty`` is overconstrained","July 2022","","" +"`3719 `__","Directory iterators should be usable with default sentinel","July 2022","","" +"`3721 `__","Allow an ``arg-id`` with a value of zero for ``width`` in ``std-format-spec``","July 2022","","","|format|" +"`3724 `__","``decay-copy`` should be constrained","July 2022","|Complete|","14.0" +"","","","","" "`3645 `__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","Not voted in","|Complete|","14.0","" -"`3656 `__","Inconsistent bit operations returning a count","Not voted in","|Complete|","15.0","" "`3631 `__","``basic_format_arg(T&&)`` should use ``remove_cvref_t`` throughout","Not voted in","|Complete|","15.0","" -"`3659 `__","Consider ``ATOMIC_FLAG_INIT`` undeprecation","Not voted in","|Complete|","15.0" "","","","","" diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv index 15531dff1e481..27ff57c92150f 100644 --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -51,3 +51,47 @@ "`P2442R1 `__","LWG","Windowing range adaptors: ``views::chunk`` and ``views::slide``","February 2022","","" "`P2443R1 `__","LWG","``views::chunk_by``","February 2022","","" "","","","","","" +"`P0009R18 `__","LWG","mdspan: A Non-Owning Multidimensional Array Reference","July 2022","","" +"`P0429R9 `__","LWG","A Standard ``flat_map``","July 2022","","" +"`P1169R4 `__","LWG","``static operator()``","July 2022","","" +"`P1222R4 `__","LWG","A Standard ``flat_set``","July 2022","","" +"`P1223R5 `__","LWG","``ranges::find_last()``, ``ranges::find_last_if()``, and ``ranges::find_last_if_not()``","July 2022","","" +"`P1467R9 `__","LWG","Extended ``floating-point`` types and standard names","July 2022","","" +"`P1642R11 `__","LWG","Freestanding ``[utilities]``, ``[ranges]``, and ``[iterators]``","July 2022","","" +"`P1899R3 `__","LWG","``stride_view``","July 2022","","" +"`P2093R14 `__","LWG","Formatted output","July 2022","","" +"`P2165R4 `__","LWG","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","July 2022","","" +"`P2278R4 `__","LWG","``cbegin`` should always return a constant iterator","July 2022","","" +"`P2286R8 `__","LWG","Formatting Ranges","July 2022","","" +"`P2291R3 `__","LWG","Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ```` Header","July 2022","","" +"`P2302R4 `__","LWG","``std::ranges::contains``","July 2022","","" +"`P2322R6 `__","LWG","``ranges::fold``","July 2022","","" +"`P2374R4 `__","LWG","``views::cartesian_product``","July 2022","","" +"`P2404R3 `__","LWG","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","July 2022","","" +"`P2408R5 `__","LWG","Ranges iterators as inputs to non-Ranges algorithms","July 2022","","" +"`P2417R2 `__","LWG","A more ``constexpr`` ``bitset``","July 2022","","" +"`P2419R2 `__","LWG","Clarify handling of encodings in localized formatting of chrono types","July 2022","","" +"`P2438R2 `__","LWG","``std::string::substr() &&``","July 2022","","" +"`P2445R1 `__","LWG","``forward_like``","July 2022","","" +"`P2446R2 `__","LWG","``views::as_rvalue``","July 2022","","" +"`P2460R2 `__","LWG","Relax requirements on ``wchar_t`` to match existing practices","July 2022","","" +"`P2465R3 `__","LWG","Standard Library Modules ``std`` and ``std.compat``","July 2022","","" +"`P2467R1 `__","LWG","Support exclusive mode for ``fstreams``","July 2022","","" +"`P2474R2 `__","LWG","``views::repeat``","July 2022","","" +"`P2494R2 `__","LWG","Relaxing range adaptors to allow for move only types","July 2022","","" +"`P2499R0 `__","LWG","``string_view`` range constructor should be ``explicit``","July 2022","","" +"`P2502R2 `__","LWG","``std::generator``: Synchronous Coroutine Generator for Ranges","July 2022","","" +"`P2508R1 `__","LWG","Exposing ``std::basic-format-string``","July 2022","|Complete|","15.0" +"`P2513R4 `__","LWG","``char8_t`` Compatibility and Portability Fixes","July 2022","","" +"`P2517R1 `__","LWG","Add a conditional ``noexcept`` specification to ``std::apply``","July 2022","","" +"`P2520R0 `__","LWG","``move_iterator`` should be a random access iterator","July 2022","","" +"`P2540R1 `__","LWG","Empty Product for certain Views","July 2022","","" +"`P2549R1 `__","LWG","``std::unexpected`` should have ``error()`` as member accessor","July 2022","","" +"`P2553R1 `__","LWG","Make ``mdspan`` ``size_type`` controllable","July 2022","","" +"`P2554R0 `__","LWG","C-Array Interoperability of MDSpan","July 2022","","" +"`P2585R0 `__","LWG","Improving default container formatting","July 2022","","" +"`P2590R2 `__","LWG","Explicit lifetime management","July 2022","","" +"`P2599R2 `__","LWG","``mdspan::size_type`` should be ``index_type``","July 2022","","" +"`P2604R0 `__","LWG","mdspan: rename pointer and contiguous","July 2022","","" +"`P2613R1 `__","LWG","Add the missing ``empty`` to ``mdspan``","July 2022","","" +"","","","","","" diff --git a/libcxx/docs/Status/FormatIssues.csv b/libcxx/docs/Status/FormatIssues.csv index 3f7304520c9e9..c3bdf169e82b1 100644 --- a/libcxx/docs/Status/FormatIssues.csv +++ b/libcxx/docs/Status/FormatIssues.csv @@ -5,6 +5,7 @@ Number,Name,Assignee,Patch,Status,First released version `P1868 `_,"width: clarifying units of width and precision in std::format (Implements the unicode support.)",Mark de Wever,"`D103413 `__ `D103425 `__ `D103670 `__",|Complete|,Clang 14 `P2216 `_,"std::format improvements",Mark de Wever,,|Complete|,Clang 15 `P2418 `__,"Add support for ``std::generator``-like types to ``std::format``",Mark de Wever,`D127570 `__,|Complete|, Clang 15 +`P2508R1 `__,"Exposing ``std::basic-format-string``","C++23","Mark de Wever","|Complete|",Clang 15 `P1361 `_,"Integration of chrono with text formatting",Mark de Wever,,|In Progress|, `P2372 `__,"Fixing locale handling in chrono formatters",Mark de Wever,,|In Progress|, diff --git a/libcxx/docs/Status/RangesAlgorithms.csv b/libcxx/docs/Status/RangesAlgorithms.csv index ecbfb3329c536..642989677c9da 100644 --- a/libcxx/docs/Status/RangesAlgorithms.csv +++ b/libcxx/docs/Status/RangesAlgorithms.csv @@ -13,7 +13,7 @@ Search,lexicographical_compare,Nikolas Klauser,`D127130 `_,✅ Search,lower_bound,Nikolas Klauser,`D121964 `_,✅ Search,upper_bound,Nikolas Klauser,`D121964 `_,✅ -Search,equal_range,Hui Xie,`D129796 `,✅ +Search,equal_range,Hui Xie,`D129796 `_,✅ Search,binary_search,Nikolas Klauser,`D121964 `_,✅ Search,min,Nikolas Klauser,`D119589 `_,✅ Search,max,Nikolas Klauser,`D122002 `_,✅ @@ -29,11 +29,11 @@ Search,find_end,Nikolas Klauser,`D124079 `_,✅ Read-only,is_partitioned,Nikolas Klauser,`D124440 `_,✅ Read-only,is_sorted,Nikolas Klauser,`D125608 `_,✅ Read-only,is_sorted_until,Nikolas Klauser,`D125608 `_,✅ -Read-only,includes,Hui Xie,`D130116 `,✅ +Read-only,includes,Hui Xie,`D130116 `_,✅ Read-only,is_heap,Konstantin Varlamov,`D130547 `_,✅ Read-only,is_heap_until,Konstantin Varlamov,`D130547 `_,✅ -Read-only,clamp,Nikolas Klauser,`D126193 `_,Under review -Read-only,is_permutation,Nikolas Klauser,`D127194 `_,Under review +Read-only,clamp,Nikolas Klauser,`D126193 `_,✅ +Read-only,is_permutation,Nikolas Klauser,`D127194 `_,✅ Read-only,for_each,Nikolas Klauser,`D124332 `_,✅ Read-only,for_each_n,Nikolas Klauser,`D124332 `_,✅ Write,copy,Nikolas Klauser,`D122982 `_,✅ @@ -47,19 +47,19 @@ Write,fill_n,Nikolas Klauser,`D123462 `_,✅ Write,transform,Nikolas Klauser,`D122173 `_,✅ Write,generate,Konstantin Varlamov,`D130552 `_,✅ Write,generate_n,Konstantin Varlamov,`D130552 `_,✅ -Write,remove_copy,Nikolas Klauser,n/a,Not started -Write,remove_copy_if,Nikolas Klauser,n/a,Not started +Write,remove_copy,Nikolas Klauser,`D130599 `_,✅ +Write,remove_copy_if,Nikolas Klauser,`D130599 `_,✅ Write,replace,Nikolas Klauser,`D126283 `_,✅ Write,replace_if,Nikolas Klauser,`D126283 `_,✅ -Write,replace_copy,Nikolas Klauser,`D129806 `_,Under review -Write,replace_copy_if,Nikolas Klauser,`D129806 `_,Under review +Write,replace_copy,Nikolas Klauser,`D129806 `_,✅ +Write,replace_copy_if,Nikolas Klauser,`D129806 `_,✅ Write,swap_ranges,Nikolas Klauser,`D116303 `_,✅ Write,reverse_copy,Nikolas Klauser,`D127211 `_,✅ Write,rotate_copy,Nikolas Klauser,`D127211 `_,✅ -Write,sample,Not assigned,n/a,Not started -Write,unique_copy,Not assigned,n/a,Not started +Write,sample,Konstantin Varlamov,`D130865 `_,✅ +Write,unique_copy,Hui Xie,`D130404 `_,✅ Write,partition_copy,Konstantin Varlamov,`D130070 `_,✅ -Write,partial_sort_copy,Konstantin Varlamov,n/a,In progress +Write,partial_sort_copy,Konstantin Varlamov,`D130532 `_,✅ Merge,merge,Hui Xie,`D128611 `_,✅ Merge,set_difference,Hui Xie,`D128983 `_,✅ Merge,set_intersection,Hui Xie,`D129233 `_,✅ @@ -68,22 +68,22 @@ Merge,set_union,Hui Xie,`D129657 `_,✅ Permutation,remove,Nikolas Klauser,`D128618 `_,✅ Permutation,remove_if,Nikolas Klauser,`D128618 `_,✅ Permutation,reverse,Nikolas Klauser,`D125752 `_,✅ -Permutation,rotate,Nikolas Klauser,`D124122 `_,Under review +Permutation,rotate,Konstantin Varlamov and Nikolas Klauser,`D130758 `_,✅ Permutation,shuffle,Konstantin Varlamov,`D130321 `_,✅ -Permutation,unique,Not assigned,n/a,Not started +Permutation,unique,Hui Xie,`D130404 `_,✅ Permutation,partition,Konstantin Varlamov,`D129624 `_,✅ Permutation,stable_partition,Konstantin Varlamov,`D129624 `_,✅ Permutation,sort,Konstantin Varlamov,`D127557 `_,✅ Permutation,stable_sort,Konstantin Varlamov,`D127834 `_,✅ Permutation,nth_element,Konstantin Varlamov,`D128149 `_,✅ Permutation,partial_sort,Konstantin Varlamov,`D128744 `_,✅ -Permutation,inplace_merge,Not assigned,n/a,Not started +Permutation,inplace_merge,Hui Xie,`D130627 `_,✅ Permutation,make_heap,Konstantin Varlamov,`D128115 `_,✅ Permutation,push_heap,Konstantin Varlamov,`D128115 `_,✅ Permutation,pop_heap,Konstantin Varlamov,`D128115 `_,✅ Permutation,sort_heap,Konstantin Varlamov,`D128115 `_,✅ -Permutation,prev_permutation,Not assigned,n/a,Not started -Permutation,next_permutation,Not assigned,n/a,Not started +Permutation,next_permutation,Nikolas Klauser,`D129859 `_,✅ +Permutation,prev_permutation,Nikolas Klauser,`D129859 `_,✅ Uninitialised memory,uninitialized_copy,Konstantin Varlamov,`D116023 `_,✅ Uninitialised memory,uninitialized_copy_n,Konstantin Varlamov,`D116023 `_,✅ Uninitialised memory,uninitialized_fill,Konstantin Varlamov,`D115626 `_,✅ diff --git a/libcxx/docs/Status/RangesIssues.csv b/libcxx/docs/Status/RangesIssues.csv index 0629255ba493c..4c64237c260c9 100644 --- a/libcxx/docs/Status/RangesIssues.csv +++ b/libcxx/docs/Status/RangesIssues.csv @@ -1,27 +1,27 @@ "Number","Name","Status","First released version" -`P0896R4 `__,,, +`P0896R4 `__,,|Complete|,15.0 `P1035R7 `__,Input Range Adaptors,, `P1207R4 `__,Movability Of Single-Pass Iterators,|Complete|,15.0 -`P1243R4 `__,Rangify New Algorithms,, +`P1243R4 `__,Rangify New Algorithms,|Complete|,15.0 `P1248R1 `__,Fixing Relations,|Complete|,13.0 -`P1252R2 `__,Ranges Design Cleanup,, +`P1252R2 `__,Ranges Design Cleanup,|Complete|,15.0 `P1391R4 `__,Range Constructor For string_view,|Complete|,14.0 `P1456R1 `__,Move-Only Views,|Complete|,15.0 `P1474R1 `__,Helpful Pointers For contiguous_iterator,|Complete|,15.0 `P1522R1 `__,Iterator Difference Type And Integer Overflow,|Complete|,15.0 `P1523R1 `__,Views And Size Types,|Complete|,15.0 `P1638R1 `__,basic_istream_view::iterator Should Not Be Copyable,, -`P1716R3 `__,Range Comparison Algorithms Are Over-Constrained,, +`P1716R3 `__,Range Comparison Algorithms Are Over-Constrained,|Complete|,15.0 `P1739R4 `__,Avoiding Template Bloat For Ranges,|Complete|,15.0 `P1862R1 `__,Range Adaptors For Non-Copyable Iterators,, `P1870R1 `__,forwarding-range is too subtle,|Complete|,15.0 -`P1871R1 `__,disable_sized_sentinel_for,|Complete|,14.0 +`P1871R1 `__,Concept traits should be named after concepts,|Complete|,14.0 `P1878R1 `__,Constraining Readable Types,|Complete|,15.0 `P1970R2 `__,Consistency for size() functions: Add ranges::ssize,|Complete|,15.0 `P1983R0 `__,"Wording for GB301, US296, US292, US291, and US283",|Complete|,15.0 `P1994R1 `__,elements_view Needs Its Own sentinel,, `P2091R0 `__,Fixing Issues With Range Access CPOs,|Complete|,15.0 -`P2106R0 `__,Range Algorithm Result Types,, +`P2106R0 `__,Alternative wording for GB315 and GB316,|Complete|,15.0 `P2325R3 `__,Views should not be required to be default constructible ,, `P2328R1 `__,join_view should join all views of ranges,|Complete|,14.0 diff --git a/libcxx/docs/TestingLibcxx.rst b/libcxx/docs/TestingLibcxx.rst index 04ed5316df23a..9d73b7056b3cd 100644 --- a/libcxx/docs/TestingLibcxx.rst +++ b/libcxx/docs/TestingLibcxx.rst @@ -27,7 +27,7 @@ Usage After building libc++, you can run parts of the libc++ test suite by simply running ``llvm-lit`` on a specified test or directory. If you're unsure whether the required libraries have been built, you can use the -`cxx-test-depends` target. For example: +``cxx-test-depends`` target. For example: .. code-block:: bash @@ -37,45 +37,41 @@ whether the required libraries have been built, you can use the $ /bin/llvm-lit -sv libcxx/test/std/depr/depr.c.headers/stdlib_h.pass.cpp # Run a single test $ /bin/llvm-lit -sv libcxx/test/std/atomics libcxx/test/std/threads # Test std::thread and std::atomic +.. note:: + If you used the Bootstrapping build instead of the default runtimes build, the + ``cxx-test-depends`` target is instead named ``runtimes-test-depends``, and + you will need to prefix ``/runtimes/runtimes--bins/`` to the + paths of all tests. + In the default configuration, the tests are built against headers that form a fake installation root of libc++. This installation root has to be updated when -changes are made to the headers, so you should re-run the `cxx-test-depends` -target before running the tests manually with `lit` when you make any sort of +changes are made to the headers, so you should re-run the ``cxx-test-depends`` +target before running the tests manually with ``lit`` when you make any sort of change, including to the headers. Sometimes you'll want to change the way LIT is running the tests. Custom options -can be specified using the `--param==` flag. The most common option -you'll want to change is the standard dialect (ie -std=c++XX). By default the +can be specified using the ``--param =`` flag. The most common option +you'll want to change is the standard dialect (ie ``-std=c++XX``). By default the test suite will select the newest C++ dialect supported by the compiler and use -that. However if you want to manually specify the option like so: +that. However, you can manually specify the option like so if you want: .. code-block:: bash $ /bin/llvm-lit -sv libcxx/test/std/containers # Run the tests with the newest -std - $ /bin/llvm-lit -sv libcxx/test/std/containers --param=std=c++03 # Run the tests in C++03 - -Occasionally you'll want to add extra compile or link flags when testing. -You can do this as follows: - -.. code-block:: bash - - $ /bin/llvm-lit -sv libcxx/test --param=compile_flags='-Wcustom-warning' - $ /bin/llvm-lit -sv libcxx/test --param=link_flags='-L/custom/library/path' + $ /bin/llvm-lit -sv libcxx/test/std/containers --param std=c++03 # Run the tests in C++03 -Some other common examples include: +Other parameters are supported by the test suite. Those are defined in ``libcxx/utils/libcxx/test/params.py``. +If you want to customize how to run the libc++ test suite beyond what is available +in ``params.py``, you most likely want to use a custom site configuration instead. -.. code-block:: bash +The libc++ test suite works by loading a site configuration that defines various +"base" parameters (via Lit substitutions). These base parameters represent things +like the compiler to use for running the tests, which default compiler and linker +flags to use, and how to run an executable. This system is meant to be easily +extended for custom needs, in particular when porting the libc++ test suite to +new platforms. - # Specify a custom compiler. - $ /bin/llvm-lit -sv libcxx/test/std --param=cxx_under_test=/opt/bin/g++ - - # Disable warnings in the test suite - $ /bin/llvm-lit -sv libcxx/test --param=enable_warnings=False - - # Use UBSAN when running the tests. - $ /bin/llvm-lit -sv libcxx/test --param=use_sanitizer=Undefined - -Using a custom site configuration +Using a Custom Site Configuration --------------------------------- By default, the libc++ test suite will use a site configuration that matches @@ -96,84 +92,6 @@ configuration easier. $ make -C cxx-test-depends $ /bin/llvm-lit -sv libcxx/test # will use your custom config file - -LIT Options -=========== - -:program:`lit` [*options*...] [*filenames*...] - -Command Line Options --------------------- - -To use these options you pass them on the LIT command line as ``--param NAME`` -or ``--param NAME=VALUE``. Some options have default values specified during -CMake's configuration. Passing the option on the command line will override the -default. - -.. program:: lit - -.. option:: cxx_under_test= - - Specify the compiler used to build the tests. - -.. option:: stdlib= - - **Values**: libc++, libstdc++, msvc - - Specify the C++ standard library being tested. The default is libc++ if this - option is not provided. This option is intended to allow running the libc++ - test suite against other standard library implementations. - -.. option:: std= - - **Values**: c++03, c++11, c++14, c++17, c++20, c++2b - - Change the standard version used when building the tests. - -.. option:: cxx_headers= - - Specify the c++ standard library headers that are tested. By default the - headers in the source tree are used. - -.. option:: cxx_library_root= - - Specify the directory of the libc++ library to be tested. By default the - library folder of the build directory is used. - - -.. option:: cxx_runtime_root= - - Specify the directory of the libc++ library to use at runtime. This directory - is not added to the linkers search path. This can be used to compile tests - against one version of libc++ and run them using another. The default value - for this option is `cxx_library_root`. - -.. option:: use_system_cxx_lib= - - **Default**: False - - Enable or disable testing against the installed version of libc++ library. - This impacts whether the ``use_system_cxx_lib`` Lit feature is defined or - not. The ``cxx_library_root`` and ``cxx_runtime_root`` parameters should - still be used to specify the path of the library to link to and run against, - respectively. - -.. option:: use_sanitizer= - - **Values**: Memory, MemoryWithOrigins, Address, Undefined - - Run the tests using the given sanitizer. If LLVM_USE_SANITIZER was given when - building libc++ then that sanitizer will be used by default. - -.. option:: llvm_unwinder - - Enable the use of LLVM unwinder instead of libgcc. - -.. option:: builtins_library - - Path to the builtins library to use instead of libgcc. - - Writing Tests ------------- diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst index 40a8d9a36838a..b3f1bf96c9687 100644 --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -152,18 +152,21 @@ where the static or shared library was compiled **with** assertions but the user disable them). However, most of the code in libc++ is in the headers, so the user-selected value for ``_LIBCPP_ENABLE_ASSERTIONS`` (if any) will usually be respected. -When an assertion fails, an assertion handler function is called. The library provides a default -assertion handler that prints an error message and calls ``std::abort()``. Note that this assertion -handler is provided by the static or shared library, so it is only available when deploying to a -platform where the compiled library is sufficiently recent. However, users can also override that -assertion handler with their own, which can be useful to provide custom behavior, or when deploying -to older platforms where the default assertion handler isn't available. - -Replacing the default assertion handler is done by defining the following function: +When an assertion fails, the program is aborted through a special verbose termination function. The +library provides a default function that prints an error message and calls ``std::abort()``. Note +that this function is provided by the static or shared library, so it is only available when deploying +to a platform where the compiled library is sufficiently recent. On older platforms, the program will +terminate in an unspecified unsuccessful manner, but the quality of diagnostics won't be great. +However, users can also override that function with their own, which can be useful to either provide +custom behavior or when deploying to an older platform where the default function isn't available. + +Replacing the default verbose termination function is done by defining the +``_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED`` macro in all translation units of your program +and defining the following function in exactly one translation unit: .. code-block:: cpp - void __libcpp_assertion_handler(char const* format, ...) + void __libcpp_verbose_abort(char const* format, ...) This mechanism is similar to how one can replace the default definition of ``operator new`` and ``operator delete``. For example: @@ -171,9 +174,9 @@ and ``operator delete``. For example: .. code-block:: cpp // In HelloWorldHandler.cpp - #include // must include any libc++ header before defining the handler (C compatibility headers excluded) + #include // must include any libc++ header before defining the function (C compatibility headers excluded) - void std::__libcpp_assertion_handler(char const* format, ...) { + void std::__libcpp_verbose_abort(char const* format, ...) { va_list list; va_start(list, format); std::vfprintf(stderr, format, list); @@ -187,31 +190,16 @@ and ``operator delete``. For example: int main() { std::vector v; - int& x = v[0]; // Your assertion handler will be called here if _LIBCPP_ENABLE_ASSERTIONS=1 + int& x = v[0]; // Your termination function will be called here if _LIBCPP_ENABLE_ASSERTIONS=1 } -Also note that the assertion handler should usually not return. Since the assertions in libc++ -catch undefined behavior, your code will proceed with undefined behavior if your assertion -handler is called and does return. - -Furthermore, throwing an exception from the assertion handler is not recommended. Indeed, many -functions in the library are ``noexcept``, and any exception thrown from the assertion handler -will result in ``std::terminate`` being called. - -Back-deploying with a custom assertion handler ----------------------------------------------- -When deploying to an older platform that does not provide a default assertion handler, the -compiler will diagnose the usage of ``std::__libcpp_assertion_handler`` with an error. This -is done to avoid the load-time error that would otherwise happen if the code was being deployed -on the older system. - -If you are providing a custom assertion handler, this error is effectively a false positive. -To let the library know that you are providing a custom assertion handler in back-deployment -scenarios, you must define the ``_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED`` macro, -and the library will assume that you are providing your own definition. If no definition is -provided and the code is back-deployed to the older platform, it will fail to load when the -dynamic linker fails to find a definition for ``std::__libcpp_assertion_handler``, so you -should only remove the guard rails if you really mean it! +Also note that the verbose termination function should never return. Since assertions in libc++ +catch undefined behavior, your code will proceed with undefined behavior if your function is called +and does return. + +Furthermore, exceptions should not be thrown from the function. Indeed, many functions in the +library are ``noexcept``, and any exception thrown from the termination function will result +in ``std::terminate`` being called. Libc++ Configuration Macros =========================== diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 970b4683d37b6..f7c2d99e78b08 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -72,6 +72,7 @@ set(files __algorithm/ranges_all_of.h __algorithm/ranges_any_of.h __algorithm/ranges_binary_search.h + __algorithm/ranges_clamp.h __algorithm/ranges_copy.h __algorithm/ranges_copy_backward.h __algorithm/ranges_copy_if.h @@ -96,6 +97,7 @@ set(files __algorithm/ranges_is_heap.h __algorithm/ranges_is_heap_until.h __algorithm/ranges_is_partitioned.h + __algorithm/ranges_is_permutation.h __algorithm/ranges_is_sorted.h __algorithm/ranges_is_sorted_until.h __algorithm/ranges_iterator_concept.h @@ -112,6 +114,7 @@ set(files __algorithm/ranges_mismatch.h __algorithm/ranges_move.h __algorithm/ranges_move_backward.h + __algorithm/ranges_next_permutation.h __algorithm/ranges_none_of.h __algorithm/ranges_nth_element.h __algorithm/ranges_partial_sort.h @@ -120,6 +123,7 @@ set(files __algorithm/ranges_partition_copy.h __algorithm/ranges_partition_point.h __algorithm/ranges_pop_heap.h + __algorithm/ranges_prev_permutation.h __algorithm/ranges_push_heap.h __algorithm/ranges_remove.h __algorithm/ranges_remove_copy.h @@ -131,7 +135,9 @@ set(files __algorithm/ranges_replace_if.h __algorithm/ranges_reverse.h __algorithm/ranges_reverse_copy.h + __algorithm/ranges_rotate.h __algorithm/ranges_rotate_copy.h + __algorithm/ranges_sample.h __algorithm/ranges_search.h __algorithm/ranges_search_n.h __algorithm/ranges_set_difference.h @@ -177,9 +183,11 @@ set(files __algorithm/stable_sort.h __algorithm/swap_ranges.h __algorithm/transform.h + __algorithm/uniform_random_bit_generator_adaptor.h __algorithm/unique.h __algorithm/unique_copy.h __algorithm/unwrap_iter.h + __algorithm/unwrap_range.h __algorithm/upper_bound.h __assert __availability @@ -635,6 +643,7 @@ set(files __utility/transaction.h __utility/unreachable.h __variant/monostate.h + __verbose_abort algorithm any array diff --git a/libcxx/include/__algorithm/adjacent_find.h b/libcxx/include/__algorithm/adjacent_find.h index 83d8c260f27a2..1089bb20d5b2d 100644 --- a/libcxx/include/__algorithm/adjacent_find.h +++ b/libcxx/include/__algorithm/adjacent_find.h @@ -11,8 +11,10 @@ #define _LIBCPP___ALGORITHM_ADJACENT_FIND_H #include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,25 +22,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter +__adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { + if (__first == __last) + return __first; + _Iter __i = __first; + while (++__i != __last) { + if (__pred(*__first, *__i)) + return __first; + __first = __i; + } + return __i; +} + template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { - if (__first != __last) { - _ForwardIterator __i = __first; - while (++__i != __last) { - if (__pred(*__first, *__i)) - return __first; - __first = __i; - } - } - return __last; + return std::__adjacent_find(std::move(__first), std::move(__last), __pred); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last) { typedef typename iterator_traits<_ForwardIterator>::value_type __v; - return _VSTD::adjacent_find(__first, __last, __equal_to<__v>()); + return std::adjacent_find(std::move(__first), std::move(__last), __equal_to<__v>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/clamp.h b/libcxx/include/__algorithm/clamp.h index b3762b85a0bc9..30ddbdce64a92 100644 --- a/libcxx/include/__algorithm/clamp.h +++ b/libcxx/include/__algorithm/clamp.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 template _LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_INLINE_VISIBILITY constexpr const _Tp& clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) { @@ -33,7 +33,7 @@ clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) template _LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_INLINE_VISIBILITY constexpr const _Tp& clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) { diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h index 5428baa688592..f7535a81547a8 100644 --- a/libcxx/include/__algorithm/copy.h +++ b/libcxx/include/__algorithm/copy.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_COPY_H #include <__algorithm/unwrap_iter.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> @@ -88,10 +89,11 @@ template ::value && is_copy_constructible<_OutIter>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -pair<_InIter, _OutIter> -__copy(_InIter __first, _Sent __last, _OutIter __result) { - auto __ret = std::__copy_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result)); - return std::make_pair(std::__rewrap_iter(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); +pair<_InIter, _OutIter> __copy(_InIter __first, _Sent __last, _OutIter __result) { + auto __range = std::__unwrap_range(__first, __last); + auto __ret = std::__copy_impl(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__result)); + return std::make_pair( + std::__rewrap_range<_Sent>(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); } template diff --git a/libcxx/include/__algorithm/copy_backward.h b/libcxx/include/__algorithm/copy_backward.h index 26b8c4d791fd3..c5fa64bc8d751 100644 --- a/libcxx/include/__algorithm/copy_backward.h +++ b/libcxx/include/__algorithm/copy_backward.h @@ -20,7 +20,6 @@ #include <__ranges/subrange.h> #include <__utility/move.h> #include <__utility/pair.h> -#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -44,9 +43,10 @@ __copy_backward(_InputIterator __first, _InputIterator __last, _OutputIterator _ template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI constexpr pair<_Iter1, _Iter2> __copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) { - auto __reverse_range = std::__reverse_range(std::ranges::subrange(std::move(__first), std::move(__last))); + auto __last_iter = _IterOps<_AlgPolicy>::next(__first, std::move(__last)); + auto __reverse_range = std::__reverse_range(std::ranges::subrange(std::move(__first), __last_iter)); auto __ret = ranges::copy(std::move(__reverse_range), std::make_reverse_iterator(__result)); - return std::make_pair(__ret.in.base(), __ret.out.base()); + return std::make_pair(__last_iter, __ret.out.base()); } #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) diff --git a/libcxx/include/__algorithm/fill.h b/libcxx/include/__algorithm/fill.h index ec9968fdb8b34..901ba4e68689a 100644 --- a/libcxx/include/__algorithm/fill.h +++ b/libcxx/include/__algorithm/fill.h @@ -20,6 +20,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// fill isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void diff --git a/libcxx/include/__algorithm/fill_n.h b/libcxx/include/__algorithm/fill_n.h index 7482a4188dd51..6c5e44efde9b0 100644 --- a/libcxx/include/__algorithm/fill_n.h +++ b/libcxx/include/__algorithm/fill_n.h @@ -19,6 +19,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator diff --git a/libcxx/include/__algorithm/find_first_of.h b/libcxx/include/__algorithm/find_first_of.h index b968329fc3186..2096b0f0c9a53 100644 --- a/libcxx/include/__algorithm/find_first_of.h +++ b/libcxx/include/__algorithm/find_first_of.h @@ -24,7 +24,8 @@ template -void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) +template +void __half_inplace_merge(_InputIterator1 __first1, _Sent1 __last1, + _InputIterator2 __first2, _Sent2 __last2, + _OutputIterator __result, _Compare&& __comp) { for (; __first1 != __last1; ++__result) { if (__first2 == __last2) { - // TODO(alg-policy): pass `_AlgPolicy` once it's supported by `move`. - _VSTD::move(__first1, __last1, __result); + std::__move<_AlgPolicy>(__first1, __last1, __result); return; } @@ -84,13 +83,15 @@ void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1, } template -void -__buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, - _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, - typename iterator_traits<_BidirectionalIterator>::difference_type __len2, - typename iterator_traits<_BidirectionalIterator>::value_type* __buff) -{ - typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; +void __buffered_inplace_merge( + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare&& __comp, + typename iterator_traits<_BidirectionalIterator>::difference_type __len1, + typename iterator_traits<_BidirectionalIterator>::difference_type __len2, + typename iterator_traits<_BidirectionalIterator>::value_type* __buff) { + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; __destruct_n __d(0); unique_ptr __h2(__buff, __d); if (__len1 <= __len2) @@ -98,7 +99,7 @@ __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator value_type* __p = __buff; for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr(), (void) ++__i, (void) ++__p) ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); - std::__half_inplace_merge<_AlgPolicy, _Compare>(__buff, __p, __middle, __last, __first, __comp); + std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp); } else { @@ -108,19 +109,22 @@ __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator typedef __unconstrained_reverse_iterator<_BidirectionalIterator> _RBi; typedef __unconstrained_reverse_iterator _Rv; typedef __invert<_Compare> _Inverted; - std::__half_inplace_merge<_AlgPolicy, _Inverted>(_Rv(__p), _Rv(__buff), + std::__half_inplace_merge<_AlgPolicy>(_Rv(__p), _Rv(__buff), _RBi(__middle), _RBi(__first), _RBi(__last), _Inverted(__comp)); } } template -void -__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, - _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1, - typename iterator_traits<_BidirectionalIterator>::difference_type __len2, - typename iterator_traits<_BidirectionalIterator>::value_type* __buff, ptrdiff_t __buff_size) -{ +void __inplace_merge( + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare&& __comp, + typename iterator_traits<_BidirectionalIterator>::difference_type __len1, + typename iterator_traits<_BidirectionalIterator>::difference_type __len2, + typename iterator_traits<_BidirectionalIterator>::value_type* __buff, + ptrdiff_t __buff_size) { using _Ops = _IterOps<_AlgPolicy>; typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; @@ -130,7 +134,7 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, if (__len2 == 0) return; if (__len1 <= __buff_size || __len2 <= __buff_size) - return std::__buffered_inplace_merge<_AlgPolicy, _Compare> + return std::__buffered_inplace_merge<_AlgPolicy> (__first, __middle, __last, __comp, __len1, __len2, __buff); // shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0 for (; true; ++__first, (void) --__len1) @@ -158,8 +162,7 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, __len21 = __len2 / 2; __m2 = __middle; _Ops::advance(__m2, __len21); - // TODO: replace _ClassicAlgPolicy and __identity with _AlgPolicy and projection - __m1 = std::__upper_bound<_ClassicAlgPolicy>(__first, __middle, *__m2, __comp, std::__identity()); + __m1 = std::__upper_bound<_AlgPolicy>(__first, __middle, *__m2, __comp, std::__identity()); __len11 = _Ops::distance(__first, __m1); } else @@ -181,15 +184,13 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, difference_type __len22 = __len2 - __len21; // distance(__m2, __last) // [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) // swap middle two partitions - // TODO(alg-policy): pass `_AlgPolicy` once it's supported by `rotate`. - __middle = _VSTD::rotate(__m1, __middle, __m2); + __middle = std::__rotate<_AlgPolicy>(__m1, __middle, __m2).first; // __len12 and __len21 now have swapped meanings // merge smaller range with recursive call and larger with tail recursion elimination if (__len11 + __len21 < __len12 + __len22) { - std::__inplace_merge<_AlgPolicy, _Compare>( + std::__inplace_merge<_AlgPolicy>( __first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); -// _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); __first = __middle; __middle = __m2; __len1 = __len12; @@ -197,9 +198,8 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, } else { - std::__inplace_merge<_AlgPolicy, _Compare>( + std::__inplace_merge<_AlgPolicy>( __middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size); -// _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size); __last = __middle; __middle = __m1; __len1 = __len11; @@ -208,33 +208,40 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, } } -template -inline _LIBCPP_INLINE_VISIBILITY +template +_LIBCPP_HIDE_FROM_ABI void -inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, - _Compare __comp) +__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, + _Compare&& __comp) { typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; - difference_type __len1 = _VSTD::distance(__first, __middle); - difference_type __len2 = _VSTD::distance(__middle, __last); + difference_type __len1 = _IterOps<_AlgPolicy>::distance(__first, __middle); + difference_type __len2 = _IterOps<_AlgPolicy>::distance(__middle, __last); difference_type __buf_size = _VSTD::min(__len1, __len2); // TODO: Remove the use of std::get_temporary_buffer _LIBCPP_SUPPRESS_DEPRECATED_PUSH pair __buf = _VSTD::get_temporary_buffer(__buf_size); _LIBCPP_SUPPRESS_DEPRECATED_POP unique_ptr __h(__buf.first); - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__inplace_merge<_ClassicAlgPolicy, _Comp_ref>(__first, __middle, __last, __comp, __len1, __len2, - __buf.first, __buf.second); + return std::__inplace_merge<_AlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last), __comp, __len1, __len2, __buf.first, __buf.second); +} + +template +inline _LIBCPP_HIDE_FROM_ABI void inplace_merge( + _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) { + typedef typename __comp_ref_type<_Compare>::type _Comp_ref; + std::__inplace_merge<_ClassicAlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last), static_cast<_Comp_ref>(__comp)); } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI void inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) { - _VSTD::inplace_merge(__first, __middle, __last, + std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less::value_type>()); } diff --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h index cdd742048412a..06a4949e21b50 100644 --- a/libcxx/include/__algorithm/is_permutation.h +++ b/libcxx/include/__algorithm/is_permutation.h @@ -11,10 +11,16 @@ #define _LIBCPP___ALGORITHM_IS_PERMUTATION_H #include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> #include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__utility/move.h> +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,140 +28,211 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 bool -is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _BinaryPredicate __pred) { - // shorten sequences as much as possible by lopping of any equal prefix - for (; __first1 != __last1; ++__first1, (void)++__first2) - if (!__pred(*__first1, *__first2)) - break; - if (__first1 == __last1) - return true; +template +struct _ConstTimeDistance : false_type {}; - // __first1 != __last1 && *__first1 != *__first2 - typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1; - _D1 __l1 = _VSTD::distance(__first1, __last1); - if (__l1 == _D1(1)) - return false; - _ForwardIterator2 __last2 = _VSTD::next(__first2, __l1); - // For each element in [f1, l1) see if there are the same number of - // equal elements in [f2, l2) - for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) { +#if _LIBCPP_STD_VER > 17 + +template +struct _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2, __enable_if_t< + sized_sentinel_for<_Sent1, _Iter1> && + sized_sentinel_for<_Sent2, _Iter2> +>> : true_type {}; + +#else + +template +struct _ConstTimeDistance<_Iter1, _Iter1, _Iter2, _Iter2, __enable_if_t< + is_same::iterator_category, random_access_iterator_tag>::value && + is_same::iterator_category, random_access_iterator_tag>::value +> > : true_type {}; + +#endif // _LIBCPP_STD_VER > 17 + +// Internal functions + +// For each element in [f1, l1) see if there are the same number of equal elements in [f2, l2) +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) { + using _D1 = __iter_diff_t<_Iter1>; + + for (auto __i = __first1; __i != __last1; ++__i) { // Have we already counted the number of *__i in [f1, l1)? - _ForwardIterator1 __match = __first1; - for (; __match != __i; ++__match) - if (__pred(*__match, *__i)) + auto __match = __first1; + for (; __match != __i; ++__match) { + if (std::__invoke(__pred, std::__invoke(__proj1, *__match), std::__invoke(__proj1, *__i))) break; + } + if (__match == __i) { // Count number of *__i in [f2, l2) _D1 __c2 = 0; - for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) - if (__pred(*__i, *__j)) + for (auto __j = __first2; __j != __last2; ++__j) { + if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj2, *__j))) ++__c2; + } if (__c2 == 0) return false; + // Count number of *__i in [__i, l1) (we can start with 1) _D1 __c1 = 1; - for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j) - if (__pred(*__i, *__j)) + for (auto __j = _IterOps<_AlgPolicy>::next(__i); __j != __last1; ++__j) { + if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj1, *__j))) ++__c1; + } if (__c1 != __c2) return false; } } + return true; } -template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool -is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { - typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; - typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; - return _VSTD::is_permutation(__first1, __last1, __first2, __equal_to<__v1, __v2>()); +// 2+1 iterators, predicate. Not used by range algorithms. +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, + _BinaryPredicate&& __pred) { + // Shorten sequences as much as possible by lopping of any equal prefix. + for (; __first1 != __last1; ++__first1, (void)++__first2) { + if (!__pred(*__first1, *__first2)) + break; + } + + if (__first1 == __last1) + return true; + + // __first1 != __last1 && *__first1 != *__first2 + using _D1 = __iter_diff_t<_ForwardIterator1>; + _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); + if (__l1 == _D1(1)) + return false; + auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __l1); + + return std::__is_permutation_impl<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __identity(), __identity()); } -#if _LIBCPP_STD_VER > 11 -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 bool -__is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _BinaryPredicate __pred, forward_iterator_tag, forward_iterator_tag) { - // shorten sequences as much as possible by lopping of any equal prefix - for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) - if (!__pred(*__first1, *__first2)) +// 2+2 iterators, predicate, non-constant time `distance`. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2, + /*_ConstTimeDistance=*/false_type) { + // Shorten sequences as much as possible by lopping of any equal prefix. + while (__first1 != __last1 && __first2 != __last2) { + if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) break; + ++__first1; + ++__first2; + } + if (__first1 == __last1) return __first2 == __last2; - else if (__first2 == __last2) + if (__first2 == __last2) // Second range is shorter return false; - typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1; - _D1 __l1 = _VSTD::distance(__first1, __last1); + using _D1 = __iter_diff_t<_Iter1>; + _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); - typedef typename iterator_traits<_ForwardIterator2>::difference_type _D2; - _D2 __l2 = _VSTD::distance(__first2, __last2); + using _D2 = __iter_diff_t<_Iter2>; + _D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2); if (__l1 != __l2) return false; - // For each element in [f1, l1) see if there are the same number of - // equal elements in [f2, l2) - for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) { - // Have we already counted the number of *__i in [f1, l1)? - _ForwardIterator1 __match = __first1; - for (; __match != __i; ++__match) - if (__pred(*__match, *__i)) - break; - if (__match == __i) { - // Count number of *__i in [f2, l2) - _D1 __c2 = 0; - for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) - if (__pred(*__i, *__j)) - ++__c2; - if (__c2 == 0) - return false; - // Count number of *__i in [__i, l1) (we can start with 1) - _D1 __c1 = 1; - for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j) - if (__pred(*__i, *__j)) - ++__c1; - if (__c1 != __c2) - return false; - } - } - return true; + return std::__is_permutation_impl<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2); } -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 bool __is_permutation(_RandomAccessIterator1 __first1, _RandomAccessIterator2 __last1, - _RandomAccessIterator1 __first2, _RandomAccessIterator2 __last2, - _BinaryPredicate __pred, random_access_iterator_tag, - random_access_iterator_tag) { - if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) +// 2+2 iterators, predicate, specialization for constant-time `distance` call. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2, + /*_ConstTimeDistance=*/true_type) { + if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) return false; - return _VSTD::is_permutation<_RandomAccessIterator1, _RandomAccessIterator2, - _BinaryPredicate&>(__first1, __last1, __first2, __pred); + return std::__is_permutation<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2, + /*_ConstTimeDistance=*/false_type()); +} + +// 2+2 iterators, predicate +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) { + return std::__is_permutation<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2, + _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2>()); } +// Public interface + +// 2+1 iterators, predicate template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _BinaryPredicate __pred) { - return _VSTD::__is_permutation<_BinaryPredicate&>( - __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_ForwardIterator1>::iterator_category(), - typename iterator_traits<_ForwardIterator2>::iterator_category()); + _BinaryPredicate __pred) { + static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, + "The predicate has to be callable"); + + return std::__is_permutation<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), __pred); } +// 2+1 iterators +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + using __v1 = __iter_value_type<_ForwardIterator1>; + using __v2 = __iter_value_type<_ForwardIterator2>; + return std::is_permutation(__first1, __last1, __first2, __equal_to<__v1, __v2>()); +} + +#if _LIBCPP_STD_VER > 11 + +// 2+2 iterators template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { - typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; - typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; - return _VSTD::__is_permutation(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>(), - typename iterator_traits<_ForwardIterator1>::iterator_category(), - typename iterator_traits<_ForwardIterator2>::iterator_category()); + using __v1 = __iter_value_type<_ForwardIterator1>; + using __v2 = __iter_value_type<_ForwardIterator2>; + + return std::__is_permutation<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __equal_to<__v1, __v2>(), __identity(), __identity()); } -#endif + +// 2+2 iterators, predicate +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _BinaryPredicate __pred) { + static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, + "The predicate has to be callable"); + + return std::__is_permutation<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __identity(), __identity()); +} + +#endif // _LIBCPP_STD_VER > 11 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/iterator_operations.h b/libcxx/include/__algorithm/iterator_operations.h index 8307d71214e58..af461878737f9 100644 --- a/libcxx/include/__algorithm/iterator_operations.h +++ b/libcxx/include/__algorithm/iterator_operations.h @@ -10,13 +10,18 @@ #define _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H #include <__algorithm/iter_swap.h> +#include <__algorithm/ranges_iterator_concept.h> #include <__config> #include <__iterator/advance.h> #include <__iterator/distance.h> +#include <__iterator/incrementable_traits.h> #include <__iterator/iter_move.h> #include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__iterator/prev.h> +#include <__iterator/readable_traits.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> #include @@ -34,11 +39,22 @@ struct _RangeAlgPolicy {}; template <> struct _IterOps<_RangeAlgPolicy> { + + template + using __value_type = iter_value_t<_Iter>; + + template + using __iterator_category = ranges::__iterator_concept<_Iter>; + + template + using __difference_type = iter_difference_t<_Iter>; + static constexpr auto advance = ranges::advance; static constexpr auto distance = ranges::distance; static constexpr auto __iter_move = ranges::iter_move; static constexpr auto iter_swap = ranges::iter_swap; static constexpr auto next = ranges::next; + static constexpr auto prev = ranges::prev; static constexpr auto __advance_to = ranges::advance; }; @@ -49,6 +65,15 @@ struct _ClassicAlgPolicy {}; template <> struct _IterOps<_ClassicAlgPolicy> { + template + using __value_type = typename iterator_traits<_Iter>::value_type; + + template + using __iterator_category = typename iterator_traits<_Iter>::iterator_category; + + template + using __difference_type = typename iterator_traits<_Iter>::difference_type; + // advance template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 @@ -63,24 +88,46 @@ struct _IterOps<_ClassicAlgPolicy> { return std::distance(__first, __last); } - // iter_move + template + using __deref_t = decltype(*std::declval<_Iter&>()); + + template + using __move_t = decltype(std::move(*std::declval<_Iter&>())); + template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 - // Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce. - static __enable_if_t< - is_reference >::reference>::value, - typename remove_reference< typename iterator_traits<__uncvref_t<_Iter> >::reference >::type&&> - __iter_move(_Iter&& __i) { + static void __validate_iter_reference() { + static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__uncvref_t<_Iter> >::reference>::value, + "It looks like your iterator's `iterator_traits::reference` does not match the return type of " + "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] " + "and can lead to dangling reference issues at runtime, so we are flagging this."); + } + + // iter_move + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static + // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note + // that the C++03 mode doesn't support `decltype(auto)` as the return type. + __enable_if_t< + is_reference<__deref_t<_Iter> >::value, + __move_t<_Iter> > + __iter_move(_Iter&& __i) { + __validate_iter_reference<_Iter>(); + return std::move(*std::forward<_Iter>(__i)); } template - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 - // Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce. - static __enable_if_t< - !is_reference >::reference>::value, - typename iterator_traits<__uncvref_t<_Iter> >::reference> - __iter_move(_Iter&& __i) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static + // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a + // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that + // temporary. Note that the C++03 mode doesn't support `auto` as the return type. + __enable_if_t< + !is_reference<__deref_t<_Iter> >::value, + __deref_t<_Iter> > + __iter_move(_Iter&& __i) { + __validate_iter_reference<_Iter>(); + return *std::forward<_Iter>(__i); } @@ -100,11 +147,19 @@ struct _IterOps<_ClassicAlgPolicy> { template _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 - __uncvref_t<_Iter> next(_Iter&& __it, - typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1){ + __uncvref_t<_Iter> next(_Iter&& __it, + typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1) { return std::next(std::forward<_Iter>(__it), __n); } + // prev + template + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 + __uncvref_t<_Iter> prev(_Iter&& __iter, + typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1) { + return std::prev(std::forward<_Iter>(__iter), __n); + } + template _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 void __advance_to(_Iter& __first, _Iter __last) { diff --git a/libcxx/include/__algorithm/make_heap.h b/libcxx/include/__algorithm/make_heap.h index bf9dd96756af1..0aa67d18ed0ac 100644 --- a/libcxx/include/__algorithm/make_heap.h +++ b/libcxx/include/__algorithm/make_heap.h @@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { +void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) { using _CompRef = typename __comp_ref_type<_Compare>::type; _CompRef __comp_ref = __comp; @@ -34,7 +34,7 @@ void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _C if (__n > 1) { // start from the first parent, there is no need to consider children for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) { - std::__sift_down<_AlgPolicy, _CompRef>(__first, __comp_ref, __n, __first + __start); + std::__sift_down<_AlgPolicy>(__first, __comp_ref, __n, __first + __start); } } } diff --git a/libcxx/include/__algorithm/make_projected.h b/libcxx/include/__algorithm/make_projected.h index 64fc3dfb6a12c..6c1d156776675 100644 --- a/libcxx/include/__algorithm/make_projected.h +++ b/libcxx/include/__algorithm/make_projected.h @@ -14,51 +14,91 @@ #include <__functional/identity.h> #include <__functional/invoke.h> #include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> #include <__type_traits/is_member_pointer.h> +#include <__type_traits/is_same.h> +#include <__utility/declval.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) - _LIBCPP_BEGIN_NAMESPACE_STD -namespace ranges { - template -_LIBCPP_HIDE_FROM_ABI constexpr static -decltype(auto) __make_projected_pred(_Pred& __pred, _Proj& __proj) { - if constexpr (same_as, identity> && !is_member_pointer_v>) { - // Avoid creating the lambda and just use the pristine predicate -- for certain algorithms, this would enable - // optimizations that rely on the type of the predicate. - return __pred; +struct _ProjectedPred { + _Pred& __pred; // Can be a unary or a binary predicate. + _Proj& __proj; + + _LIBCPP_CONSTEXPR _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) : __pred(__pred_arg), __proj(__proj_arg) {} + + template + typename __invoke_of<_Pred&, + decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>())) + >::type + _LIBCPP_CONSTEXPR operator()(_Tp&& __v) const { + return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v))); + } - } else { - return [&](auto&& __x) { - return std::invoke(__pred, std::invoke(__proj, std::forward(__x))); - }; + template + typename __invoke_of<_Pred&, + decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())), + decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>())) + >::type + _LIBCPP_CONSTEXPR operator()(_T1&& __lhs, _T2&& __rhs) const { + return std::__invoke(__pred, + std::__invoke(__proj, std::forward<_T1>(__lhs)), + std::__invoke(__proj, std::forward<_T2>(__rhs))); } -} -template -_LIBCPP_HIDE_FROM_ABI constexpr static -decltype(auto) __make_projected_comp(_Comp& __comp, _Proj& __proj) { - if constexpr (same_as, identity> && !is_member_pointer_v>) { - // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable - // optimizations that rely on the type of the comparator. - return __comp; +}; - } else { - return [&](auto&& __lhs, auto&& __rhs) { - return std::invoke(__comp, - std::invoke(__proj, std::forward(__lhs)), - std::invoke(__proj, std::forward(__rhs))); - }; - } +template +struct __can_use_pristine_comp : false_type {}; + +template +struct __can_use_pristine_comp<_Pred, _Proj, __enable_if_t< + !is_member_pointer::type>::value && ( +#if _LIBCPP_STD_VER > 17 + is_same::type, identity>::value || +#endif + is_same::type, __identity>::value + ) +> > : true_type {}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static +__enable_if_t< + !__can_use_pristine_comp<_Pred, _Proj>::value, + _ProjectedPred<_Pred, _Proj> +> +__make_projected(_Pred& __pred, _Proj& __proj) { + return _ProjectedPred<_Pred, _Proj>(__pred, __proj); +} + +// Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable +// optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in +// the call stack when the comparator is invoked, even in an unoptimized build. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static +__enable_if_t< + __can_use_pristine_comp<_Pred, _Proj>::value, + _Pred& +> +__make_projected(_Pred& __pred, _Proj&) { + return __pred; } +_LIBCPP_END_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + template _LIBCPP_HIDE_FROM_ABI constexpr static decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) { diff --git a/libcxx/include/__algorithm/move.h b/libcxx/include/__algorithm/move.h index 0b08d31c176ef..c090faf6b6dc3 100644 --- a/libcxx/include/__algorithm/move.h +++ b/libcxx/include/__algorithm/move.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_H #define _LIBCPP___ALGORITHM_MOVE_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/unwrap_iter.h> #include <__config> #include <__iterator/iterator_traits.h> @@ -26,18 +27,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD // move -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 pair<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { while (__first != __last) { - *__result = std::move(*__first); + *__result = _IterOps<_AlgPolicy>::__iter_move(__first); ++__first; ++__result; } return std::make_pair(std::move(__first), std::move(__result)); } -template ::type, _OutType>::value && is_trivially_move_assignable<_OutType>::value> > @@ -49,7 +51,7 @@ pair<_InType*, _OutType*> __move_impl(_InType* __first, _InType* __last, _OutTyp && !is_trivially_copyable<_InType>::value #endif ) - return std::__move_impl<_InType*, _InType*, _OutType*>(__first, __last, __result); + return std::__move_impl<_AlgPolicy, _InType*, _InType*, _OutType*>(__first, __last, __result); const size_t __n = static_cast(__last - __first); ::__builtin_memmove(__result, __first, __n * sizeof(_OutType)); return std::make_pair(__first + __n, __result + __n); @@ -65,7 +67,8 @@ template struct __is_trivially_move_assignable_unwrapped : __is_trivially_move_assignable_unwrapped_impl(std::declval<_Iter>()))> {}; -template ::value_type>::type, typename iterator_traits<_OutIter>::value_type>::value @@ -81,33 +84,34 @@ __move_impl(reverse_iterator<_InIter> __first, auto __last_base = std::__unwrap_iter(__last.base()); auto __result_base = std::__unwrap_iter(__result.base()); auto __result_first = __result_base - (__first_base - __last_base); - std::__move_impl(__last_base, __first_base, __result_first); + std::__move_impl<_AlgPolicy>(__last_base, __first_base, __result_first); return std::make_pair(__last, reverse_iterator<_OutIter>(std::__rewrap_iter(__result.base(), __result_first))); } -template +template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __enable_if_t::value && is_copy_constructible<_Sent>::value && is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> > __move(_InIter __first, _Sent __last, _OutIter __result) { - auto __ret = std::__move_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result)); + auto __ret = std::__move_impl<_AlgPolicy>( + std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result)); return std::make_pair(std::__rewrap_iter(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); } -template +template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __enable_if_t::value || !is_copy_constructible<_Sent>::value || !is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> > __move(_InIter __first, _Sent __last, _OutIter __result) { - return std::__move_impl(std::move(__first), std::move(__last), std::move(__result)); + return std::__move_impl<_AlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); } template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - return std::__move(__first, __last, __result).second; + return std::__move<_ClassicAlgPolicy>(__first, __last, __result).second; } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/move_backward.h b/libcxx/include/__algorithm/move_backward.h index a56f6b826ce33..626e250b6d413 100644 --- a/libcxx/include/__algorithm/move_backward.h +++ b/libcxx/include/__algorithm/move_backward.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H #define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/unwrap_iter.h> #include <__config> #include <__utility/move.h> @@ -21,25 +22,25 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _OutputIterator __move_backward_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { while (__first != __last) - *--__result = _VSTD::move(*--__last); + *--__result = _IterOps<_AlgPolicy>::__iter_move(--__last); return __result; } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _OutputIterator -__move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) +__move_backward_impl(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - return _VSTD::__move_backward_constexpr(__first, __last, __result); + return _VSTD::__move_backward_constexpr<_AlgPolicy>(__first, __last, __result); } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 typename enable_if < @@ -47,7 +48,7 @@ typename enable_if is_trivially_move_assignable<_Up>::value, _Up* >::type -__move_backward(_Tp* __first, _Tp* __last, _Up* __result) +__move_backward_impl(_Tp* __first, _Tp* __last, _Up* __result) { const size_t __n = static_cast(__last - __first); if (__n > 0) @@ -58,22 +59,31 @@ __move_backward(_Tp* __first, _Tp* __last, _Up* __result) return __result; } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _BidirectionalIterator2 -move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, - _BidirectionalIterator2 __result) +__move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, + _BidirectionalIterator2 __result) { if (__libcpp_is_constant_evaluated()) { - return _VSTD::__move_backward_constexpr(__first, __last, __result); + return _VSTD::__move_backward_constexpr<_AlgPolicy>(__first, __last, __result); } else { return _VSTD::__rewrap_iter(__result, - _VSTD::__move_backward(_VSTD::__unwrap_iter(__first), - _VSTD::__unwrap_iter(__last), - _VSTD::__unwrap_iter(__result))); + _VSTD::__move_backward_impl<_AlgPolicy>(_VSTD::__unwrap_iter(__first), + _VSTD::__unwrap_iter(__last), + _VSTD::__unwrap_iter(__result))); } } +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +_BidirectionalIterator2 +move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, + _BidirectionalIterator2 __result) +{ + return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___ALGORITHM_MOVE_BACKWARD_H diff --git a/libcxx/include/__algorithm/next_permutation.h b/libcxx/include/__algorithm/next_permutation.h index 05e56f4a17ff6..b58dcf4e1a913 100644 --- a/libcxx/include/__algorithm/next_permutation.h +++ b/libcxx/include/__algorithm/next_permutation.h @@ -11,10 +11,12 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/reverse.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <__utility/swap.h> +#include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,29 +24,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 bool -__next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 +pair<_BidirectionalIterator, bool> +__next_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) { - _BidirectionalIterator __i = __last; + using _Result = pair<_BidirectionalIterator, bool>; + + _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + _BidirectionalIterator __i = __last_iter; if (__first == __last || __first == --__i) - return false; + return _Result(std::move(__last_iter), false); + while (true) { _BidirectionalIterator __ip1 = __i; if (__comp(*--__i, *__ip1)) { - _BidirectionalIterator __j = __last; + _BidirectionalIterator __j = __last_iter; while (!__comp(*__i, *--__j)) ; - swap(*__i, *__j); - _VSTD::reverse(__ip1, __last); - return true; + _IterOps<_AlgPolicy>::iter_swap(__i, __j); + std::__reverse<_AlgPolicy>(__ip1, __last_iter); + return _Result(std::move(__last_iter), true); } if (__i == __first) { - _VSTD::reverse(__first, __last); - return false; + std::__reverse<_AlgPolicy>(__first, __last_iter); + return _Result(std::move(__last_iter), false); } } } @@ -54,8 +61,9 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__next_permutation<_Comp_ref>(__first, __last, __comp); + using _Comp_ref = typename __comp_ref_type<_Compare>::type; + return std::__next_permutation<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), static_cast<_Comp_ref>(__comp)).second; } template diff --git a/libcxx/include/__algorithm/partial_sort.h b/libcxx/include/__algorithm/partial_sort.h index 24016e5cf5a5d..dff0cd01f35a1 100644 --- a/libcxx/include/__algorithm/partial_sort.h +++ b/libcxx/include/__algorithm/partial_sort.h @@ -31,12 +31,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator __partial_sort_impl( - _RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare __comp) { + _RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare&& __comp) { if (__first == __middle) { return _IterOps<_AlgPolicy>::next(__middle, __last); } - std::__make_heap<_AlgPolicy, _Compare>(__first, __middle, __comp); + std::__make_heap<_AlgPolicy>(__first, __middle, __comp); typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first; _RandomAccessIterator __i = __middle; @@ -45,11 +45,11 @@ _RandomAccessIterator __partial_sort_impl( if (__comp(*__i, *__first)) { _IterOps<_AlgPolicy>::iter_swap(__i, __first); - std::__sift_down<_AlgPolicy, _Compare>(__first, __comp, __len, __first); + std::__sift_down<_AlgPolicy>(__first, __comp, __len, __first); } } - std::__sort_heap<_AlgPolicy, _Compare>(std::move(__first), std::move(__middle), __comp); + std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp); return __i; } @@ -64,7 +64,7 @@ _RandomAccessIterator __partial_sort(_RandomAccessIterator __first, _RandomAcces std::__debug_randomize_range<_AlgPolicy>(__first, __last); using _Comp_ref = typename __comp_ref_type<_Compare>::type; - auto __last_iter = std::__partial_sort_impl<_AlgPolicy, _Comp_ref>(__first, __middle, __last, __comp); + auto __last_iter = std::__partial_sort_impl<_AlgPolicy>(__first, __middle, __last, static_cast<_Comp_ref>(__comp)); std::__debug_randomize_range<_AlgPolicy>(__middle, __last); diff --git a/libcxx/include/__algorithm/partial_sort_copy.h b/libcxx/include/__algorithm/partial_sort_copy.h index 3556764e652d3..55edf31b0f921 100644 --- a/libcxx/include/__algorithm/partial_sort_copy.h +++ b/libcxx/include/__algorithm/partial_sort_copy.h @@ -13,10 +13,16 @@ #include <__algorithm/comp_ref_type.h> #include <__algorithm/iterator_operations.h> #include <__algorithm/make_heap.h> +#include <__algorithm/make_projected.h> #include <__algorithm/sift_down.h> #include <__algorithm/sort_heap.h> #include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> +#include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,27 +30,33 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator -__partial_sort_copy(_InputIterator __first, _InputIterator __last, - _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator, _RandomAccessIterator> +__partial_sort_copy(_InputIterator __first, _Sentinel1 __last, + _RandomAccessIterator __result_first, _Sentinel2 __result_last, + _Compare&& __comp, _Proj1&& __proj1, _Proj2&& __proj2) { _RandomAccessIterator __r = __result_first; + auto&& __projected_comp = std::__make_projected(__comp, __proj2); + if (__r != __result_last) { for (; __first != __last && __r != __result_last; ++__first, (void) ++__r) *__r = *__first; - std::__make_heap<_AlgPolicy, _Compare>(__result_first, __r, __comp); + std::__make_heap<_AlgPolicy>(__result_first, __r, __projected_comp); typename iterator_traits<_RandomAccessIterator>::difference_type __len = __r - __result_first; for (; __first != __last; ++__first) - if (__comp(*__first, *__result_first)) - { + if (std::__invoke(__comp, std::__invoke(__proj1, *__first), std::__invoke(__proj2, *__result_first))) { *__result_first = *__first; - std::__sift_down<_AlgPolicy, _Compare>(__result_first, __comp, __len, __result_first); + std::__sift_down<_AlgPolicy>(__result_first, __projected_comp, __len, __result_first); } - std::__sort_heap<_AlgPolicy, _Compare>(__result_first, __r, __comp); + std::__sort_heap<_AlgPolicy>(__result_first, __r, __projected_comp); } - return __r; + + return pair<_InputIterator, _RandomAccessIterator>( + _IterOps<_AlgPolicy>::next(std::move(__first), std::move(__last)), std::move(__r)); } template @@ -53,9 +65,13 @@ _RandomAccessIterator partial_sort_copy(_InputIterator __first, _InputIterator __last, _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp) { - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return std::__partial_sort_copy<_ClassicAlgPolicy, _Comp_ref>( - __first, __last, __result_first, __result_last, __comp); + static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__result_first)>::value, + "Comparator has to be callable"); + + using _Comp_ref = typename __comp_ref_type<_Compare>::type; + auto __result = std::__partial_sort_copy<_ClassicAlgPolicy>(__first, __last, __result_first, __result_last, + static_cast<_Comp_ref>(__comp), __identity(), __identity()); + return __result.second; } template diff --git a/libcxx/include/__algorithm/pop_heap.h b/libcxx/include/__algorithm/pop_heap.h index 870af50c133e4..44d5d39726058 100644 --- a/libcxx/include/__algorithm/pop_heap.h +++ b/libcxx/include/__algorithm/pop_heap.h @@ -38,7 +38,7 @@ void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; if (__len > 1) { value_type __top = _IterOps<_AlgPolicy>::__iter_move(__first); // create a hole at __first - _RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy, _CompRef>(__first, __comp_ref, __len); + _RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy>(__first, __comp_ref, __len); --__last; if (__hole == __last) { @@ -47,7 +47,7 @@ void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co *__hole = _IterOps<_AlgPolicy>::__iter_move(__last); ++__hole; *__last = std::move(__top); - std::__sift_up<_AlgPolicy, _CompRef>(__first, __hole, __comp_ref, __hole - __first); + std::__sift_up<_AlgPolicy>(__first, __hole, __comp_ref, __hole - __first); } } } diff --git a/libcxx/include/__algorithm/prev_permutation.h b/libcxx/include/__algorithm/prev_permutation.h index 9dbc1dad01244..698506372b6f1 100644 --- a/libcxx/include/__algorithm/prev_permutation.h +++ b/libcxx/include/__algorithm/prev_permutation.h @@ -11,10 +11,12 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/reverse.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <__utility/swap.h> +#include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,29 +24,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 bool -__prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 +pair<_BidirectionalIterator, bool> +__prev_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) { - _BidirectionalIterator __i = __last; + using _Result = pair<_BidirectionalIterator, bool>; + + _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + _BidirectionalIterator __i = __last_iter; if (__first == __last || __first == --__i) - return false; + return _Result(std::move(__last_iter), false); + while (true) { _BidirectionalIterator __ip1 = __i; if (__comp(*__ip1, *--__i)) { - _BidirectionalIterator __j = __last; + _BidirectionalIterator __j = __last_iter; while (!__comp(*--__j, *__i)) ; - swap(*__i, *__j); - _VSTD::reverse(__ip1, __last); - return true; + _IterOps<_AlgPolicy>::iter_swap(__i, __j); + std::__reverse<_AlgPolicy>(__ip1, __last_iter); + return _Result(std::move(__last_iter), true); } if (__i == __first) { - _VSTD::reverse(__first, __last); - return false; + std::__reverse<_AlgPolicy>(__first, __last_iter); + return _Result(std::move(__last_iter), false); } } } @@ -54,8 +61,9 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__prev_permutation<_Comp_ref>(__first, __last, __comp); + using _Comp_ref = typename __comp_ref_type<_Compare>::type; + return std::__prev_permutation<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), static_cast<_Comp_ref>(__comp)).second; } template diff --git a/libcxx/include/__algorithm/push_heap.h b/libcxx/include/__algorithm/push_heap.h index 716670b767887..72ad51e1a887f 100644 --- a/libcxx/include/__algorithm/push_heap.h +++ b/libcxx/include/__algorithm/push_heap.h @@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, +void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len) { using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h new file mode 100644 index 0000000000000..bdde97e178a7b --- /dev/null +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___ALGORITHM_RANGES_CLAMP_H +#define _LIBCPP___ALGORITHM_RANGES_CLAMP_H + +#include <__assert> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __clamp { +struct __fn { + + template > _Comp = ranges::less> + _LIBCPP_HIDE_FROM_ABI constexpr + const _Type& operator()(const _Type& __value, + const _Type& __low, + const _Type& __high, + _Comp __comp = {}, + _Proj __proj = {}) const { + _LIBCPP_ASSERT(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), + "Bad bounds passed to std::ranges::clamp"); + + if (std::invoke(__comp, std::invoke(__proj, __value), std::invoke(__proj, __low))) + return __low; + else if (std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __value))) + return __high; + else + return __value; + } + +}; +} // namespace __clamp + +inline namespace __cpo { + inline constexpr auto clamp = __clamp::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_CLAMP_H diff --git a/libcxx/include/__algorithm/ranges_inplace_merge.h b/libcxx/include/__algorithm/ranges_inplace_merge.h index a0867e486c3a0..12c90908c2105 100644 --- a/libcxx/include/__algorithm/ranges_inplace_merge.h +++ b/libcxx/include/__algorithm/ranges_inplace_merge.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H #include <__algorithm/inplace_merge.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__config> #include <__functional/identity.h> @@ -17,6 +18,7 @@ #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__iterator/next.h> #include <__iterator/projected.h> #include <__iterator/sortable.h> #include <__ranges/access.h> @@ -36,28 +38,38 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __inplace_merge { -struct __fn { + struct __fn { + template + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) { + auto __last_iter = ranges::next(__middle, __last); + std::__inplace_merge<_RangeAlgPolicy>( + std::move(__first), std::move(__middle), __last_iter, std::__make_projected(__comp, __proj)); + return __last_iter; + } - template _Sent, class _Comp = ranges::less, class _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI - _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__middle; (void)__last; (void)__comp; (void)__proj; - return {}; - } + template < + bidirectional_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Comp = ranges::less, + class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __inplace_merge_impl( + std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj)); + } - template - requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI - borrowed_iterator_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle, - _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__middle; (void)__comp; (void)__proj; - return {}; - } - -}; + template + requires sortable< + iterator_t<_Range>, + _Comp, + _Proj> _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> + operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const { + return __inplace_merge_impl( + ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj)); + } + }; } // namespace __inplace_merge diff --git a/libcxx/include/__algorithm/ranges_is_heap.h b/libcxx/include/__algorithm/ranges_is_heap.h index a3e86d1a8d724..0bb1dcda0e341 100644 --- a/libcxx/include/__algorithm/ranges_is_heap.h +++ b/libcxx/include/__algorithm/ranges_is_heap.h @@ -39,7 +39,7 @@ struct __fn { _LIBCPP_HIDE_FROM_ABI constexpr static bool __is_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); auto __result = std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp); return __result == __last; diff --git a/libcxx/include/__algorithm/ranges_is_heap_until.h b/libcxx/include/__algorithm/ranges_is_heap_until.h index bcd33ad404e88..8a751fcc51302 100644 --- a/libcxx/include/__algorithm/ranges_is_heap_until.h +++ b/libcxx/include/__algorithm/ranges_is_heap_until.h @@ -40,7 +40,7 @@ struct __fn { _LIBCPP_HIDE_FROM_ABI constexpr static _Iter __is_heap_until_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); return std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp); } diff --git a/libcxx/include/__algorithm/ranges_is_permutation.h b/libcxx/include/__algorithm/ranges_is_permutation.h new file mode 100644 index 0000000000000..41e302fe99dc3 --- /dev/null +++ b/libcxx/include/__algorithm/ranges_is_permutation.h @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H +#define _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H + +#include <__algorithm/is_permutation.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/projected.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __is_permutation { +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr static + bool __is_permutation_func_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + return std::__is_permutation<_RangeAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2); + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_equivalence_relation, + projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> + _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __is_permutation_func_impl( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2); + } + + template , _Proj1>, projected, _Proj2>> _Pred = ranges::equal_to> + _LIBCPP_HIDE_FROM_ABI constexpr + bool operator()(_Range1&& __range1, _Range2&& __range2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + if constexpr (sized_range<_Range1> && sized_range<_Range2>) { + if (ranges::distance(__range1) != ranges::distance(__range2)) + return false; + } + + return __is_permutation_func_impl( + ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), ranges::end(__range2), + __pred, __proj1, __proj2); + } +}; +} // namespace __is_permutation + +inline namespace __cpo { + inline constexpr auto is_permutation = __is_permutation::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H diff --git a/libcxx/include/__algorithm/ranges_make_heap.h b/libcxx/include/__algorithm/ranges_make_heap.h index 8eabdd12cd2ff..b114286a85cc8 100644 --- a/libcxx/include/__algorithm/ranges_make_heap.h +++ b/libcxx/include/__algorithm/ranges_make_heap.h @@ -45,7 +45,7 @@ struct __fn { _Iter __make_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); std::__make_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; diff --git a/libcxx/include/__algorithm/ranges_move.h b/libcxx/include/__algorithm/ranges_move.h index ad4342d7c989a..9e1d4c72fb585 100644 --- a/libcxx/include/__algorithm/ranges_move.h +++ b/libcxx/include/__algorithm/ranges_move.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_MOVE_H #include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/move.h> #include <__config> #include <__iterator/concepts.h> @@ -36,24 +37,12 @@ namespace __move { struct __fn { template - requires __iter_move::__move_deref<_InIter> // check that we are allowed to std::move() the value _LIBCPP_HIDE_FROM_ABI constexpr static move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { - auto __ret = std::__move(std::move(__first), std::move(__last), std::move(__result)); + auto __ret = std::__move<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } - template - _LIBCPP_HIDE_FROM_ABI constexpr static - move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { - while (__first != __last) { - *__result = ranges::iter_move(__first); - ++__first; - ++__result; - } - return {std::move(__first), std::move(__result)}; - } - template _Sent, weakly_incrementable _OutIter> requires indirectly_movable<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI constexpr diff --git a/libcxx/include/__algorithm/ranges_move_backward.h b/libcxx/include/__algorithm/ranges_move_backward.h index b3dfa7139603c..583a6bf29d51f 100644 --- a/libcxx/include/__algorithm/ranges_move_backward.h +++ b/libcxx/include/__algorithm/ranges_move_backward.h @@ -40,10 +40,11 @@ struct __fn { template _LIBCPP_HIDE_FROM_ABI constexpr static move_backward_result<_InIter, _OutIter> __move_backward_impl(_InIter __first, _Sent __last, _OutIter __result) { - auto __ret = ranges::move(std::make_reverse_iterator(ranges::next(__first, __last)), + auto __last_iter = ranges::next(__first, std::move(__last)); + auto __ret = ranges::move(std::make_reverse_iterator(__last_iter), std::make_reverse_iterator(__first), std::make_reverse_iterator(__result)); - return {std::move(__ret.in.base()), std::move(__ret.out.base())}; + return {std::move(__last_iter), std::move(__ret.out.base())}; } template _Sent, bidirectional_iterator _OutIter> diff --git a/libcxx/include/__algorithm/ranges_next_permutation.h b/libcxx/include/__algorithm/ranges_next_permutation.h new file mode 100644 index 0000000000000..34c5fee040500 --- /dev/null +++ b/libcxx/include/__algorithm/ranges_next_permutation.h @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H +#define _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H + +#include <__algorithm/in_found_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/next_permutation.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using next_permutation_result = in_found_result<_InIter>; + +namespace __next_permutation { + +struct __fn { + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr next_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__next_permutation<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr next_permutation_result> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__next_permutation<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } +}; + +} // namespace __next_permutation + +inline namespace __cpo { +constexpr inline auto next_permutation = __next_permutation::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H diff --git a/libcxx/include/__algorithm/ranges_nth_element.h b/libcxx/include/__algorithm/ranges_nth_element.h index b15eb816b9189..ad63bd20fb477 100644 --- a/libcxx/include/__algorithm/ranges_nth_element.h +++ b/libcxx/include/__algorithm/ranges_nth_element.h @@ -44,7 +44,7 @@ struct __fn { _Iter __nth_element_fn_impl(_Iter __first, _Iter __nth, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); std::__nth_element_impl<_RangeAlgPolicy>(std::move(__first), std::move(__nth), __last_iter, __projected_comp); return __last_iter; diff --git a/libcxx/include/__algorithm/ranges_partial_sort.h b/libcxx/include/__algorithm/ranges_partial_sort.h index 5e82bc6fcc325..020e34925df7b 100644 --- a/libcxx/include/__algorithm/ranges_partial_sort.h +++ b/libcxx/include/__algorithm/ranges_partial_sort.h @@ -43,7 +43,7 @@ struct __fn { template _LIBCPP_HIDE_FROM_ABI constexpr static _Iter __partial_sort_fn_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp& __comp, _Proj& __proj) { - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); return std::__partial_sort<_RangeAlgPolicy>(std::move(__first), std::move(__middle), __last, __projected_comp); } diff --git a/libcxx/include/__algorithm/ranges_partial_sort_copy.h b/libcxx/include/__algorithm/ranges_partial_sort_copy.h index 55ad2ca4e686b..271c347b7aa28 100644 --- a/libcxx/include/__algorithm/ranges_partial_sort_copy.h +++ b/libcxx/include/__algorithm/ranges_partial_sort_copy.h @@ -10,11 +10,11 @@ #define _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_COPY_H #include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/partial_sort_copy.h> #include <__config> #include <__functional/identity.h> -#include <__functional/invoke.h> #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> @@ -23,7 +23,6 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__utility/forward.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -52,9 +51,11 @@ struct __fn { partial_sort_copy_result<_Iter1, _Iter2> operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result_first, _Sent2 __result_last, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__result_first; (void)__result_last; (void)__comp; (void)__proj1; (void)__proj2; - return {}; + auto __result = std::__partial_sort_copy<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::move(__result_first), std::move(__result_last), + __comp, __proj1, __proj2 + ); + return {std::move(__result.first), std::move(__result.second)}; } template , borrowed_iterator_t<_Range2>> operator()(_Range1&& __range, _Range2&& __result_range, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - // TODO: implement - (void)__range; (void)__result_range; (void)__comp; (void)__proj1; (void)__proj2; - return {}; + auto __result = std::__partial_sort_copy<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), ranges::begin(__result_range), ranges::end(__result_range), + __comp, __proj1, __proj2 + ); + return {std::move(__result.first), std::move(__result.second)}; } }; diff --git a/libcxx/include/__algorithm/ranges_partition.h b/libcxx/include/__algorithm/ranges_partition.h index 60bee699d90e2..6a53933f37aa3 100644 --- a/libcxx/include/__algorithm/ranges_partition.h +++ b/libcxx/include/__algorithm/ranges_partition.h @@ -44,7 +44,7 @@ struct __fn { template _LIBCPP_HIDE_FROM_ABI static constexpr subrange<__uncvref_t<_Iter>> __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { - auto&& __projected_pred = ranges::__make_projected_pred(__pred, __proj); + auto&& __projected_pred = std::__make_projected(__pred, __proj); auto __result = std::__partition<_RangeAlgPolicy>( std::move(__first), std::move(__last), __projected_pred, __iterator_concept<_Iter>()); diff --git a/libcxx/include/__algorithm/ranges_pop_heap.h b/libcxx/include/__algorithm/ranges_pop_heap.h index 92df6119d34a0..fc7554fb0733a 100644 --- a/libcxx/include/__algorithm/ranges_pop_heap.h +++ b/libcxx/include/__algorithm/ranges_pop_heap.h @@ -46,7 +46,7 @@ struct __fn { auto __last_iter = ranges::next(__first, __last); auto __len = __last_iter - __first; - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); std::__pop_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp, __len); return __last_iter; diff --git a/libcxx/include/__algorithm/ranges_prev_permutation.h b/libcxx/include/__algorithm/ranges_prev_permutation.h new file mode 100644 index 0000000000000..58da606d07f78 --- /dev/null +++ b/libcxx/include/__algorithm/ranges_prev_permutation.h @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H +#define _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H + +#include <__algorithm/in_found_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/prev_permutation.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using prev_permutation_result = in_found_result<_InIter>; + +namespace __prev_permutation { + +struct __fn { + + template _Sent, + class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__prev_permutation<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__prev_permutation<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } + +}; + +} // namespace __prev_permutation + +inline namespace __cpo { +constexpr inline auto prev_permutation = __prev_permutation::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H diff --git a/libcxx/include/__algorithm/ranges_push_heap.h b/libcxx/include/__algorithm/ranges_push_heap.h index 4c41b00128ded..3436b39e12cc7 100644 --- a/libcxx/include/__algorithm/ranges_push_heap.h +++ b/libcxx/include/__algorithm/ranges_push_heap.h @@ -45,7 +45,7 @@ struct __fn { _Iter __push_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); std::__push_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; diff --git a/libcxx/include/__algorithm/ranges_remove_copy.h b/libcxx/include/__algorithm/ranges_remove_copy.h index 16e9009e7ef02..a8144ce0ecbf9 100644 --- a/libcxx/include/__algorithm/ranges_remove_copy.h +++ b/libcxx/include/__algorithm/ranges_remove_copy.h @@ -10,19 +10,16 @@ #define _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_H #include <__algorithm/in_out_result.h> -#include <__algorithm/make_projected.h> -#include <__algorithm/remove_copy.h> +#include <__algorithm/ranges_remove_copy_if.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> -#include <__iterator/iterator_traits.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__utility/forward.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -40,32 +37,30 @@ using remove_copy_result = in_out_result<_InIter, _OutIter>; namespace __remove_copy { -struct __fn { - - template _Sent, weakly_incrementable _OutIter, class _Type, - class _Proj = identity> - requires indirectly_copyable<_InIter, _OutIter> && - indirect_binary_predicate, const _Type*> - _LIBCPP_HIDE_FROM_ABI constexpr - remove_copy_result<_InIter, _OutIter> - operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__value; (void)__proj; - return {}; - } - - template - requires indirectly_copyable, _OutIter> && - indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_HIDE_FROM_ABI constexpr - remove_copy_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__value; (void)__proj; - return {}; - } - -}; + struct __fn { + template _Sent, + weakly_incrementable _OutIter, + class _Type, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate, const _Type*> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __val) { return __value == __val; }; + return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); + } + + template + requires indirectly_copyable, _OutIter> && + indirect_binary_predicate, _Proj>, const _Type*> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __val) { return __value == __val; }; + return ranges::__remove_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); + } + }; } // namespace __remove_copy diff --git a/libcxx/include/__algorithm/ranges_remove_copy_if.h b/libcxx/include/__algorithm/ranges_remove_copy_if.h index 4eafe425b8e3a..3f56693fa1f2b 100644 --- a/libcxx/include/__algorithm/ranges_remove_copy_if.h +++ b/libcxx/include/__algorithm/ranges_remove_copy_if.h @@ -38,33 +38,43 @@ namespace ranges { template using remove_copy_if_result = in_out_result<_InIter, _OutIter>; -namespace __remove_copy_if { - -struct __fn { - - template _Sent, weakly_incrementable _OutIter, - class _Proj = identity, indirect_unary_predicate> _Pred> - requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - remove_copy_if_result<_InIter, _OutIter> - operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__pred; (void)__proj; - return {}; +template +_LIBCPP_HIDE_FROM_ABI constexpr in_out_result<_InIter, _OutIter> +__remove_copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) { + for (; __first != __last; ++__first) { + if (!std::invoke(__pred, std::invoke(__proj, *__first))) { + *__result = *__first; + ++__result; + } } + return {std::move(__first), std::move(__result)}; +} - template , _Proj>> _Pred> - requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - remove_copy_if_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__pred; (void)__proj; - return {}; - } +namespace __remove_copy_if { -}; + struct __fn { + template _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); + } + + template , _Proj>> _Pred> + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); + } + }; } // namespace __remove_copy_if diff --git a/libcxx/include/__algorithm/ranges_replace_copy.h b/libcxx/include/__algorithm/ranges_replace_copy.h index 19ef635d6f159..7d59dbe7dbed8 100644 --- a/libcxx/include/__algorithm/ranges_replace_copy.h +++ b/libcxx/include/__algorithm/ranges_replace_copy.h @@ -10,19 +10,16 @@ #define _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_H #include <__algorithm/in_out_result.h> -#include <__algorithm/make_projected.h> -#include <__algorithm/replace_copy.h> +#include <__algorithm/ranges_replace_copy_if.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> -#include <__iterator/iterator_traits.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__utility/forward.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -40,35 +37,45 @@ using replace_copy_result = in_out_result<_InIter, _OutIter>; namespace __replace_copy { -struct __fn { - - template _Sent, class _Type1, class _Type2, - output_iterator _OutIter, class _Proj = identity> - requires indirectly_copyable<_InIter, _OutIter> && - indirect_binary_predicate, const _Type1*> - _LIBCPP_HIDE_FROM_ABI constexpr - replace_copy_result<_InIter, _OutIter> - operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type1& __old_value, const _Type2& __new_value, + struct __fn { + template _Sent, + class _OldType, + class _NewType, + output_iterator _OutIter, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate, const _OldType*> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<_InIter, _OutIter> + operator()(_InIter __first, + _Sent __last, + _OutIter __result, + const _OldType& __old_value, + const _NewType& __new_value, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__old_value; (void)__new_value; (void)__proj; - return {}; - } - - template _OutIter, - class _Proj = identity> - requires indirectly_copyable, _OutIter> && - indirect_binary_predicate, _Proj>, const _Type1*> - _LIBCPP_HIDE_FROM_ABI constexpr - replace_copy_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, const _Type1& __old_value, const _Type2& __new_value, + auto __pred = [&](const auto& __value) { return __value == __old_value; }; + return ranges::__replace_copy_if_impl( + std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); + } + + template _OutIter, + class _Proj = identity> + requires indirectly_copyable, _OutIter> && + indirect_binary_predicate, _Proj>, const _OldType*> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result, _OutIter> + operator()(_Range&& __range, + _OutIter __result, + const _OldType& __old_value, + const _NewType& __new_value, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__old_value; (void)__new_value; (void)__proj; - return {}; - } - -}; + auto __pred = [&](const auto& __value) { return __value == __old_value; }; + return ranges::__replace_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); + } + }; } // namespace __replace_copy diff --git a/libcxx/include/__algorithm/ranges_replace_copy_if.h b/libcxx/include/__algorithm/ranges_replace_copy_if.h index 2a908e2057afd..7602e8a14487a 100644 --- a/libcxx/include/__algorithm/ranges_replace_copy_if.h +++ b/libcxx/include/__algorithm/ranges_replace_copy_if.h @@ -10,19 +10,14 @@ #define _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_IF_H #include <__algorithm/in_out_result.h> -#include <__algorithm/make_projected.h> -#include <__algorithm/replace_copy_if.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> -#include <__functional/ranges_operations.h> #include <__iterator/concepts.h> -#include <__iterator/iterator_traits.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__utility/forward.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -38,34 +33,51 @@ namespace ranges { template using replace_copy_if_result = in_out_result<_InIter, _OutIter>; -namespace __replace_copy_if { - -struct __fn { - - template _Sent, class _Type, output_iterator _OutIter, - class _Proj = identity, indirect_unary_predicate> _Pred> - requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - replace_copy_if_result<_InIter, _OutIter> - operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, const _Type& __new_value, - _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__pred; (void)__new_value; (void)__proj; - return {}; +template +_LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> __replace_copy_if_impl( + _InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, const _Type& __new_value, _Proj& __proj) { + while (__first != __last) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) + *__result = __new_value; + else + *__result = *__first; + + ++__first; + ++__result; } - template _OutIter, class _Proj = identity, - indirect_unary_predicate, _Proj>> _Pred> - requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - replace_copy_if_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__pred; (void)__new_value; (void)__proj; - return {}; - } + return {std::move(__first), std::move(__result)}; +} + +namespace __replace_copy_if { -}; + struct __fn { + template _Sent, + class _Type, + output_iterator _OutIter, + class _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> operator()( + _InIter __first, _Sent __last, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) + const { + return ranges::__replace_copy_if_impl( + std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); + } + + template _OutIter, + class _Proj = identity, + indirect_unary_predicate, _Proj>> _Pred> + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { + return ranges::__replace_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); + } + }; } // namespace __replace_copy_if diff --git a/libcxx/include/__algorithm/ranges_rotate.h b/libcxx/include/__algorithm/ranges_rotate.h new file mode 100644 index 0000000000000..1cd69a141fe3b --- /dev/null +++ b/libcxx/include/__algorithm/ranges_rotate.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___ALGORITHM_RANGES_ROTATE_H +#define _LIBCPP___ALGORITHM_RANGES_ROTATE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/ranges_iterator_concept.h> +#include <__algorithm/rotate.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/permutable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/subrange.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __rotate { + +struct __fn { + + template + _LIBCPP_HIDE_FROM_ABI constexpr + static subrange<_Iter> __rotate_fn_impl(_Iter __first, _Iter __middle, _Sent __last) { + auto __ret = std::__rotate<_RangeAlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + + template _Sent> + _LIBCPP_HIDE_FROM_ABI constexpr + subrange<_Iter> operator()(_Iter __first, _Iter __middle, _Sent __last) const { + return __rotate_fn_impl(std::move(__first), std::move(__middle), std::move(__last)); + } + + template + requires permutable> + _LIBCPP_HIDE_FROM_ABI constexpr + borrowed_subrange_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle) const { + return __rotate_fn_impl(ranges::begin(__range), std::move(__middle), ranges::end(__range)); + } + +}; + +} // namespace __rotate + +inline namespace __cpo { + inline constexpr auto rotate = __rotate::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_H diff --git a/libcxx/include/__algorithm/ranges_sample.h b/libcxx/include/__algorithm/ranges_sample.h new file mode 100644 index 0000000000000..a8477f803788d --- /dev/null +++ b/libcxx/include/__algorithm/ranges_sample.h @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___ALGORITHM_RANGES_SAMPLE_H +#define _LIBCPP___ALGORITHM_RANGES_SAMPLE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/sample.h> +#include <__algorithm/uniform_random_bit_generator_adaptor.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__random/uniform_random_bit_generator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __sample { + +struct __fn { + + template _Sent, weakly_incrementable _OutIter, class _Gen> + requires (forward_iterator<_Iter> || random_access_iterator<_OutIter>) && + indirectly_copyable<_Iter, _OutIter> && + uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI + _OutIter operator()(_Iter __first, _Sent __last, + _OutIter __out_first, iter_difference_t<_Iter> __n, _Gen&& __gen) const { + _ClassicGenAdaptor<_Gen> __adapted_gen(__gen); + return std::__sample<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::move(__out_first), __n, __adapted_gen); + } + + template + requires (forward_range<_Range> || random_access_iterator<_OutIter>) && + indirectly_copyable, _OutIter> && + uniform_random_bit_generator> + _LIBCPP_HIDE_FROM_ABI + _OutIter operator()(_Range&& __range, _OutIter __out_first, range_difference_t<_Range> __n, _Gen&& __gen) const { + return (*this)(ranges::begin(__range), ranges::end(__range), + std::move(__out_first), __n, std::forward<_Gen>(__gen)); + } + +}; + +} // namespace __sample + +inline namespace __cpo { + inline constexpr auto sample = __sample::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_SAMPLE_H diff --git a/libcxx/include/__algorithm/ranges_shuffle.h b/libcxx/include/__algorithm/ranges_shuffle.h index b101a8582eac5..9b7f81e489b34 100644 --- a/libcxx/include/__algorithm/ranges_shuffle.h +++ b/libcxx/include/__algorithm/ranges_shuffle.h @@ -11,6 +11,7 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/shuffle.h> +#include <__algorithm/uniform_random_bit_generator_adaptor.h> #include <__config> #include <__functional/invoke.h> #include <__functional/ranges_operations.h> @@ -32,43 +33,12 @@ #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __shuffle { struct __fn { - // `std::shuffle` is more constrained than `std::ranges::shuffle`. `std::ranges::shuffle` only requires the given - // generator to satisfy the `std::uniform_random_bit_generator` concept. `std::shuffle` requires the given - // generator to meet the uniform random bit generator requirements; these requirements include satisfying - // `std::uniform_random_bit_generator` and add a requirement for the generator to provide a nested `result_type` - // typedef (see `[rand.req.urng]`). - // - // To reuse the implementation from `std::shuffle`, make the given generator meet the classic requirements by wrapping - // it into an adaptor type that forwards all of its interface and adds the required typedef. - template - class _ClassicGenAdaptor { - private: - // The generator is not required to be copyable or movable, so it has to be stored as a reference. - _Gen& __gen; - - public: - using result_type = invoke_result_t<_Gen&>; - - _LIBCPP_HIDE_FROM_ABI - static constexpr auto min() { return __uncvref_t<_Gen>::min(); } - _LIBCPP_HIDE_FROM_ABI - static constexpr auto max() { return __uncvref_t<_Gen>::max(); } - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen(__g) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr auto operator()() const { return __gen(); } - }; template _Sent, class _Gen> requires permutable<_Iter> && uniform_random_bit_generator> @@ -96,8 +66,6 @@ inline namespace __cpo { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) #endif // _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H diff --git a/libcxx/include/__algorithm/ranges_sort.h b/libcxx/include/__algorithm/ranges_sort.h index ef14db64295d8..c3f3cbff007c9 100644 --- a/libcxx/include/__algorithm/ranges_sort.h +++ b/libcxx/include/__algorithm/ranges_sort.h @@ -44,7 +44,7 @@ struct __fn { _Iter __sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); std::__sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; diff --git a/libcxx/include/__algorithm/ranges_sort_heap.h b/libcxx/include/__algorithm/ranges_sort_heap.h index eb6a30dcd3d06..f6e4dcb43ddf5 100644 --- a/libcxx/include/__algorithm/ranges_sort_heap.h +++ b/libcxx/include/__algorithm/ranges_sort_heap.h @@ -45,7 +45,7 @@ struct __fn { _Iter __sort_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); std::__sort_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; diff --git a/libcxx/include/__algorithm/ranges_stable_partition.h b/libcxx/include/__algorithm/ranges_stable_partition.h index 27957db8829f1..b20dfa3a8bfc5 100644 --- a/libcxx/include/__algorithm/ranges_stable_partition.h +++ b/libcxx/include/__algorithm/ranges_stable_partition.h @@ -49,7 +49,7 @@ struct __fn { _Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { auto __last_iter = ranges::next(__first, __last); - auto&& __projected_pred = ranges::__make_projected_pred(__pred, __proj); + auto&& __projected_pred = std::__make_projected(__pred, __proj); auto __result = std::__stable_partition<_RangeAlgPolicy>( std::move(__first), __last_iter, __projected_pred, __iterator_concept<_Iter>()); diff --git a/libcxx/include/__algorithm/ranges_stable_sort.h b/libcxx/include/__algorithm/ranges_stable_sort.h index de48416a41bef..7ecffefc19da9 100644 --- a/libcxx/include/__algorithm/ranges_stable_sort.h +++ b/libcxx/include/__algorithm/ranges_stable_sort.h @@ -44,7 +44,7 @@ struct __fn { static _Iter __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj); + auto&& __projected_comp = std::__make_projected(__comp, __proj); std::__stable_sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp); return __last_iter; diff --git a/libcxx/include/__algorithm/ranges_swap_ranges.h b/libcxx/include/__algorithm/ranges_swap_ranges.h index 3254e1c60abbd..d980fdec2c491 100644 --- a/libcxx/include/__algorithm/ranges_swap_ranges.h +++ b/libcxx/include/__algorithm/ranges_swap_ranges.h @@ -10,6 +10,8 @@ #define _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H #include <__algorithm/in_in_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/swap_ranges.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/iter_swap.h> @@ -38,12 +40,9 @@ struct __fn { requires indirectly_swappable<_I1, _I2> _LIBCPP_HIDE_FROM_ABI constexpr swap_ranges_result<_I1, _I2> operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2) const { - while (__first1 != __last1 && __first2 != __last2) { - ranges::iter_swap(__first1, __first2); - ++__first1; - ++__first2; - } - return {_VSTD::move(__first1), _VSTD::move(__first2)}; + auto __ret = std::__swap_ranges<_RangeAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2)); + return {std::move(__ret.first), std::move(__ret.second)}; } template diff --git a/libcxx/include/__algorithm/ranges_unique.h b/libcxx/include/__algorithm/ranges_unique.h index bdf755e9406e2..11370aeccd24a 100644 --- a/libcxx/include/__algorithm/ranges_unique.h +++ b/libcxx/include/__algorithm/ranges_unique.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_UNIQUE_H #define _LIBCPP___ALGORITHM_RANGES_UNIQUE_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/unique.h> #include <__config> @@ -37,28 +38,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __unique { -struct __fn { + struct __fn { + template < + permutable _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, + indirect_equivalence_relation> _Comp = ranges::equal_to> + _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } - template _Sent, class _Proj = identity, - indirect_equivalence_relation> _Comp = ranges::equal_to> - _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__comp; (void)__proj; - return {}; - } - - template , _Proj>> _Comp = ranges::equal_to> - requires permutable> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__comp; (void)__proj; - return {}; - } - -}; + template < + forward_range _Range, + class _Proj = identity, + indirect_equivalence_relation, _Proj>> _Comp = ranges::equal_to> + requires permutable> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } + }; } // namespace __unique diff --git a/libcxx/include/__algorithm/ranges_unique_copy.h b/libcxx/include/__algorithm/ranges_unique_copy.h index 56361aa8ae2f3..8c0b970d043fb 100644 --- a/libcxx/include/__algorithm/ranges_unique_copy.h +++ b/libcxx/include/__algorithm/ranges_unique_copy.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H #include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/unique_copy.h> #include <__concepts/same_as.h> @@ -19,8 +20,8 @@ #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> -#include <__iterator/readable_traits.h> #include <__iterator/projected.h> +#include <__iterator/readable_traits.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> @@ -42,42 +43,68 @@ using unique_copy_result = in_out_result<_InIter, _OutIter>; namespace __unique_copy { +template +concept __can_reread_from_output = (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>); + struct __fn { + template + static consteval auto __get_algo_tag() { + if constexpr (forward_iterator<_InIter>) { + return __unique_copy_tags::__reread_from_input_tag{}; + } else if constexpr (__can_reread_from_output<_InIter, _OutIter>) { + return __unique_copy_tags::__reread_from_output_tag{}; + } else if constexpr (indirectly_copyable_storable<_InIter, _OutIter>) { + return __unique_copy_tags::__read_from_tmp_value_tag{}; + } + } + + template + using __algo_tag_t = decltype(__get_algo_tag<_InIter, _OutIter>()); - template _Sent, weakly_incrementable _OutIter, class _Proj = identity, + template _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, indirect_equivalence_relation> _Comp = ranges::equal_to> - requires indirectly_copyable<_InIter, _OutIter> && - (forward_iterator<_InIter> || - (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || - indirectly_copyable_storable<_InIter, _OutIter>) - _LIBCPP_HIDE_FROM_ABI constexpr - unique_copy_result<_InIter, _OutIter> + requires indirectly_copyable<_InIter, _OutIter> && + (forward_iterator<_InIter> || + (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || + indirectly_copyable_storable<_InIter, _OutIter>) + _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__comp; (void)__proj; - return {}; + auto __ret = std::__unique_copy<_RangeAlgPolicy>( + std::move(__first), + std::move(__last), + std::move(__result), + std::__make_projected(__comp, __proj), + __algo_tag_t<_InIter, _OutIter>()); + return {std::move(__ret.first), std::move(__ret.second)}; } - template , _Proj>> _Comp = ranges::equal_to> - requires indirectly_copyable, _OutIter> && - (forward_iterator> || - (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || - indirectly_copyable_storable, _OutIter>) - _LIBCPP_HIDE_FROM_ABI constexpr - unique_copy_result, _OutIter> + requires indirectly_copyable, _OutIter> && + (forward_iterator> || + (input_iterator<_OutIter> && same_as, iter_value_t<_OutIter>>) || + indirectly_copyable_storable, _OutIter>) + _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result, _OutIter> operator()(_Range&& __range, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__comp; (void)__proj; - return {}; + auto __ret = std::__unique_copy<_RangeAlgPolicy>( + ranges::begin(__range), + ranges::end(__range), + std::move(__result), + std::__make_projected(__comp, __proj), + __algo_tag_t, _OutIter>()); + return {std::move(__ret.first), std::move(__ret.second)}; } - }; } // namespace __unique_copy inline namespace __cpo { - inline constexpr auto unique_copy = __unique_copy::__fn{}; +inline constexpr auto unique_copy = __unique_copy::__fn{}; } // namespace __cpo } // namespace ranges diff --git a/libcxx/include/__algorithm/reverse.h b/libcxx/include/__algorithm/reverse.h index 0202cd7408332..6484c73752efb 100644 --- a/libcxx/include/__algorithm/reverse.h +++ b/libcxx/include/__algorithm/reverse.h @@ -10,8 +10,10 @@ #define _LIBCPP___ALGORITHM_REVERSE_H #include <__algorithm/iter_swap.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,28 +21,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void -__reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, bidirectional_iterator_tag) +__reverse_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, bidirectional_iterator_tag) { while (__first != __last) { if (__first == --__last) break; - _VSTD::iter_swap(__first, __last); + _IterOps<_AlgPolicy>::iter_swap(__first, __last); ++__first; } } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void -__reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag) +__reverse_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag) { if (__first != __last) for (; __first < --__last; ++__first) - _VSTD::iter_swap(__first, __last); + _IterOps<_AlgPolicy>::iter_swap(__first, __last); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 +void __reverse(_BidirectionalIterator __first, _Sentinel __last) { + using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_BidirectionalIterator>; + std::__reverse_impl<_AlgPolicy>(std::move(__first), std::move(__last), _IterCategory()); } template @@ -48,7 +57,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) { - _VSTD::__reverse(__first, __last, typename iterator_traits<_BidirectionalIterator>::iterator_category()); + std::__reverse<_ClassicAlgPolicy>(std::move(__first), std::move(__last)); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/rotate.h b/libcxx/include/__algorithm/rotate.h index fcf8444a65a08..beb5409d5b886 100644 --- a/libcxx/include/__algorithm/rotate.h +++ b/libcxx/include/__algorithm/rotate.h @@ -15,10 +15,8 @@ #include <__algorithm/swap_ranges.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <__iterator/next.h> -#include <__iterator/prev.h> #include <__utility/move.h> -#include <__utility/swap.h> +#include <__utility/pair.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -32,9 +30,11 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator __rotate_left(_ForwardIterator __first, _ForwardIterator __last) { typedef typename iterator_traits<_ForwardIterator>::value_type value_type; - value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__first); - // TODO(ranges): pass `_AlgPolicy` to `move`. - _ForwardIterator __lm1 = _VSTD::move(_VSTD::next(__first), __last, __first); + using _Ops = _IterOps<_AlgPolicy>; + + value_type __tmp = _Ops::__iter_move(__first); + _ForwardIterator __lm1 = std::__move<_AlgPolicy>( + _Ops::next(__first), __last, __first).second; *__lm1 = _VSTD::move(__tmp); return __lm1; } @@ -44,11 +44,11 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator __rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) { typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; - // TODO(ranges): pass `_AlgPolicy` to `prev`. - _BidirectionalIterator __lm1 = _VSTD::prev(__last); - value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__lm1); - // TODO(ranges): pass `_AlgPolicy` to `move_backward`. - _BidirectionalIterator __fp1 = _VSTD::move_backward(__first, __lm1, __last); + using _Ops = _IterOps<_AlgPolicy>; + + _BidirectionalIterator __lm1 = _Ops::prev(__last); + value_type __tmp = _Ops::__iter_move(__lm1); + _BidirectionalIterator __fp1 = std::__move_backward<_AlgPolicy>(__first, __lm1, std::move(__last)); *__first = _VSTD::move(__tmp); return __fp1; } @@ -108,26 +108,26 @@ __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ran { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; + using _Ops = _IterOps<_AlgPolicy>; const difference_type __m1 = __middle - __first; - const difference_type __m2 = __last - __middle; + const difference_type __m2 = _Ops::distance(__middle, __last); if (__m1 == __m2) { - // TODO(ranges): pass `_AlgPolicy` to `swap_ranges`. - _VSTD::swap_ranges(__first, __middle, __middle); + std::__swap_ranges<_AlgPolicy>(__first, __middle, __middle, __last); return __middle; } const difference_type __g = _VSTD::__algo_gcd(__m1, __m2); for (_RandomAccessIterator __p = __first + __g; __p != __first;) { - value_type __t(_IterOps<_AlgPolicy>::__iter_move(--__p)); + value_type __t(_Ops::__iter_move(--__p)); _RandomAccessIterator __p1 = __p; _RandomAccessIterator __p2 = __p1 + __m1; do { - *__p1 = _IterOps<_AlgPolicy>::__iter_move(__p2); + *__p1 = _Ops::__iter_move(__p2); __p1 = __p2; - const difference_type __d = __last - __p2; + const difference_type __d = _Ops::distance(__p2, __last); if (__m1 < __d) __p2 += __m1; else @@ -188,16 +188,23 @@ __rotate_impl(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ra return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); } -template +template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -_RandomAccessIterator __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, - _RandomAccessIterator __last, _IterCategory __iter_category) { +pair<_Iterator, _Iterator> +__rotate(_Iterator __first, _Iterator __middle, _Sentinel __last) { + using _Ret = pair<_Iterator, _Iterator>; + _Iterator __last_iter = _IterOps<_AlgPolicy>::next(__middle, __last); + if (__first == __middle) - return __last; + return _Ret(__last_iter, __last_iter); if (__middle == __last) - return __first; + return _Ret(std::move(__first), std::move(__last_iter)); + + using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_Iterator>; + auto __result = std::__rotate_impl<_AlgPolicy>( + std::move(__first), std::move(__middle), __last_iter, _IterCategory()); - return std::__rotate_impl<_AlgPolicy>(std::move(__first), std::move(__middle), std::move(__last), __iter_category); + return _Ret(std::move(__result), std::move(__last_iter)); } template @@ -205,8 +212,8 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { - return std::__rotate<_ClassicAlgPolicy>(__first, __middle, __last, - typename iterator_traits<_ForwardIterator>::iterator_category()); + return std::__rotate<_ClassicAlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last)).first; } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/sample.h b/libcxx/include/__algorithm/sample.h index e04466a08d5a9..f403ba612580c 100644 --- a/libcxx/include/__algorithm/sample.h +++ b/libcxx/include/__algorithm/sample.h @@ -9,12 +9,14 @@ #ifndef _LIBCPP___ALGORITHM_SAMPLE_H #define _LIBCPP___ALGORITHM_SAMPLE_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/min.h> #include <__assert> #include <__config> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__random/uniform_int_distribution.h> +#include <__utility/move.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -26,13 +28,14 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template _LIBCPP_INLINE_VISIBILITY _SampleIterator __sample(_PopulationIterator __first, - _PopulationIterator __last, _SampleIterator __output_iter, + _PopulationSentinel __last, _SampleIterator __output_iter, _Distance __n, - _UniformRandomNumberGenerator & __g, + _UniformRandomNumberGenerator& __g, input_iterator_tag) { _Distance __k = 0; @@ -47,15 +50,16 @@ _SampleIterator __sample(_PopulationIterator __first, return __output_iter + _VSTD::min(__n, __k); } -template _LIBCPP_INLINE_VISIBILITY _SampleIterator __sample(_PopulationIterator __first, - _PopulationIterator __last, _SampleIterator __output_iter, + _PopulationSentinel __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator& __g, forward_iterator_tag) { - _Distance __unsampled_sz = _VSTD::distance(__first, __last); + _Distance __unsampled_sz = _IterOps<_AlgPolicy>::distance(__first, __last); for (__n = _VSTD::min(__n, __unsampled_sz); __n != 0; ++__first) { _Distance __r = uniform_int_distribution<_Distance>(0, --__unsampled_sz)(__g); if (__r < __n) { @@ -66,24 +70,22 @@ _SampleIterator __sample(_PopulationIterator __first, return __output_iter; } -template _LIBCPP_INLINE_VISIBILITY _SampleIterator __sample(_PopulationIterator __first, - _PopulationIterator __last, _SampleIterator __output_iter, + _PopulationSentinel __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator& __g) { - typedef typename iterator_traits<_PopulationIterator>::iterator_category - _PopCategory; - typedef typename iterator_traits<_PopulationIterator>::difference_type - _Difference; - static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value || - __is_cpp17_random_access_iterator<_SampleIterator>::value, - "SampleIterator must meet the requirements of RandomAccessIterator"); - typedef typename common_type<_Distance, _Difference>::type _CommonType; _LIBCPP_ASSERT(__n >= 0, "N must be a positive number."); - return _VSTD::__sample( - __first, __last, __output_iter, _CommonType(__n), - __g, _PopCategory()); + + using _PopIterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_PopulationIterator>; + using _Difference = typename _IterOps<_AlgPolicy>::template __difference_type<_PopulationIterator>; + using _CommonType = typename common_type<_Distance, _Difference>::type; + + return std::__sample<_AlgPolicy>( + std::move(__first), std::move(__last), std::move(__output_iter), _CommonType(__n), + __g, _PopIterCategory()); } #if _LIBCPP_STD_VER > 14 @@ -93,8 +95,14 @@ inline _LIBCPP_INLINE_VISIBILITY _SampleIterator sample(_PopulationIterator __first, _PopulationIterator __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator&& __g) { - return _VSTD::__sample(__first, __last, __output_iter, __n, __g); + static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value || + __is_cpp17_random_access_iterator<_SampleIterator>::value, + "SampleIterator must meet the requirements of RandomAccessIterator"); + + return std::__sample<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), std::move(__output_iter), __n, __g); } + #endif // _LIBCPP_STD_VER > 14 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/sift_down.h b/libcxx/include/__algorithm/sift_down.h index be2eb29dd53a3..06811239f84fd 100644 --- a/libcxx/include/__algorithm/sift_down.h +++ b/libcxx/include/__algorithm/sift_down.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_CONSTEXPR_AFTER_CXX11 void -__sift_down(_RandomAccessIterator __first, _Compare __comp, +__sift_down(_RandomAccessIterator __first, _Compare&& __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len, _RandomAccessIterator __start) { @@ -79,7 +79,7 @@ __sift_down(_RandomAccessIterator __first, _Compare __comp, template _LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator -__floyd_sift_down(_RandomAccessIterator __first, _Compare __comp, +__floyd_sift_down(_RandomAccessIterator __first, _Compare&& __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len) { using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; diff --git a/libcxx/include/__algorithm/sort_heap.h b/libcxx/include/__algorithm/sort_heap.h index b9f0b2c9690d2..7713b766f913e 100644 --- a/libcxx/include/__algorithm/sort_heap.h +++ b/libcxx/include/__algorithm/sort_heap.h @@ -26,13 +26,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) { +void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) { using _CompRef = typename __comp_ref_type<_Compare>::type; _CompRef __comp_ref = __comp; using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; for (difference_type __n = __last - __first; __n > 1; --__last, (void) --__n) - std::__pop_heap<_AlgPolicy, _CompRef>(__first, __last, __comp_ref, __n); + std::__pop_heap<_AlgPolicy>(__first, __last, __comp_ref, __n); } template diff --git a/libcxx/include/__algorithm/stable_partition.h b/libcxx/include/__algorithm/stable_partition.h index e5ad48b2ed516..c7aa3f07a88ce 100644 --- a/libcxx/include/__algorithm/stable_partition.h +++ b/libcxx/include/__algorithm/stable_partition.h @@ -108,7 +108,7 @@ __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Pred __second_half_done: // TTTFFFFFTTTTTFFFFF // f ff m sf l - return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false, __fit); + return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; // TTTTTTTTFFFFFFFFFF // | } @@ -253,7 +253,7 @@ __stable_partition_impl(_BidirectionalIterator __first, _BidirectionalIterator _ __second_half_done: // TTTFFFFFTTTTTFFFFF // f ff m sf l - return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false, __bit); + return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; // TTTTTTTTFFFFFFFFFF // | } diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h index 6122758bdefe8..fb149eeb65dc0 100644 --- a/libcxx/include/__algorithm/stable_sort.h +++ b/libcxx/include/__algorithm/stable_sort.h @@ -203,7 +203,7 @@ __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp } std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size); std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size); - std::__inplace_merge<_AlgPolicy, _Compare>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); + std::__inplace_merge<_AlgPolicy>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size); } template diff --git a/libcxx/include/__algorithm/swap_ranges.h b/libcxx/include/__algorithm/swap_ranges.h index 0422265bb4be4..0cff519a8da94 100644 --- a/libcxx/include/__algorithm/swap_ranges.h +++ b/libcxx/include/__algorithm/swap_ranges.h @@ -9,8 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_SWAP_RANGES_H #define _LIBCPP___ALGORITHM_SWAP_RANGES_H +#include <__algorithm/iterator_operations.h> #include <__config> -#include <__utility/swap.h> +#include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -18,12 +20,39 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// 2+2 iterators: the shorter size will be used. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 +pair<_ForwardIterator1, _ForwardIterator2> +__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _Sentinel2 __last2) { + while (__first1 != __last1 && __first2 != __last2) { + _IterOps<_AlgPolicy>::iter_swap(__first1, __first2); + ++__first1; + ++__first2; + } + + return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2)); +} + +// 2+1 iterators: size2 >= size1. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 +pair<_ForwardIterator1, _ForwardIterator2> +__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2) { + while (__first1 != __last1) { + _IterOps<_AlgPolicy>::iter_swap(__first1, __first2); + ++__first1; + ++__first2; + } + + return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2)); +} + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator2 swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { - for (; __first1 != __last1; ++__first1, (void)++__first2) - swap(*__first1, *__first2); - return __first2; + return std::__swap_ranges<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2)).second; } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h b/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h new file mode 100644 index 0000000000000..04a67752dd0bc --- /dev/null +++ b/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H +#define _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H + +#include <__config> +#include <__functional/invoke.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Range versions of random algorithms (e.g. `std::shuffle`) are less constrained than their classic counterparts. +// Range algorithms only require the given generator to satisfy the `std::uniform_random_bit_generator` concept. +// Classic algorithms require the given generator to meet the uniform random bit generator requirements; these +// requirements include satisfying `std::uniform_random_bit_generator` and add a requirement for the generator to +// provide a nested `result_type` typedef (see `[rand.req.urng]`). +// +// To be able to reuse classic implementations, make the given generator meet the classic requirements by wrapping +// it into an adaptor type that forwards all of its interface and adds the required typedef. +template +class _ClassicGenAdaptor { +private: + // The generator is not required to be copyable or movable, so it has to be stored as a reference. + _Gen& __gen; + +public: + using result_type = invoke_result_t<_Gen&>; + + _LIBCPP_HIDE_FROM_ABI + static constexpr auto min() { return __uncvref_t<_Gen>::min(); } + _LIBCPP_HIDE_FROM_ABI + static constexpr auto max() { return __uncvref_t<_Gen>::max(); } + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen(__g) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()() const { return __gen(); } +}; + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H diff --git a/libcxx/include/__algorithm/unique.h b/libcxx/include/__algorithm/unique.h index 264d727d93c88..1727225a91cdb 100644 --- a/libcxx/include/__algorithm/unique.h +++ b/libcxx/include/__algorithm/unique.h @@ -11,9 +11,11 @@ #include <__algorithm/adjacent_find.h> #include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,32 +25,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD // unique +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 std::pair<_Iter, _Iter> +__unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { + __first = std::__adjacent_find(__first, __last, __pred); + if (__first != __last) { + // ... a a ? ... + // f i + _Iter __i = __first; + for (++__i; ++__i != __last;) + if (!__pred(*__first, *__i)) + *++__first = _IterOps<_AlgPolicy>::__iter_move(__i); + ++__first; + return std::pair<_Iter, _Iter>(std::move(__first), std::move(__i)); + } + return std::pair<_Iter, _Iter>(__first, __first); +} + template -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator -unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) -{ - __first = _VSTD::adjacent_find<_ForwardIterator, _BinaryPredicate&>(__first, __last, __pred); - if (__first != __last) - { - // ... a a ? ... - // f i - _ForwardIterator __i = __first; - for (++__i; ++__i != __last;) - if (!__pred(*__first, *__i)) - *++__first = _VSTD::move(*__i); - ++__first; - } - return __first; +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { + return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first; } template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_ForwardIterator -unique(_ForwardIterator __first, _ForwardIterator __last) -{ - typedef typename iterator_traits<_ForwardIterator>::value_type __v; - return _VSTD::unique(__first, __last, __equal_to<__v>()); +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator +unique(_ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type __v; + return std::unique(__first, __last, __equal_to<__v>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/unique_copy.h b/libcxx/include/__algorithm/unique_copy.h index f58517749f514..c7c8d8e9d8fde 100644 --- a/libcxx/include/__algorithm/unique_copy.h +++ b/libcxx/include/__algorithm/unique_copy.h @@ -10,8 +10,14 @@ #define _LIBCPP___ALGORITHM_UNIQUE_COPY_H #include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_same.h> +#include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,88 +25,99 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator -__unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred, - input_iterator_tag, output_iterator_tag) -{ - if (__first != __last) - { - typename iterator_traits<_InputIterator>::value_type __t(*__first); +namespace __unique_copy_tags { + +struct __reread_from_input_tag {}; +struct __reread_from_output_tag {}; +struct __read_from_tmp_value_tag {}; + +} // namespace __unique_copy_tags + +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _OutputIterator> +__unique_copy(_InputIterator __first, + _Sent __last, + _OutputIterator __result, + _BinaryPredicate&& __pred, + __unique_copy_tags::__read_from_tmp_value_tag) { + if (__first != __last) { + typename _IterOps<_AlgPolicy>::template __value_type<_InputIterator> __t(*__first); + *__result = __t; + ++__result; + while (++__first != __last) { + if (!__pred(__t, *__first)) { + __t = *__first; *__result = __t; ++__result; - while (++__first != __last) - { - if (!__pred(__t, *__first)) - { - __t = *__first; - *__result = __t; - ++__result; - } - } + } } - return __result; + } + return pair<_InputIterator, _OutputIterator>(std::move(__first), std::move(__result)); } -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator -__unique_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _BinaryPredicate __pred, - forward_iterator_tag, output_iterator_tag) -{ - if (__first != __last) - { - _ForwardIterator __i = __first; - *__result = *__i; +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator, _OutputIterator> +__unique_copy(_ForwardIterator __first, + _Sent __last, + _OutputIterator __result, + _BinaryPredicate&& __pred, + __unique_copy_tags::__reread_from_input_tag) { + if (__first != __last) { + _ForwardIterator __i = __first; + *__result = *__i; + ++__result; + while (++__first != __last) { + if (!__pred(*__i, *__first)) { + *__result = *__first; ++__result; - while (++__first != __last) - { - if (!__pred(*__i, *__first)) - { - *__result = *__first; - ++__result; - __i = __first; - } - } + __i = __first; + } } - return __result; + } + return pair<_ForwardIterator, _OutputIterator>(std::move(__first), std::move(__result)); } -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator -__unique_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result, _BinaryPredicate __pred, - input_iterator_tag, forward_iterator_tag) -{ - if (__first != __last) - { - *__result = *__first; - while (++__first != __last) - if (!__pred(*__result, *__first)) - *++__result = *__first; - ++__result; - } - return __result; +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _InputAndOutputIterator> +__unique_copy(_InputIterator __first, + _Sent __last, + _InputAndOutputIterator __result, + _BinaryPredicate&& __pred, + __unique_copy_tags::__reread_from_output_tag) { + if (__first != __last) { + *__result = *__first; + while (++__first != __last) + if (!__pred(*__result, *__first)) + *++__result = *__first; + ++__result; + } + return pair<_InputIterator, _InputAndOutputIterator>(std::move(__first), std::move(__result)); } template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_OutputIterator -unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) -{ - return _VSTD::__unique_copy<_BinaryPredicate&>(__first, __last, __result, __pred, - typename iterator_traits<_InputIterator>::iterator_category(), - typename iterator_traits<_OutputIterator>::iterator_category()); +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator +unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) { + using __algo_tag = typename conditional< + is_base_of::iterator_category>::value, + __unique_copy_tags::__reread_from_input_tag, + typename conditional< + is_base_of::iterator_category>::value && + is_same< typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_OutputIterator>::value_type>::value, + __unique_copy_tags::__reread_from_output_tag, + __unique_copy_tags::__read_from_tmp_value_tag>::type >::type; + return std::__unique_copy<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), std::move(__result), __pred, __algo_tag()) + .second; } template -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 -_OutputIterator -unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) -{ - typedef typename iterator_traits<_InputIterator>::value_type __v; - return _VSTD::unique_copy(__first, __last, __result, __equal_to<__v>()); +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator +unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type __v; + return std::unique_copy(std::move(__first), std::move(__last), std::move(__result), __equal_to<__v>()); } - _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___ALGORITHM_UNIQUE_COPY_H diff --git a/libcxx/include/__algorithm/unwrap_range.h b/libcxx/include/__algorithm/unwrap_range.h new file mode 100644 index 0000000000000..745906a96e15b --- /dev/null +++ b/libcxx/include/__algorithm/unwrap_range.h @@ -0,0 +1,97 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___ALGORITHM_UNWRAP_RANGE_H +#define _LIBCPP___ALGORITHM_UNWRAP_RANGE_H + +#include <__algorithm/unwrap_iter.h> +#include <__concepts/constructible.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/next.h> +#include <__utility/declval.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __unwrap_range and __rewrap_range are used to unwrap ranges which may have different iterator and sentinel types. +// __unwrap_iter and __rewrap_iter don't work for this, because they assume that the iterator and sentinel have +// the same type. __unwrap_range tries to get two iterators and then forward to __unwrap_iter. + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +template +struct __unwrap_range_impl { + _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __sent) + requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter> + { + auto __last = ranges::next(__first, __sent); + return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))}; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __last) { + return pair{std::move(__first), std::move(__last)}; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) + requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter> + { + return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto __rewrap(const _Iter&, _Iter __iter) + requires (!(random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>)) + { + return __iter; + } +}; + +template +struct __unwrap_range_impl<_Iter, _Iter> { + _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Iter __last) { + return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))}; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) { + return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); + } +}; + +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __unwrap_range(_Iter __first, _Sent __last) { + return __unwrap_range_impl<_Iter, _Sent>::__unwrap(std::move(__first), std::move(__last)); +} + +template < + class _Sent, + class _Iter, + class _Unwrapped = decltype(std::__unwrap_range(std::declval<_Iter>(), std::declval<_Sent>()))> +_LIBCPP_HIDE_FROM_ABI constexpr _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) { + return __unwrap_range_impl<_Iter, _Sent>::__rewrap(std::move(__orig_iter), std::move(__iter)); +} +#else // _LIBCPP_STD_VER > 17 +template ()))> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair<_Unwrapped, _Unwrapped> __unwrap_range(_Iter __first, _Iter __last) { + return std::make_pair(std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))); +} + +template ()))> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) { + return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); +} +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_UNWRAP_RANGE_H diff --git a/libcxx/include/__assert b/libcxx/include/__assert index 82db2cf052b5e..87556085eabbb 100644 --- a/libcxx/include/__assert +++ b/libcxx/include/__assert @@ -10,8 +10,8 @@ #ifndef _LIBCPP___ASSERT #define _LIBCPP___ASSERT -#include <__availability> #include <__config> +#include <__verbose_abort> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -45,7 +45,7 @@ # define _LIBCPP_ASSERT(expression, message) \ (__builtin_expect(static_cast(expression), 1) ? \ (void)0 : \ - ::std::__libcpp_assertion_handler("%s:%d: assertion %s failed: %s", __FILE__, __LINE__, #expression, message)) + ::std::__libcpp_verbose_abort("%s:%d: assertion %s failed: %s", __FILE__, __LINE__, #expression, message)) #elif !defined(_LIBCPP_ASSERTIONS_DISABLE_ASSUME) && __has_builtin(__builtin_assume) # define _LIBCPP_ASSERT(expression, message) \ (_LIBCPP_DIAGNOSTIC_PUSH \ @@ -56,11 +56,4 @@ # define _LIBCPP_ASSERT(expression, message) ((void)0) #endif -_LIBCPP_BEGIN_NAMESPACE_STD - -_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ASSERTION_HANDLER _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) -void __libcpp_assertion_handler(const char *__format, ...); - -_LIBCPP_END_NAMESPACE_STD - #endif // _LIBCPP___ASSERT diff --git a/libcxx/include/__availability b/libcxx/include/__availability index f9d824509f3d1..72ff663334d36 100644 --- a/libcxx/include/__availability +++ b/libcxx/include/__availability @@ -156,22 +156,21 @@ # define _LIBCPP_AVAILABILITY_FORMAT // # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format - // This controls whether the std::__libcpp_assertion_handler default - // assertion handler is provided by the library. + // This controls whether the default verbose termination function is + // provided by the library. // - // Note that when users provide their own custom assertion handler, - // it doesn't matter whether the dylib provides a default handler, - // and the availability markup can actually give a false positive - // diagnostic (it will think that no handler is provided, when in - // reality the user has provided their own). + // Note that when users provide their own custom function, it doesn't + // matter whether the dylib provides a default function, and the + // availability markup can actually give a false positive diagnostic + // (it will think that no function is provided, when in reality the + // user has provided their own). // - // Users can pass -D_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED - // to the compiler to tell the library to ignore the fact that the - // default handler isn't available on their deployment target. Note that - // defining this macro but failing to define a custom assertion handler - // will lead to a load-time error on back-deployment targets, so it - // should be avoided. -# define _LIBCPP_AVAILABILITY_DEFAULT_ASSERTION_HANDLER + // Users can pass -D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED + // to the compiler to tell the library not to define its own verbose abort. + // Note that defining this macro but failing to define a custom function + // will lead to a load-time error on back-deployment targets, so it should + // be avoided. +// # define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY #elif defined(__APPLE__) @@ -272,8 +271,8 @@ __attribute__((unavailable)) # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format -# define _LIBCPP_AVAILABILITY_DEFAULT_ASSERTION_HANDLER \ - __attribute__((unavailable)) +# define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY + #else // ...New vendors can add availability markup here... @@ -297,14 +296,4 @@ # define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS #endif -// Define the special assertion handler availability attribute, which can be silenced by -// users if they provide their own custom assertion handler. The rest of the code should -// not use the *_DEFAULT_* macro directly, since that would make it ignore the fact that -// the user provided a custom handler. -#if defined(_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED) -# define _LIBCPP_AVAILABILITY_ASSERTION_HANDLER /* nothing */ -#else -# define _LIBCPP_AVAILABILITY_ASSERTION_HANDLER _LIBCPP_AVAILABILITY_DEFAULT_ASSERTION_HANDLER -#endif - #endif // _LIBCPP___AVAILABILITY diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference index f54cb6c16f48e..60f57d665a1cb 100644 --- a/libcxx/include/__bit_reference +++ b/libcxx/include/__bit_reference @@ -10,10 +10,13 @@ #ifndef _LIBCPP___BIT_REFERENCE #define _LIBCPP___BIT_REFERENCE +#include <__algorithm/copy_n.h> +#include <__algorithm/fill_n.h> #include <__algorithm/min.h> #include <__bits> #include <__config> #include <__iterator/iterator_traits.h> +#include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include #include @@ -51,15 +54,15 @@ class __bit_reference friend class __bit_const_reference<_Cp>; friend class __bit_iterator<_Cp, false>; public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_reference(const __bit_reference&) = default; - _LIBCPP_INLINE_VISIBILITY operator bool() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 operator bool() const _NOEXCEPT {return static_cast(*__seg_ & __mask_);} - _LIBCPP_INLINE_VISIBILITY bool operator ~() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool operator ~() const _NOEXCEPT {return !static_cast(*this);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_reference& operator=(bool __x) _NOEXCEPT { if (__x) @@ -70,7 +73,7 @@ public: } #if _LIBCPP_STD_VER > 20 - _LIBCPP_HIDE_FROM_ABI const __bit_reference& operator=(bool __x) const noexcept { + _LIBCPP_HIDE_FROM_ABI constexpr const __bit_reference& operator=(bool __x) const noexcept { if (__x) *__seg_ |= __mask_; else @@ -79,15 +82,15 @@ public: } #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_reference& operator=(const __bit_reference& __x) _NOEXCEPT {return operator=(static_cast(__x));} - _LIBCPP_INLINE_VISIBILITY void flip() _NOEXCEPT {*__seg_ ^= __mask_;} - _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, false> operator&() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void flip() _NOEXCEPT {*__seg_ ^= __mask_;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> operator&() const _NOEXCEPT {return __bit_iterator<_Cp, false>(__seg_, static_cast(__libcpp_ctz(__mask_)));} private: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT : __seg_(__s), __mask_(__m) {} }; @@ -98,7 +101,7 @@ class __bit_reference<_Cp, false> }; template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT { @@ -108,7 +111,7 @@ swap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT { @@ -118,7 +121,7 @@ swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT { @@ -128,7 +131,7 @@ swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(bool& __x, __bit_reference<_Cp> __y) _NOEXCEPT { @@ -152,14 +155,14 @@ public: _LIBCPP_INLINE_VISIBILITY __bit_const_reference(const __bit_const_reference&) = default; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_const_reference(const __bit_reference<_Cp>& __x) _NOEXCEPT : __seg_(__x.__seg_), __mask_(__x.__mask_) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator bool() const _NOEXCEPT {return static_cast(*__seg_ & __mask_);} - _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, true> operator&() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, true> operator&() const _NOEXCEPT {return __bit_iterator<_Cp, true>(__seg_, static_cast(__libcpp_ctz(__mask_)));} private: _LIBCPP_INLINE_VISIBILITY @@ -173,12 +176,12 @@ private: // find template -__bit_iterator<_Cp, _IsConst> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, _IsConst> __find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) { typedef __bit_iterator<_Cp, _IsConst> _It; typedef typename _It::__storage_type __storage_type; - static const int __bits_per_word = _It::__bits_per_word; + const int __bits_per_word = _It::__bits_per_word; // do first partial word if (__first.__ctz_ != 0) { @@ -209,7 +212,7 @@ __find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type } template -__bit_iterator<_Cp, _IsConst> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, _IsConst> __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) { typedef __bit_iterator<_Cp, _IsConst> _It; @@ -248,7 +251,7 @@ __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, _IsConst> find(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value) { @@ -334,7 +337,7 @@ count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __las // fill_n template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __fill_n_false(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) { typedef __bit_iterator<_Cp, false> _It; @@ -352,7 +355,7 @@ __fill_n_false(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) } // do middle whole words __storage_type __nw = __n / __bits_per_word; - _VSTD::memset(_VSTD::__to_address(__first.__seg_), 0, __nw * sizeof(__storage_type)); + std::fill_n(std::__to_address(__first.__seg_), __nw, 0); __n -= __nw * __bits_per_word; // do last partial word if (__n > 0) @@ -364,7 +367,7 @@ __fill_n_false(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __fill_n_true(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) { typedef __bit_iterator<_Cp, false> _It; @@ -382,7 +385,8 @@ __fill_n_true(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) } // do middle whole words __storage_type __nw = __n / __bits_per_word; - _VSTD::memset(_VSTD::__to_address(__first.__seg_), -1, __nw * sizeof(__storage_type)); + // __storage_type is always an unsigned type, so -1 sets all bits + std::fill_n(std::__to_address(__first.__seg_), __nw, static_cast<__storage_type>(-1)); __n -= __nw * __bits_per_word; // do last partial word if (__n > 0) @@ -394,7 +398,7 @@ __fill_n_true(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void fill_n(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n, bool __value) { @@ -410,7 +414,7 @@ fill_n(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n, bool __v // fill template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void fill(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __last, bool __value) { @@ -420,6 +424,7 @@ fill(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __last, bool // copy template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> __copy_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) @@ -449,9 +454,7 @@ __copy_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsCon // __first.__ctz_ == 0; // do middle words __storage_type __nw = __n / __bits_per_word; - _VSTD::memmove(_VSTD::__to_address(__result.__seg_), - _VSTD::__to_address(__first.__seg_), - __nw * sizeof(__storage_type)); + std::copy_n(std::__to_address(__first.__seg_), __nw, std::__to_address(__result.__seg_)); __n -= __nw * __bits_per_word; __result.__seg_ += __nw; // do last word @@ -469,6 +472,7 @@ __copy_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsCon } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> __copy_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) @@ -476,7 +480,7 @@ __copy_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsC typedef __bit_iterator<_Cp, _IsConst> _In; typedef typename _In::difference_type difference_type; typedef typename _In::__storage_type __storage_type; - static const int __bits_per_word = _In::__bits_per_word; + const int __bits_per_word = _In::__bits_per_word; difference_type __n = __last - __first; if (__n > 0) { @@ -547,7 +551,7 @@ __copy_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsC } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { @@ -559,7 +563,7 @@ copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last // copy_backward template -__bit_iterator<_Cp, false> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> __copy_backward_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { @@ -590,9 +594,7 @@ __copy_backward_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_C __storage_type __nw = __n / __bits_per_word; __result.__seg_ -= __nw; __last.__seg_ -= __nw; - _VSTD::memmove(_VSTD::__to_address(__result.__seg_), - _VSTD::__to_address(__last.__seg_), - __nw * sizeof(__storage_type)); + std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_)); __n -= __nw * __bits_per_word; // do last word if (__n > 0) @@ -608,7 +610,7 @@ __copy_backward_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_C } template -__bit_iterator<_Cp, false> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> __copy_backward_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { @@ -694,7 +696,7 @@ __copy_backward_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator< } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> copy_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) { @@ -901,14 +903,19 @@ struct __bit_array difference_type __size_; __storage_type __word_[_Np]; - _LIBCPP_INLINE_VISIBILITY static difference_type capacity() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static difference_type capacity() {return static_cast(_Np * __bits_per_word);} - _LIBCPP_INLINE_VISIBILITY explicit __bit_array(difference_type __s) : __size_(__s) {} - _LIBCPP_INLINE_VISIBILITY iterator begin() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __bit_array(difference_type __s) : __size_(__s) { + if (__libcpp_is_constant_evaluated()) { + for (size_t __i = 0; __i != __bit_array<_Cp>::_Np; ++__i) + std::__construct_at(__word_ + __i, 0); + } + } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator begin() { return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]), 0); } - _LIBCPP_INLINE_VISIBILITY iterator end() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator end() { return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]) + __size_ / __bits_per_word, static_cast(__size_ % __bits_per_word)); @@ -916,7 +923,7 @@ struct __bit_array }; template -__bit_iterator<_Cp, false> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator<_Cp, false> rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) { typedef __bit_iterator<_Cp, false> _I1; @@ -967,14 +974,14 @@ rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, // equal template -bool +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool __equal_unaligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { typedef __bit_iterator<_Cp, _IC1> _It; typedef typename _It::difference_type difference_type; typedef typename _It::__storage_type __storage_type; - static const int __bits_per_word = _It::__bits_per_word; + const int __bits_per_word = _It::__bits_per_word; difference_type __n = __last1 - __first1; if (__n > 0) { @@ -1049,14 +1056,14 @@ __equal_unaligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> } template -bool +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool __equal_aligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { typedef __bit_iterator<_Cp, _IC1> _It; typedef typename _It::difference_type difference_type; typedef typename _It::__storage_type __storage_type; - static const int __bits_per_word = _It::__bits_per_word; + const int __bits_per_word = _It::__bits_per_word; difference_type __n = __last1 - __first1; if (__n > 0) { @@ -1092,7 +1099,7 @@ __equal_aligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __ } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool equal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) { @@ -1126,7 +1133,7 @@ private: unsigned __ctz_; public: - _LIBCPP_INLINE_VISIBILITY __bit_iterator() _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator() _NOEXCEPT #if _LIBCPP_STD_VER > 11 : __seg_(nullptr), __ctz_(0) #endif @@ -1137,7 +1144,7 @@ public: // When _IsConst=true, this is a converting constructor; // the copy and move constructors are implicitly generated // and trivial. - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT : __seg_(__it.__seg_), __ctz_(__it.__ctz_) {} @@ -1146,19 +1153,19 @@ public: // the implicit generation of a defaulted one is deprecated. // When _IsConst=true, the assignment operators are // implicitly generated and trivial. - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator=(const _If<_IsConst, struct __private_nat, __bit_iterator>& __it) { __seg_ = __it.__seg_; __ctz_ = __it.__ctz_; return *this; } - _LIBCPP_INLINE_VISIBILITY reference operator*() const _NOEXCEPT { + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference operator*() const _NOEXCEPT { return typename conditional<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> > ::type(__seg_, __storage_type(1) << __ctz_); } - _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator++() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator++() { if (__ctz_ != __bits_per_word-1) ++__ctz_; @@ -1170,14 +1177,14 @@ public: return *this; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator operator++(int) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator operator++(int) { __bit_iterator __tmp = *this; ++(*this); return __tmp; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator--() + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator--() { if (__ctz_ != 0) --__ctz_; @@ -1189,14 +1196,14 @@ public: return *this; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator operator--(int) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator operator--(int) { __bit_iterator __tmp = *this; --(*this); return __tmp; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator+=(difference_type __n) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator+=(difference_type __n) { if (__n >= 0) __seg_ += (__n + __ctz_) / __bits_per_word; @@ -1208,54 +1215,54 @@ public: return *this; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator-=(difference_type __n) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator& operator-=(difference_type __n) { return *this += -__n; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator operator+(difference_type __n) const + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator operator+(difference_type __n) const { __bit_iterator __t(*this); __t += __n; return __t; } - _LIBCPP_INLINE_VISIBILITY __bit_iterator operator-(difference_type __n) const + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __bit_iterator operator-(difference_type __n) const { __bit_iterator __t(*this); __t -= __n; return __t; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend __bit_iterator operator+(difference_type __n, const __bit_iterator& __it) {return __it + __n;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend difference_type operator-(const __bit_iterator& __x, const __bit_iterator& __y) {return (__x.__seg_ - __y.__seg_) * __bits_per_word + __x.__ctz_ - __y.__ctz_;} - _LIBCPP_INLINE_VISIBILITY reference operator[](difference_type __n) const {return *(*this + __n);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference operator[](difference_type __n) const {return *(*this + __n);} - _LIBCPP_INLINE_VISIBILITY friend bool operator==(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator==(const __bit_iterator& __x, const __bit_iterator& __y) {return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_;} - _LIBCPP_INLINE_VISIBILITY friend bool operator!=(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator!=(const __bit_iterator& __x, const __bit_iterator& __y) {return !(__x == __y);} - _LIBCPP_INLINE_VISIBILITY friend bool operator<(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator<(const __bit_iterator& __x, const __bit_iterator& __y) {return __x.__seg_ < __y.__seg_ || (__x.__seg_ == __y.__seg_ && __x.__ctz_ < __y.__ctz_);} - _LIBCPP_INLINE_VISIBILITY friend bool operator>(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator>(const __bit_iterator& __x, const __bit_iterator& __y) {return __y < __x;} - _LIBCPP_INLINE_VISIBILITY friend bool operator<=(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator<=(const __bit_iterator& __x, const __bit_iterator& __y) {return !(__y < __x);} - _LIBCPP_INLINE_VISIBILITY friend bool operator>=(const __bit_iterator& __x, const __bit_iterator& __y) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 friend bool operator>=(const __bit_iterator& __x, const __bit_iterator& __y) {return !(__x < __y);} private: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT : __seg_(__s), __ctz_(__ctz) {} @@ -1265,26 +1272,44 @@ private: friend class __bit_const_reference<_Cp>; friend class __bit_iterator<_Cp, true>; template friend struct __bit_array; - template friend void __fill_n_false(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); - template friend void __fill_n_true(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); - template friend __bit_iterator<_Dp, false> __copy_aligned(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> __copy_unaligned(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> copy(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> __copy_backward_aligned(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> __copy_backward_unaligned(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); - template friend __bit_iterator<_Dp, false> copy_backward(__bit_iterator<_Dp, _IC> __first, - __bit_iterator<_Dp, _IC> __last, - __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend void __fill_n_false(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); + + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend void __fill_n_true(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); + + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> __copy_aligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> __copy_unaligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> copy(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> __copy_backward_aligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> __copy_backward_unaligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> copy_backward(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); template friend __bit_iterator<__C2, false> __swap_ranges_aligned(__bit_iterator<__C1, false>, __bit_iterator<__C1, false>, __bit_iterator<__C2, false>); @@ -1294,22 +1319,32 @@ private: template friend __bit_iterator<__C2, false> swap_ranges(__bit_iterator<__C1, false>, __bit_iterator<__C1, false>, __bit_iterator<__C2, false>); - template friend __bit_iterator<_Dp, false> rotate(__bit_iterator<_Dp, false>, - __bit_iterator<_Dp, false>, - __bit_iterator<_Dp, false>); - template friend bool __equal_aligned(__bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC2>); - template friend bool __equal_unaligned(__bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC2>); - template friend bool equal(__bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC1>, - __bit_iterator<_Dp, _IC2>); - template friend __bit_iterator<_Dp, _IC> __find_bool_true(__bit_iterator<_Dp, _IC>, - typename _Dp::size_type); - template friend __bit_iterator<_Dp, _IC> __find_bool_false(__bit_iterator<_Dp, _IC>, - typename _Dp::size_type); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, false> rotate(__bit_iterator<_Dp, false>, + __bit_iterator<_Dp, false>, + __bit_iterator<_Dp, false>); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend bool __equal_aligned(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend bool __equal_unaligned(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend bool equal(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, _IC> __find_bool_true(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); + template + _LIBCPP_CONSTEXPR_AFTER_CXX17 + friend __bit_iterator<_Dp, _IC> __find_bool_false(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); template friend typename __bit_iterator<_Dp, _IC>::difference_type __count_bool_true(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); template friend typename __bit_iterator<_Dp, _IC>::difference_type diff --git a/libcxx/include/__config b/libcxx/include/__config index 8c2f7614af537..c97cbae96fbac 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -22,9 +22,21 @@ # pragma GCC system_header #endif +#if defined(__apple_build_version__) +# define _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000) +#elif defined(__clang__) +# define _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__) +#elif defined(__GNUC__) +# define _LIBCPP_COMPILER_GCC +#elif defined(_MSC_VER) +# define _LIBCPP_COMPILER_MSVC +#endif + #ifdef __cplusplus -# define _LIBCPP_VERSION 15000 +# define _LIBCPP_VERSION 15007 # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) @@ -198,18 +210,6 @@ # define __has_include(...) 0 # endif -# if defined(__apple_build_version__) -# define _LIBCPP_COMPILER_CLANG_BASED -# define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000) -# elif defined(__clang__) -# define _LIBCPP_COMPILER_CLANG_BASED -# define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__) -# elif defined(__GNUC__) -# define _LIBCPP_COMPILER_GCC -# elif defined(_MSC_VER) -# define _LIBCPP_COMPILER_MSVC -# endif - # if !defined(_LIBCPP_COMPILER_CLANG_BASED) && __cplusplus < 201103L # error "libc++ only supports C++03 with Clang-based compilers. Please enable C++11" # endif @@ -1101,6 +1101,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION # endif // _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES +// Leave the deprecation notices in by default, but don't remove unary_function and +// binary_function entirely just yet. That way, folks will have one release to act +// on the deprecation warnings. +# ifndef _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION +# define _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION +# endif + # if defined(_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES) # define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS # define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h index db3af6e24101b..55b607f3f8047 100644 --- a/libcxx/include/__functional/function.h +++ b/libcxx/include/__functional/function.h @@ -883,7 +883,7 @@ template class __policy_func<_Rp(_ArgTypes...)> #endif // _LIBCPP_NO_RTTI }; -#if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) && !defined(_LIBCPP_HAS_OBJC_ARC) +#if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) extern "C" void *_Block_copy(const void *); extern "C" void _Block_release(const void *); @@ -898,14 +898,22 @@ class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> public: _LIBCPP_INLINE_VISIBILITY explicit __func(__block_type const& __f) +#ifdef _LIBCPP_HAS_OBJC_ARC + : __f_(__f) +#else : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) +#endif { } // [TODO] add && to save on a retain _LIBCPP_INLINE_VISIBILITY explicit __func(__block_type __f, const _Alloc& /* unused */) +#ifdef _LIBCPP_HAS_OBJC_ARC + : __f_(__f) +#else : __f_(reinterpret_cast<__block_type>(__f ? _Block_copy(__f) : nullptr)) +#endif { } virtual __base<_Rp(_ArgTypes...)>* __clone() const { @@ -921,8 +929,10 @@ class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> } virtual void destroy() _NOEXCEPT { +#ifndef _LIBCPP_HAS_OBJC_ARC if (__f_) _Block_release(__f_); +#endif __f_ = 0; } @@ -950,7 +960,7 @@ class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)> #endif // _LIBCPP_NO_RTTI }; -#endif // _LIBCPP_HAS_EXTENSION_BLOCKS && !_LIBCPP_HAS_OBJC_ARC +#endif // _LIBCPP_HAS_EXTENSION_BLOCKS } // namespace __function diff --git a/libcxx/include/__iterator/incrementable_traits.h b/libcxx/include/__iterator/incrementable_traits.h index 4109b58d46a9e..e6a5ed720f9fa 100644 --- a/libcxx/include/__iterator/incrementable_traits.h +++ b/libcxx/include/__iterator/incrementable_traits.h @@ -13,6 +13,7 @@ #include <__config> #include <__type_traits/is_primary_template.h> #include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h index 254f8c2339e41..0cc64adc0de96 100644 --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -14,6 +14,7 @@ #include <__iterator/incrementable_traits.h> #include <__iterator/readable_traits.h> #include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -507,6 +508,12 @@ using __iterator_category_type = typename iterator_traits<_Iter>::iterator_categ template using __iterator_pointer_type = typename iterator_traits<_Iter>::pointer; +template +using __iter_diff_t = typename iterator_traits<_Iter>::difference_type; + +template +using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___ITERATOR_ITERATOR_TRAITS_H diff --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h index 5c344c2ee3104..7b002205f3337 100644 --- a/libcxx/include/__iterator/reverse_iterator.h +++ b/libcxx/include/__iterator/reverse_iterator.h @@ -70,9 +70,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP typename iterator_traits<_Iter>::iterator_category>; using pointer = typename iterator_traits<_Iter>::pointer; #if _LIBCPP_STD_VER > 17 - using iterator_concept = _If<__is_cpp17_random_access_iterator<_Iter>::value, - random_access_iterator_tag, - bidirectional_iterator_tag>; + using iterator_concept = _If, random_access_iterator_tag, bidirectional_iterator_tag>; using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; using reference = iter_reference_t<_Iter>; @@ -365,7 +363,7 @@ class __unconstrained_reverse_iterator { _Iter __iter_; public: - static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value); + static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value || bidirectional_iterator<_Iter>); using iterator_type = _Iter; using iterator_category = @@ -393,6 +391,14 @@ class __unconstrained_reverse_iterator { } } + _LIBCPP_HIDE_FROM_ABI friend constexpr + iter_rvalue_reference_t<_Iter> iter_move(const __unconstrained_reverse_iterator& __i) + noexcept(is_nothrow_copy_constructible_v<_Iter> && + noexcept(ranges::iter_move(--declval<_Iter&>()))) { + auto __tmp = __i.base(); + return ranges::iter_move(--__tmp); + } + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator++() { --__iter_; return *this; diff --git a/libcxx/include/__memory/construct_at.h b/libcxx/include/__memory/construct_at.h index bfa20a149d51c..f5985b7731fda 100644 --- a/libcxx/include/__memory/construct_at.h +++ b/libcxx/include/__memory/construct_at.h @@ -42,7 +42,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __construct_at(_Tp* __location, _Ar #if _LIBCPP_STD_VER > 17 return std::construct_at(__location, std::forward<_Args>(__args)...); #else - return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...); + return _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at"), + ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...); #endif } diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h index 2549e4be7df12..348f7323a41d5 100644 --- a/libcxx/include/__memory/pointer_traits.h +++ b/libcxx/include/__memory/pointer_traits.h @@ -12,6 +12,7 @@ #include <__config> #include <__memory/addressof.h> +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -122,7 +123,7 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits private: struct __nat {}; public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static pointer pointer_to(typename conditional::value, __nat, element_type>::type& __r) {return pointer::pointer_to(__r);} @@ -171,9 +172,30 @@ _Tp* __to_address(_Tp* __p) _NOEXCEPT { return __p; } +template +struct _HasToAddress : false_type {}; + +template +struct _HasToAddress<_Pointer, + decltype((void)pointer_traits<_Pointer>::to_address(declval())) +> : true_type {}; + +template +struct _HasArrow : false_type {}; + +template +struct _HasArrow<_Pointer, + decltype((void)declval().operator->()) +> : true_type {}; + +template +struct _IsFancyPointer { + static const bool value = _HasArrow<_Pointer>::value || _HasToAddress<_Pointer>::value; +}; + // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers template ::value && !is_array<_Pointer>::value && !is_function<_Pointer>::value + _And, _IsFancyPointer<_Pointer> >::value > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename decay::__call(declval()))>::type @@ -208,7 +230,7 @@ auto to_address(_Tp *__p) noexcept { template inline _LIBCPP_INLINE_VISIBILITY constexpr -auto to_address(const _Pointer& __p) noexcept { +auto to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) { return _VSTD::__to_address(__p); } #endif diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h index 72b6890c22251..4f3d4e90cb6e2 100644 --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -509,10 +509,11 @@ __allocator_destroy(_Alloc& __alloc, _Iter __first, _Sent __last) { template class _AllocatorDestroyRangeReverse { public: - _LIBCPP_HIDE_FROM_ABI _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 + _AllocatorDestroyRangeReverse(_Alloc& __alloc, _Iter& __first, _Iter& __last) : __alloc_(__alloc), __first_(__first), __last_(__last) {} - _LIBCPP_CONSTEXPR_AFTER_CXX11 void operator()() const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void operator()() const { std::__allocator_destroy(__alloc_, std::reverse_iterator<_Iter>(__last_), std::reverse_iterator<_Iter>(__first_)); } @@ -621,7 +622,7 @@ template < class _Type = typename iterator_traits<_Iter1>::value_type, class = __enable_if_t::value && is_trivially_move_assignable<_Type>::value && __allocator_has_trivial_move_construct<_Alloc, _Type>::value> > -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter1 +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter2 __uninitialized_allocator_move_if_noexcept(_Alloc&, _Iter1 __first1, _Iter1 __last1, _Iter2 __first2) { if (__libcpp_is_constant_evaluated()) { while (__first1 != __last1) { diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h index 32ca4b854bc3b..0e6d295651a3c 100644 --- a/libcxx/include/__ranges/size.h +++ b/libcxx/include/__ranges/size.h @@ -16,6 +16,7 @@ #include <__ranges/access.h> #include <__utility/auto_cast.h> #include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index f781674662175..4d40732a75cf0 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -62,107 +62,107 @@ public: typedef typename add_lvalue_reference::type __alloc_ref; typedef typename add_lvalue_reference::type __alloc_const_ref; - _LIBCPP_INLINE_VISIBILITY __alloc_rr& __alloc() _NOEXCEPT {return __end_cap_.second();} - _LIBCPP_INLINE_VISIBILITY const __alloc_rr& __alloc() const _NOEXCEPT {return __end_cap_.second();} - _LIBCPP_INLINE_VISIBILITY pointer& __end_cap() _NOEXCEPT {return __end_cap_.first();} - _LIBCPP_INLINE_VISIBILITY const pointer& __end_cap() const _NOEXCEPT {return __end_cap_.first();} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY __alloc_rr& __alloc() _NOEXCEPT {return __end_cap_.second();} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const __alloc_rr& __alloc() const _NOEXCEPT {return __end_cap_.second();} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY pointer& __end_cap() _NOEXCEPT {return __end_cap_.first();} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const pointer& __end_cap() const _NOEXCEPT {return __end_cap_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY __split_buffer() _NOEXCEPT_(is_nothrow_default_constructible::value); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY explicit __split_buffer(__alloc_rr& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY explicit __split_buffer(const __alloc_rr& __a); - __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); - ~__split_buffer(); + _LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__split_buffer(); - __split_buffer(__split_buffer&& __c) + _LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer(__split_buffer&& __c) _NOEXCEPT_(is_nothrow_move_constructible::value); - __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); - __split_buffer& operator=(__split_buffer&& __c) + _LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer& operator=(__split_buffer&& __c) _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable::value) || !__alloc_traits::propagate_on_container_move_assignment::value); - _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __begin_;} - _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __begin_;} - _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return __end_;} - _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return __end_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return __end_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return __end_;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__destruct_at_end(__begin_);} - _LIBCPP_INLINE_VISIBILITY size_type size() const {return static_cast(__end_ - __begin_);} - _LIBCPP_INLINE_VISIBILITY bool empty() const {return __end_ == __begin_;} - _LIBCPP_INLINE_VISIBILITY size_type capacity() const {return static_cast(__end_cap() - __first_);} - _LIBCPP_INLINE_VISIBILITY size_type __front_spare() const {return static_cast(__begin_ - __first_);} - _LIBCPP_INLINE_VISIBILITY size_type __back_spare() const {return static_cast(__end_cap() - __end_);} - - _LIBCPP_INLINE_VISIBILITY reference front() {return *__begin_;} - _LIBCPP_INLINE_VISIBILITY const_reference front() const {return *__begin_;} - _LIBCPP_INLINE_VISIBILITY reference back() {return *(__end_ - 1);} - _LIBCPP_INLINE_VISIBILITY const_reference back() const {return *(__end_ - 1);} - - void reserve(size_type __n); - void shrink_to_fit() _NOEXCEPT; - void push_front(const_reference __x); - _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x); - void push_front(value_type&& __x); - void push_back(value_type&& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type size() const {return static_cast(__end_ - __begin_);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool empty() const {return __end_ == __begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type capacity() const {return static_cast(__end_cap() - __first_);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type __front_spare() const {return static_cast(__begin_ - __first_);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type __back_spare() const {return static_cast(__end_cap() - __end_);} + + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference front() {return *__begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference front() const {return *__begin_;} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference back() {return *(__end_ - 1);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference back() const {return *(__end_ - 1);} + + _LIBCPP_CONSTEXPR_AFTER_CXX17 void reserve(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void shrink_to_fit() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_front(const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_front(value_type&& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_back(value_type&& __x); template - void emplace_back(_Args&&... __args); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void emplace_back(_Args&&... __args); - _LIBCPP_INLINE_VISIBILITY void pop_front() {__destruct_at_begin(__begin_+1);} - _LIBCPP_INLINE_VISIBILITY void pop_back() {__destruct_at_end(__end_-1);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void pop_front() {__destruct_at_begin(__begin_+1);} + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void pop_back() {__destruct_at_end(__end_-1);} - void __construct_at_end(size_type __n); - void __construct_at_end(size_type __n, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_at_end(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_at_end(size_type __n, const_reference __x); template - __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> + _LIBCPP_CONSTEXPR_AFTER_CXX17 __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> __construct_at_end(_InputIter __first, _InputIter __last); template - __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> + _LIBCPP_CONSTEXPR_AFTER_CXX17 __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); - _LIBCPP_INLINE_VISIBILITY void __destruct_at_begin(pointer __new_begin) + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_begin(pointer __new_begin) {__destruct_at_begin(__new_begin, is_trivially_destructible());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_begin(pointer __new_begin, false_type); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_begin(pointer __new_begin, true_type); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_end(pointer __new_last) _NOEXCEPT {__destruct_at_end(__new_last, false_type());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT; - void swap(__split_buffer& __x) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(__split_buffer& __x) _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| __is_nothrow_swappable<__alloc_rr>::value); - bool __invariants() const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __invariants() const; private: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__split_buffer& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __alloc() = _VSTD::move(__c.__alloc()); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {} struct _ConstructTransaction { - explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT : __pos_(*__p), __end_(*__p + __n), __dest_(__p) { } - ~_ConstructTransaction() { + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~_ConstructTransaction() { *__dest_ = __pos_; } pointer __pos_; @@ -173,6 +173,7 @@ private: }; template +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool __split_buffer<_Tp, _Allocator>::__invariants() const { @@ -203,6 +204,7 @@ __split_buffer<_Tp, _Allocator>::__invariants() const // Precondition: size() + __n <= capacity() // Postcondition: size() == size() + __n template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) { @@ -219,6 +221,7 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) // Postcondition: size() == old size() + __n // Postcondition: [i] == __x for all i in [size() - __n, __n) template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) { @@ -231,7 +234,7 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_referen template template -__enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> __split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIter __last) { __alloc_rr& __a = this->__alloc(); @@ -254,7 +257,7 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIt template template -__enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> +_LIBCPP_CONSTEXPR_AFTER_CXX17 __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> __split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) { _ConstructTransaction __tx(&this->__end_, _VSTD::distance(__first, __last)); @@ -265,6 +268,7 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _F } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) @@ -274,6 +278,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type) @@ -282,6 +287,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_t } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT @@ -291,6 +297,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_typ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type) _NOEXCEPT @@ -299,6 +306,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a) : __end_cap_(nullptr, __a) { @@ -314,6 +322,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __sta } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline __split_buffer<_Tp, _Allocator>::__split_buffer() _NOEXCEPT_(is_nothrow_default_constructible::value) @@ -322,6 +331,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer() } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline __split_buffer<_Tp, _Allocator>::__split_buffer(__alloc_rr& __a) : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) @@ -329,6 +339,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(__alloc_rr& __a) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline __split_buffer<_Tp, _Allocator>::__split_buffer(const __alloc_rr& __a) : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) @@ -336,6 +347,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(const __alloc_rr& __a) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>::~__split_buffer() { clear(); @@ -344,6 +356,7 @@ __split_buffer<_Tp, _Allocator>::~__split_buffer() } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c) _NOEXCEPT_(is_nothrow_move_constructible::value) : __first_(_VSTD::move(__c.__first_)), @@ -358,6 +371,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a) : __end_cap_(nullptr, __a) { @@ -384,6 +398,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __al } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 __split_buffer<_Tp, _Allocator>& __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && @@ -404,6 +419,7 @@ __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x) _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| @@ -417,6 +433,7 @@ __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::reserve(size_type __n) { @@ -433,6 +450,7 @@ __split_buffer<_Tp, _Allocator>::reserve(size_type __n) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { @@ -460,6 +478,7 @@ __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) { @@ -489,6 +508,7 @@ __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) { @@ -519,6 +539,7 @@ __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void __split_buffer<_Tp, _Allocator>::push_back(const_reference __x) @@ -549,6 +570,7 @@ __split_buffer<_Tp, _Allocator>::push_back(const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) { @@ -580,6 +602,7 @@ __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) { @@ -610,6 +633,7 @@ __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) diff --git a/libcxx/include/__support/musl/xlocale.h b/libcxx/include/__support/musl/xlocale.h index f564c87885ac1..e674a41fa622a 100644 --- a/libcxx/include/__support/musl/xlocale.h +++ b/libcxx/include/__support/musl/xlocale.h @@ -39,7 +39,7 @@ wcstoll_l(const wchar_t *__nptr, wchar_t **__endptr, int __base, locale_t) { return ::wcstoll(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI long long +inline _LIBCPP_HIDE_FROM_ABI unsigned long long wcstoull_l(const wchar_t *__nptr, wchar_t **__endptr, int __base, locale_t) { return ::wcstoull(__nptr, __endptr, __base); } diff --git a/libcxx/include/__verbose_abort b/libcxx/include/__verbose_abort new file mode 100644 index 0000000000000..3c9cba824ce0b --- /dev/null +++ b/libcxx/include/__verbose_abort @@ -0,0 +1,51 @@ +// -*- 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 _LIBCPP___VERBOSE_ABORT +#define _LIBCPP___VERBOSE_ABORT + +#include <__availability> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// Provide a default implementation of __libcpp_verbose_abort if we know that neither the built +// library not the user is providing one. Otherwise, just declare it and use the one from the +// built library or the one provided by the user. +// +// We can't provide a great implementation because it needs to be pretty much +// dependency-free (this is included everywhere else in the library). +#if defined(_LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY) && !defined(_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED) + +extern "C" void abort(); + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_NORETURN _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) _LIBCPP_HIDE_FROM_ABI inline +void __libcpp_verbose_abort(const char *, ...) { + ::abort(); + __builtin_unreachable(); // never reached, but needed to tell the compiler that the function never returns +} + +_LIBCPP_END_NAMESPACE_STD + +#else + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_NORETURN _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) +void __libcpp_verbose_abort(const char *__format, ...); + +_LIBCPP_END_NAMESPACE_STD + +#endif + +#endif // _LIBCPP___VERBOSE_ABORT diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index 197b3b1043bbe..69ada038747cf 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -446,6 +446,25 @@ namespace ranges { indirect_unary_predicate, Proj>> Pred> constexpr bool ranges::none_of(R&& r, Pred pred, Proj proj = {}); // since C++20 + template S1, + random_access_iterator I2, sentinel_for S2, + class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> + requires indirectly_copyable && sortable && + indirect_strict_weak_order, projected> + constexpr partial_sort_copy_result + partial_sort_copy(I1 first, S1 last, I2 result_first, S2 result_last, + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + + template + requires indirectly_copyable, iterator_t> && + sortable, Comp, Proj2> && + indirect_strict_weak_order, Proj1>, + projected, Proj2>> + constexpr partial_sort_copy_result, borrowed_iterator_t> + partial_sort_copy(R1&& r, R2&& result_r, Comp comp = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + template S, class Proj = identity, indirect_strict_weak_order> Comp = ranges::less> constexpr bool ranges::is_sorted(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20 @@ -574,6 +593,11 @@ namespace ranges { constexpr borrowed_iterator_t ranges::replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {}); // since C++20 + template> Comp = ranges::less> + constexpr const T& + ranges::clamp(const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {}); // since C++20 + template S1, input_iterator I2, sentinel_for S2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order, @@ -726,6 +750,13 @@ namespace ranges { constexpr ranges::reverse_copy_result, O> ranges::reverse_copy(R&& r, O result); // since C++20 + template S> + constexpr subrange rotate(I first, I middle, S last); // since C++20 + + template + requires permutable> + constexpr borrowed_subrange_t rotate(R&& r, iterator_t middle); // Since C++20 + template using rotate_copy_result = in_out_result<_InIter, _OutIter>; // since C++20 @@ -739,6 +770,18 @@ namespace ranges { constexpr ranges::rotate_copy_result, O> ranges::rotate_copy(R&& r, iterator_t middle, O result); // since C++20 + template S, weakly_incrementable O, class Gen> + requires (forward_iterator || random_access_iterator) && + indirectly_copyable && + uniform_random_bit_generator> + O sample(I first, S last, O out, iter_difference_t n, Gen&& g); // Since C++20 + + template + requires (forward_range || random_access_iterator) && + indirectly_copyable, O> && + uniform_random_bit_generator> + O sample(R&& r, O out, range_difference_t n, Gen&& g); // Since C++20 + template S, class Gen> requires permutable && uniform_random_bit_generator> @@ -749,6 +792,21 @@ namespace ranges { uniform_random_bit_generator> borrowed_iterator_t shuffle(R&& r, Gen&& g); // Since C++20 + template S1, forward_iterator I2, + sentinel_for S2, class Proj1 = identity, class Proj2 = identity, + indirect_equivalence_relation, + projected> Pred = ranges::equal_to> + constexpr bool ranges::is_permutation(I1 first1, S1 last1, I2 first2, S2 last2, + Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + + template, Proj1>, + projected, Proj2>> Pred = ranges::equal_to> + constexpr bool ranges::is_permutation(R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + template S1, forward_iterator I2, sentinel_for S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> @@ -803,7 +861,7 @@ namespace ranges { set_symmetric_difference(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 - + template requires mergeable, iterator_t, O, Comp, Proj1, Proj2> @@ -816,13 +874,13 @@ namespace ranges { indirect_strict_weak_order> Comp = ranges::less> constexpr subrange equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 - + template, Proj>> Comp = ranges::less> constexpr borrowed_subrange_t equal_range(R&& r, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 - + template using set_union_result = in_in_out_result; // since C++20 @@ -847,15 +905,154 @@ namespace ranges { ranges::less> constexpr bool includes(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 - + template, Proj1>, projected, Proj2>> Comp = ranges::less> constexpr bool includes(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + + template S, class Comp = ranges::less, + class Proj = identity> + requires sortable + I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + + template + requires sortable, Comp, Proj> + borrowed_iterator_t + inplace_merge(R&& r, iterator_t middle, Comp comp = {}, + Proj proj = {}); // Since C++20 + + template S, class Proj = identity, + indirect_equivalence_relation> C = ranges::equal_to> + constexpr subrange unique(I first, S last, C comp = {}, Proj proj = {}); // Since C++20 + + template, Proj>> C = ranges::equal_to> + requires permutable> + constexpr borrowed_subrange_t + unique(R&& r, C comp = {}, Proj proj = {}); // Since C++20 + + template S, weakly_incrementable O, class Proj = identity, + indirect_equivalence_relation> C = ranges::equal_to> + requires indirectly_copyable && + (forward_iterator || + (input_iterator && same_as, iter_value_t>) || + indirectly_copyable_storable) + constexpr unique_copy_result + unique_copy(I first, S last, O result, C comp = {}, Proj proj = {}); // Since C++20 + + template, Proj>> C = ranges::equal_to> + requires indirectly_copyable, O> && + (forward_iterator> || + (input_iterator && same_as, iter_value_t>) || + indirectly_copyable_storable, O>) + constexpr unique_copy_result, O> + unique_copy(R&& r, O result, C comp = {}, Proj proj = {}); // Since C++20 + + template + using remove_copy_result = in_out_result; // Since C++20 + + template S, weakly_incrementable O, class T, + class Proj = identity> + indirect_binary_predicate, const T*> + constexpr remove_copy_result + remove_copy(I first, S last, O result, const T& value, Proj proj = {}); // Since C++20 + + template + requires indirectly_copyable, O> && + indirect_binary_predicate, Proj>, const T*> + constexpr remove_copy_result, O> + remove_copy(R&& r, O result, const T& value, Proj proj = {}); // Since C++20 + + template + using remove_copy_if_result = in_out_result; // Since C++20 + + template S, weakly_incrementable O, + class Proj = identity, indirect_unary_predicate> Pred> + requires indirectly_copyable + constexpr remove_copy_if_result + remove_copy_if(I first, S last, O result, Pred pred, Proj proj = {}); // Since C++20 + + template, Proj>> Pred> + requires indirectly_copyable, O> + constexpr remove_copy_if_result, O> + remove_copy_if(R&& r, O result, Pred pred, Proj proj = {}); // Since C++20 + + template + using replace_copy_result = in_out_result; // Since C++20 + + template S, class T1, class T2, + output_iterator O, class Proj = identity> + requires indirectly_copyable && + indirect_binary_predicate, const T1*> + constexpr replace_copy_result + replace_copy(I first, S last, O result, const T1& old_value, const T2& new_value, + Proj proj = {}); // Since C++20 + + template O, + class Proj = identity> + requires indirectly_copyable, O> && + indirect_binary_predicate, Proj>, const T1*> + constexpr replace_copy_result, O> + replace_copy(R&& r, O result, const T1& old_value, const T2& new_value, + Proj proj = {}); // Since C++20 + + template + using replace_copy_if_result = in_out_result; // Since C++20 + + template S, class T, output_iterator O, + class Proj = identity, indirect_unary_predicate> Pred> + requires indirectly_copyable + constexpr replace_copy_if_result + replace_copy_if(I first, S last, O result, Pred pred, const T& new_value, + Proj proj = {}); // Since C++20 + + template O, class Proj = identity, + indirect_unary_predicate, Proj>> Pred> + requires indirectly_copyable, O> + constexpr replace_copy_if_result, O> + replace_copy_if(R&& r, O result, Pred pred, const T& new_value, + Proj proj = {}); // Since C++20 + + template + using prev_permutation_result = in_found_result; // Since C++20 + + template S, class Comp = ranges::less, + class Proj = identity> + requires sortable + constexpr ranges::prev_permutation_result + ranges::prev_permutation(I first, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + + template + requires sortable, Comp, Proj> + constexpr ranges::prev_permutation_result> + ranges::prev_permutation(R&& r, Comp comp = {}, Proj proj = {}); // Since C++20 + + template + using next_permutation_result = in_found_result; // Since C++20 + + template S, class Comp = ranges::less, + class Proj = identity> + requires sortable + constexpr ranges::next_permutation_result + ranges::next_permutation(I first, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + + template + requires sortable, Comp, Proj> + constexpr ranges::next_permutation_result> + ranges::next_permutation(R&& r, Comp comp = {}, Proj proj = {}); // Since C++20 + } +template constexpr bool // constexpr in C++20 all_of(InputIterator first, InputIterator last, Predicate pred); @@ -1587,6 +1784,7 @@ template #include <__algorithm/ranges_all_of.h> #include <__algorithm/ranges_any_of.h> #include <__algorithm/ranges_binary_search.h> +#include <__algorithm/ranges_clamp.h> #include <__algorithm/ranges_copy.h> #include <__algorithm/ranges_copy_backward.h> #include <__algorithm/ranges_copy_if.h> @@ -1607,9 +1805,11 @@ template #include <__algorithm/ranges_generate.h> #include <__algorithm/ranges_generate_n.h> #include <__algorithm/ranges_includes.h> +#include <__algorithm/ranges_inplace_merge.h> #include <__algorithm/ranges_is_heap.h> #include <__algorithm/ranges_is_heap_until.h> #include <__algorithm/ranges_is_partitioned.h> +#include <__algorithm/ranges_is_permutation.h> #include <__algorithm/ranges_is_sorted.h> #include <__algorithm/ranges_is_sorted_until.h> #include <__algorithm/ranges_lexicographical_compare.h> @@ -1625,21 +1825,30 @@ template #include <__algorithm/ranges_mismatch.h> #include <__algorithm/ranges_move.h> #include <__algorithm/ranges_move_backward.h> +#include <__algorithm/ranges_next_permutation.h> #include <__algorithm/ranges_none_of.h> #include <__algorithm/ranges_nth_element.h> #include <__algorithm/ranges_partial_sort.h> +#include <__algorithm/ranges_partial_sort_copy.h> #include <__algorithm/ranges_partition.h> #include <__algorithm/ranges_partition_copy.h> #include <__algorithm/ranges_partition_point.h> #include <__algorithm/ranges_pop_heap.h> +#include <__algorithm/ranges_prev_permutation.h> #include <__algorithm/ranges_push_heap.h> #include <__algorithm/ranges_remove.h> +#include <__algorithm/ranges_remove_copy.h> +#include <__algorithm/ranges_remove_copy_if.h> #include <__algorithm/ranges_remove_if.h> #include <__algorithm/ranges_replace.h> +#include <__algorithm/ranges_replace_copy.h> +#include <__algorithm/ranges_replace_copy_if.h> #include <__algorithm/ranges_replace_if.h> #include <__algorithm/ranges_reverse.h> #include <__algorithm/ranges_reverse_copy.h> +#include <__algorithm/ranges_rotate.h> #include <__algorithm/ranges_rotate_copy.h> +#include <__algorithm/ranges_sample.h> #include <__algorithm/ranges_search.h> #include <__algorithm/ranges_search_n.h> #include <__algorithm/ranges_set_difference.h> @@ -1653,6 +1862,8 @@ template #include <__algorithm/ranges_stable_sort.h> #include <__algorithm/ranges_swap_ranges.h> #include <__algorithm/ranges_transform.h> +#include <__algorithm/ranges_unique.h> +#include <__algorithm/ranges_unique_copy.h> #include <__algorithm/ranges_upper_bound.h> #include <__algorithm/remove.h> #include <__algorithm/remove_copy.h> diff --git a/libcxx/include/atomic b/libcxx/include/atomic index 92da4820e928b..3a93b9b0a1081 100644 --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -1113,6 +1113,12 @@ _Tp kill_dependency(_Tp __y) _NOEXCEPT # define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE #endif +template +struct __libcpp_is_always_lock_free { + // __atomic_always_lock_free is available in all Standard modes + static const bool __value = __atomic_always_lock_free(sizeof(_Tp), 0); +}; + #ifdef _LIBCPP_ATOMIC_ONLY_USE_BUILTINS template @@ -1404,42 +1410,8 @@ _Tp __cxx_atomic_fetch_xor(__cxx_atomic_lock_impl<_Tp>* __a, return __old; } -#ifdef __cpp_lib_atomic_is_always_lock_free - -template struct __cxx_is_always_lock_free { - enum { __value = __atomic_always_lock_free(sizeof(_Tp), 0) }; }; - -#else - -template struct __cxx_is_always_lock_free { enum { __value = false }; }; -// Implementations must match the C ATOMIC_*_LOCK_FREE macro values. -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_BOOL_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR_LOCK_FREE }; }; -#ifndef _LIBCPP_HAS_NO_CHAR8_T -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR8_T_LOCK_FREE }; }; -#endif -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR16_T_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_CHAR32_T_LOCK_FREE }; }; -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_WCHAR_T_LOCK_FREE }; }; -#endif -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_SHORT_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_SHORT_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_INT_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_INT_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_LONG_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_LONG_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_LLONG_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_LLONG_LOCK_FREE }; }; -template struct __cxx_is_always_lock_free<_Tp*> { enum { __value = 2 == ATOMIC_POINTER_LOCK_FREE }; }; -template<> struct __cxx_is_always_lock_free { enum { __value = 2 == ATOMIC_POINTER_LOCK_FREE }; }; - -#endif //__cpp_lib_atomic_is_always_lock_free - template ::__value, + typename _Base = typename conditional<__libcpp_is_always_lock_free<_Tp>::__value, __cxx_atomic_base_impl<_Tp>, __cxx_atomic_lock_impl<_Tp> >::type> #else @@ -1561,7 +1533,7 @@ struct __atomic_base // false mutable __cxx_atomic_impl<_Tp> __a_; #if defined(__cpp_lib_atomic_is_always_lock_free) - static _LIBCPP_CONSTEXPR bool is_always_lock_free = __atomic_always_lock_free(sizeof(__a_), 0); + static _LIBCPP_CONSTEXPR bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; #endif _LIBCPP_INLINE_VISIBILITY @@ -2664,7 +2636,7 @@ typedef atomic atomic_uintmax_t; // atomic_*_lock_free : prefer the contention type most highly, then the largest lock-free type #ifdef __cpp_lib_atomic_is_always_lock_free -# define _LIBCPP_CONTENTION_LOCK_FREE __atomic_always_lock_free(sizeof(__cxx_contention_t), 0) +# define _LIBCPP_CONTENTION_LOCK_FREE ::std::__libcpp_is_always_lock_free<__cxx_contention_t>::__value #else # define _LIBCPP_CONTENTION_LOCK_FREE false #endif diff --git a/libcxx/include/format b/libcxx/include/format index d2ec8fc233634..6b14570bc6272 100644 --- a/libcxx/include/format +++ b/libcxx/include/format @@ -23,16 +23,23 @@ namespace std { using format_args = basic_format_args; using wformat_args = basic_format_args; - // [format.fmt.string], class template basic-format-string + // [format.fmt.string], class template basic_format_string template - struct basic-format-string; // exposition only + struct basic_format_string { // since C++23, exposition only before C++23 + private: + basic_string_view str; // exposition only + public: + template consteval basic_format_string(const T& s); + + constexpr basic_string_view get() const noexcept { return str; } + }; template - using format-string = // exposition only - basic-format-string...>; + using format_string = // since C++23, exposition only before C++23 + basic_format_string...>; template - using wformat-string = // exposition only - basic-format-string...>; + using wformat_string = // since C++23, exposition only before C++23 + basic_format_string...>; // [format.functions], formatting functions template @@ -233,7 +240,7 @@ private: }; // Dummy format_context only providing the parts used during constant -// validation of the basic-format-string. +// validation of the basic_format_string. template struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { public: @@ -468,17 +475,21 @@ __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { } // namespace __format template -struct _LIBCPP_TEMPLATE_VIS __basic_format_string { - basic_string_view<_CharT> __str_; - +struct _LIBCPP_TEMPLATE_VIS basic_format_string { template requires convertible_to> - consteval __basic_format_string(const _Tp& __str) : __str_{__str} { + consteval basic_format_string(const _Tp& __str) : __str_{__str} { __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { + return __str_; + } + private: + basic_string_view<_CharT> __str_; + using _Context = __format::__compile_time_basic_format_context<_CharT>; static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ @@ -510,11 +521,11 @@ private: }; template -using __format_string_t = __basic_format_string...>; +using format_string = basic_format_string...>; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -using __wformat_string_t = __basic_format_string...>; +using wformat_string = basic_format_string...>; #endif template @@ -555,16 +566,16 @@ vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, +format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, +format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -586,16 +597,16 @@ vformat(wstring_view __fmt, wformat_args __args) { #endif template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(__format_string_t<_Args...> __fmt, +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(__fmt.__str_, _VSTD::make_format_args(__args...)); + return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -format(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(__fmt.__str_, _VSTD::make_wformat_args(__args...)); +format(wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -611,16 +622,16 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_format_args(__args...)); +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __wformat_string_t<_Args...> __fmt, +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_wformat_args(__args...)); + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -634,15 +645,15 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(__format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); +formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); +formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); } #endif @@ -686,16 +697,16 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt v template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, +format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, +format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -720,17 +731,17 @@ vformat(locale __loc, wstring_view __fmt, wformat_args __args) { template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, - __format_string_t<_Args...> __fmt, + format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, + return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -format(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, +format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -748,18 +759,18 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __format_string_t<_Args...> __fmt, +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __wformat_string_t<_Args...> __fmt, +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -775,15 +786,15 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_ template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); +formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); +formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); } #endif diff --git a/libcxx/include/memory b/libcxx/include/memory index 56f8159fbd445..a986d76c8b4ef 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -838,6 +838,8 @@ template */ +#include <__algorithm/copy.h> +#include <__algorithm/move.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__memory/addressof.h> @@ -941,21 +943,31 @@ template struct __temp_value { typedef allocator_traits<_Alloc> _Traits; +#ifdef _LIBCPP_CXX03_LANG typename aligned_storage::type __v; +#else + union { _Tp __v; }; +#endif _Alloc &__a; - _Tp *__addr() { return reinterpret_cast<_Tp *>(addressof(__v)); } - _Tp & get() { return *__addr(); } + _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp *__addr() { +#ifdef _LIBCPP_CXX03_LANG + return reinterpret_cast<_Tp*>(std::addressof(__v)); +#else + return std::addressof(__v); +#endif + } + + _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & get() { return *__addr(); } template _LIBCPP_NO_CFI - __temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) { - _Traits::construct(__a, reinterpret_cast<_Tp*>(addressof(__v)), - _VSTD::forward<_Args>(__args)...); + _LIBCPP_CONSTEXPR_AFTER_CXX17 __temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) { + _Traits::construct(__a, __addr(), std::forward<_Args>(__args)...); } - ~__temp_value() { _Traits::destroy(__a, __addr()); } - }; + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__temp_value() { _Traits::destroy(__a, __addr()); } +}; template struct __is_allocator : false_type {}; diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 98485bcd93ab3..83c6384433ce3 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -59,7 +59,10 @@ module std [system] { // FIXME: is missing. // provided by C library. // provided by compiler. - // provided by compiler. + module stdbool_h { + // 's __bool_true_false_are_defined macro requires textual inclusion. + textual header "stdbool.h" + } module stddef_h { // 's __need_* macros require textual inclusion. textual header "stddef.h" @@ -311,6 +314,7 @@ module std [system] { module ranges_all_of { private header "__algorithm/ranges_all_of.h" } module ranges_any_of { private header "__algorithm/ranges_any_of.h" } module ranges_binary_search { private header "__algorithm/ranges_binary_search.h" } + module ranges_clamp { private header "__algorithm/ranges_clamp.h" } module ranges_copy { private header "__algorithm/ranges_copy.h" } module ranges_copy_backward { private header "__algorithm/ranges_copy_backward.h" } module ranges_copy_if { private header "__algorithm/ranges_copy_if.h" } @@ -335,6 +339,7 @@ module std [system] { module ranges_is_heap { private header "__algorithm/ranges_is_heap.h" } module ranges_is_heap_until { private header "__algorithm/ranges_is_heap_until.h" } module ranges_is_partitioned { private header "__algorithm/ranges_is_partitioned.h" } + module ranges_is_permutation { private header "__algorithm/ranges_is_permutation.h" } module ranges_is_sorted { private header "__algorithm/ranges_is_sorted.h" } module ranges_is_sorted_until { private header "__algorithm/ranges_is_sorted_until.h" } module ranges_iterator_concept { private header "__algorithm/ranges_iterator_concept.h" } @@ -351,6 +356,7 @@ module std [system] { module ranges_mismatch { private header "__algorithm/ranges_mismatch.h" } module ranges_move { private header "__algorithm/ranges_move.h" } module ranges_move_backward { private header "__algorithm/ranges_move_backward.h" } + module ranges_next_permutation { private header "__algorithm/ranges_next_permutation.h" } module ranges_none_of { private header "__algorithm/ranges_none_of.h" } module ranges_nth_element { private header "__algorithm/ranges_nth_element.h" } module ranges_partial_sort { private header "__algorithm/ranges_partial_sort.h" } @@ -359,6 +365,7 @@ module std [system] { module ranges_partition_copy { private header "__algorithm/ranges_partition_copy.h" } module ranges_partition_point { private header "__algorithm/ranges_partition_point.h" } module ranges_pop_heap { private header "__algorithm/ranges_pop_heap.h" } + module ranges_prev_permutation { private header "__algorithm/ranges_prev_permutation.h" } module ranges_push_heap { private header "__algorithm/ranges_push_heap.h" } module ranges_remove { private header "__algorithm/ranges_remove.h" } module ranges_remove_copy { private header "__algorithm/ranges_remove_copy.h" } @@ -370,7 +377,9 @@ module std [system] { module ranges_replace_if { private header "__algorithm/ranges_replace_if.h" } module ranges_reverse { private header "__algorithm/ranges_reverse.h" } module ranges_reverse_copy { private header "__algorithm/ranges_reverse_copy.h" } + module ranges_rotate { private header "__algorithm/ranges_rotate.h" } module ranges_rotate_copy { private header "__algorithm/ranges_rotate_copy.h" } + module ranges_sample { private header "__algorithm/ranges_sample.h" } module ranges_search { private header "__algorithm/ranges_search.h" } module ranges_search_n { private header "__algorithm/ranges_search_n.h" } module ranges_set_difference { private header "__algorithm/ranges_set_difference.h" } @@ -384,6 +393,9 @@ module std [system] { module ranges_stable_sort { private header "__algorithm/ranges_stable_sort.h" } module ranges_swap_ranges { private header "__algorithm/ranges_swap_ranges.h" } module ranges_transform { private header "__algorithm/ranges_transform.h" } + module uniform_random_bit_generator_adaptor { + private header "__algorithm/uniform_random_bit_generator_adaptor.h" + } module ranges_unique { private header "__algorithm/ranges_unique.h" } module ranges_unique_copy { private header "__algorithm/ranges_unique_copy.h" } module ranges_upper_bound { private header "__algorithm/ranges_upper_bound.h" } @@ -419,6 +431,7 @@ module std [system] { module unique { private header "__algorithm/unique.h" } module unique_copy { private header "__algorithm/unique_copy.h" } module unwrap_iter { private header "__algorithm/unwrap_iter.h" } + module unwrap_range { private header "__algorithm/unwrap_range.h" } module upper_bound { private header "__algorithm/upper_bound.h" } } } @@ -1292,6 +1305,7 @@ module std [system] { module __tree { header "__tree" export * } module __tuple { private header "__tuple" export * } module __undef_macros { header "__undef_macros" export * } + module __verbose_abort { header "__verbose_abort" export * } module experimental { requires cplusplus11 diff --git a/libcxx/include/regex b/libcxx/include/regex index 850fe099df1e0..26887e84bf281 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -1355,7 +1355,7 @@ inline _LIBCPP_INLINE_VISIBILITY unsigned char __to_lower(unsigned char __c) { #if defined(__MVS__) && !defined(__NATIVE_ASCII_F) - return c & 0xBF; + return __c & 0xBF; #else return __c | 0x20; #endif diff --git a/libcxx/include/span b/libcxx/include/span index 00793a210cbe7..67d2ac241ff2b 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -453,9 +453,10 @@ public: : __data{_VSTD::to_address(__first)}, __size{__count} {} template <__span_compatible_iterator _It, __span_compatible_sentinel_for<_It> _End> - _LIBCPP_INLINE_VISIBILITY - constexpr span(_It __first, _End __last) - : __data(_VSTD::to_address(__first)), __size(__last - __first) {} + _LIBCPP_INLINE_VISIBILITY constexpr span(_It __first, _End __last) + : __data(_VSTD::to_address(__first)), __size(__last - __first) { + _LIBCPP_ASSERT(__last - __first >= 0, "invalid range in span's constructor (iterator, sentinel)"); + } template _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/stdatomic.h b/libcxx/include/stdatomic.h index d9550c44061c5..ff2a5682f5bb6 100644 --- a/libcxx/include/stdatomic.h +++ b/libcxx/include/stdatomic.h @@ -121,7 +121,7 @@ using std::atomic_signal_fence // see below # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 20 +#if defined(__cplusplus) && _LIBCPP_STD_VER > 20 #include #include @@ -230,6 +230,6 @@ using std::atomic_thread_fence _LIBCPP_USING_IF_EXISTS; # include_next # endif -#endif // _LIBCPP_STD_VER > 20 +#endif // defined(__cplusplus) && _LIBCPP_STD_VER > 20 #endif // _LIBCPP_STDATOMIC_H diff --git a/libcxx/include/vector b/libcxx/include/vector index 30030f85e43c3..63759407ce940 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -297,6 +297,7 @@ erase_if(vector& c, Predicate pred); // C++20 #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> +#include <__utility/transaction.h> #include #include #include @@ -360,12 +361,12 @@ public: static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector() _NOEXCEPT_(is_nothrow_default_constructible::value) { _VSTD::__debug_db_insert_c(this); } - _LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a) + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value) #else @@ -375,13 +376,14 @@ public: { _VSTD::__debug_db_insert_c(this); } - explicit vector(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n); #if _LIBCPP_STD_VER > 11 - explicit vector(size_type __n, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n, const allocator_type& __a); #endif - vector(size_type __n, const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(size_type __n, const value_type& __x); template ::value> > + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(size_type __n, const value_type& __x, const allocator_type& __a) : __end_cap_(nullptr, __a) { @@ -394,6 +396,7 @@ public: } template + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_InputIterator __first, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< @@ -401,12 +404,14 @@ public: typename iterator_traits<_InputIterator>::reference>::value, _InputIterator>::type __last); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value>::type* = 0); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_ForwardIterator __first, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible< @@ -414,43 +419,53 @@ public: typename iterator_traits<_ForwardIterator>::reference>::value, _ForwardIterator>::type __last); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible< value_type, typename iterator_traits<_ForwardIterator>::reference>::value>::type* = 0); - _LIBCPP_INLINE_VISIBILITY - ~vector() - { - __annotate_delete(); - std::__debug_db_erase_c(this); +private: + class __destroy_vector { + public: + _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} - if (this->__begin_ != nullptr) - { - __clear(); - __alloc_traits::deallocate(__alloc(), this->__begin_, capacity()); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI void operator()() { + __vec_.__annotate_delete(); + std::__debug_db_erase_c(std::addressof(__vec_)); + + if (__vec_.__begin_ != nullptr) { + __vec_.__clear(); + __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.capacity()); + } } - } - vector(const vector& __x); - vector(const vector& __x, const __type_identity_t& __a); - _LIBCPP_INLINE_VISIBILITY + private: + vector& __vec_; + }; + +public: + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector(*this)(); } + + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __x, const __type_identity_t& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector& operator=(const vector& __x); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector(initializer_list __il); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector(initializer_list __il, const allocator_type& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector& operator=(initializer_list __il) {assign(__il.begin(), __il.end()); return *this;} #endif // !_LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector(vector&& __x) #if _LIBCPP_STD_VER > 14 noexcept; @@ -458,14 +473,14 @@ public: _NOEXCEPT_(is_nothrow_move_constructible::value); #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector(vector&& __x, const __type_identity_t& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY vector& operator=(vector&& __x) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); template - typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value, @@ -473,6 +488,7 @@ public: >::type assign(_InputIterator __first, _InputIterator __last); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value && @@ -483,119 +499,120 @@ public: >::type assign(_ForwardIterator __first, _ForwardIterator __last); - void assign(size_type __n, const_reference __u); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void assign(size_type __n, const_reference __u); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void assign(initializer_list __il) {assign(__il.begin(), __il.end());} #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return this->__alloc();} - _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const _NOEXCEPT {return begin();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator cend() const _NOEXCEPT {return end();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crend() const _NOEXCEPT {return rend();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return static_cast(this->__end_ - this->__begin_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type capacity() const _NOEXCEPT {return static_cast(__end_cap() - this->__begin_);} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return this->__begin_ == this->__end_;} - size_type max_size() const _NOEXCEPT; - void reserve(size_type __n); - void shrink_to_fit() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type max_size() const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void reserve(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void shrink_to_fit() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const _NOEXCEPT; - reference at(size_type __n); - const_reference at(size_type __n) const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 reference at(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference at(size_type __n) const; - _LIBCPP_INLINE_VISIBILITY reference front() _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference front() _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); return *this->__begin_; } - _LIBCPP_INLINE_VISIBILITY const_reference front() const _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference front() const _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); return *this->__begin_; } - _LIBCPP_INLINE_VISIBILITY reference back() _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY reference back() _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); return *(this->__end_ - 1); } - _LIBCPP_INLINE_VISIBILITY const_reference back() const _NOEXCEPT + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_reference back() const _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); return *(this->__end_ - 1); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY value_type* data() _NOEXCEPT {return _VSTD::__to_address(this->__begin_);} - _LIBCPP_INLINE_VISIBILITY + + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const value_type* data() const _NOEXCEPT {return _VSTD::__to_address(this->__begin_);} - _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x); - _LIBCPP_INLINE_VISIBILITY void push_back(value_type&& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void push_back(value_type&& __x); template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY #if _LIBCPP_STD_VER > 14 reference emplace_back(_Args&&... __args); #else void emplace_back(_Args&&... __args); #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void pop_back(); - iterator insert(const_iterator __position, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, const_reference __x); - iterator insert(const_iterator __position, value_type&& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, value_type&& __x); template - iterator emplace(const_iterator __position, _Args&&... __args); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator emplace(const_iterator __position, _Args&&... __args); - iterator insert(const_iterator __position, size_type __n, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, size_type __n, const_reference __x); template - typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value, @@ -603,6 +620,7 @@ public: >::type insert(const_iterator __position, _InputIterator __first, _InputIterator __last); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value && @@ -614,15 +632,15 @@ public: insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __position, initializer_list __il) {return insert(__position, __il.begin(), __il.end());} #endif - _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __position); - iterator erase(const_iterator __first, const_iterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __position); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator erase(const_iterator __first, const_iterator __last); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT { size_type __old_size = size(); @@ -631,10 +649,10 @@ public: std::__debug_db_invalidate_all(this); } - void resize(size_type __sz); - void resize(size_type __sz, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void resize(size_type __sz); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void resize(size_type __sz, const_reference __x); - void swap(vector&) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(vector&) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else @@ -642,7 +660,7 @@ public: __is_nothrow_swappable::value); #endif - bool __invariants() const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __invariants() const; #ifdef _LIBCPP_ENABLE_DEBUG_MODE @@ -661,7 +679,6 @@ private: _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(pointer __new_last); - // Allocate space for __n objects // throws length_error if __n > max_size() // throws (probably bad_alloc) if memory run out @@ -669,7 +686,7 @@ private: // Precondition: __n > 0 // Postcondition: capacity() >= __n // Postcondition: size() == 0 - _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) { + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) { if (__n > max_size()) __throw_length_error(); auto __allocation = std::__allocate_at_least(__alloc(), __n); @@ -679,46 +696,48 @@ private: __annotate_new(0); } - void __vdeallocate() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const; - void __construct_at_end(size_type __n); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __vdeallocate() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_at_end(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __construct_at_end(size_type __n, const_reference __x); template + _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type __construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n); - void __append(size_type __n); - void __append(size_type __n, const_reference __x); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __append(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __append(size_type __n, const_reference __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY iterator __make_iter(pointer __p) _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const_iterator __make_iter(const_pointer __p) const _NOEXCEPT; - void __swap_out_circular_buffer(__split_buffer& __v); - pointer __swap_out_circular_buffer(__split_buffer& __v, pointer __p); - void __move_range(pointer __from_s, pointer __from_e, pointer __to); - void __move_assign(vector& __c, true_type) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __swap_out_circular_buffer(__split_buffer& __v); + _LIBCPP_CONSTEXPR_AFTER_CXX17 pointer __swap_out_circular_buffer(__split_buffer& __v, pointer __p); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_range(pointer __from_s, pointer __from_e, pointer __to); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); - void __move_assign(vector& __c, false_type) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign(vector& __c, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __destruct_at_end(pointer __new_last) _NOEXCEPT { - __invalidate_iterators_past(__new_last); + if (!__libcpp_is_constant_evaluated()) + __invalidate_iterators_past(__new_last); size_type __old_size = size(); __base_destruct_at_end(__new_last); __annotate_shrink(__old_size); } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY inline void __push_back_slow_path(_Up&& __x); template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY inline void __emplace_back_slow_path(_Args&&... __args); // The following functions are no-ops outside of AddressSanitizer mode. @@ -726,39 +745,40 @@ private: // may not meet the AddressSanitizer alignment constraints. // See the documentation for __sanitizer_annotate_contiguous_container for more details. #ifndef _LIBCPP_HAS_NO_ASAN + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __annotate_contiguous_container(const void *__beg, const void *__end, const void *__old_mid, const void *__new_mid) const { - if (__beg && is_same::value) + if (!__libcpp_is_constant_evaluated() && __beg && is_same::value) __sanitizer_annotate_contiguous_container(__beg, __end, __old_mid, __new_mid); } #else - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_contiguous_container(const void*, const void*, const void*, const void*) const _NOEXCEPT {} #endif - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_new(size_type __current_size) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + capacity(), data() + __current_size); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_delete() const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + size(), data() + capacity()); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_increase(size_type __n) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), data() + size(), data() + size() + __n); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __annotate_shrink(size_type __old_size) const _NOEXCEPT { __annotate_contiguous_container(data(), data() + capacity(), @@ -766,13 +786,14 @@ private: } struct _ConstructTransaction { + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit _ConstructTransaction(vector &__v, size_type __n) : __v_(__v), __pos_(__v.__end_), __new_end_(__v.__end_ + __n) { #ifndef _LIBCPP_HAS_NO_ASAN __v_.__annotate_increase(__n); #endif } - ~_ConstructTransaction() { + _LIBCPP_CONSTEXPR_AFTER_CXX17 ~_ConstructTransaction() { __v_.__end_ = __pos_; #ifndef _LIBCPP_HAS_NO_ASAN if (__pos_ != __new_end_) { @@ -791,7 +812,7 @@ private: }; template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __construct_one_at_end(_Args&& ...__args) { _ConstructTransaction __tx(*this, 1); __alloc_traits::construct(this->__alloc(), _VSTD::__to_address(__tx.__pos_), @@ -799,23 +820,23 @@ private: ++__tx.__pos_; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY allocator_type& __alloc() _NOEXCEPT {return this->__end_cap_.second();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const allocator_type& __alloc() const _NOEXCEPT {return this->__end_cap_.second();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY pointer& __end_cap() _NOEXCEPT {return this->__end_cap_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY const pointer& __end_cap() const _NOEXCEPT {return this->__end_cap_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __clear() _NOEXCEPT {__base_destruct_at_end(this->__begin_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __base_destruct_at_end(pointer __new_last) _NOEXCEPT { pointer __soon_to_be_end = this->__end_; while (__new_last != __soon_to_be_end) @@ -823,12 +844,12 @@ private: this->__end_ = __new_last; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const vector& __c) {__copy_assign_alloc(__c, integral_constant());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(vector& __c) _NOEXCEPT_( !__alloc_traits::propagate_on_container_move_assignment::value || @@ -846,7 +867,7 @@ private: _VSTD::__throw_out_of_range("vector"); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const vector& __c, true_type) { if (__alloc() != __c.__alloc()) @@ -858,18 +879,18 @@ private: __alloc() = __c.__alloc(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const vector&, false_type) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __alloc() = _VSTD::move(__c.__alloc()); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(vector&, false_type) _NOEXCEPT {} @@ -894,6 +915,7 @@ vector(_InputIterator, _InputIterator, _Alloc) #endif template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v) { @@ -911,6 +933,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::pointer vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer __p) { @@ -931,6 +954,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT { @@ -943,6 +967,7 @@ vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::size_type vector<_Tp, _Allocator>::max_size() const _NOEXCEPT { @@ -952,6 +977,7 @@ vector<_Tp, _Allocator>::max_size() const _NOEXCEPT // Precondition: __new_size > capacity() template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type vector<_Tp, _Allocator>::__recommend(size_type __new_size) const @@ -971,6 +997,7 @@ vector<_Tp, _Allocator>::__recommend(size_type __new_size) const // Precondition: size() + __n <= capacity() // Postcondition: size() == size() + __n template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__construct_at_end(size_type __n) { @@ -988,6 +1015,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n) // Postcondition: size() == old size() + __n // Postcondition: [i] == __x for all i in [size() - __n, __n) template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) @@ -1001,6 +1029,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, @@ -1017,6 +1046,7 @@ vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIt // Postcondition: size() == size() + __n // Exception safety: strong. template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__append(size_type __n) { @@ -1036,6 +1066,7 @@ vector<_Tp, _Allocator>::__append(size_type __n) // Postcondition: size() == size() + __n // Exception safety: strong. template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__append(size_type __n, const_reference __x) { @@ -1051,43 +1082,53 @@ vector<_Tp, _Allocator>::__append(size_type __n, const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(size_type __n) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n); } + __guard.__complete(); } #if _LIBCPP_STD_VER > 11 template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n); } + __guard.__complete(); } #endif template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); __construct_at_end(__n, __x); } + __guard.__complete(); } template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(_InputIterator __first, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< @@ -1095,13 +1136,16 @@ vector<_Tp, _Allocator>::vector(_InputIterator __first, typename iterator_traits<_InputIterator>::reference>::value, _InputIterator>::type __last) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); + __guard.__complete(); } template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< @@ -1109,13 +1153,16 @@ vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, c typename iterator_traits<_InputIterator>::reference>::value>::type*) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); for (; __first != __last; ++__first) emplace_back(*__first); + __guard.__complete(); } template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible< @@ -1123,17 +1170,20 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, typename iterator_traits<_ForwardIterator>::reference>::value, _ForwardIterator>::type __last) { - _VSTD::__debug_db_insert_c(this); - size_type __n = static_cast(_VSTD::distance(__first, __last)); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); + size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last, __n); } + __guard.__complete(); } template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible< @@ -1141,42 +1191,51 @@ vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __las typename iterator_traits<_ForwardIterator>::reference>::value>::type*) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); - size_type __n = static_cast(_VSTD::distance(__first, __last)); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); + size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last, __n); } + __guard.__complete(); } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(const vector& __x) : __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc())) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) { __vallocate(__n); __construct_at_end(__x.__begin_, __x.__end_, __n); } + __guard.__complete(); } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t& __a) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); size_type __n = __x.size(); if (__n > 0) { __vallocate(__n); __construct_at_end(__x.__begin_, __x.__end_, __n); } + __guard.__complete(); } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(vector&& __x) #if _LIBCPP_STD_VER > 14 @@ -1195,6 +1254,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t& __a) : __end_cap_(nullptr, __a) @@ -1211,40 +1271,49 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t _Ip; + auto __guard = std::__make_transaction(__destroy_vector(*this)); assign(_Ip(__x.begin()), _Ip(__x.end())); + __guard.__complete(); } } #ifndef _LIBCPP_CXX03_LANG template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(initializer_list __il) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); __construct_at_end(__il.begin(), __il.end(), __il.size()); } + __guard.__complete(); } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>::vector(initializer_list __il, const allocator_type& __a) : __end_cap_(nullptr, __a) { - _VSTD::__debug_db_insert_c(this); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); __construct_at_end(__il.begin(), __il.end(), __il.size()); } + __guard.__complete(); } #endif // _LIBCPP_CXX03_LANG template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(vector&& __x) @@ -1256,6 +1325,7 @@ vector<_Tp, _Allocator>::operator=(vector&& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value) @@ -1270,6 +1340,7 @@ vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) @@ -1284,6 +1355,7 @@ vector<_Tp, _Allocator>::__move_assign(vector& __c, true_type) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(const vector& __x) @@ -1298,7 +1370,7 @@ vector<_Tp, _Allocator>::operator=(const vector& __x) template template -typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< _Tp, typename iterator_traits<_InputIterator>::reference>::value, @@ -1313,6 +1385,7 @@ vector<_Tp, _Allocator>::assign(_InputIterator __first, _InputIterator __last) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value && @@ -1350,6 +1423,7 @@ vector<_Tp, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __las } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) { @@ -1372,6 +1446,7 @@ vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::begin() _NOEXCEPT @@ -1380,6 +1455,7 @@ vector<_Tp, _Allocator>::begin() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::const_iterator vector<_Tp, _Allocator>::begin() const _NOEXCEPT @@ -1388,6 +1464,7 @@ vector<_Tp, _Allocator>::begin() const _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::end() _NOEXCEPT @@ -1396,6 +1473,7 @@ vector<_Tp, _Allocator>::end() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::const_iterator vector<_Tp, _Allocator>::end() const _NOEXCEPT @@ -1404,6 +1482,7 @@ vector<_Tp, _Allocator>::end() const _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT @@ -1413,6 +1492,7 @@ vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::const_reference vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT @@ -1422,6 +1502,7 @@ vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::at(size_type __n) { @@ -1431,6 +1512,7 @@ vector<_Tp, _Allocator>::at(size_type __n) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::const_reference vector<_Tp, _Allocator>::at(size_type __n) const { @@ -1440,6 +1522,7 @@ vector<_Tp, _Allocator>::at(size_type __n) const } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::reserve(size_type __n) { @@ -1454,6 +1537,7 @@ vector<_Tp, _Allocator>::reserve(size_type __n) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { @@ -1477,6 +1561,7 @@ vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x) { @@ -1489,6 +1574,7 @@ vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void vector<_Tp, _Allocator>::push_back(const_reference __x) @@ -1502,6 +1588,7 @@ vector<_Tp, _Allocator>::push_back(const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void vector<_Tp, _Allocator>::push_back(value_type&& __x) @@ -1516,6 +1603,7 @@ vector<_Tp, _Allocator>::push_back(value_type&& __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) { @@ -1529,6 +1617,7 @@ vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline #if _LIBCPP_STD_VER > 14 typename vector<_Tp, _Allocator>::reference @@ -1549,6 +1638,7 @@ vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline void vector<_Tp, _Allocator>::pop_back() @@ -1558,6 +1648,7 @@ vector<_Tp, _Allocator>::pop_back() } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __position) @@ -1569,12 +1660,14 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) difference_type __ps = __position - cbegin(); pointer __p = this->__begin_ + __ps; this->__destruct_at_end(_VSTD::move(__p + 1, this->__end_, __p)); - this->__invalidate_iterators_past(__p-1); + if (!__libcpp_is_constant_evaluated()) + this->__invalidate_iterators_past(__p - 1); iterator __r = iterator(this, __p); return __r; } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) { @@ -1587,13 +1680,15 @@ vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) pointer __p = this->__begin_ + (__first - begin()); if (__first != __last) { this->__destruct_at_end(_VSTD::move(__p + (__last - __first), this->__end_, __p)); - this->__invalidate_iterators_past(__p - 1); + if (!__libcpp_is_constant_evaluated()) + this->__invalidate_iterators_past(__p - 1); } iterator __r = iterator(this, __p); return __r; } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) { @@ -1613,13 +1708,15 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) { _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this, "vector::insert(iterator, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); - if (this->__end_ < this->__end_cap()) + // We can't compare unrelated pointers inside constant expressions + if (!__libcpp_is_constant_evaluated() && this->__end_ < this->__end_cap()) { if (__p == this->__end_) { @@ -1645,6 +1742,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) { @@ -1675,6 +1773,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) { @@ -1705,6 +1804,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) { @@ -1713,7 +1813,8 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_ pointer __p = this->__begin_ + (__position - begin()); if (__n > 0) { - if (__n <= static_cast(this->__end_cap() - this->__end_)) + // We can't compare unrelated pointers inside constant expressions + if (!__libcpp_is_constant_evaluated() && __n <= static_cast(this->__end_cap() - this->__end_)) { size_type __old_n = __n; pointer __old_last = this->__end_; @@ -1745,7 +1846,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_ template template -typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible< _Tp, typename iterator_traits<_InputIterator>::reference>::value, @@ -1793,6 +1894,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __firs template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value && @@ -1841,6 +1943,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __fi } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::resize(size_type __sz) { @@ -1852,6 +1955,7 @@ vector<_Tp, _Allocator>::resize(size_type __sz) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) { @@ -1863,6 +1967,7 @@ vector<_Tp, _Allocator>::resize(size_type __sz, const_reference __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector<_Tp, _Allocator>::swap(vector& __x) #if _LIBCPP_STD_VER >= 14 @@ -1885,6 +1990,7 @@ vector<_Tp, _Allocator>::swap(vector& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool vector<_Tp, _Allocator>::__invariants() const { @@ -2007,81 +2113,99 @@ public: typedef __bit_const_reference const_reference; #endif private: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type& __cap() _NOEXCEPT {return __cap_alloc_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const size_type& __cap() const _NOEXCEPT {return __cap_alloc_.first();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __storage_allocator& __alloc() _NOEXCEPT {return __cap_alloc_.second();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const __storage_allocator& __alloc() const _NOEXCEPT {return __cap_alloc_.second();} static const unsigned __bits_per_word = static_cast(sizeof(__storage_type) * CHAR_BIT); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static size_type __internal_cap_to_external(size_type __n) _NOEXCEPT {return __n * __bits_per_word;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static size_type __external_cap_to_internal(size_type __n) _NOEXCEPT {return (__n - 1) / __bits_per_word + 1;} public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector() _NOEXCEPT_(is_nothrow_default_constructible::value); - _LIBCPP_INLINE_VISIBILITY explicit vector(const allocator_type& __a) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value); #else _NOEXCEPT; #endif - ~vector(); - explicit vector(size_type __n); + +private: + class __destroy_vector { + public: + _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} + + _LIBCPP_CONSTEXPR_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI void operator()() { + if (__vec_.__begin_ != nullptr) + __storage_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.__cap()); + std::__debug_db_invalidate_all(this); + } + + private: + vector& __vec_; + }; + +public: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 ~vector() { __destroy_vector(*this)(); } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n); #if _LIBCPP_STD_VER > 11 - explicit vector(size_type __n, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit vector(size_type __n, const allocator_type& __a); #endif - vector(size_type __n, const value_type& __v); - vector(size_type __n, const value_type& __v, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(size_type __n, const value_type& __v); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(size_type __n, const value_type& __v, const allocator_type& __a); template - vector(_InputIterator __first, _InputIterator __last, + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_InputIterator __first, _InputIterator __last, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type* = 0); template - vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type* = 0); template - vector(_ForwardIterator __first, _ForwardIterator __last, + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_ForwardIterator __first, _ForwardIterator __last, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0); template - vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0); - vector(const vector& __v); - vector(const vector& __v, const allocator_type& __a); - vector& operator=(const vector& __v); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __v); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(const vector& __v, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector& operator=(const vector& __v); #ifndef _LIBCPP_CXX03_LANG - vector(initializer_list __il); - vector(initializer_list __il, const allocator_type& __a); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(initializer_list __il); + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(initializer_list __il, const allocator_type& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector& operator=(initializer_list __il) {assign(__il.begin(), __il.end()); return *this;} #endif // !_LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(vector&& __v) #if _LIBCPP_STD_VER > 14 noexcept; #else _NOEXCEPT_(is_nothrow_move_constructible::value); #endif - vector(vector&& __v, const __type_identity_t& __a); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 vector(vector&& __v, const __type_identity_t& __a); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector& operator=(vector&& __v) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); @@ -2089,93 +2213,93 @@ public: typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, void >::type - assign(_InputIterator __first, _InputIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 assign(_InputIterator __first, _InputIterator __last); template typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type - assign(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 assign(_ForwardIterator __first, _ForwardIterator __last); - void assign(size_type __n, const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void assign(size_type __n, const value_type& __x); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void assign(initializer_list __il) {assign(__il.begin(), __il.end());} #endif - _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 allocator_type get_allocator() const _NOEXCEPT {return allocator_type(this->__alloc());} - size_type max_size() const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type max_size() const _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type capacity() const _NOEXCEPT {return __internal_cap_to_external(__cap());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type size() const _NOEXCEPT {return __size_;} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool empty() const _NOEXCEPT {return __size_ == 0;} - void reserve(size_type __n); - void shrink_to_fit() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void reserve(size_type __n); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void shrink_to_fit() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator begin() _NOEXCEPT {return __make_iter(0);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator begin() const _NOEXCEPT {return __make_iter(0);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator end() _NOEXCEPT {return __make_iter(__size_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator end() const _NOEXCEPT {return __make_iter(__size_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator cbegin() const _NOEXCEPT {return __make_iter(0);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator cend() const _NOEXCEPT {return __make_iter(__size_);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reverse_iterator crend() const _NOEXCEPT {return rend();} - _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) {return __make_ref(__n);} - _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const {return __make_ref(__n);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference operator[](size_type __n) {return __make_ref(__n);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference operator[](size_type __n) const {return __make_ref(__n);} reference at(size_type __n); const_reference at(size_type __n) const; - _LIBCPP_INLINE_VISIBILITY reference front() {return __make_ref(0);} - _LIBCPP_INLINE_VISIBILITY const_reference front() const {return __make_ref(0);} - _LIBCPP_INLINE_VISIBILITY reference back() {return __make_ref(__size_ - 1);} - _LIBCPP_INLINE_VISIBILITY const_reference back() const {return __make_ref(__size_ - 1);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference front() {return __make_ref(0);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference front() const {return __make_ref(0);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference back() {return __make_ref(__size_ - 1);} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference back() const {return __make_ref(__size_ - 1);} - void push_back(const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void push_back(const value_type& __x); #if _LIBCPP_STD_VER > 11 template #if _LIBCPP_STD_VER > 14 - _LIBCPP_INLINE_VISIBILITY reference emplace_back(_Args&&... __args) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference emplace_back(_Args&&... __args) #else _LIBCPP_INLINE_VISIBILITY void emplace_back(_Args&&... __args) #endif @@ -2187,54 +2311,54 @@ public: } #endif - _LIBCPP_INLINE_VISIBILITY void pop_back() {--__size_;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void pop_back() {--__size_;} #if _LIBCPP_STD_VER > 11 template - _LIBCPP_INLINE_VISIBILITY iterator emplace(const_iterator __position, _Args&&... __args) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator emplace(const_iterator __position, _Args&&... __args) { return insert ( __position, value_type ( _VSTD::forward<_Args>(__args)... )); } #endif - iterator insert(const_iterator __position, const value_type& __x); - iterator insert(const_iterator __position, size_type __n, const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, const value_type& __x); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, size_type __n, const value_type& __x); template typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, iterator >::type - insert(const_iterator __position, _InputIterator __first, _InputIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 insert(const_iterator __position, _InputIterator __first, _InputIterator __last); template typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, iterator >::type - insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator insert(const_iterator __position, initializer_list __il) {return insert(__position, __il.begin(), __il.end());} #endif - _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __position); - iterator erase(const_iterator __first, const_iterator __last); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator erase(const_iterator __position); + _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator erase(const_iterator __first, const_iterator __last); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void clear() _NOEXCEPT {__size_ = 0;} - void swap(vector&) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(vector&) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value); #endif - static void swap(reference __x, reference __y) _NOEXCEPT { _VSTD::swap(__x, __y); } + _LIBCPP_CONSTEXPR_AFTER_CXX17 static void swap(reference __x, reference __y) _NOEXCEPT { _VSTD::swap(__x, __y); } - void resize(size_type __sz, value_type __x = false); - void flip() _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 void resize(size_type __sz, value_type __x = false); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void flip() _NOEXCEPT; - bool __invariants() const; + _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __invariants() const; private: _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI @@ -2254,52 +2378,56 @@ private: // Precondition: __n > 0 // Postcondition: capacity() >= __n // Postcondition: size() == 0 - _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 void __vallocate(size_type __n) { if (__n > max_size()) __throw_length_error(); auto __allocation = std::__allocate_at_least(__alloc(), __external_cap_to_internal(__n)); __begin_ = __allocation.ptr; __size_ = 0; __cap() = __allocation.count; + if (__libcpp_is_constant_evaluated()) { + for (size_type __i = 0; __i != __cap(); ++__i) + std::__construct_at(std::__to_address(__begin_) + __i); + } } - void __vdeallocate() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __vdeallocate() _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static size_type __align_it(size_type __new_size) _NOEXCEPT {return (__new_size + (__bits_per_word-1)) & ~((size_type)__bits_per_word-1);} - _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const; - _LIBCPP_INLINE_VISIBILITY void __construct_at_end(size_type __n, bool __x); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type __recommend(size_type __new_size) const; + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_at_end(size_type __n, bool __x); template typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, void >::type - __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); - void __append(size_type __n, const_reference __x); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_AFTER_CXX17 __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __append(size_type __n, const_reference __x); + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 reference __make_ref(size_type __pos) _NOEXCEPT {return reference(__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_reference __make_ref(size_type __pos) const _NOEXCEPT { return __bit_const_reference(__begin_ + __pos / __bits_per_word, __storage_type(1) << __pos % __bits_per_word); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator __make_iter(size_type __pos) _NOEXCEPT {return iterator(__begin_ + __pos / __bits_per_word, static_cast(__pos % __bits_per_word));} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 const_iterator __make_iter(size_type __pos) const _NOEXCEPT {return const_iterator(__begin_ + __pos / __bits_per_word, static_cast(__pos % __bits_per_word));} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 iterator __const_iterator_cast(const_iterator __p) _NOEXCEPT {return begin() + (__p - cbegin());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __copy_assign_alloc(const vector& __v) {__copy_assign_alloc(__v, integral_constant());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __copy_assign_alloc(const vector& __c, true_type) { if (__alloc() != __c.__alloc()) @@ -2307,33 +2435,33 @@ private: __alloc() = __c.__alloc(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __copy_assign_alloc(const vector&, false_type) {} - void __move_assign(vector& __c, false_type); - void __move_assign(vector& __c, true_type) + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign(vector& __c, false_type); + _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign_alloc(vector& __c) _NOEXCEPT_( !__storage_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable::value) {__move_assign_alloc(__c, integral_constant());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign_alloc(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __alloc() = _VSTD::move(__c.__alloc()); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void __move_assign_alloc(vector&, false_type) _NOEXCEPT {} - size_t __hash_code() const _NOEXCEPT; + _LIBCPP_CONSTEXPR_AFTER_CXX17 size_t __hash_code() const _NOEXCEPT; friend class __bit_reference; friend class __bit_const_reference; @@ -2344,7 +2472,7 @@ private: }; template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::__vdeallocate() _NOEXCEPT { if (this->__begin_ != nullptr) @@ -2357,6 +2485,7 @@ vector::__vdeallocate() _NOEXCEPT } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::size_type vector::max_size() const _NOEXCEPT { @@ -2369,7 +2498,7 @@ vector::max_size() const _NOEXCEPT // Precondition: __new_size > capacity() template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::size_type vector::__recommend(size_type __new_size) const { @@ -2387,7 +2516,7 @@ vector::__recommend(size_type __new_size) const // Precondition: size() + __n <= capacity() // Postcondition: size() == size() + __n template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::__construct_at_end(size_type __n, bool __x) { @@ -2405,6 +2534,7 @@ vector::__construct_at_end(size_type __n, bool __x) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, @@ -2425,7 +2555,7 @@ vector::__construct_at_end(_ForwardIterator __first, _ForwardI } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector() _NOEXCEPT_(is_nothrow_default_constructible::value) : __begin_(nullptr), @@ -2435,7 +2565,7 @@ vector::vector() } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value) @@ -2449,6 +2579,7 @@ vector::vector(const allocator_type& __a) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(size_type __n) : __begin_(nullptr), __size_(0), @@ -2463,6 +2594,7 @@ vector::vector(size_type __n) #if _LIBCPP_STD_VER > 11 template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(size_type __n, const allocator_type& __a) : __begin_(nullptr), __size_(0), @@ -2477,6 +2609,7 @@ vector::vector(size_type __n, const allocator_type& __a) #endif template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(size_type __n, const value_type& __x) : __begin_(nullptr), __size_(0), @@ -2490,6 +2623,7 @@ vector::vector(size_type __n, const value_type& __x) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(size_type __n, const value_type& __x, const allocator_type& __a) : __begin_(nullptr), __size_(0), @@ -2504,6 +2638,7 @@ vector::vector(size_type __n, const value_type& __x, const all template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(_InputIterator __first, _InputIterator __last, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type*) : __begin_(nullptr), @@ -2530,6 +2665,7 @@ vector::vector(_InputIterator __first, _InputIterator __last, template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type*) : __begin_(nullptr), @@ -2556,39 +2692,46 @@ vector::vector(_InputIterator __first, _InputIterator __last, template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(_ForwardIterator __first, _ForwardIterator __last, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) { - size_type __n = static_cast(_VSTD::distance(__first, __last)); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last); } + __guard.__complete(); } template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { - size_type __n = static_cast(_VSTD::distance(__first, __last)); + auto __guard = std::__make_transaction(__destroy_vector(*this)); + size_type __n = static_cast(std::distance(__first, __last)); if (__n > 0) { __vallocate(__n); __construct_at_end(__first, __last); } + __guard.__complete(); } #ifndef _LIBCPP_CXX03_LANG template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(initializer_list __il) : __begin_(nullptr), __size_(0), @@ -2603,6 +2746,7 @@ vector::vector(initializer_list __il) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(initializer_list __il, const allocator_type& __a) : __begin_(nullptr), __size_(0), @@ -2619,14 +2763,7 @@ vector::vector(initializer_list __il, const alloca #endif // _LIBCPP_CXX03_LANG template -vector::~vector() -{ - if (__begin_ != nullptr) - __storage_traits::deallocate(__alloc(), __begin_, __cap()); - std::__debug_db_invalidate_all(this); -} - -template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(const vector& __v) : __begin_(nullptr), __size_(0), @@ -2640,6 +2777,7 @@ vector::vector(const vector& __v) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(const vector& __v, const allocator_type& __a) : __begin_(nullptr), __size_(0), @@ -2653,6 +2791,7 @@ vector::vector(const vector& __v, const allocator_type& __a) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector& vector::operator=(const vector& __v) { @@ -2674,7 +2813,7 @@ vector::operator=(const vector& __v) } template -inline _LIBCPP_INLINE_VISIBILITY vector::vector(vector&& __v) +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(vector&& __v) #if _LIBCPP_STD_VER > 14 _NOEXCEPT #else @@ -2689,6 +2828,7 @@ inline _LIBCPP_INLINE_VISIBILITY vector::vector(vector&& __v) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 vector::vector(vector&& __v, const __type_identity_t& __a) : __begin_(nullptr), __size_(0), @@ -2710,7 +2850,7 @@ vector::vector(vector&& __v, const __type_identity_t -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 vector& vector::operator=(vector&& __v) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) @@ -2721,7 +2861,7 @@ vector::operator=(vector&& __v) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::__move_assign(vector& __c, false_type) { if (__alloc() != __c.__alloc()) @@ -2731,7 +2871,7 @@ vector::__move_assign(vector& __c, false_type) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::__move_assign(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { @@ -2745,7 +2885,7 @@ vector::__move_assign(vector& __c, true_type) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::assign(size_type __n, const value_type& __x) { __size_ = 0; @@ -2768,7 +2908,7 @@ vector::assign(size_type __n, const value_type& __x) template template -typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, void >::type vector::assign(_InputIterator __first, _InputIterator __last) @@ -2780,6 +2920,7 @@ vector::assign(_InputIterator __first, _InputIterator __last) template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, @@ -2803,7 +2944,7 @@ vector::assign(_ForwardIterator __first, _ForwardIterator __la } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::reserve(size_type __n) { if (__n > capacity()) @@ -2819,7 +2960,7 @@ vector::reserve(size_type __n) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::shrink_to_fit() _NOEXCEPT { if (__external_cap_to_internal(size()) > __cap()) @@ -2857,7 +2998,7 @@ vector::at(size_type __n) const } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::push_back(const value_type& __x) { if (this->__size_ == this->capacity()) @@ -2867,7 +3008,7 @@ vector::push_back(const value_type& __x) } template -typename vector::iterator +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::iterator vector::insert(const_iterator __position, const value_type& __x) { iterator __r; @@ -2892,7 +3033,7 @@ vector::insert(const_iterator __position, const value_type& __ } template -typename vector::iterator +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::iterator vector::insert(const_iterator __position, size_type __n, const value_type& __x) { iterator __r; @@ -2919,7 +3060,7 @@ vector::insert(const_iterator __position, size_type __n, const template template -typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, typename vector::iterator >::type vector::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) @@ -2961,6 +3102,7 @@ vector::insert(const_iterator __position, _InputIterator __fir template template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < __is_cpp17_forward_iterator<_ForwardIterator>::value, @@ -2994,7 +3136,7 @@ vector::insert(const_iterator __position, _ForwardIterator __f } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::iterator vector::erase(const_iterator __position) { @@ -3005,6 +3147,7 @@ vector::erase(const_iterator __position) } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 typename vector::iterator vector::erase(const_iterator __first, const_iterator __last) { @@ -3016,7 +3159,7 @@ vector::erase(const_iterator __first, const_iterator __last) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::swap(vector& __x) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT @@ -3033,7 +3176,7 @@ vector::swap(vector& __x) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::resize(size_type __sz, value_type __x) { size_type __cs = size(); @@ -3062,7 +3205,7 @@ vector::resize(size_type __sz, value_type __x) } template -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 void vector::flip() _NOEXCEPT { // do middle whole words @@ -3081,7 +3224,7 @@ vector::flip() _NOEXCEPT } template -bool +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool vector::__invariants() const { if (this->__begin_ == nullptr) @@ -3100,7 +3243,7 @@ vector::__invariants() const } template -size_t +_LIBCPP_CONSTEXPR_AFTER_CXX17 size_t vector::__hash_code() const _NOEXCEPT { size_t __h = 0; @@ -3122,12 +3265,13 @@ template struct _LIBCPP_TEMPLATE_VIS hash > : public __unary_function, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_t operator()(const vector& __vec) const _NOEXCEPT {return __vec.__hash_code();} }; template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator==(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3137,6 +3281,7 @@ operator==(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3145,6 +3290,7 @@ operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3153,6 +3299,7 @@ operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3161,6 +3308,7 @@ operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3169,6 +3317,7 @@ operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3177,6 +3326,7 @@ operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY void swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) @@ -3187,6 +3337,7 @@ swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) #if _LIBCPP_STD_VER > 17 template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type erase(vector<_Tp, _Allocator>& __c, const _Up& __v) { auto __old_size = __c.size(); @@ -3195,6 +3346,7 @@ erase(vector<_Tp, _Allocator>& __c, const _Up& __v) { } template +_LIBCPP_CONSTEXPR_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) { auto __old_size = __c.size(); diff --git a/libcxx/include/version b/libcxx/include/version index 1df51fa1cb867..d0c6fe466e70b 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -331,7 +331,7 @@ __cpp_lib_void_t 201411L # define __cpp_lib_erase_if 202002L # undef __cpp_lib_execution // # define __cpp_lib_execution 201902L -# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) +# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) // # define __cpp_lib_format 202106L # endif # define __cpp_lib_generic_unordered_lookup 201811L @@ -351,7 +351,9 @@ __cpp_lib_void_t 201411L # define __cpp_lib_list_remove_return_type 201806L # define __cpp_lib_math_constants 201907L // # define __cpp_lib_polymorphic_allocator 201902L -// # define __cpp_lib_ranges 201811L +# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +# define __cpp_lib_ranges 201811L +# endif # define __cpp_lib_remove_cvref 201711L # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) # define __cpp_lib_semaphore 201907L diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT index 32080320cbc0d..5e65e943c6e95 100644 --- a/libcxx/lib/abi/CHANGELOG.TXT +++ b/libcxx/lib/abi/CHANGELOG.TXT @@ -64,7 +64,7 @@ Version 15.0 Symbol removed: _ZTSNSt3__18__c_nodeE Symbol removed: _ZTVNSt3__18__c_nodeE -* b0fd9497af6d and 7de5aca84c54 - [libc++] Add a lightweight overridable assertion handler +* b0fd9497af6d, 7de5aca84c54 and XXXXXXXX - [libc++] Add a lightweight overridable assertion handler This patch adds a lightweight assertion handler mechanism that can be overriden at link-time in a fashion similar to `operator new`. A default @@ -73,7 +73,7 @@ Version 15.0 All platforms ------------- - Symbol added: _ZNSt3__126__libcpp_assertion_handlerEPKcz + Symbol added: _ZNSt3__122__libcpp_verbose_abortEPKcz ------------ Version 14.0 diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index dd2438dfcb436..50cbe4c2b013d 100644 --- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1534,7 +1534,7 @@ {'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} -{'is_defined': True, 'name': '__ZNSt3__126__libcpp_assertion_handlerEPKcz', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__122__libcpp_verbose_abortEPKcz', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index c662644418d49..56ec7aaa171d9 100644 --- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1678,7 +1678,7 @@ {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} -{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index d730eaeb776e2..9d30600440bd0 100644 --- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1678,7 +1678,7 @@ {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} -{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index bc81e61c55e2c..d0e8b7347172d 100644 --- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1534,7 +1534,7 @@ {'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} -{'is_defined': True, 'name': '__ZNSt3__126__libcpp_assertion_handlerEPKcz', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__122__libcpp_verbose_abortEPKcz', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist index 1437c1cc4b731..8de5a0b4da946 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1225,7 +1225,7 @@ {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} -{'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKcz', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist index 1348fc6ca3034..90d9a665a1c72 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist @@ -1197,7 +1197,7 @@ {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} -{'is_defined': True, 'name': '_ZNSt3__126__libcpp_assertion_handlerEPKcz', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'} diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index f7d2896d10f31..9abf548abbb95 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -4,7 +4,6 @@ set(LIBCXX_LIB_CMAKEFILES_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTOR set(LIBCXX_SOURCES algorithm.cpp any.cpp - assert.cpp atomic.cpp barrier.cpp bind.cpp @@ -62,6 +61,7 @@ set(LIBCXX_SOURCES valarray.cpp variant.cpp vector.cpp + verbose_abort.cpp ) if (LIBCXX_ENABLE_DEBUG_MODE OR LIBCXX_ENABLE_BACKWARDS_COMPATIBILITY_DEBUG_MODE_SYMBOLS) @@ -212,20 +212,6 @@ if (LIBCXX_ENABLE_SHARED) cxx_add_common_build_flags(cxx_shared) cxx_set_common_defines(cxx_shared) - # Link against LLVM libunwind - # Note that we do need to link against libunwind directly to ensure that the correct - # dependencies are recorded when creating a linker script. - # TODO: Look into modifying the linker script creation to recursively consider interface libraries - if (LIBCXXABI_USE_LLVM_UNWINDER) - if (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY) - # libunwind is already included in libc++abi - elseif (TARGET unwind_shared OR HAVE_LIBUNWIND) - target_link_libraries(cxx_shared PUBLIC unwind_shared) - else() - target_link_libraries(cxx_shared PUBLIC unwind) - endif() - endif() - # Link against libc++abi if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY) target_link_libraries(cxx_shared PRIVATE libcxx-abi-shared-objects) @@ -254,8 +240,30 @@ if (LIBCXX_ENABLE_SHARED) # Generate a linker script in place of a libc++.so symlink. if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT) - include(DefineLinkerScript) - define_linker_script(cxx_shared) + set(link_libraries) + + set(imported_libname "$") + set(output_name "$") + string(APPEND link_libraries "${CMAKE_LINK_LIBRARY_FLAG}$,${imported_libname},${output_name}>") + + # TODO: Move to the same approach as above for the unwind library + if (LIBCXXABI_USE_LLVM_UNWINDER) + if (LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY) + # libunwind is already included in libc++abi + elseif (TARGET unwind_shared OR HAVE_LIBUNWIND) + string(APPEND link_libraries " ${CMAKE_LINK_LIBRARY_FLAG}$") + else() + string(APPEND link_libraries " ${CMAKE_LINK_LIBRARY_FLAG}unwind") + endif() + endif() + + set(linker_script "INPUT($ ${link_libraries})") + add_custom_command(TARGET cxx_shared POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E remove "$" + COMMAND "${CMAKE_COMMAND}" -E echo "${linker_script}" > "$" + COMMENT "Generating linker script: '${linker_script}' as file $" + VERBATIM + ) endif() list(APPEND LIBCXX_BUILD_TARGETS "cxx_shared") diff --git a/libcxx/src/include/sso_allocator.h b/libcxx/src/include/sso_allocator.h index 2baf599c5c242..6a682fc43f86f 100644 --- a/libcxx/src/include/sso_allocator.h +++ b/libcxx/src/include/sso_allocator.h @@ -41,6 +41,11 @@ class _LIBCPP_HIDDEN __sso_allocator typedef _Tp* pointer; typedef _Tp value_type; + template + struct rebind { + using other = __sso_allocator; + }; + _LIBCPP_INLINE_VISIBILITY __sso_allocator() throw() : __allocated_(false) {} _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator&) throw() : __allocated_(false) {} template _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator<_Up, _Np>&) throw() diff --git a/libcxx/src/assert.cpp b/libcxx/src/verbose_abort.cpp similarity index 76% rename from libcxx/src/assert.cpp rename to libcxx/src/verbose_abort.cpp index c218645f17712..a9fba5e3c007d 100644 --- a/libcxx/src/assert.cpp +++ b/libcxx/src/verbose_abort.cpp @@ -6,17 +6,21 @@ // //===----------------------------------------------------------------------===// -#include <__assert> #include <__config> +#include <__verbose_abort> #include #include #include #ifdef __BIONIC__ # include -# include +# if __ANDROID_API__ >= 21 +# include extern "C" void android_set_abort_message(const char* msg); -#endif +# else +# include +# endif // __ANDROID_API__ >= 21 +#endif // __BIONIC__ #if defined(__APPLE__) && __has_include() # include @@ -25,7 +29,7 @@ extern "C" void android_set_abort_message(const char* msg); _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_WEAK -void __libcpp_assertion_handler(char const* format, ...) { +void __libcpp_verbose_abort(char const* format, ...) { // Write message to stderr. We do this before formatting into a // buffer so that we still get some information out if that fails. { @@ -48,14 +52,22 @@ void __libcpp_assertion_handler(char const* format, ...) { vasprintf(&buffer, format, list); CRSetCrashLogMessage(buffer); #elif defined(__BIONIC__) - // Show error in tombstone. vasprintf(&buffer, format, list); + +# if __ANDROID_API__ >= 21 + // Show error in tombstone. android_set_abort_message(buffer); // Show error in logcat. openlog("libc++", 0, 0); syslog(LOG_CRIT, "%s", buffer); closelog(); +# else + // The good error reporting wasn't available in Android until L. Since we're + // about to abort anyway, just call __assert2, which will log _somewhere_ + // (tombstone and/or logcat) in older releases. + __assert2(__FILE__, __LINE__, __func__, buffer); +# endif // __ANDROID_API__ >= 21 #endif va_end(list); diff --git a/libcxx/test/libcxx/algorithms/bad_iterator_traits.verify.cpp b/libcxx/test/libcxx/algorithms/bad_iterator_traits.verify.cpp new file mode 100644 index 0000000000000..61e1712987e7c --- /dev/null +++ b/libcxx/test/libcxx/algorithms/bad_iterator_traits.verify.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// std::sort + +#include +#include +#include +#include + +struct BadIter { + struct Value { + friend bool operator==(const Value& x, const Value& y); + friend bool operator!=(const Value& x, const Value& y); + friend bool operator< (const Value& x, const Value& y); + friend bool operator<=(const Value& x, const Value& y); + friend bool operator> (const Value& x, const Value& y); + friend bool operator>=(const Value& x, const Value& y); + friend void swap(Value, Value); + }; + + using iterator_category = std::random_access_iterator_tag; + using value_type = Value; + using reference = Value&; + using difference_type = long; + using pointer = Value*; + + Value operator*() const; // Not `Value&`. + reference operator[](difference_type n) const; + + BadIter& operator++(); + BadIter& operator--(); + BadIter operator++(int); + BadIter operator--(int); + + BadIter& operator+=(difference_type n); + BadIter& operator-=(difference_type n); + friend BadIter operator+(BadIter x, difference_type n); + friend BadIter operator+(difference_type n, BadIter x); + friend BadIter operator-(BadIter x, difference_type n); + friend difference_type operator-(BadIter x, BadIter y); + + friend bool operator==(const BadIter& x, const BadIter& y); + friend bool operator!=(const BadIter& x, const BadIter& y); + friend bool operator< (const BadIter& x, const BadIter& y); + friend bool operator<=(const BadIter& x, const BadIter& y); + friend bool operator> (const BadIter& x, const BadIter& y); + friend bool operator>=(const BadIter& x, const BadIter& y); +}; + +// Verify that iterators with incorrect `iterator_traits` are rejected. This protects against potential undefined +// behavior when these iterators are passed to standard algorithms. +void test() { + std::sort(BadIter(), BadIter()); + //expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}It looks like your iterator's `iterator_traits::reference` does not match the return type of dereferencing the iterator}} +} diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp index 48eeb01b57587..343ef41c4b92d 100644 --- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp +++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp @@ -98,7 +98,7 @@ constexpr bool all_the_algorithms() (void)std::ranges::any_of(a, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::binary_search(first, last, value, Less(&copies)); assert(copies == 0); (void)std::ranges::binary_search(a, value, Less(&copies)); assert(copies == 0); - //(void)std::ranges::clamp(value, value, value, Less(&copies)); assert(copies == 0); + (void)std::ranges::clamp(value, value, value, Less(&copies)); assert(copies == 0); (void)std::ranges::count_if(first, last, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::count_if(a, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::copy_if(first, last, first2, UnaryTrue(&copies)); assert(copies == 0); @@ -121,9 +121,9 @@ constexpr bool all_the_algorithms() (void)std::ranges::for_each(first, last, UnaryVoid(&copies)); assert(copies == 1); copies = 0; (void)std::ranges::for_each(a, UnaryVoid(&copies)); assert(copies == 1); copies = 0; (void)std::ranges::for_each_n(first, count, UnaryVoid(&copies)); assert(copies == 1); copies = 0; - //(void)std::ranges::generate(first, last, NullaryValue(&copies)); assert(copies == 0); - //(void)std::ranges::generate(a, NullaryValue(&copies)); assert(copies == 0); - //(void)std::ranges::generate_n(first, count, NullaryValue(&copies)); assert(copies == 0); + (void)std::ranges::generate(first, last, NullaryValue(&copies)); assert(copies == 0); + (void)std::ranges::generate(a, NullaryValue(&copies)); assert(copies == 0); + (void)std::ranges::generate_n(first, count, NullaryValue(&copies)); assert(copies == 0); (void)std::ranges::includes(first, last, first2, last2, Less(&copies)); assert(copies == 0); (void)std::ranges::includes(a, b, Less(&copies)); assert(copies == 0); (void)std::ranges::is_heap(first, last, Less(&copies)); assert(copies == 0); @@ -132,14 +132,14 @@ constexpr bool all_the_algorithms() (void)std::ranges::is_heap_until(a, Less(&copies)); assert(copies == 0); (void)std::ranges::is_partitioned(first, last, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::is_partitioned(a, UnaryTrue(&copies)); assert(copies == 0); - //(void)std::ranges::is_permutation(first, last, first2, last2, Equal(&copies)); assert(copies == 0); - //(void)std::ranges::is_permutation(a, b, Equal(&copies)); assert(copies == 0); + (void)std::ranges::is_permutation(first, last, first2, last2, Equal(&copies)); assert(copies == 0); + (void)std::ranges::is_permutation(a, b, Equal(&copies)); assert(copies == 0); (void)std::ranges::is_sorted(first, last, Less(&copies)); assert(copies == 0); (void)std::ranges::is_sorted(a, Less(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(first, last, Less(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(a, Less(&copies)); assert(copies == 0); - //if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); } - //if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(&copies)); assert(copies == 0); } + if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); } + if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(&copies)); assert(copies == 0); } (void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(&copies)); assert(copies == 0); (void)std::ranges::lexicographical_compare(a, b, Less(&copies)); assert(copies == 0); (void)std::ranges::lower_bound(first, last, value, Less(&copies)); assert(copies == 0); @@ -165,16 +165,16 @@ constexpr bool all_the_algorithms() (void)std::ranges::minmax_element(a, Less(&copies)); assert(copies == 0); (void)std::ranges::mismatch(first, last, first2, last2, Equal(&copies)); assert(copies == 0); (void)std::ranges::mismatch(a, b, Equal(&copies)); assert(copies == 0); - //(void)std::ranges::next_permutation(first, last, Less(&copies)); assert(copies == 0); - //(void)std::ranges::next_permutation(a, Less(&copies)); assert(copies == 0); + (void)std::ranges::next_permutation(first, last, Less(&copies)); assert(copies == 0); + (void)std::ranges::next_permutation(a, Less(&copies)); assert(copies == 0); (void)std::ranges::none_of(first, last, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::none_of(a, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::nth_element(first, mid, last, Less(&copies)); assert(copies == 0); (void)std::ranges::nth_element(a, mid, Less(&copies)); assert(copies == 0); (void)std::ranges::partial_sort(first, mid, last, Less(&copies)); assert(copies == 0); (void)std::ranges::partial_sort(a, mid, Less(&copies)); assert(copies == 0); - //(void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(&copies)); assert(copies == 0); - //(void)std::ranges::partial_sort_copy(a, b, Less(&copies)); assert(copies == 0); + (void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(&copies)); assert(copies == 0); + (void)std::ranges::partial_sort_copy(a, b, Less(&copies)); assert(copies == 0); (void)std::ranges::partition(first, last, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::partition(a, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::partition_copy(first, last, first2, last2, UnaryTrue(&copies)); assert(copies == 0); @@ -183,16 +183,16 @@ constexpr bool all_the_algorithms() (void)std::ranges::partition_point(a, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::pop_heap(first, last, Less(&copies)); assert(copies == 0); (void)std::ranges::pop_heap(a, Less(&copies)); assert(copies == 0); - //(void)std::ranges::prev_permutation(first, last, Less(&copies)); assert(copies == 0); - //(void)std::ranges::prev_permutation(a, Less(&copies)); assert(copies == 0); + (void)std::ranges::prev_permutation(first, last, Less(&copies)); assert(copies == 0); + (void)std::ranges::prev_permutation(a, Less(&copies)); assert(copies == 0); (void)std::ranges::push_heap(first, last, Less(&copies)); assert(copies == 0); (void)std::ranges::push_heap(a, Less(&copies)); assert(copies == 0); - //(void)std::ranges::remove_copy_if(first, last, first2, UnaryTrue(&copies)); assert(copies == 0); - //(void)std::ranges::remove_copy_if(a, first2, UnaryTrue(&copies)); assert(copies == 0); + (void)std::ranges::remove_copy_if(first, last, first2, UnaryTrue(&copies)); assert(copies == 0); + (void)std::ranges::remove_copy_if(a, first2, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::remove_if(first, last, UnaryTrue(&copies)); assert(copies == 0); (void)std::ranges::remove_if(a, UnaryTrue(&copies)); assert(copies == 0); - //(void)std::ranges::replace_copy_if(first, last, first2, UnaryTrue(&copies), value); assert(copies == 0); - //(void)std::ranges::replace_copy_if(a, first2, UnaryTrue(&copies), value); assert(copies == 0); + (void)std::ranges::replace_copy_if(first, last, first2, UnaryTrue(&copies), value); assert(copies == 0); + (void)std::ranges::replace_copy_if(a, first2, UnaryTrue(&copies), value); assert(copies == 0); (void)std::ranges::replace_if(first, last, UnaryTrue(&copies), value); assert(copies == 0); (void)std::ranges::replace_if(a, UnaryTrue(&copies), value); assert(copies == 0); (void)std::ranges::search(first, last, first2, mid2, Equal(&copies)); assert(copies == 0); @@ -222,10 +222,10 @@ constexpr bool all_the_algorithms() (void)std::ranges::transform(a, first2, UnaryTransform(&copies)); assert(copies == 0); (void)std::ranges::transform(first, mid, mid, last, first2, BinaryTransform(&copies)); assert(copies == 0); (void)std::ranges::transform(a, b, first2, BinaryTransform(&copies)); assert(copies == 0); - //(void)std::ranges::unique(first, last, Equal(&copies)); assert(copies == 0); - //(void)std::ranges::unique(a, Equal(&copies)); assert(copies == 0); - //(void)std::ranges::unique_copy(first, last, first2, Equal(&copies)); assert(copies == 0); - //(void)std::ranges::unique_copy(a, first2, Equal(&copies)); assert(copies == 0); + (void)std::ranges::unique(first, last, Equal(&copies)); assert(copies == 0); + (void)std::ranges::unique(a, Equal(&copies)); assert(copies == 0); + (void)std::ranges::unique_copy(first, last, first2, Equal(&copies)); assert(copies == 0); + (void)std::ranges::unique_copy(a, first2, Equal(&copies)); assert(copies == 0); (void)std::ranges::upper_bound(first, last, value, Less(&copies)); assert(copies == 0); (void)std::ranges::upper_bound(a, value, Less(&copies)); assert(copies == 0); diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp index 80b8a5ec4d836..c0295b81f8796 100644 --- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp +++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp @@ -80,7 +80,7 @@ constexpr bool all_the_algorithms() (void)std::ranges::any_of(a, UnaryTrue(), Proj(&copies)); assert(copies == 0); (void)std::ranges::binary_search(first, last, value, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::binary_search(a, value, Less(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::clamp(T(), T(), T(), Less(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::clamp(T(), T(), T(), Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::count(first, last, value, Proj(&copies)); assert(copies == 0); (void)std::ranges::count(a, value, Proj(&copies)); assert(copies == 0); (void)std::ranges::count_if(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0); @@ -115,14 +115,14 @@ constexpr bool all_the_algorithms() (void)std::ranges::is_heap_until(a, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_partitioned(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_partitioned(a, UnaryTrue(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::is_permutation(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::is_permutation(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0); + (void)std::ranges::is_permutation(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0); + (void)std::ranges::is_permutation(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_sorted(first, last, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_sorted(a, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(first, last, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(a, Less(), Proj(&copies)); assert(copies == 0); - //if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); } - //if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); assert(copies == 0); } + if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); } + if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); assert(copies == 0); } (void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::lexicographical_compare(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::lower_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0); @@ -148,16 +148,16 @@ constexpr bool all_the_algorithms() (void)std::ranges::minmax_element(a, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::mismatch(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::mismatch(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::next_permutation(first, last, Less(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::next_permutation(a, Less(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::next_permutation(first, last, Less(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::next_permutation(a, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::none_of(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0); (void)std::ranges::none_of(a, UnaryTrue(), Proj(&copies)); assert(copies == 0); (void)std::ranges::nth_element(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::nth_element(a, mid, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::partial_sort(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::partial_sort(a, mid, Less(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::partial_sort_copy(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); + (void)std::ranges::partial_sort_copy(first, last, first2, mid2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); + (void)std::ranges::partial_sort_copy(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::partition(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0); (void)std::ranges::partition(a, UnaryTrue(), Proj(&copies)); assert(copies == 0); (void)std::ranges::partition_copy(first, last, first2, last2, UnaryTrue(), Proj(&copies)); assert(copies == 0); @@ -166,22 +166,22 @@ constexpr bool all_the_algorithms() (void)std::ranges::partition_point(a, UnaryTrue(), Proj(&copies)); assert(copies == 0); (void)std::ranges::pop_heap(first, last, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::pop_heap(a, Less(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::prev_permutation(first, last, Less(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::prev_permutation(a, Less(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::prev_permutation(first, last, Less(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::prev_permutation(a, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::push_heap(first, last, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::push_heap(a, Less(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::remove_copy(first, last, first2, value, Proj(&copies)); assert(copies == 0); - //(void)std::ranges::remove_copy(a, first2, value, Proj(&copies)); assert(copies == 0); - //(void)std::ranges::remove_copy_if(first, last, first2, UnaryTrue(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::remove_copy_if(a, first2, UnaryTrue(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::remove_copy(first, last, first2, value, Proj(&copies)); assert(copies == 0); + (void)std::ranges::remove_copy(a, first2, value, Proj(&copies)); assert(copies == 0); + (void)std::ranges::remove_copy_if(first, last, first2, UnaryTrue(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::remove_copy_if(a, first2, UnaryTrue(), Proj(&copies)); assert(copies == 0); (void)std::ranges::remove(first, last, value, Proj(&copies)); assert(copies == 0); (void)std::ranges::remove(a, value, Proj(&copies)); assert(copies == 0); (void)std::ranges::remove_if(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0); (void)std::ranges::remove_if(a, UnaryTrue(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::replace_copy(first, last, first2, value, T(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::replace_copy(a, first2, value, T(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::replace_copy_if(first, last, first2, UnaryTrue(), T(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::replace_copy_if(a, first2, UnaryTrue(), T(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::replace_copy(first, last, first2, value, T(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::replace_copy(a, first2, value, T(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::replace_copy_if(first, last, first2, UnaryTrue(), T(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::replace_copy_if(a, first2, UnaryTrue(), T(), Proj(&copies)); assert(copies == 0); (void)std::ranges::replace(first, last, value, T(), Proj(&copies)); assert(copies == 0); (void)std::ranges::replace(a, value, T(), Proj(&copies)); assert(copies == 0); (void)std::ranges::replace_if(first, last, UnaryTrue(), T(), Proj(&copies)); assert(copies == 0); @@ -213,10 +213,10 @@ constexpr bool all_the_algorithms() (void)std::ranges::transform(a, first2, UnaryTransform(), Proj(&copies)); assert(copies == 0); (void)std::ranges::transform(first, mid, mid, last, first2, BinaryTransform(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::transform(a, b, first2, BinaryTransform(), Proj(&copies), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::unique(first, last, Equal(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::unique(a, Equal(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::unique_copy(first, last, first2, Equal(), Proj(&copies)); assert(copies == 0); - //(void)std::ranges::unique_copy(a, first2, Equal(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::unique(first, last, Equal(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::unique(a, Equal(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::unique_copy(first, last, first2, Equal(), Proj(&copies)); assert(copies == 0); + (void)std::ranges::unique_copy(a, first2, Equal(), Proj(&copies)); assert(copies == 0); (void)std::ranges::upper_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::upper_bound(a, value, Less(), Proj(&copies)); assert(copies == 0); diff --git a/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp b/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp index 66b8b3637f5f3..0f50d1cdaa827 100644 --- a/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp +++ b/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp @@ -120,7 +120,7 @@ TEST_CONSTEXPR_CXX20 bool all_the_algorithms() #endif (void)std::equal_range(first, last, value, Less(&copies)); assert(copies == 0); (void)std::find_end(first, last, first2, mid2, Equal(&copies)); assert(copies == 0); - //(void)std::find_first_of(first, last, first2, last2, Equal(&copies)); assert(copies == 0); + (void)std::find_first_of(first, last, first2, last2, Equal(&copies)); assert(copies == 0); (void)std::find_if(first, last, UnaryTrue(&copies)); assert(copies == 0); (void)std::find_if_not(first, last, UnaryTrue(&copies)); assert(copies == 0); (void)std::for_each(first, last, UnaryVoid(&copies)); assert(copies == 1); copies = 0; diff --git a/libcxx/test/libcxx/assertions/customize_handler.backdeployment.pass.cpp b/libcxx/test/libcxx/assertions/customize_verbose_abort.backdeployment.pass.cpp similarity index 56% rename from libcxx/test/libcxx/assertions/customize_handler.backdeployment.pass.cpp rename to libcxx/test/libcxx/assertions/customize_verbose_abort.backdeployment.pass.cpp index b1b5e0c8b1b6c..15962671a4690 100644 --- a/libcxx/test/libcxx/assertions/customize_handler.backdeployment.pass.cpp +++ b/libcxx/test/libcxx/assertions/customize_verbose_abort.backdeployment.pass.cpp @@ -7,22 +7,20 @@ //===----------------------------------------------------------------------===// // Make sure that we can enable assertions when we back-deploy to older platforms -// if we define _LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED. +// if we define _LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED. // -// Note that this test isn't really different from customize_handler.pass.cpp when -// run outside of back-deployment scenarios, but we still run it all the time. +// Note that this test isn't really different from customize_verbose_abort.pass.cpp when +// run outside of back-deployment scenarios, but we always want to run this test. -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 -D_LIBCPP_AVAILABILITY_CUSTOM_ASSERTION_HANDLER_PROVIDED +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 -D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED -#include +#include -bool handler_called = false; -void std::__libcpp_assertion_handler(char const*, ...) { - handler_called = true; +void std::__libcpp_verbose_abort(char const*, ...) { + std::exit(EXIT_SUCCESS); } int main(int, char**) { _LIBCPP_ASSERT(false, "message"); - assert(handler_called); - return 0; + return EXIT_FAILURE; } diff --git a/libcxx/test/libcxx/assertions/customize_handler.pass.cpp b/libcxx/test/libcxx/assertions/customize_verbose_abort.pass.cpp similarity index 67% rename from libcxx/test/libcxx/assertions/customize_handler.pass.cpp rename to libcxx/test/libcxx/assertions/customize_verbose_abort.pass.cpp index e6faf1b914b9a..3ee9b7803b709 100644 --- a/libcxx/test/libcxx/assertions/customize_handler.pass.cpp +++ b/libcxx/test/libcxx/assertions/customize_verbose_abort.pass.cpp @@ -6,23 +6,21 @@ // //===----------------------------------------------------------------------===// -// Test that we can set a custom assertion handler. +// Test that we can set a custom verbose termination function. // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 -// We flag uses of the assertion handler in older dylibs at compile-time to avoid runtime +// We flag uses of the verbose termination function in older dylibs at compile-time to avoid runtime // failures when back-deploying. // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} -#include +#include -bool handler_called = false; -void std::__libcpp_assertion_handler(char const*, ...) { - handler_called = true; +void std::__libcpp_verbose_abort(char const*, ...) { + std::exit(EXIT_SUCCESS); } int main(int, char**) { _LIBCPP_ASSERT(false, "message"); - assert(handler_called); - return 0; + return EXIT_FAILURE; } diff --git a/libcxx/test/libcxx/assertions/debug_mode_compatibility.pass.cpp b/libcxx/test/libcxx/assertions/debug_mode_compatibility.pass.cpp index 6cee46ae7a6f0..fe7f0389de911 100644 --- a/libcxx/test/libcxx/assertions/debug_mode_compatibility.pass.cpp +++ b/libcxx/test/libcxx/assertions/debug_mode_compatibility.pass.cpp @@ -16,15 +16,13 @@ // failures when back-deploying. // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} -#include +#include -bool handler_called = false; -void std::__libcpp_assertion_handler(char const*, ...) { - handler_called = true; +void std::__libcpp_verbose_abort(char const*, ...) { + std::exit(EXIT_SUCCESS); } int main(int, char**) { _LIBCPP_ASSERT(false, "message"); - assert(handler_called); - return 0; + return EXIT_FAILURE; } diff --git a/libcxx/test/libcxx/assertions/default_handler.availability.verify.cpp b/libcxx/test/libcxx/assertions/default_handler.availability.verify.cpp deleted file mode 100644 index 6fc8d1601aed7..0000000000000 --- a/libcxx/test/libcxx/assertions/default_handler.availability.verify.cpp +++ /dev/null @@ -1,20 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Make sure that we diagnose any usage of the default assertion handler on a platform -// that doesn't support it at compile-time. - -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 - -// REQUIRES: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11|12}} - -#include // any header would work - -void f() { - _LIBCPP_ASSERT(true, "message"); // expected-error {{'__libcpp_assertion_handler' is unavailable}} -} diff --git a/libcxx/test/libcxx/assertions/default_handler.abort.pass.cpp b/libcxx/test/libcxx/assertions/default_verbose_abort.pass.cpp similarity index 70% rename from libcxx/test/libcxx/assertions/default_handler.abort.pass.cpp rename to libcxx/test/libcxx/assertions/default_verbose_abort.pass.cpp index 4c0390d07790f..79d26c8c48476 100644 --- a/libcxx/test/libcxx/assertions/default_handler.abort.pass.cpp +++ b/libcxx/test/libcxx/assertions/default_verbose_abort.pass.cpp @@ -6,14 +6,10 @@ // //===----------------------------------------------------------------------===// -// Test that the default assertion handler aborts the program. +// Test that the default verbose termination function aborts the program. // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 -// We flag uses of the assertion handler in older dylibs at compile-time to avoid runtime -// failures when back-deploying. -// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} - #include #include diff --git a/libcxx/test/libcxx/assertions/headers_declare_assertion_handler.sh.cpp b/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp similarity index 59% rename from libcxx/test/libcxx/assertions/headers_declare_assertion_handler.sh.cpp rename to libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp index 8c8be13b56b93..53ad13b4d59ba 100644 --- a/libcxx/test/libcxx/assertions/headers_declare_assertion_handler.sh.cpp +++ b/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp @@ -6,11 +6,7 @@ // //===----------------------------------------------------------------------===// -// Test that all public C++ headers define the assertion handler. - -// We flag uses of the assertion handler in older dylibs at compile-time to avoid runtime -// failures when back-deploying. -// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// Test that all public C++ headers define the verbose termination function. // The system-provided seems to be broken on AIX, which trips up this test. // XFAIL: LIBCXX-AIX-FIXME @@ -34,7 +30,7 @@ for i, header in enumerate(public_headers): // {run}: %{{build}} -DTEST_{i} #if defined(TEST_{i}){restrictions} # include <{header}> - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif """.format(**vars)) @@ -55,715 +51,715 @@ int main(int, char**) { return 0; } // RUN: %{build} -DTEST_0 #if defined(TEST_0) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_1 #if defined(TEST_1) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_2 #if defined(TEST_2) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_3 #if defined(TEST_3) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_4 #if defined(TEST_4) && !defined(_LIBCPP_HAS_NO_THREADS) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_5 #if defined(TEST_5) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_6 #if defined(TEST_6) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_7 #if defined(TEST_7) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_8 #if defined(TEST_8) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_9 #if defined(TEST_9) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_10 #if defined(TEST_10) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_11 #if defined(TEST_11) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_12 #if defined(TEST_12) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_13 #if defined(TEST_13) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_14 #if defined(TEST_14) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_15 #if defined(TEST_15) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_16 #if defined(TEST_16) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_17 #if defined(TEST_17) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_18 #if defined(TEST_18) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_19 #if defined(TEST_19) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_20 #if defined(TEST_20) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_21 #if defined(TEST_21) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_22 #if defined(TEST_22) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_24 #if defined(TEST_24) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_25 #if defined(TEST_25) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_26 #if defined(TEST_26) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_27 #if defined(TEST_27) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_28 #if defined(TEST_28) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_29 #if defined(TEST_29) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_30 #if defined(TEST_30) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_31 #if defined(TEST_31) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_32 #if defined(TEST_32) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_33 #if defined(TEST_33) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_34 #if defined(TEST_34) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_35 #if defined(TEST_35) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_36 #if defined(TEST_36) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_37 #if defined(TEST_37) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_39 #if defined(TEST_39) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_40 #if defined(TEST_40) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_41 #if defined(TEST_41) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_42 #if defined(TEST_42) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_44 #if defined(TEST_44) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_45 #if defined(TEST_45) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_47 #if defined(TEST_47) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_49 #if defined(TEST_49) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_50 #if defined(TEST_50) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_51 #if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_52 #if defined(TEST_52) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_53 #if defined(TEST_53) && !defined(_LIBCPP_HAS_NO_THREADS) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_54 #if defined(TEST_54) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_56 #if defined(TEST_56) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_57 #if defined(TEST_57) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_58 #if defined(TEST_58) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_59 #if defined(TEST_59) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_60 #if defined(TEST_60) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_61 #if defined(TEST_61) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_62 #if defined(TEST_62) && !defined(_LIBCPP_HAS_NO_THREADS) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_63 #if defined(TEST_63) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_65 #if defined(TEST_65) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_66 #if defined(TEST_66) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_68 #if defined(TEST_68) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_70 #if defined(TEST_70) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_71 #if defined(TEST_71) && !defined(_LIBCPP_HAS_NO_THREADS) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_72 #if defined(TEST_72) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_73 #if defined(TEST_73) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_74 #if defined(TEST_74) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_75 #if defined(TEST_75) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_76 #if defined(TEST_76) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_77 #if defined(TEST_77) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_78 #if defined(TEST_78) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_79 #if defined(TEST_79) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_80 #if defined(TEST_80) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_81 #if defined(TEST_81) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_82 #if defined(TEST_82) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_83 #if defined(TEST_83) && !defined(_LIBCPP_HAS_NO_THREADS) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_84 #if defined(TEST_84) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_86 #if defined(TEST_86) && !defined(_LIBCPP_HAS_NO_THREADS) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_87 #if defined(TEST_87) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_88 #if defined(TEST_88) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_89 #if defined(TEST_89) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_93 #if defined(TEST_93) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_97 #if defined(TEST_97) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_98 #if defined(TEST_98) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_100 #if defined(TEST_100) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_101 #if defined(TEST_101) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_102 #if defined(TEST_102) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_104 #if defined(TEST_104) && !defined(_LIBCPP_HAS_NO_THREADS) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_105 #if defined(TEST_105) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_106 #if defined(TEST_106) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_107 #if defined(TEST_107) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_108 #if defined(TEST_108) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_110 #if defined(TEST_110) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_111 #if defined(TEST_111) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_112 #if defined(TEST_112) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_113 #if defined(TEST_113) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_114 #if defined(TEST_114) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_115 #if defined(TEST_115) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_116 #if defined(TEST_116) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_119 #if defined(TEST_119) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_120 #if defined(TEST_120) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_121 #if defined(TEST_121) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_122 #if defined(TEST_122) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_123 #if defined(TEST_123) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_124 #if defined(TEST_124) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_125 #if defined(TEST_125) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_126 #if defined(TEST_126) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_127 #if defined(TEST_127) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_128 #if defined(TEST_128) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_129 #if defined(TEST_129) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_130 #if defined(TEST_130) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_131 #if defined(TEST_131) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_132 #if defined(TEST_132) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_133 #if defined(TEST_133) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_134 #if defined(TEST_134) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_135 #if defined(TEST_135) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_136 #if defined(TEST_136) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_137 #if defined(TEST_137) && __cplusplus >= 201103L # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_138 #if defined(TEST_138) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // RUN: %{build} -DTEST_139 #if defined(TEST_139) # include - using HandlerType = decltype(std::__libcpp_assertion_handler); + using HandlerType = decltype(std::__libcpp_verbose_abort); #endif // GENERATED-MARKER diff --git a/libcxx/test/libcxx/assertions/single_expression.sh.cpp b/libcxx/test/libcxx/assertions/single_expression.sh.cpp index fb661103b6de6..60847f3eef74f 100644 --- a/libcxx/test/libcxx/assertions/single_expression.sh.cpp +++ b/libcxx/test/libcxx/assertions/single_expression.sh.cpp @@ -18,10 +18,6 @@ // RUN: %{build} -Wno-macro-redefined -D_LIBCPP_ENABLE_ASSERTIONS=0 -D_LIBCPP_ASSERTIONS_DISABLE_ASSUME // RUN: %{run} -// We flag uses of the assertion handler in older dylibs at compile-time to avoid runtime -// failures when back-deploying. -// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} - #include <__assert> #include diff --git a/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp b/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp index 3c8efde1deb4f..e99af02e4f8e2 100644 --- a/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp +++ b/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp @@ -105,6 +105,7 @@ int main(int, char**) { CHECK_ALIGNMENT(struct LLIArr16 { long long int i[16]; }); CHECK_ALIGNMENT(struct Padding { char c; /* padding */ long long int i; }); CHECK_ALIGNMENT(union IntFloat { int i; float f; }); + CHECK_ALIGNMENT(enum class StrongEnum { foo }); return 0; } diff --git a/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_sent.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_sent.pass.cpp new file mode 100644 index 0000000000000..cd373e71b4b45 --- /dev/null +++ b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_sent.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// +// +// constexpr span::span(Iterator it, Sentinel sent); +// +// Check that we ensure `Extent == sent - it` and also that `[it, sent)` is a valid range. +// +// +// constexpr span::span(Iterator it, Sentinel sent); +// +// Check that we ensure that `[it, sent)` is a valid range. + +// REQUIRES: has-unix-headers +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 + +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + { + std::array array{0, 1, 2}; + + auto invalid_range = [&] { std::span const s(array.end(), array.begin()); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_range(), "invalid range in span's constructor (iterator, sentinel)"); + } + { + std::array array{0, 1, 2}; + + auto invalid_range = [&] { std::span const s(array.end(), array.begin()); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_range(), "invalid range in span's constructor (iterator, sentinel)"); + + auto invalid_size = [&] { std::span const s(array.begin(), array.begin() + 2); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_size(), "invalid range in span's constructor (iterator, sentinel): last - first != extent"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_size.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_size.pass.cpp new file mode 100644 index 0000000000000..1888b4b5d0b23 --- /dev/null +++ b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_size.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// +// +// constexpr span::span(Iterator, size_type); +// +// Check that the passed size is equal to the statically known extent. +// Note that it doesn't make sense to validate the incoming size in the +// dynamic_extent version. + +// REQUIRES: has-unix-headers +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 + +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + std::array array{0, 1, 2}; + + auto too_large = [&] { std::span const s(array.data(), 4); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(too_large(), "size mismatch in span's constructor (iterator, len)"); + + auto too_small = [&] { std::span const s(array.data(), 2); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(too_small(), "size mismatch in span's constructor (iterator, len)"); + + return 0; +} diff --git a/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.other_span.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.other_span.pass.cpp new file mode 100644 index 0000000000000..9e92e837f795b --- /dev/null +++ b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.other_span.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// +// +// constexpr span::span(const span& other); +// +// Check that we ensure `other.size() == Extent`. + +// REQUIRES: has-unix-headers +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 + +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + std::array array{0, 1, 2}; + std::span other(array.data(), 3); + + auto invalid_source = [&] { std::span const s(other); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_source(), "size mismatch in span's constructor (other span)"); + + return 0; +} diff --git a/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.range.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.range.pass.cpp new file mode 100644 index 0000000000000..bf1233f207b33 --- /dev/null +++ b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.range.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// +// +// constexpr span::span(Range&& r); +// +// Check that we ensure `size(r) == Extent`. + +// REQUIRES: has-unix-headers +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 + +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + std::vector vec{0, 1, 2}; // must use std::vector instead of std::array, because std::span has a special constructor from std::array + + auto invalid_size = [&] { std::span const s(vec); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_size(), "size mismatch in span's constructor (range)"); + + return 0; +} diff --git a/libcxx/test/libcxx/depr/depr.func.adaptor.typedefs/typedefs.depr_in_cxx17.verify.cpp b/libcxx/test/libcxx/depr/depr.func.adaptor.typedefs/typedefs.depr_in_cxx17.verify.cpp index 422f405042208..65a0d2b9bfabd 100644 --- a/libcxx/test/libcxx/depr/depr.func.adaptor.typedefs/typedefs.depr_in_cxx17.verify.cpp +++ b/libcxx/test/libcxx/depr/depr.func.adaptor.typedefs/typedefs.depr_in_cxx17.verify.cpp @@ -19,6 +19,12 @@ #include #include "test_macros.h" +// This test is disabled in LLVM 15 because we enable the removed +// unary_function and binary_function classes by default, which means +// that we also don't produce deprecation warnings for using their members. + +// expected-no-diagnostics +#if 0 void test_functional() { { @@ -123,3 +129,4 @@ void test_map() (void)c; } } +#endif diff --git a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp index c04dd5abb1d30..c58de9c6d4764 100644 --- a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp +++ b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp @@ -16,7 +16,7 @@ // UNSUPPORTED: clang-13, clang-14 // AppleClang does not support the -fexperimental-library flag yet -// UNSUPPORTED: apple-clang-13 +// UNSUPPORTED: apple-clang-13, apple-clang-14.0 // Clang on AIX currently pretends that it is Clang 15, even though it is not (as of writing // this, LLVM 15 hasn't even been branched yet). diff --git a/libcxx/test/libcxx/include_as_c.sh.cpp b/libcxx/test/libcxx/include_as_c.sh.cpp index a3e5d533040d4..f649c9c54f1be 100644 --- a/libcxx/test/libcxx/include_as_c.sh.cpp +++ b/libcxx/test/libcxx/include_as_c.sh.cpp @@ -34,6 +34,7 @@ #endif #include #include +#include #include #include #include diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp index f9cb581c16b83..a6a07f49e7f3d 100644 --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -109,6 +109,7 @@ END-SCRIPT #include <__algorithm/ranges_all_of.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_all_of.h'}} #include <__algorithm/ranges_any_of.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_any_of.h'}} #include <__algorithm/ranges_binary_search.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_binary_search.h'}} +#include <__algorithm/ranges_clamp.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_clamp.h'}} #include <__algorithm/ranges_copy.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_copy.h'}} #include <__algorithm/ranges_copy_backward.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_copy_backward.h'}} #include <__algorithm/ranges_copy_if.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_copy_if.h'}} @@ -133,6 +134,7 @@ END-SCRIPT #include <__algorithm/ranges_is_heap.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_is_heap.h'}} #include <__algorithm/ranges_is_heap_until.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_is_heap_until.h'}} #include <__algorithm/ranges_is_partitioned.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_is_partitioned.h'}} +#include <__algorithm/ranges_is_permutation.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_is_permutation.h'}} #include <__algorithm/ranges_is_sorted.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_is_sorted.h'}} #include <__algorithm/ranges_is_sorted_until.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_is_sorted_until.h'}} #include <__algorithm/ranges_iterator_concept.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_iterator_concept.h'}} @@ -149,6 +151,7 @@ END-SCRIPT #include <__algorithm/ranges_mismatch.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_mismatch.h'}} #include <__algorithm/ranges_move.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_move.h'}} #include <__algorithm/ranges_move_backward.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_move_backward.h'}} +#include <__algorithm/ranges_next_permutation.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_next_permutation.h'}} #include <__algorithm/ranges_none_of.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_none_of.h'}} #include <__algorithm/ranges_nth_element.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_nth_element.h'}} #include <__algorithm/ranges_partial_sort.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_partial_sort.h'}} @@ -157,6 +160,7 @@ END-SCRIPT #include <__algorithm/ranges_partition_copy.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_partition_copy.h'}} #include <__algorithm/ranges_partition_point.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_partition_point.h'}} #include <__algorithm/ranges_pop_heap.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_pop_heap.h'}} +#include <__algorithm/ranges_prev_permutation.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_prev_permutation.h'}} #include <__algorithm/ranges_push_heap.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_push_heap.h'}} #include <__algorithm/ranges_remove.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_remove.h'}} #include <__algorithm/ranges_remove_copy.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_remove_copy.h'}} @@ -168,7 +172,9 @@ END-SCRIPT #include <__algorithm/ranges_replace_if.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_replace_if.h'}} #include <__algorithm/ranges_reverse.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_reverse.h'}} #include <__algorithm/ranges_reverse_copy.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_reverse_copy.h'}} +#include <__algorithm/ranges_rotate.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_rotate.h'}} #include <__algorithm/ranges_rotate_copy.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_rotate_copy.h'}} +#include <__algorithm/ranges_sample.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_sample.h'}} #include <__algorithm/ranges_search.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_search.h'}} #include <__algorithm/ranges_search_n.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_search_n.h'}} #include <__algorithm/ranges_set_difference.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/ranges_set_difference.h'}} @@ -214,9 +220,11 @@ END-SCRIPT #include <__algorithm/stable_sort.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/stable_sort.h'}} #include <__algorithm/swap_ranges.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/swap_ranges.h'}} #include <__algorithm/transform.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/transform.h'}} +#include <__algorithm/uniform_random_bit_generator_adaptor.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/uniform_random_bit_generator_adaptor.h'}} #include <__algorithm/unique.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/unique.h'}} #include <__algorithm/unique_copy.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/unique_copy.h'}} #include <__algorithm/unwrap_iter.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/unwrap_iter.h'}} +#include <__algorithm/unwrap_range.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/unwrap_range.h'}} #include <__algorithm/upper_bound.h> // expected-error@*:* {{use of private header from outside its module: '__algorithm/upper_bound.h'}} #include <__availability> // expected-error@*:* {{use of private header from outside its module: '__availability'}} #include <__bit/bit_cast.h> // expected-error@*:* {{use of private header from outside its module: '__bit/bit_cast.h'}} diff --git a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py index 6ffedad2523fb..81fb60ac790fe 100644 --- a/libcxx/test/libcxx/selftest/dsl/dsl.sh.py +++ b/libcxx/test/libcxx/selftest/dsl/dsl.sh.py @@ -64,6 +64,7 @@ def setUp(self): params={}) self.config = lit.TestingConfig.TestingConfig.fromdefaults(self.litConfig) + self.config.environment = dict(os.environ) self.config.test_source_root = SOURCE_ROOT self.config.test_exec_root = EXEC_PATH self.config.recursiveExpansionLimit = 10 diff --git a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp index 4d6248b9af1d1..3f3ed5baf1f4a 100644 --- a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp +++ b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp @@ -64,7 +64,7 @@ bool test() { #if _LIBCPP_ABI_VERSION == 1 -# if defined(__x86_64__) +# if defined(__x86_64__) || defined(__i386__) full_size(); # elif defined(__APPLE__) && defined(__aarch64__) half_size(); @@ -75,6 +75,12 @@ bool test() { full_size(); # endif # elif defined(__powerpc__) || defined(__powerpc64__) +# ifdef __BIG_ENDIAN__ + half_size(); +# else + full_size(); +# endif +# elif defined(__sparc64__) half_size(); # elif defined(_WIN32) full_size(); diff --git a/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm b/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm new file mode 100644 index 0000000000000..186fe22e6e476 --- /dev/null +++ b/libcxx/test/libcxx/utilities/function.objects/func.blocks.arc.pass.mm @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// std::function support for "blocks" when ARC is enabled + +// UNSUPPORTED: c++03 + +// This test requires the Blocks runtime, which is (only?) available on Darwin +// out-of-the-box. +// REQUIRES: has-fblocks && darwin + +// ADDITIONAL_COMPILE_FLAGS: -fblocks -fobjc-arc + +#include + +#include +#include +#include + +struct Foo { + Foo() = default; + Foo(std::size_t (^bl)()) : f(bl) {} + + std::function f; +}; + +Foo Factory(std::size_t (^bl)()) { + Foo result(bl); + return result; +} + +Foo Factory2() { + auto hello = std::string("Hello world"); + return Factory(^() { + return hello.size(); + }); +} + +Foo AssignmentFactory(std::size_t (^bl)()) { + Foo result; + result.f = bl; + return result; +} + +Foo AssignmentFactory2() { + auto hello = std::string("Hello world"); + return AssignmentFactory(^() { + return hello.size(); + }); +} + +int main(int, char **) { + // Case 1, works + { + auto hello = std::string("Hello world"); + auto f = AssignmentFactory(^() { + return hello.size(); + }); + assert(f.f() == 11); + } + + // Case 2, works + { + auto f = AssignmentFactory2(); + assert(f.f() == 11); + } + + // Case 3, works + { + auto hello = std::string("Hello world"); + auto f = Factory(^() { + return hello.size(); + }); + assert(f.f() == 11); + } + + // Case 4, used to crash under ARC + { + auto f = Factory2(); + assert(f.f() == 11); + } + + return 0; +} diff --git a/libcxx/test/libcxx/utilities/function.objects/func.blocks.sh.cpp b/libcxx/test/libcxx/utilities/function.objects/func.blocks.pass.cpp similarity index 98% rename from libcxx/test/libcxx/utilities/function.objects/func.blocks.sh.cpp rename to libcxx/test/libcxx/utilities/function.objects/func.blocks.pass.cpp index ecebc7c9800ff..b95b6ebb534a1 100644 --- a/libcxx/test/libcxx/utilities/function.objects/func.blocks.sh.cpp +++ b/libcxx/test/libcxx/utilities/function.objects/func.blocks.pass.cpp @@ -14,8 +14,7 @@ // on Darwin out-of-the-box. // REQUIRES: has-fblocks && darwin -// RUN: %{build} -fblocks -// RUN: %{run} +// ADDITIONAL_COMPILE_FLAGS: -fblocks #include #include diff --git a/libcxx/test/libcxx/vendor/clang-cl/static-lib-exports.sh.cpp b/libcxx/test/libcxx/vendor/clang-cl/static-lib-exports.sh.cpp index fb66c4a28fa08..447454ee229ca 100644 --- a/libcxx/test/libcxx/vendor/clang-cl/static-lib-exports.sh.cpp +++ b/libcxx/test/libcxx/vendor/clang-cl/static-lib-exports.sh.cpp @@ -8,7 +8,9 @@ // REQUIRES: msvc -// This file checks that the built static library doesn't contain dllexport +// This file checks that the built static libraries don't contain dllexport // directives in clang-cl builds. // RUN: llvm-readobj --coff-directives "%{lib}/libc++.lib" | not grep -i "export:" > /dev/null + +// RUN: llvm-readobj --coff-directives "%{lib}/libc++experimental.lib" | not grep -i "export:" > /dev/null diff --git a/libcxx/test/libcxx/vendor/mingw/experimental-lib-exports.sh.cpp b/libcxx/test/libcxx/vendor/mingw/experimental-lib-exports.sh.cpp deleted file mode 100644 index 5aca961536ee6..0000000000000 --- a/libcxx/test/libcxx/vendor/mingw/experimental-lib-exports.sh.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// REQUIRES: target={{.+}}-windows-gnu && c++experimental - -// This file checks that the built experimental static library doesn't contain dllexport -// directives in MinGW builds. - -// RUN: llvm-readobj --coff-directives "%{lib}/libc++experimental.a" | not grep -i "export:" > /dev/null diff --git a/libcxx/test/libcxx/vendor/mingw/static-lib-exports.sh.cpp b/libcxx/test/libcxx/vendor/mingw/static-lib-exports.sh.cpp index 7dfedb761f0c7..8f29f5ad051d4 100644 --- a/libcxx/test/libcxx/vendor/mingw/static-lib-exports.sh.cpp +++ b/libcxx/test/libcxx/vendor/mingw/static-lib-exports.sh.cpp @@ -8,7 +8,9 @@ // REQUIRES: target={{.+}}-windows-gnu -// This file checks that the built static library doesn't contain dllexport +// This file checks that the built static libraries don't contain dllexport // directives in MinGW builds. // RUN: llvm-readobj --coff-directives "%{lib}/libc++.a" | not grep -i "export:" > /dev/null + +// RUN: llvm-readobj --coff-directives "%{lib}/libc++experimental.a" | not grep -i "export:" > /dev/null diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp index 390bafed7aa54..cc58dd2732c49 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.pass.cpp @@ -95,13 +95,20 @@ constexpr void test_iterators() { } } +template +constexpr void test_sentinels() { + test_iterators(); + test_iterators>(); + test_iterators>(); +} + template constexpr void test_in_iterators() { test_iterators, Out, sentinel_wrapper>>(); - test_iterators, Out>(); - test_iterators, Out>(); - test_iterators, Out>(); - test_iterators, Out>(); + test_sentinels, Out>(); + test_sentinels, Out>(); + test_sentinels, Out>(); + test_sentinels, Out>(); } template diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp index b75eced30b793..d99fa4888430f 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp @@ -65,7 +65,7 @@ constexpr void test_iterators() { std::same_as> auto ret = std::ranges::copy_backward(In(in.data()), Sent(In(in.data() + in.size())), Out(out.data() + out.size())); assert(in == out); - assert(base(ret.in) == in.data()); + assert(base(ret.in) == in.data() + in.size()); assert(base(ret.out) == out.data()); } { @@ -75,7 +75,7 @@ constexpr void test_iterators() { std::same_as> auto ret = std::ranges::copy_backward(range, Out(out.data() + out.size())); assert(in == out); - assert(base(ret.in) == in.data()); + assert(base(ret.in) == in.data() + in.size()); assert(base(ret.out) == out.data()); } } @@ -86,7 +86,7 @@ constexpr void test_iterators() { std::array out; auto ret = std::ranges::copy_backward(In(in.data()), Sent(In(in.data() + in.size())), Out(out.data() + out.size())); - assert(base(ret.in) == in.data()); + assert(base(ret.in) == in.data() + in.size()); assert(base(ret.out) == out.data()); } { @@ -94,7 +94,7 @@ constexpr void test_iterators() { std::array out; auto range = std::ranges::subrange(In(in.data()), Sent(In(in.data() + in.size()))); auto ret = std::ranges::copy_backward(range, Out(out.data())); - assert(base(ret.in) == in.data()); + assert(base(ret.in) == in.data() + in.size()); assert(base(ret.out) == out.data()); } } @@ -143,7 +143,7 @@ constexpr bool test() { std::array out; std::same_as> auto ret = std::ranges::copy_backward(std::views::all(in), out.data() + out.size()); - assert(ret.in == in.data()); + assert(ret.in == in.data() + in.size()); assert(ret.out == out.data()); assert(in == out); } @@ -163,7 +163,7 @@ constexpr bool test() { std::array in {}; std::array out {}; auto ret = std::ranges::copy_backward(in.begin(), in.end(), out.end()); - assert(ret.in == in.begin()); + assert(ret.in == in.end()); assert(ret.out == out.begin()); assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.copied; })); } @@ -171,7 +171,7 @@ constexpr bool test() { std::array in {}; std::array out {}; auto ret = std::ranges::copy_backward(in, out.end()); - assert(ret.in == in.begin()); + assert(ret.in == in.end()); assert(ret.out == out.begin()); assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.copied; })); } @@ -196,7 +196,7 @@ constexpr bool test() { out[2].next = &out[1]; out[2].canCopy = true; auto ret = std::ranges::copy_backward(in, out.end()); - assert(ret.in == in.begin()); + assert(ret.in == in.end()); assert(ret.out == out.begin()); assert(out[0].canCopy); assert(out[1].canCopy); @@ -209,7 +209,7 @@ constexpr bool test() { out[2].next = &out[1]; out[2].canCopy = true; auto ret = std::ranges::copy_backward(in.begin(), in.end(), out.end()); - assert(ret.in == in.begin()); + assert(ret.in == in.end()); assert(ret.out == out.begin()); assert(out[0].canCopy); assert(out[1].canCopy); diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/ranges.move_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/ranges.move_backward.pass.cpp index 2211409f6ab3c..fc2706d1e07f6 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/ranges.move_backward.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/ranges.move_backward.pass.cpp @@ -64,7 +64,7 @@ constexpr void test(std::array in) { std::same_as> decltype(auto) ret = std::ranges::move_backward(In(in.data()), Sent(In(in.data() + in.size())), Out(out.data() + out.size())); assert(in == out); - assert(base(ret.in) == in.data()); + assert(base(ret.in) == in.data() + in.size()); assert(base(ret.out) == out.data()); } { @@ -73,7 +73,7 @@ constexpr void test(std::array in) { std::same_as> decltype(auto) ret = std::ranges::move_backward(range, Out(out.data() + out.size())); assert(in == out); - assert(base(ret.in) == in.data()); + assert(base(ret.in) == in.data() + in.size()); assert(base(ret.out) == out.data()); } } @@ -186,7 +186,7 @@ constexpr bool test() { std::array out; std::same_as> auto ret = std::ranges::move_backward(std::views::all(in), out.data() + out.size()); - assert(ret.in == in.data()); + assert(ret.in == in.data() + in.size()); assert(ret.out == out.data()); assert(in == out); } @@ -206,7 +206,7 @@ constexpr bool test() { std::array in {}; std::array out {}; auto ret = std::ranges::move_backward(in.begin(), in.end(), out.end()); - assert(ret.in == in.begin()); + assert(ret.in == in.end()); assert(ret.out == out.begin()); assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.moved; })); } @@ -214,7 +214,7 @@ constexpr bool test() { std::array in {}; std::array out {}; auto ret = std::ranges::move_backward(in, out.end()); - assert(ret.in == in.begin()); + assert(ret.in == in.end()); assert(ret.out == out.begin()); assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.moved; })); } @@ -239,7 +239,7 @@ constexpr bool test() { out[2].next = &out[1]; out[2].canMove = true; auto ret = std::ranges::move_backward(in, out.end()); - assert(ret.in == in.begin()); + assert(ret.in == in.end()); assert(ret.out == out.begin()); assert(out[0].canMove); assert(out[1].canMove); @@ -252,7 +252,7 @@ constexpr bool test() { out[2].next = &out[1]; out[2].canMove = true; auto ret = std::ranges::move_backward(in.begin(), in.end(), out.end()); - assert(ret.in == in.begin()); + assert(ret.in == in.end()); assert(ret.out == out.begin()); assert(out[0].canMove); assert(out[1].canMove); @@ -265,7 +265,7 @@ constexpr bool test() { int a[] = {1, 2, 3, 4}; std::array b; auto ret = std::ranges::move_backward(IteratorWithMoveIter(a), IteratorWithMoveIter(a + 4), b.data() + b.size()); - assert(ret.in == a); + assert(ret.in == a + 4); assert(ret.out == b.data()); assert((b == std::array {42, 42, 42, 42})); } @@ -274,7 +274,7 @@ constexpr bool test() { std::array b; auto range = std::ranges::subrange(IteratorWithMoveIter(a), IteratorWithMoveIter(a + 4)); auto ret = std::ranges::move_backward(range, b.data() + b.size()); - assert(ret.in == a); + assert(ret.in == a + 4); assert(ret.out == b.data()); assert((b == std::array {42, 42, 42, 42})); } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.random.sample/ranges_sample.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.random.sample/ranges_sample.pass.cpp new file mode 100644 index 0000000000000..1b15acd715ac8 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.random.sample/ranges_sample.pass.cpp @@ -0,0 +1,334 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// + +// template S, weakly_incrementable O, class Gen> +// requires (forward_iterator || random_access_iterator) && +// indirectly_copyable && +// uniform_random_bit_generator> +// O sample(I first, S last, O out, iter_difference_t n, Gen&& g); // Since C++20 +// +// template +// requires (forward_range || random_access_iterator) && +// indirectly_copyable, O> && +// uniform_random_bit_generator> +// O sample(R&& r, O out, range_difference_t n, Gen&& g); // Since C++20 + +#include +#include +#include +#include +#include +#include +#include + +#include "almost_satisfies_types.h" +#include "test_iterators.h" +#include "test_macros.h" + +class RandGen { +public: + constexpr static size_t min() { return 0; } + constexpr static size_t max() { return 255; } + + constexpr size_t operator()() { + flip = !flip; + return flip; + } + +private: + bool flip = false; +}; + +static_assert(std::uniform_random_bit_generator); +// `std::uniform_random_bit_generator` is a subset of requirements of `__libcpp_random_is_valid_urng`. Make sure that +// a type satisfying the required minimum is still accepted by `ranges::shuffle`. +LIBCPP_STATIC_ASSERT(!std::__libcpp_random_is_valid_urng::value); + +struct BadGen { + constexpr static size_t min() { return 255; } + constexpr static size_t max() { return 0; } + constexpr size_t operator()() const; +}; +static_assert(!std::uniform_random_bit_generator); + +// Test constraints of the (iterator, sentinel) overload. +// ====================================================== + +template +concept HasSampleIter = + requires(Iter&& iter, Sent&& sent, Out&& out, std::iter_difference_t n, Gen&& gen) { + std::ranges::sample(std::forward(iter), std::forward(sent), + std::forward(out), n, std::forward(gen)); + }; + +static_assert(HasSampleIter); + +// !input_iterator +static_assert(!HasSampleIter); +static_assert(!HasSampleIter); +static_assert(!HasSampleIter); + +// !sentinel_for +static_assert(!HasSampleIter); +static_assert(!HasSampleIter); + +// !weakly_incrementable +static_assert(!HasSampleIter); + +// (forward_iterator || random_access_iterator) +static_assert(HasSampleIter< + forward_iterator, forward_iterator, + cpp20_output_iterator +>); +static_assert(HasSampleIter< + cpp20_input_iterator, sentinel_wrapper>, + random_access_iterator +>); +// !(forward_iterator || random_access_iterator) +static_assert(!HasSampleIter< + cpp20_input_iterator, sentinel_wrapper>, + cpp20_output_iterator +>); + +// !indirectly_copyable +static_assert(!HasSampleIter); + +// !uniform_random_bit_generator> +static_assert(!HasSampleIter); + +// Test constraints of the (range) overload. +// ========================================= + +template +concept HasSampleRange = + requires(Range&& range, Out&& out, std::ranges::range_difference_t n, Gen&& gen) { + std::ranges::sample(std::forward(range), std::forward(out), n, std::forward(gen)); + }; + +template +using R = UncheckedRange; + +static_assert(HasSampleRange, int*, RandGen>); + +// !input_range +static_assert(!HasSampleRange); +static_assert(!HasSampleRange); +static_assert(!HasSampleRange); + +// !weakly_incrementable +static_assert(!HasSampleRange, WeaklyIncrementableNotMovable>); + +// (forward_range || random_access_iterator) +static_assert(HasSampleRange< + R>, + cpp20_output_iterator +>); +static_assert(HasSampleRange< + R>, + random_access_iterator +>); +// !(forward_range || random_access_iterator) +static_assert(!HasSampleRange< + R>, + cpp20_output_iterator +>); + +// !indirectly_copyable +static_assert(!HasSampleRange, int**>); + +// !uniform_random_bit_generator> +static_assert(!HasSampleRange, int*, BadGen>); + +template +void test_one(std::array in, size_t n, Gen gen) { + assert(n <= static_cast(N)); + + auto verify_is_subsequence = [&] (auto output) { + auto sorted_input = in; + std::ranges::sort(sorted_input); + auto sorted_output = std::ranges::subrange(output.begin(), output.begin() + n); + std::ranges::sort(sorted_output); + assert(std::ranges::includes(sorted_input, sorted_output)); + }; + + { // (iterator, sentinel) overload. + auto begin = Iter(in.data()); + auto end = Sent(Iter(in.data() + in.size())); + std::array output; + auto out = Out(output.begin()); + + std::same_as decltype(auto) result = std::ranges::sample( + std::move(begin), std::move(end), std::move(out), n, gen); + assert(base(result) == output.data() + n); + verify_is_subsequence(output); + // The output of `sample` is implementation-specific. + } + + { // (range) overload. + auto begin = Iter(in.data()); + auto end = Sent(Iter(in.data() + in.size())); + std::array output; + auto out = Out(output.begin()); + + std::same_as decltype(auto) result = std::ranges::sample(std::ranges::subrange( + std::move(begin), std::move(end)), std::move(out), n, gen); + assert(base(result) == output.data() + n); + verify_is_subsequence(output); + // The output of `sample` is implementation-specific. + } +} + +template +void test_iterators_iter_sent_out() { + RandGen gen; + + // Empty sequence. + test_one({}, 0, gen); + // 1-element sequence. + test_one({1}, 1, gen); + // 2-element sequence. + test_one({1, 2}, 1, gen); + test_one({1, 2}, 2, gen); + // n == 0. + test_one({1, 2, 3}, 0, gen); + + // Longer sequence. + { + std::array input = {1, 8, 2, 3, 4, 6, 5, 7}; + for (int i = 0; i <= static_cast(input.size()); ++i){ + test_one(input, i, gen); + } + } +} + +template +void test_iterators_iter_sent() { + if constexpr (std::forward_iterator) { + test_iterators_iter_sent_out>(); + test_iterators_iter_sent_out>(); + } + test_iterators_iter_sent_out>(); + test_iterators_iter_sent_out>(); + test_iterators_iter_sent_out(); +} + +template +void test_iterators_iter() { + if constexpr (std::sentinel_for) { + test_iterators_iter_sent(); + } + test_iterators_iter_sent>(); +} + +void test_iterators() { + test_iterators_iter>(); + test_iterators_iter>(); + test_iterators_iter>(); + test_iterators_iter(); + test_iterators_iter(); +} + +// Checks the logic for wrapping the given iterator to make sure it works correctly regardless of the value category of +// the given generator object. +template +void test_generator() { + std::array in = {1, 2, 3, 4, 5, 6, 7, 8}; + constexpr int N = 5; + std::array output; + auto begin = in.begin(); + auto end = in.end(); + auto out = output.begin(); + + { // Lvalue. + Gen g; + std::ranges::sample(begin, end, out, N, g); + std::ranges::sample(in, out, N, g); + } + + if constexpr (CheckConst) { // Const lvalue. + const Gen g; + std::ranges::sample(begin, end, out, N, g); + std::ranges::sample(in, out, N, g); + } + + { // Prvalue. + std::ranges::sample(begin, end, out, N, Gen()); + std::ranges::sample(in, out, N, Gen()); + } + + { // Xvalue. + Gen g1, g2; + std::ranges::sample(begin, end, out, N, std::move(g1)); + std::ranges::sample(in, out, N, std::move(g2)); + } +} + +// Checks the logic for wrapping the given iterator to make sure it works correctly regardless of whether the given +// generator class has a const or non-const invocation operator (or both). +void test_generators() { + struct GenBase { + constexpr static size_t min() { return 0; } + constexpr static size_t max() { return 255; } + }; + struct NonconstGen : GenBase { + size_t operator()() { return 1; } + }; + struct ConstGen : GenBase { + size_t operator()() const { return 1; } + }; + struct ConstAndNonconstGen : GenBase { + size_t operator()() { return 1; } + size_t operator()() const { return 1; } + }; + + test_generator(); + test_generator(); + test_generator(); +} + +void test() { + test_iterators(); + test_generators(); + + { // Stable (if `I` models `forward_iterator`). + struct OrderedValue { + int value; + int original_order; + bool operator==(const OrderedValue&) const = default; + auto operator<=>(const OrderedValue& rhs) const { return value <=> rhs.value; } + }; + + const std::array in = {{ + {1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8} + }}; + + { // (iterator, sentinel) overload. + std::array out; + std::ranges::sample(in.begin(), in.end(), out.begin(), in.size(), RandGen()); + assert(out == in); + } + + { // (range) overload. + std::array out; + std::ranges::sample(in, out.begin(), in.size(), RandGen()); + assert(out == in); + } + } +} + +int main(int, char**) { + test(); + // Note: `ranges::sample` is not `constexpr`. + + return 0; +} diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.remove/ranges_remove_copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.remove/ranges_remove_copy.pass.cpp index fb8a615f682d5..f31734417bfaf 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.remove/ranges_remove_copy.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.remove/ranges_remove_copy.pass.cpp @@ -30,16 +30,223 @@ #include #include #include +#include #include "almost_satisfies_types.h" +#include "counting_projection.h" #include "test_iterators.h" -// TODO: SFINAE tests. +struct ToPtr { + int* operator()(int) const; +}; + +template +concept HasRemoveCopyIter = + requires(Iter&& iter, Sent&& sent, OutIter&& out, Proj&& proj) { + std::ranges::remove_copy( + std::forward(iter), std::forward(sent), std::forward(out), 0, std::forward(proj)); +}; + +static_assert(HasRemoveCopyIter); + +// !input_iterator +static_assert(!HasRemoveCopyIter); +static_assert(!HasRemoveCopyIter>); + +// !sentinel_for +static_assert(!HasRemoveCopyIter); +static_assert(!HasRemoveCopyIter); + +// !weakly_incrementable +static_assert(!HasRemoveCopyIter); + +// !indirect_binary_predicate, const T*> +static_assert(!HasRemoveCopyIter); + +// !indirectly_copyable +static_assert(!HasRemoveCopyIter); +static_assert(!HasRemoveCopyIter); + +template +concept HasRemoveCopyRange = + requires(Range&& range, OutIter&& out, Proj&& proj) { + std::ranges::remove_copy( + std::forward(range), std::forward(out), 0, std::forward(proj)); +}; + +template +using R = UncheckedRange; + +static_assert(HasRemoveCopyRange>); + +// !input_range +static_assert(!HasRemoveCopyRange); +static_assert(!HasRemoveCopyRange); +static_assert(!HasRemoveCopyRange); +static_assert(!HasRemoveCopyRange); +static_assert(!HasRemoveCopyRange); + +// !weakly_incrementable +static_assert(!HasRemoveCopyRange, WeaklyIncrementableNotMovable>); + +// !indirect_binary_predicate, Proj>, const T*> +static_assert(!HasRemoveCopyRange, int*, ToPtr>); + +// !indirectly_copyable +static_assert(!HasRemoveCopyRange, int*, OutputIteratorNotIndirectlyWritable>); +static_assert(!HasRemoveCopyRange); + +template +struct Data { + std::array input; + std::array expected; + int val; +}; + +template +constexpr void test(Data d) { + using Result = std::ranges::remove_copy_result; + + { // iterator overload + std::array output; + + std::same_as decltype(auto) ret = std::ranges::remove_copy( + InIter(d.input.data()), Sent(InIter(d.input.data() + d.input.size())), OutIter(output.data()), d.val); + + assert(base(ret.in) == d.input.data() + N); + assert(base(ret.out) == output.data() + M); + assert(d.expected == output); + } + + { // range overload + std::array output; + auto range = std::ranges::subrange(InIter(d.input.data()), Sent(InIter(d.input.data() + d.input.size()))); + + std::same_as decltype(auto) ret = + std::ranges::remove_copy(range, OutIter(output.data()), d.val); + + assert(base(ret.in) == d.input.data() + N); + assert(base(ret.out) == output.data() + M); + assert(d.expected == output); + } +} + +template +constexpr void tests() { + // simple test + test({.input = {1, 2, 3, 4, 5, 6}, .expected = {1, 2, 3, 4, 6}, .val = 5}); + // empty range + test({}); + // single element range - match + test({.input = {1}, .expected = {}, .val = 1}); + // single element range - no match + test({.input = {1}, .expected = {1}, .val = 2}); + // two element range - same order + test({.input = {1, 2}, .expected = {1}, .val = 2}); + // two element range - reversed order + test({.input = {1, 2}, .expected = {2}, .val = 1}); + // all elements match + test({.input = {1, 1, 1, 1, 1}, .expected = {}, .val = 1}); + // the relative order of elements isn't changed + test({.input = {1, 2, 3, 2, 3, 4, 2, 5}, .expected = {1, 3, 3, 4, 5}, .val = 2}); +} + +template +constexpr void test_output_iterators() { + tests>(); + tests>(); + tests>(); + tests>(); + tests>(); + tests(); +} + +template +constexpr void test_sentinels() { + test_output_iterators(); + test_output_iterators>(); + test_output_iterators>(); +} constexpr bool test() { - // TODO: main tests. - // TODO: A custom comparator works. - // TODO: A custom projection works. + test_output_iterators, sentinel_wrapper>>(); + test_output_iterators, sized_sentinel>>(); + test_output_iterators, sentinel_wrapper>>(); + test_output_iterators, sized_sentinel>>(); + test_sentinels>(); + test_sentinels>(); + test_sentinels>(); + test_sentinels>(); + test_sentinels(); + + { // check that passing a different type works + struct S { + constexpr operator int() const { return 3; } + }; + + { // iterator overload + int a[] = {1, 2, 3, 4}; + int b[3]; + std::ranges::remove_copy(std::begin(a), std::end(a), std::begin(b), S{}); + } + + { // range overload + int a[] = {1, 2, 3, 4}; + int b[3]; + std::ranges::remove_copy(a, std::begin(b), S{}); + } + } + + { // check that a custom projection works + struct S { + constexpr operator int() const { return 3; } + }; + + { // iterator overload + int a[] = {1, 2, 3, 4}; + int b[3]; + std::ranges::remove_copy(std::begin(a), std::end(a), std::begin(b), S{}); + + } + { // range overload + int a[] = {1, 2, 3, 4}; + int b[3]; + std::ranges::remove_copy(a, std::begin(b), S{}); + } + } + + // Complexity: Exactly last - first applications of the corresponding predicate and any projection. + + { + std::array in{4, 4, 5, 6}; + std::array expected{5, 6}; + + // iterator overload + { + int numberOfProj = 0; + std::array out; + std::ranges::remove_copy( + in.begin(), + in.end(), + out.begin(), + 4, + counting_projection(numberOfProj)); + + assert(numberOfProj == static_cast(in.size())); + + assert(std::ranges::equal(out, expected)); + } + + // range overload + { + int numberOfProj = 0; + std::array out; + std::ranges::remove_copy( + in, out.begin(), 4, counting_projection(numberOfProj)); + assert(numberOfProj == static_cast(in.size())); + assert(std::ranges::equal(out, expected)); + } + } return true; } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.remove/ranges_remove_copy_if.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.remove/ranges_remove_copy_if.pass.cpp index 8e3e46e12192c..3a0d1ea424fd9 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.remove/ranges_remove_copy_if.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.remove/ranges_remove_copy_if.pass.cpp @@ -28,16 +28,264 @@ #include #include #include +#include +#include #include "almost_satisfies_types.h" +#include "counting_predicates.h" +#include "counting_projection.h" #include "test_iterators.h" -// TODO: SFINAE tests. +struct AlwaysTrue { + constexpr bool operator()(auto&&...) const { return true; } +}; + +template < + class I, + class S = sentinel_wrapper>, + class O = int*, + class Pred = AlwaysTrue> +concept HasRemoveCopyIfIter = + requires(I&& iter, S&& sent, O&& out, Pred&& pred) { + std::ranges::remove_copy_if(std::forward(iter), std::forward(sent), + std::forward(out), std::forward(pred)); +}; + +static_assert(HasRemoveCopyIfIter); + +// !input_iterator +static_assert(!HasRemoveCopyIfIter); +static_assert(!HasRemoveCopyIfIter>); + +// !sentinel_for +static_assert(!HasRemoveCopyIfIter); +static_assert(!HasRemoveCopyIfIter); + +// !weakly_incrementable +static_assert(!HasRemoveCopyIfIter); + +// !indirect_unary_predicate> +static_assert(!HasRemoveCopyIfIter); +static_assert(!HasRemoveCopyIfIter); + +// !indirectly_copyable +static_assert(!HasRemoveCopyIfIter); +static_assert(!HasRemoveCopyIfIter); + +template < class R, class O = int*, class Pred = AlwaysTrue, class Proj = std::identity> +concept HasRemoveCopyIfRange = + requires(R&& r, O&& out, Pred&& pred, Proj&& proj) { + std::ranges::remove_copy_if( + std::forward(r), std::forward(out), std::forward(pred), std::forward(proj)); + }; + +template +using R = UncheckedRange; + +static_assert(HasRemoveCopyIfRange>); + +// !input_range +static_assert(!HasRemoveCopyIfRange>); +static_assert(!HasRemoveCopyIfRange>>); + +// !weakly_incrementable +static_assert(!HasRemoveCopyIfRange, WeaklyIncrementableNotMovable>); + +// !indirect_unary_predicate, Proj>> +static_assert(!HasRemoveCopyIfRange, int*, IndirectUnaryPredicateNotPredicate>); +static_assert(!HasRemoveCopyIfRange, int*, IndirectUnaryPredicateNotCopyConstructible>); + +// !indirectly_copyable, O> +static_assert(!HasRemoveCopyIfRange, OutputIteratorNotIndirectlyWritable>); +static_assert(!HasRemoveCopyIfRange, const int*>); + +template class SentWrapper, std::size_t N1, std::size_t N2, class Pred> +constexpr void testRemoveCopyIfImpl(std::array in, std::array expected, Pred pred) { + using Sent = SentWrapper; + using Result = std::ranges::remove_copy_if_result; + + // iterator overload + { + std::array out; + std::same_as decltype(auto) result = + std::ranges::remove_copy_if(InIter{in.data()}, Sent{InIter{in.data() + in.size()}}, OutIter{out.data()}, pred); + assert(std::ranges::equal(out, expected)); + assert(base(result.in) == in.data() + in.size()); + assert(base(result.out) == out.data() + out.size()); + } + + // range overload + { + std::array out; + std::ranges::subrange r{InIter{in.data()}, Sent{InIter{in.data() + in.size()}}}; + std::same_as decltype(auto) result = + std::ranges::remove_copy_if(r, OutIter{out.data()}, pred); + assert(std::ranges::equal(out, expected)); + assert(base(result.in) == in.data() + in.size()); + assert(base(result.out) == out.data() + out.size()); + } +} + +template class SentWrapper> +constexpr void testImpl() { + // remove multiple elements + { + std::array in{1, 2, 3, 2, 1}; + std::array expected{1, 3, 1}; + auto pred = [](int i) { return i == 2; }; + testRemoveCopyIfImpl(in, expected, pred); + } + + // remove single elements + { + std::array in{1, 2, 3, 2, 1}; + std::array expected{1, 2, 2, 1}; + auto pred = [](int i) { return i == 3; }; + testRemoveCopyIfImpl(in, expected, pred); + } + + // nothing removed + { + std::array in{1, 2, 3, 2, 1}; + std::array expected{1, 2, 3, 2, 1}; + auto pred = [](int) { return false; }; + testRemoveCopyIfImpl(in, expected, pred); + } + + // all removed + { + std::array in{1, 2, 3, 2, 1}; + std::array expected{}; + auto pred = [](int) { return true; }; + testRemoveCopyIfImpl(in, expected, pred); + } + + // remove first + { + std::array in{1, 2, 3, 2}; + std::array expected{2, 3, 2}; + auto pred = [](int i) { return i < 2; }; + testRemoveCopyIfImpl(in, expected, pred); + } + + // remove last + { + std::array in{1, 2, 3, 2, 5}; + std::array expected{1, 2, 3, 2}; + auto pred = [](int i) { return i > 3; }; + testRemoveCopyIfImpl(in, expected, pred); + } + + // stable + { + std::array in{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::array expected{6, 7, 8, 9, 10}; + auto pred = [](int i) { return i < 6; }; + testRemoveCopyIfImpl(in, expected, pred); + } + + // empty range + { + std::array in{}; + std::array expected{}; + auto pred = [](int) { return false; }; + testRemoveCopyIfImpl(in, expected, pred); + } + + // one element range + { + std::array in{1}; + std::array expected{}; + auto pred = [](int i) { return i == 1; }; + testRemoveCopyIfImpl(in, expected, pred); + } +} + +template class SentWrapper> +constexpr void withAllPermutationsOfInIter() { + testImpl, OutIter, sentinel_wrapper>(); + testImpl, OutIter, SentWrapper>(); + testImpl, OutIter, SentWrapper>(); + testImpl, OutIter, SentWrapper>(); + testImpl, OutIter, SentWrapper>(); + testImpl(); +} + +template