diff --git a/bolt/lib/Core/HashUtilities.cpp b/bolt/lib/Core/HashUtilities.cpp index dfbbdb8a968fe..6bdf30460f340 100644 --- a/bolt/lib/Core/HashUtilities.cpp +++ b/bolt/lib/Core/HashUtilities.cpp @@ -145,7 +145,7 @@ std::string hashBlockLoose(BinaryContext &BC, const BinaryBasicBlock &BB) { continue; } - std::string Mnemonic = BC.InstPrinter->getMnemonic(&Inst).first; + std::string Mnemonic = BC.InstPrinter->getMnemonic(Inst).first; llvm::erase_if(Mnemonic, [](unsigned char ch) { return std::isspace(ch); }); Opcodes.insert(Mnemonic); } diff --git a/clang-tools-extra/clang-query/Query.cpp b/clang-tools-extra/clang-query/Query.cpp index 282d136aff721..382aa5d6fe25e 100644 --- a/clang-tools-extra/clang-query/Query.cpp +++ b/clang-tools-extra/clang-query/Query.cpp @@ -44,7 +44,9 @@ bool HelpQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { " set bind-root (true|false) " "Set whether to bind the root matcher to \"root\".\n" " set print-matcher (true|false) " - "Set whether to print the current matcher,\n" + "Set whether to print the current matcher.\n" + " set enable-profile (true|false) " + "Set whether to enable matcher profiling.\n" " set traversal " "Set traversal kind of clang-query session. Available kinds are:\n" " AsIs " @@ -82,10 +84,24 @@ namespace { struct CollectBoundNodes : MatchFinder::MatchCallback { std::vector &Bindings; - CollectBoundNodes(std::vector &Bindings) : Bindings(Bindings) {} + StringRef Unit; + CollectBoundNodes(std::vector &Bindings, StringRef Unit) + : Bindings(Bindings), Unit(Unit) {} void run(const MatchFinder::MatchResult &Result) override { Bindings.push_back(Result.Nodes); } + StringRef getID() const override { return Unit; } +}; + +struct QueryProfiler { + llvm::StringMap Records; + + ~QueryProfiler() { + llvm::TimerGroup TG("clang-query", "clang-query matcher profiling", + Records); + TG.print(llvm::errs()); + llvm::errs().flush(); + } }; } // namespace @@ -93,8 +109,19 @@ struct CollectBoundNodes : MatchFinder::MatchCallback { bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { unsigned MatchCount = 0; + std::optional Profiler; + if (QS.EnableProfile) + Profiler.emplace(); + for (auto &AST : QS.ASTs) { - MatchFinder Finder; + ast_matchers::MatchFinder::MatchFinderOptions FinderOptions; + std::optional> Records; + if (QS.EnableProfile) { + Records.emplace(); + FinderOptions.CheckProfiling.emplace(*Records); + } + + MatchFinder Finder(FinderOptions); std::vector Matches; DynTypedMatcher MaybeBoundMatcher = Matcher; if (QS.BindRoot) { @@ -102,7 +129,8 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { if (M) MaybeBoundMatcher = *M; } - CollectBoundNodes Collect(Matches); + StringRef OrigSrcName = AST->getOriginalSourceFileName(); + CollectBoundNodes Collect(Matches, OrigSrcName); if (!Finder.addDynamicMatcher(MaybeBoundMatcher, &Collect)) { OS << "Not a valid top-level matcher.\n"; return false; @@ -111,6 +139,8 @@ bool MatchQuery::run(llvm::raw_ostream &OS, QuerySession &QS) const { ASTContext &Ctx = AST->getASTContext(); Ctx.getParentMapContext().setTraversalKind(QS.TK); Finder.matchAST(Ctx); + if (QS.EnableProfile) + Profiler->Records[OrigSrcName] += (*Records)[OrigSrcName]; if (QS.PrintMatcher) { SmallVector Lines; diff --git a/clang-tools-extra/clang-query/QueryParser.cpp b/clang-tools-extra/clang-query/QueryParser.cpp index 97cb264a611af..1d5ec281defd4 100644 --- a/clang-tools-extra/clang-query/QueryParser.cpp +++ b/clang-tools-extra/clang-query/QueryParser.cpp @@ -182,6 +182,7 @@ enum ParsedQueryVariable { PQV_Output, PQV_BindRoot, PQV_PrintMatcher, + PQV_EnableProfile, PQV_Traversal }; @@ -285,6 +286,7 @@ QueryRef QueryParser::doParse() { .Case("output", PQV_Output) .Case("bind-root", PQV_BindRoot) .Case("print-matcher", PQV_PrintMatcher) + .Case("enable-profile", PQV_EnableProfile) .Case("traversal", PQV_Traversal) .Default(PQV_Invalid); if (VarStr.empty()) @@ -303,6 +305,9 @@ QueryRef QueryParser::doParse() { case PQV_PrintMatcher: Q = parseSetBool(&QuerySession::PrintMatcher); break; + case PQV_EnableProfile: + Q = parseSetBool(&QuerySession::EnableProfile); + break; case PQV_Traversal: Q = parseSetTraversalKind(&QuerySession::TK); break; diff --git a/clang-tools-extra/clang-query/QuerySession.h b/clang-tools-extra/clang-query/QuerySession.h index 31a4900e26190..c7d5a64c33200 100644 --- a/clang-tools-extra/clang-query/QuerySession.h +++ b/clang-tools-extra/clang-query/QuerySession.h @@ -26,7 +26,7 @@ class QuerySession { QuerySession(llvm::ArrayRef> ASTs) : ASTs(ASTs), PrintOutput(false), DiagOutput(true), DetailedASTOutput(false), BindRoot(true), PrintMatcher(false), - Terminate(false), TK(TK_AsIs) {} + EnableProfile(false), Terminate(false), TK(TK_AsIs) {} llvm::ArrayRef> ASTs; @@ -36,6 +36,7 @@ class QuerySession { bool BindRoot; bool PrintMatcher; + bool EnableProfile; bool Terminate; TraversalKind TK; diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index 295ccd26a4045..761f96846d453 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -504,6 +504,16 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R, P.field("offsetEncoding"))) return false; } + + if (auto *Experimental = O->getObject("experimental")) { + if (auto *TextDocument = Experimental->getObject("textDocument")) { + if (auto *Completion = TextDocument->getObject("completion")) { + if (auto EditsNearCursor = Completion->getBoolean("editsNearCursor")) + R.CompletionFixes |= *EditsNearCursor; + } + } + } + return true; } diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp index a87238e0c0938..2ac123246a4cb 100644 --- a/clang-tools-extra/clangd/TidyProvider.cpp +++ b/clang-tools-extra/clangd/TidyProvider.cpp @@ -46,7 +46,7 @@ class DotClangTidyCache : private FileCache { [this](std::optional Data) { Value.reset(); if (Data && !Data->empty()) { - tidy::DiagCallback Diagnostics = [](const llvm::SMDiagnostic &D) { + auto Diagnostics = [](const llvm::SMDiagnostic &D) { switch (D.getKind()) { case llvm::SourceMgr::DK_Error: elog("tidy-config error at {0}:{1}:{2}: {3}", D.getFilename(), @@ -149,7 +149,7 @@ static void mergeCheckList(std::optional &Checks, *Checks = llvm::join_items(",", *Checks, List); } -TidyProviderRef provideEnvironment() { +TidyProvider provideEnvironment() { static const std::optional User = [] { std::optional Ret = llvm::sys::Process::GetEnv("USER"); #ifdef _WIN32 @@ -167,7 +167,7 @@ TidyProviderRef provideEnvironment() { return [](tidy::ClangTidyOptions &, llvm::StringRef) {}; } -TidyProviderRef provideDefaultChecks() { +TidyProvider provideDefaultChecks() { // These default checks are chosen for: // - low false-positive rate // - providing a lot of value @@ -251,7 +251,7 @@ TidyProvider disableUnusableChecks(llvm::ArrayRef ExtraBadChecks) { }; } -TidyProviderRef provideClangdConfig() { +TidyProvider provideClangdConfig() { return [](tidy::ClangTidyOptions &Opts, llvm::StringRef) { const auto &CurTidyConfig = Config::current().Diagnostics.ClangTidy; if (!CurTidyConfig.Checks.empty()) diff --git a/clang-tools-extra/clangd/TidyProvider.h b/clang-tools-extra/clangd/TidyProvider.h index 7d849d340f3aa..8424f5e62d448 100644 --- a/clang-tools-extra/clangd/TidyProvider.h +++ b/clang-tools-extra/clangd/TidyProvider.h @@ -30,11 +30,11 @@ using TidyProviderRef = llvm::function_ref Providers); /// Provider that just sets the defaults. -TidyProviderRef provideEnvironment(); +TidyProvider provideEnvironment(); /// Provider that will enable a nice set of default checks if none are /// specified. -TidyProviderRef provideDefaultChecks(); +TidyProvider provideDefaultChecks(); /// Provider the enables a specific set of checks and warnings as errors. TidyProvider addTidyChecks(llvm::StringRef Checks, @@ -51,7 +51,7 @@ disableUnusableChecks(llvm::ArrayRef ExtraBadChecks = {}); TidyProvider provideClangTidyFiles(ThreadsafeFS &); // Provider that uses clangd configuration files. -TidyProviderRef provideClangdConfig(); +TidyProvider provideClangdConfig(); tidy::ClangTidyOptions getTidyOptionsForFile(TidyProviderRef Provider, llvm::StringRef Filename); diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index b34aba603b530..4fd11307857ff 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -2238,7 +2238,10 @@ prepareCallHierarchy(ParsedAST &AST, Position Pos, PathRef TUPath) { for (const NamedDecl *Decl : getDeclAtPosition(AST, *Loc, {})) { if (!(isa(Decl) && cast(Decl)->isFunctionOrMethod()) && - Decl->getKind() != Decl::Kind::FunctionTemplate) + Decl->getKind() != Decl::Kind::FunctionTemplate && + !(Decl->getKind() == Decl::Kind::Var && + !cast(Decl)->isLocalVarDecl()) && + Decl->getKind() != Decl::Kind::Field) continue; if (auto CHI = declToCallHierarchyItem(*Decl, AST.tuPath())) Result.emplace_back(std::move(*CHI)); diff --git a/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp b/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp index 6fa76aa6094bf..b2278ff12735d 100644 --- a/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp +++ b/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp @@ -446,6 +446,51 @@ TEST(CallHierarchy, CallInLocalVarDecl) { AllOf(from(withName("caller3")), fromRanges(Source.range("call3"))))); } +TEST(CallHierarchy, HierarchyOnField) { + // Tests that the call hierarchy works on fields. + Annotations Source(R"cpp( + struct Vars { + int v^ar1 = 1; + }; + void caller() { + Vars values; + values.$Callee[[var1]]; + } + )cpp"); + TestTU TU = TestTU::withCode(Source.code()); + auto AST = TU.build(); + auto Index = TU.index(); + + std::vector Items = + prepareCallHierarchy(AST, Source.point(), testPath(TU.Filename)); + ASSERT_THAT(Items, ElementsAre(withName("var1"))); + auto IncomingLevel1 = incomingCalls(Items[0], Index.get()); + ASSERT_THAT(IncomingLevel1, + ElementsAre(AllOf(from(withName("caller")), + fromRanges(Source.range("Callee"))))); +} + +TEST(CallHierarchy, HierarchyOnVar) { + // Tests that the call hierarchy works on non-local variables. + Annotations Source(R"cpp( + int v^ar = 1; + void caller() { + $Callee[[var]]; + } + )cpp"); + TestTU TU = TestTU::withCode(Source.code()); + auto AST = TU.build(); + auto Index = TU.index(); + + std::vector Items = + prepareCallHierarchy(AST, Source.point(), testPath(TU.Filename)); + ASSERT_THAT(Items, ElementsAre(withName("var"))); + auto IncomingLevel1 = incomingCalls(Items[0], Index.get()); + ASSERT_THAT(IncomingLevel1, + ElementsAre(AllOf(from(withName("caller")), + fromRanges(Source.range("Callee"))))); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 51ba157ab05de..abcdcc25705bf 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -98,7 +98,7 @@ Improvements to clang-doc Improvements to clang-query --------------------------- -The improvements are... +- Added `set enable-profile true/false` command for basic matcher profiling. Improvements to clang-tidy -------------------------- diff --git a/clang/Maintainers.rst b/clang/Maintainers.rst index 896b463d882d0..26495f3d87794 100644 --- a/clang/Maintainers.rst +++ b/clang/Maintainers.rst @@ -68,6 +68,15 @@ Sema | Sirraide | aeternalmail\@gmail.com (email), Sirraide (GitHub), Ætérnal (Discord), Sirraide (Discourse) +| Mariya Podchishchaeva +| mariya.podchishchaeva\@intel.com (email), Fznamznon (GitHub), fznamznon (Discord), Fznamznon (Discourse) + + +Recovery AST +~~~~~~~~~~~~ +| Haojian Wu +| hokein.wu\@gmail.com (email), hokein (Phabricator), hokein (GitHub), hokein (Discourse) + Experimental new constant interpreter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -132,6 +141,15 @@ Compiler options | jan_svoboda\@apple.com (email), jansvoboda11 (Phabricator), jansvoboda11 (GitHub) +API Notes +~~~~~~~~~~~~~~~~ +| Egor Zhdan +| e_zhdan\@apple.com (email), egorzhdan (GitHub), egor.zhdan (Discourse) + +| Saleem Abdulrasool +| compnerd\@compnerd.org (email), compnerd (GitHub), compnerd (Discourse) + + OpenBSD driver ~~~~~~~~~~~~~~ | Brad Smith @@ -144,6 +162,12 @@ Driver parts not covered by someone else | i\@maskray.me (email), MaskRay (Phabricator), MaskRay (GitHub) +Constant Expressions +~~~~~~~~~~~~~~~~~~~~ +| Mariya Podchishchaeva +| mariya.podchishchaeva\@intel.com (email), Fznamznon (GitHub), fznamznon (Discord), Fznamznon (Discourse) + + Tools ----- These maintainers are responsible for user-facing tools under the Clang @@ -295,6 +319,21 @@ SYCL conformance | alexey.bader\@intel.com (email), bader (Phabricator), bader (GitHub) +HLSL conformance +~~~~~~~~~~~~~~~~ +| Chris Bieneman +| chris.bieneman\@gmail.com (email), llvm-beanz (GitHub), beanz (Discord), beanz (Discourse) + + +Issue Triage +~~~~~~~~~~~~ +| Shafik Yaghmour +| shafik.yaghmour\@intel.com (email), shafik (GitHub), shafik.yaghmour (Discord), shafik (Discourse) + +| hstk30 +| hanwei62\@huawei.com (email), hstk30-hw (GitHub), hstk30(Discord), hstk30 (Discourse) + + Inactive Maintainers ==================== The following people have graciously spent time performing maintainership diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst index dcefa6810dac6..d20c4f9b5ba84 100644 --- a/clang/docs/APINotes.rst +++ b/clang/docs/APINotes.rst @@ -169,6 +169,20 @@ declaration kind), all of which are optional: to ``SWIFT_RETURNS_INDEPENDENT_VALUE``) or ``computed_property`` (equivalent to ``SWIFT_COMPUTED_PROPERTY``). + :: + + Tags: + - Name: OwnedStorage + SwiftImportAs: owned + +:SwiftRetainOp, SwiftReleaseOp: + + Controls the lifetime operations of a class which uses custom reference + counting. The class must be annotated as a reference type using + ``SwiftImportAs: reference``. The values are either names of global functions, + each taking a single parameter of a pointer type, or ``immortal`` for a type + that is considered alive for the duration of the program. + :: Tags: @@ -176,6 +190,10 @@ declaration kind), all of which are optional: SwiftImportAs: reference SwiftReleaseOp: RCRelease SwiftRetainOp: RCRetain + - Name: ImmortalSingleton + SwiftImportAs: reference + SwiftReleaseOp: immortal + SwiftRetainOp: immortal :SwiftCopyable: diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 9ef1fd5f36d1d..dc34094b5053a 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2259,7 +2259,7 @@ the configuration (without a prefix: ``Auto``). **BraceWrapping** (``BraceWrappingFlags``) :versionbadge:`clang-format 3.8` :ref:`¶ ` Control of individual brace wrapping cases. - If ``BreakBeforeBraces`` is set to ``BS_Custom``, use this to specify how + If ``BreakBeforeBraces`` is set to ``Custom``, use this to specify how each individual brace case should be handled. Otherwise, this is ignored. .. code-block:: yaml diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 10232ff41da15..f00422cd8b804 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -3979,9 +3979,9 @@ standard: - ``4`` - to nearest, ties away from zero The effect of passing some other value to ``__builtin_flt_rounds`` is implementation-defined. ``__builtin_set_flt_rounds`` is currently only supported -to work on x86, x86_64, Arm and AArch64 targets. These builtins read and modify -the floating-point environment, which is not always allowed and may have unexpected -behavior. Please see the section on `Accessing the floating point environment `_ for more information. +to work on x86, x86_64, powerpc, powerpc64, Arm and AArch64 targets. These builtins +read and modify the floating-point environment, which is not always allowed and may +have unexpected behavior. Please see the section on `Accessing the floating point environment `_ for more information. String builtins --------------- diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 1372e49dfac03..4e555914caee8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -559,6 +559,7 @@ Bug Fixes to C++ Support - Fixed an assertion failure in debug mode, and potential crashes in release mode, when diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter. - Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326) +- Fixed a crash when mixture of designated and non-designated initializers in union. (#GH113855) - Fixed an issue deducing non-type template arguments of reference type. (#GH73460) - Fixed an issue in constraint evaluation, where type constraints on the lambda expression containing outer unexpanded parameters were not correctly expanded. (#GH101754) @@ -871,6 +872,13 @@ Sanitizers This new flag should allow those projects to enable integer sanitizers with less noise. +- ``-fsanitize=signed-integer-overflow``, ``-fsanitize=unsigned-integer-overflow``, + ``-fsanitize=implicit-signed-integer-truncation``, ``-fsanitize=implicit-unsigned-integer-truncation``, + ``-fsanitize=enum`` now properly support the + "type" prefix within `Sanitizer Special Case Lists (SSCL) + `_. See that link + for examples. + Python Binding Changes ---------------------- - Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``. diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst index c7fb0fa3f8a82..5c88c2976e861 100644 --- a/clang/docs/SanitizerSpecialCaseList.rst +++ b/clang/docs/SanitizerSpecialCaseList.rst @@ -15,9 +15,10 @@ file at compile-time. Goal and usage ============== -Users of sanitizer tools, such as :doc:`AddressSanitizer`, :doc:`ThreadSanitizer` -or :doc:`MemorySanitizer` may want to disable or alter some checks for -certain source-level entities to: +Users of sanitizer tools, such as :doc:`AddressSanitizer`, +:doc:`HardwareAssistedAddressSanitizerDesign`, :doc:`ThreadSanitizer`, +:doc:`MemorySanitizer` or :doc:`UndefinedBehaviorSanitizer` may want to disable +or alter some checks for certain source-level entities to: * speedup hot function, which is known to be correct; * ignore a function that does some low-level magic (e.g. walks through the @@ -48,6 +49,60 @@ Example $ clang -fsanitize=address -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out # No error report here. +Usage with UndefinedBehaviorSanitizer +===================================== + +``unsigned-integer-overflow``, ``signed-integer-overflow``, +``implicit-signed-integer-truncation``, +``implicit-unsigned-integer-truncation``, and ``enum`` sanitizers support the +ability to adjust instrumentation based on type. + +By default, supported sanitizers will have their instrumentation disabled for +types specified within an ignorelist. + +.. code-block:: bash + + $ cat foo.c + void foo() { + int a = 2147483647; // INT_MAX + ++a; // Normally, an overflow with -fsanitize=signed-integer-overflow + } + $ cat ignorelist.txt + [signed-integer-overflow] + type:int + $ clang -fsanitize=signed-integer-overflow -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out + # no signed-integer-overflow error + +For example, supplying the above ``ignorelist.txt`` to +``-fsanitize-ignorelist=ignorelist.txt`` disables overflow sanitizer +instrumentation for arithmetic operations containing values of type ``int``. + +The ``=sanitize`` category is also supported. Any types assigned to the +``sanitize`` category will have their sanitizer instrumentation remain. If the +same type appears within or across ignorelists with different categories the +``sanitize`` category takes precedence -- regardless of order. + +With this, one may disable instrumentation for some or all types and +specifically allow instrumentation for one or many types -- including types +created via ``typedef``. This is a way to achieve a sort of "allowlist" for +supported sanitizers. + +.. code-block:: bash + + $ cat ignorelist.txt + [implicit-signed-integer-truncation] + type:* + type:T=sanitize + + $ cat foo.c + typedef char T; + typedef char U; + void foo(int toobig) { + T a = toobig; // instrumented + U b = toobig; // not instrumented + char c = toobig; // also not instrumented + } + Format ====== diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index da4ec712dc44e..8a9e2076a875f 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -3459,8 +3459,8 @@ Raw pointers and references to an object which supports CheckedPtr or CheckedRef .. code-block:: cpp struct CheckableObj { - void incrementPtrCount() {} - void decrementPtrCount() {} + void incrementCheckedPtrCount() {} + void decrementCheckedPtrCount() {} }; struct Foo { diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 89889910d1a07..6327b7d75486f 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -425,6 +425,14 @@ class ParamInfo : public VariableInfo { LLVM_PREFERRED_TYPE(bool) unsigned NoEscape : 1; + /// Whether lifetimebound was specified. + LLVM_PREFERRED_TYPE(bool) + unsigned LifetimeboundSpecified : 1; + + /// Whether the this parameter has the 'lifetimebound' attribute. + LLVM_PREFERRED_TYPE(bool) + unsigned Lifetimebound : 1; + /// A biased RetainCountConventionKind, where 0 means "unspecified". /// /// Only relevant for out-parameters. @@ -432,7 +440,9 @@ class ParamInfo : public VariableInfo { public: ParamInfo() - : NoEscapeSpecified(false), NoEscape(false), RawRetainCountConvention() {} + : NoEscapeSpecified(false), NoEscape(false), + LifetimeboundSpecified(false), Lifetimebound(false), + RawRetainCountConvention() {} std::optional isNoEscape() const { if (!NoEscapeSpecified) @@ -444,6 +454,16 @@ class ParamInfo : public VariableInfo { NoEscape = Value.value_or(false); } + std::optional isLifetimebound() const { + if (!LifetimeboundSpecified) + return std::nullopt; + return Lifetimebound; + } + void setLifetimebound(std::optional Value) { + LifetimeboundSpecified = Value.has_value(); + Lifetimebound = Value.value_or(false); + } + std::optional getRetainCountConvention() const { if (!RawRetainCountConvention) return std::nullopt; @@ -463,6 +483,11 @@ class ParamInfo : public VariableInfo { NoEscape = RHS.NoEscape; } + if (!LifetimeboundSpecified && RHS.LifetimeboundSpecified) { + LifetimeboundSpecified = true; + Lifetimebound = RHS.Lifetimebound; + } + if (!RawRetainCountConvention) RawRetainCountConvention = RHS.RawRetainCountConvention; @@ -478,6 +503,8 @@ inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) { return static_cast(LHS) == RHS && LHS.NoEscapeSpecified == RHS.NoEscapeSpecified && LHS.NoEscape == RHS.NoEscape && + LHS.LifetimeboundSpecified == RHS.LifetimeboundSpecified && + LHS.Lifetimebound == RHS.Lifetimebound && LHS.RawRetainCountConvention == RHS.RawRetainCountConvention; } diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 4c1455a3e1bbf..1e8101f60b03f 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -23,6 +23,7 @@ #include "clang/AST/ExternalASTSource.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/RawCommentList.h" +#include "clang/AST/SYCLKernelInfo.h" #include "clang/AST/TemplateName.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/PartialDiagnostic.h" @@ -838,6 +839,9 @@ class ASTContext : public RefCountedBase { const NoSanitizeList &getNoSanitizeList() const { return *NoSanitizeL; } + bool isTypeIgnoredBySanitizer(const SanitizerMask &Mask, + const QualType &Ty) const; + const XRayFunctionFilter &getXRayFilter() const { return *XRayFilter; } @@ -1236,6 +1240,11 @@ class ASTContext : public RefCountedBase { /// in device compilation. llvm::DenseSet CUDAImplicitHostDeviceFunUsedByDevice; + /// Map of SYCL kernels indexed by the unique type used to name the kernel. + /// Entries are not serialized but are recreated on deserialization of a + /// sycl_kernel_entry_point attributed function declaration. + llvm::DenseMap SYCLKernels; + /// For capturing lambdas with an explicit object parameter whose type is /// derived from the lambda type, we need to perform derived-to-base /// conversion so we can access the captures; the cast paths for that @@ -3337,6 +3346,14 @@ class ASTContext : public RefCountedBase { void getFunctionFeatureMap(llvm::StringMap &FeatureMap, GlobalDecl GD) const; + /// Generates and stores SYCL kernel metadata for the provided + /// SYCL kernel entry point function. The provided function must have + /// an attached sycl_kernel_entry_point attribute that specifies a unique + /// type for the name of a SYCL kernel. Callers are required to detect + /// conflicting SYCL kernel names and issue a diagnostic prior to calling + /// this function. + void registerSYCLEntryPointFunction(FunctionDecl *FD); + //===--------------------------------------------------------------------===// // Statistics //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 7ff35d73df599..8c39ef3d5a9fa 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -737,7 +737,7 @@ class DeclaratorDecl : public ValueDecl { // qualifier, to be used for the (uncommon) case of out-of-line declarations // and constrained function decls. struct ExtInfo : public QualifierInfo { - TypeSourceInfo *TInfo; + TypeSourceInfo *TInfo = nullptr; Expr *TrailingRequiresClause = nullptr; }; diff --git a/clang/include/clang/AST/SYCLKernelInfo.h b/clang/include/clang/AST/SYCLKernelInfo.h new file mode 100644 index 0000000000000..55dba1f8e31fd --- /dev/null +++ b/clang/include/clang/AST/SYCLKernelInfo.h @@ -0,0 +1,41 @@ +//===--- SYCLKernelInfo.h --- Information about SYCL kernels --------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares types used to describe SYCL kernels. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_SYCLKERNELINFO_H +#define LLVM_CLANG_AST_SYCLKERNELINFO_H + +#include "clang/AST/Decl.h" +#include "clang/AST/Type.h" + +namespace clang { + +class SYCLKernelInfo { +public: + SYCLKernelInfo(CanQualType KernelNameType, + const FunctionDecl *KernelEntryPointDecl) + : KernelNameType(KernelNameType), + KernelEntryPointDecl(KernelEntryPointDecl) {} + + CanQualType getKernelNameType() const { return KernelNameType; } + + const FunctionDecl *getKernelEntryPointDecl() const { + return KernelEntryPointDecl; + } + +private: + CanQualType KernelNameType; + const FunctionDecl *KernelEntryPointDecl; +}; + +} // namespace clang + +#endif // LLVM_CLANG_AST_SYCLKERNELINFO_H diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 156fbd1c4442e..fbad11b376e7e 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -407,7 +407,8 @@ def MicrosoftExt : LangOpt<"MicrosoftExt">; def Borland : LangOpt<"Borland">; def CUDA : LangOpt<"CUDA">; def HIP : LangOpt<"HIP">; -def SYCL : LangOpt<"SYCLIsDevice">; +def SYCLHost : LangOpt<"SYCLIsHost">; +def SYCLDevice : LangOpt<"SYCLIsDevice">; def COnly : LangOpt<"", "!LangOpts.CPlusPlus">; def CPlusPlus : LangOpt<"CPlusPlus">; def OpenCL : LangOpt<"OpenCL">; @@ -1493,14 +1494,23 @@ def : MutualExclusions<[CUDAConstant, CUDAShared, HIPManaged]>; def SYCLKernel : InheritableAttr { let Spellings = [Clang<"sycl_kernel">]; let Subjects = SubjectList<[FunctionTmpl]>; - let LangOpts = [SYCL]; + let LangOpts = [SYCLDevice]; let Documentation = [SYCLKernelDocs]; } +def SYCLKernelEntryPoint : InheritableAttr { + let Spellings = [Clang<"sycl_kernel_entry_point">]; + let Args = [TypeArgument<"KernelName">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let TemplateDependent = 1; + let LangOpts = [SYCLHost, SYCLDevice]; + let Documentation = [SYCLKernelEntryPointDocs]; +} + def SYCLSpecialClass: InheritableAttr { let Spellings = [Clang<"sycl_special_class">]; let Subjects = SubjectList<[CXXRecord]>; - let LangOpts = [SYCL]; + let LangOpts = [SYCLDevice]; let Documentation = [SYCLSpecialClassDocs]; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b497cce37625c..ed251b0a74c39 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -455,6 +455,180 @@ The SYCL kernel in the previous code sample meets these expectations. }]; } +def SYCLKernelEntryPointDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``sycl_kernel_entry_point`` attribute facilitates the generation of an +offload kernel entry point, sometimes called a SYCL kernel caller function, +suitable for invoking a SYCL kernel on an offload device. The attribute is +intended for use in the implementation of SYCL kernel invocation functions +like the ``single_task`` and ``parallel_for`` member functions of the +``sycl::handler`` class specified in section 4.9.4, "Command group ``handler`` +class", of the SYCL 2020 specification. + +The attribute requires a single type argument that specifies a class type that +meets the requirements for a SYCL kernel name as described in section 5.2, +"Naming of kernels", of the SYCL 2020 specification. A unique kernel name type +is required for each function declared with the attribute. The attribute may +not first appear on a declaration that follows a definition of the function. + +The attribute only appertains to functions and only those that meet the +following requirements. + +* Has a ``void`` return type. +* Is not a non-static member function, constructor, or destructor. +* Is not a C variadic function. +* Is not a coroutine. +* Is not defined as deleted or as defaulted. +* Is not declared with the ``constexpr`` or ``consteval`` specifiers. +* Is not declared with the ``[[noreturn]]`` attribute. + +Use in the implementation of a SYCL kernel invocation function might look as +follows. + +.. code-block:: c++ + + namespace sycl { + class handler { + template + [[ clang::sycl_kernel_entry_point(KernelNameType) ]] + static void kernel_entry_point(KernelType kernel) { + kernel(); + } + + public: + template + void single_task(KernelType kernel) { + // Call kernel_entry_point() to trigger generation of an offload + // kernel entry point. + kernel_entry_point(kernel); + // Call functions appropriate for the desired offload backend + // (OpenCL, CUDA, HIP, Level Zero, etc...). + } + }; + } // namespace sycl + +A SYCL kernel is a callable object of class type that is constructed on a host, +often via a lambda expression, and then passed to a SYCL kernel invocation +function to be executed on an offload device. A SYCL kernel invocation function +is responsible for copying the provided SYCL kernel object to an offload +device and initiating a call to it. The SYCL kernel object and its data members +constitute the parameters of an offload kernel. + +A SYCL kernel type is required to satisfy the device copyability requirements +specified in section 3.13.1, "Device copyable", of the SYCL 2020 specification. +Additionally, any data members of the kernel object type are required to satisfy +section 4.12.4, "Rules for parameter passing to kernels". For most types, these +rules require that the type is trivially copyable. However, the SYCL +specification mandates that certain special SYCL types, such as +``sycl::accessor`` and ``sycl::stream`` be device copyable even if they are not +trivially copyable. These types require special handling because they cannot +be copied to device memory as if by ``memcpy()``. Additionally, some offload +backends, OpenCL for example, require objects of some of these types to be +passed as individual arguments to the offload kernel. + +An offload kernel consists of an entry point function that declares the +parameters of the offload kernel and the set of all functions and variables that +are directly or indirectly used by the entry point function. + +A SYCL kernel invocation function invokes a SYCL kernel on a device by +performing the following tasks (likely with the help of an offload backend +like OpenCL): + +#. Identifying the offload kernel entry point to be used for the SYCL kernel. + +#. Deconstructing the SYCL kernel object, if necessary, to produce the set of + offload kernel arguments required by the offload kernel entry point. + +#. Copying the offload kernel arguments to device memory. + +#. Initiating execution of the offload kernel entry point. + +The offload kernel entry point for a SYCL kernel performs the following tasks: + +#. Reconstituting the SYCL kernel object, if necessary, using the offload + kernel parameters. + +#. Calling the ``operator()`` member function of the (reconstituted) SYCL kernel + object. + +The ``sycl_kernel_entry_point`` attribute automates generation of an offload +kernel entry point that performs those latter tasks. The parameters and body of +a function declared with the ``sycl_kernel_entry_point`` attribute specify a +pattern from which the parameters and body of the entry point function are +derived. Consider the following call to a SYCL kernel invocation function. + +.. code-block:: c++ + + struct S { int i; }; + void f(sycl::handler &handler, sycl::stream &sout, S s) { + handler.single_task([=] { + sout << "The value of s.i is " << s.i << "\n"; + }); + } + +The SYCL kernel object is the result of the lambda expression. It has two +data members corresponding to the captures of ``sout`` and ``s``. Since one +of these data members corresponds to a special SYCL type that must be passed +individually as an offload kernel parameter, it is necessary to decompose the +SYCL kernel object into its constituent parts; the offload kernel will have +two kernel parameters. Given a SYCL implementation that uses a +``sycl_kernel_entry_point`` attributed function like the one shown above, an +offload kernel entry point function will be generated that looks approximately +as follows. + +.. code-block:: c++ + + void sycl-kernel-caller-for-KN(sycl::stream sout, S s) { + kernel-type kernel = { sout, s ); + kernel(); + } + +There are a few items worthy of note: + +#. The name of the generated function incorporates the SYCL kernel name, + ``KN``, that was passed as the ``KernelNameType`` template parameter to + ``kernel_entry_point()`` and provided as the argument to the + ``sycl_kernel_entry_point`` attribute. There is a one-to-one correspondence + between SYCL kernel names and offload kernel entry points. + +#. The SYCL kernel is a lambda closure type and therefore has no name; + ``kernel-type`` is substituted above and corresponds to the ``KernelType`` + template parameter deduced in the call to ``kernel_entry_point()``. + Lambda types cannot be declared and initialized using the aggregate + initialization syntax used above, but the intended behavior should be clear. + +#. ``S`` is a device copyable type that does not directly or indirectly contain + a data member of a SYCL special type. It therefore does not need to be + decomposed into its constituent members to be passed as a kernel argument. + +#. The depiction of the ``sycl::stream`` parameter as a single self contained + kernel parameter is an oversimplification. SYCL special types may require + additional decomposition such that the generated function might have three + or more parameters depending on how the SYCL library implementation defines + these types. + +#. The call to ``kernel_entry_point()`` has no effect other than to trigger + emission of the entry point function. The statments that make up the body + of the function are not executed when the function is called; they are + only used in the generation of the entry point function. + +It is not necessary for a function declared with the ``sycl_kernel_entry_point`` +attribute to be called for the offload kernel entry point to be emitted. For +inline functions and function templates, any ODR-use will suffice. For other +functions, an ODR-use is not required; the offload kernel entry point will be +emitted if the function is defined. + +Functions declared with the ``sycl_kernel_entry_point`` attribute are not +limited to the simple example shown above. They may have additional template +parameters, declare additional function parameters, and have complex control +flow in the function body. Function parameter decomposition and reconstitution +is performed for all function parameters. The function must abide by the +language feature restrictions described in section 5.4, "Language restrictions +for device functions" in the SYCL 2020 specification. + }]; +} + def SYCLSpecialClassDocs : Documentation { let Category = DocCatStmt; let Content = [{ diff --git a/clang/include/clang/Basic/BuiltinsLoongArchLASX.def b/clang/include/clang/Basic/BuiltinsLoongArchLASX.def index 477f704860873..f644b820a6189 100644 --- a/clang/include/clang/Basic/BuiltinsLoongArchLASX.def +++ b/clang/include/clang/Basic/BuiltinsLoongArchLASX.def @@ -368,7 +368,7 @@ TARGET_BUILTIN(__builtin_lasx_xvrepli_d, "V4LLiIi", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvand_v, "V32UcV32UcV32Uc", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvor_v, "V32UcV32UcV32Uc", "nc", "lasx") -TARGET_BUILTIN(__builtin_lasx_xvxor_v, "V32ScV32ScV32Sc", "nc", "lasx") +TARGET_BUILTIN(__builtin_lasx_xvxor_v, "V32UcV32UcV32Uc", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvnor_v, "V32UcV32UcV32Uc", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvandn_v, "V32UcV32UcV32Uc", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvorn_v, "V32ScV32ScV32Sc", "nc", "lasx") @@ -935,7 +935,7 @@ TARGET_BUILTIN(__builtin_lasx_xvilvh_h, "V16sV16sV16s", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvilvh_w, "V8iV8iV8i", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvilvh_d, "V4LLiV4LLiV4LLi", "nc", "lasx") -TARGET_BUILTIN(__builtin_lasx_xvshuf_b, "V32UcV32UcV32UcV32Uc", "nc", "lasx") +TARGET_BUILTIN(__builtin_lasx_xvshuf_b, "V32ScV32ScV32ScV32Sc", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvshuf_h, "V16sV16sV16sV16s", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvshuf_w, "V8iV8iV8iV8i", "nc", "lasx") diff --git a/clang/include/clang/Basic/BuiltinsLoongArchLSX.def b/clang/include/clang/Basic/BuiltinsLoongArchLSX.def index e847985f39036..b3056971986d1 100644 --- a/clang/include/clang/Basic/BuiltinsLoongArchLSX.def +++ b/clang/include/clang/Basic/BuiltinsLoongArchLSX.def @@ -352,7 +352,7 @@ TARGET_BUILTIN(__builtin_lsx_vrepli_d, "V2LLiIi", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vand_v, "V16UcV16UcV16Uc", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vor_v, "V16UcV16UcV16Uc", "nc", "lsx") -TARGET_BUILTIN(__builtin_lsx_vxor_v, "V16ScV16ScV16Sc", "nc", "lsx") +TARGET_BUILTIN(__builtin_lsx_vxor_v, "V16UcV16UcV16Uc", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vnor_v, "V16UcV16UcV16Uc", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vandn_v, "V16UcV16UcV16Uc", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vorn_v, "V16ScV16ScV16Sc", "nc", "lsx") @@ -910,7 +910,7 @@ TARGET_BUILTIN(__builtin_lsx_vilvh_h, "V8sV8sV8s", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vilvh_w, "V4iV4iV4i", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vilvh_d, "V2LLiV2LLiV2LLi", "nc", "lsx") -TARGET_BUILTIN(__builtin_lsx_vshuf_b, "V16UcV16UcV16UcV16Uc", "nc", "lsx") +TARGET_BUILTIN(__builtin_lsx_vshuf_b, "V16ScV16ScV16ScV16Sc", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vshuf_h, "V8sV8sV8sV8s", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vshuf_w, "V4iV4iV4iV4i", "nc", "lsx") diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d697e6d61afa9..fe2725477e9b7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8477,6 +8477,8 @@ def err_incomplete_object_call : Error< def warn_condition_is_assignment : Warning<"using the result of an " "assignment as a condition without parentheses">, InGroup; +def warn_assignment_bool_context : Warning<"suggest parentheses around assignment used as truth value">, + InGroup; def warn_free_nonheap_object : Warning<"attempt to call %0 on non-heap %select{object %2|object: block expression|object: lambda-to-function-pointer conversion}1">, InGroup; diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index c9b72e65cb236..ea6b414618c1d 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1569,7 +1569,7 @@ struct FormatStyle { /// Control of individual brace wrapping cases. /// - /// If ``BreakBeforeBraces`` is set to ``BS_Custom``, use this to specify how + /// If ``BreakBeforeBraces`` is set to ``Custom``, use this to specify how /// each individual brace case should be handled. Otherwise, this is ignored. /// \code{.yaml} /// # Example of usage: diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 38a527d2324ff..3312d4ed1d798 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -2617,6 +2617,19 @@ class Preprocessor { /// \#pragma GCC poison/system_header/dependency and \#pragma once. void RegisterBuiltinPragmas(); + /// RegisterBuiltinMacro - Register the specified identifier in the identifier + /// table and mark it as a builtin macro to be expanded. + IdentifierInfo *RegisterBuiltinMacro(const char *Name) { + // Get the identifier. + IdentifierInfo *Id = getIdentifierInfo(Name); + + // Mark it as being a macro that is builtin. + MacroInfo *MI = AllocateMacroInfo(SourceLocation()); + MI->setIsBuiltinMacro(); + appendDefMacroDirective(Id, MI); + return Id; + } + /// Register builtin macros such as __LINE__ with the identifier table. void RegisterBuiltinMacros(); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 93d98e1cbb9c8..6bf73956d3f94 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7232,6 +7232,8 @@ class Sema final : public SemaBase { /// being used as a boolean condition, warn if it's an assignment. void DiagnoseAssignmentAsCondition(Expr *E); + void DiagnoseAssignmentBoolContext(Expr *E, QualType ToType); + /// Redundant parentheses over an equality comparison can indicate /// that the user intended an assignment used as condition. void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE); diff --git a/clang/include/clang/Sema/SemaSYCL.h b/clang/include/clang/Sema/SemaSYCL.h index 27c42b5401830..c9f3358124eda 100644 --- a/clang/include/clang/Sema/SemaSYCL.h +++ b/clang/include/clang/Sema/SemaSYCL.h @@ -62,6 +62,7 @@ class SemaSYCL : public SemaBase { ParsedType ParsedTy); void handleKernelAttr(Decl *D, const ParsedAttr &AL); + void handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL); }; } // namespace clang diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index d724a9ea471b5..014ee7e2e3d39 100644 --- a/clang/lib/APINotes/APINotesFormat.h +++ b/clang/lib/APINotes/APINotesFormat.h @@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0; /// API notes file minor version number. /// /// When the format changes IN ANY WAY, this number should be incremented. -const uint16_t VERSION_MINOR = 30; // fields +const uint16_t VERSION_MINOR = 31; // lifetimebound const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index da8a86f7adb16..1bde8482fce03 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -331,6 +331,9 @@ void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) { Info.setRetainCountConvention(Convention); } Payload >>= 3; + if (Payload & 0x01) + Info.setLifetimebound(Payload & 0x02); + Payload >>= 2; if (Payload & 0x01) Info.setNoEscape(Payload & 0x02); Payload >>= 2; diff --git a/clang/lib/APINotes/APINotesTypes.cpp b/clang/lib/APINotes/APINotesTypes.cpp index a87ecb3bc30ee..be7dec3295b4c 100644 --- a/clang/lib/APINotes/APINotesTypes.cpp +++ b/clang/lib/APINotes/APINotesTypes.cpp @@ -65,6 +65,8 @@ LLVM_DUMP_METHOD void ParamInfo::dump(llvm::raw_ostream &OS) const { static_cast(*this).dump(OS); if (NoEscapeSpecified) OS << (NoEscape ? "[NoEscape] " : ""); + if (LifetimeboundSpecified) + OS << (Lifetimebound ? "[Lifetimebound] " : ""); OS << "RawRetainCountConvention: " << RawRetainCountConvention << ' '; OS << '\n'; } diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index a2b3669a31447..d81394edfde30 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -1052,6 +1052,12 @@ void emitParamInfo(raw_ostream &OS, const ParamInfo &PI) { if (*noescape) flags |= 0x02; } + flags <<= 2; + if (auto lifetimebound = PI.isLifetimebound()) { + flags |= 0x01; + if (*lifetimebound) + flags |= 0x02; + } flags <<= 3; if (auto RCC = PI.getRetainCountConvention()) flags |= static_cast(RCC.value()) + 1; diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index f72a1d65b5456..11578e4d054b7 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -70,6 +70,7 @@ namespace { struct Param { unsigned Position; std::optional NoEscape = false; + std::optional Lifetimebound = false; std::optional Nullability; std::optional RetainCountConvention; StringRef Type; @@ -121,6 +122,7 @@ template <> struct MappingTraits { IO.mapOptional("Nullability", P.Nullability, std::nullopt); IO.mapOptional("RetainCountConvention", P.RetainCountConvention); IO.mapOptional("NoEscape", P.NoEscape); + IO.mapOptional("Lifetimebound", P.Lifetimebound); IO.mapOptional("Type", P.Type, StringRef("")); } }; @@ -734,6 +736,7 @@ class YAMLConverter { if (P.Nullability) PI.setNullabilityAudited(*P.Nullability); PI.setNoEscape(P.NoEscape); + PI.setLifetimebound(P.Lifetimebound); PI.setType(std::string(P.Type)); PI.setRetainCountConvention(P.RetainCountConvention); if (OutInfo.Params.size() <= P.Position) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index d248084666d1b..061a6866fb5fb 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -831,6 +831,15 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( return CanonTTP; } +/// Check if a type can have its sanitizer instrumentation elided based on its +/// presence within an ignorelist. +bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask, + const QualType &Ty) const { + std::string TyName = Ty.getUnqualifiedType().getAsString(getPrintingPolicy()); + return NoSanitizeL->containsType(Mask, TyName) && + !NoSanitizeL->containsType(Mask, TyName, "sanitize"); +} + TargetCXXABI::Kind ASTContext::getCXXABIKind() const { auto Kind = getTargetInfo().getCXXABI().getKind(); return getLangOpts().CXXABI.value_or(Kind); @@ -14402,6 +14411,32 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap &FeatureMap, } } +static SYCLKernelInfo BuildSYCLKernelInfo(CanQualType KernelNameType, + const FunctionDecl *FD) { + return {KernelNameType, FD}; +} + +void ASTContext::registerSYCLEntryPointFunction(FunctionDecl *FD) { + // If the function declaration to register is invalid or dependent, the + // registration attempt is ignored. + if (FD->isInvalidDecl() || FD->isTemplated()) + return; + + const auto *SKEPAttr = FD->getAttr(); + assert(SKEPAttr && "Missing sycl_kernel_entry_point attribute"); + + // Be tolerant of multiple registration attempts so long as each attempt + // is for the same entity. Callers are obligated to detect and diagnose + // conflicting kernel names prior to calling this function. + CanQualType KernelNameType = getCanonicalType(SKEPAttr->getKernelName()); + auto IT = SYCLKernels.find(KernelNameType); + assert((IT == SYCLKernels.end() || + declaresSameEntity(FD, IT->second.getKernelEntryPointDecl())) && + "SYCL kernel name conflict"); + SYCLKernels.insert( + std::make_pair(KernelNameType, BuildSYCLKernelInfo(KernelNameType, FD))); +} + OMPTraitInfo &ASTContext::getNewOMPTraitInfo() { OMPTraitInfoVector.emplace_back(new OMPTraitInfo()); return *OMPTraitInfoVector.back(); diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 75f790d17033c..7cf2519d6a71f 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -2735,7 +2735,7 @@ bool Compiler::VisitMaterializeTemporaryExpr( InitLinkScope ILS(this, InitLink::Temp(*LocalIndex)); if (!this->emitGetPtrLocal(*LocalIndex, E)) return false; - return this->visitInitializer(SubExpr); + return this->visitInitializer(SubExpr) && this->emitFinishInit(E); } } return false; @@ -6446,8 +6446,6 @@ bool Compiler::emitBuiltinBitCast(const CastExpr *E) { QualType ToType = E->getType(); std::optional ToT = classify(ToType); - assert(!DiscardResult && "Implement DiscardResult mode for bitcasts."); - if (ToType->isNullPtrType()) { if (!this->discard(SubExpr)) return false; @@ -6463,13 +6461,23 @@ bool Compiler::emitBuiltinBitCast(const CastExpr *E) { } assert(!ToType->isReferenceType()); + // Prepare storage for the result in case we discard. + if (DiscardResult && !Initializing && !ToT) { + std::optional LocalIndex = allocateLocal(E); + if (!LocalIndex) + return false; + if (!this->emitGetPtrLocal(*LocalIndex, E)) + return false; + } + // Get a pointer to the value-to-cast on the stack. if (!this->visit(SubExpr)) return false; if (!ToT || ToT == PT_Ptr) { - // Conversion to an array or record type. - assert(false && "Implement bitcast to pointers."); + if (!this->emitBitCastPtr(E)) + return false; + return DiscardResult ? this->emitPopPtr(E) : true; } assert(ToT); diff --git a/clang/lib/AST/ByteCode/Floating.h b/clang/lib/AST/ByteCode/Floating.h index be38e6991dad7..3a874fc6f0b41 100644 --- a/clang/lib/AST/ByteCode/Floating.h +++ b/clang/lib/AST/ByteCode/Floating.h @@ -135,7 +135,7 @@ class Floating final { return Floating(APFloat(Sem, API)); } - void bitcastToMemory(std::byte *Buff) { + void bitcastToMemory(std::byte *Buff) const { llvm::APInt API = F.bitcastToAPInt(); llvm::StoreIntToMemory(API, (uint8_t *)Buff, bitWidth() / 8); } diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index ade6f7424b1fd..1f3134e1cd155 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -3062,7 +3062,17 @@ inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte, return false; if constexpr (std::is_same_v) { - assert(false && "Implement bitcasting to a floating type"); + assert(Sem); + ptrdiff_t Offset = 0; + + if (llvm::sys::IsBigEndianHost) { + unsigned NumBits = llvm::APFloatBase::getSizeInBits(*Sem); + assert(NumBits % 8 == 0); + assert(NumBits <= ResultBitWidth); + Offset = (ResultBitWidth - NumBits) / 8; + } + + S.Stk.push(T::bitcastFromMemory(Buff.data() + Offset, *Sem)); } else { assert(!Sem); S.Stk.push(T::bitcastFromMemory(Buff.data(), ResultBitWidth)); @@ -3070,6 +3080,16 @@ inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte, return true; } +inline bool BitCastPtr(InterpState &S, CodePtr OpPC) { + const Pointer &FromPtr = S.Stk.pop(); + Pointer &ToPtr = S.Stk.peek(); + + if (!DoBitCastPtr(S, OpPC, FromPtr, ToPtr)) + return false; + + return true; +} + //===----------------------------------------------------------------------===// // Read opcode arguments //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp index fde2c6d9b11ac..17a175a48b5df 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp @@ -26,8 +26,8 @@ using namespace clang; using namespace clang::interp; /// Used to iterate over pointer fields. -using DataFunc = - llvm::function_ref; +using DataFunc = llvm::function_ref; #define BITCAST_TYPE_SWITCH(Expr, B) \ do { \ @@ -48,9 +48,7 @@ using DataFunc = } \ } while (0) -/// Float is a special case that sometimes needs the floating point semantics -/// to be available. -#define BITCAST_TYPE_SWITCH_WITH_FLOAT(Expr, B) \ +#define BITCAST_TYPE_SWITCH_FIXED_SIZE(Expr, B) \ do { \ switch (Expr) { \ TYPE_SWITCH_CASE(PT_Sint8, B) \ @@ -61,10 +59,7 @@ using DataFunc = TYPE_SWITCH_CASE(PT_Uint32, B) \ TYPE_SWITCH_CASE(PT_Sint64, B) \ TYPE_SWITCH_CASE(PT_Uint64, B) \ - TYPE_SWITCH_CASE(PT_IntAP, B) \ - TYPE_SWITCH_CASE(PT_IntAPS, B) \ TYPE_SWITCH_CASE(PT_Bool, B) \ - TYPE_SWITCH_CASE(PT_Float, B) \ default: \ llvm_unreachable("Unhandled bitcast type"); \ } \ @@ -83,28 +78,19 @@ static void swapBytes(std::byte *M, size_t N) { /// have indeterminate value. /// All offsets are in bits. struct BitcastBuffer { - llvm::BitVector Data; + size_t SizeInBits = 0; + llvm::SmallVector Data; BitcastBuffer() = default; - size_t size() const { return Data.size(); } + size_t size() const { return SizeInBits; } - const std::byte *data() const { - unsigned NBytes = Data.size() / 8; - unsigned BitVectorWordSize = sizeof(uintptr_t); - bool FullWord = (NBytes % BitVectorWordSize == 0); + const std::byte *data() const { return Data.data(); } - // llvm::BitVector uses 64-bit fields internally, so when we have - // fewer bytes than that, we need to compensate for that on - // big endian hosts. - unsigned DataPlus; - if (llvm::sys::IsBigEndianHost) - DataPlus = BitVectorWordSize - (NBytes % BitVectorWordSize); - else - DataPlus = 0; - - return reinterpret_cast(Data.getData().data()) + - (FullWord ? 0 : DataPlus); + std::byte *getBytes(unsigned BitOffset) const { + assert(BitOffset % 8 == 0); + assert(BitOffset < SizeInBits); + return const_cast(data() + (BitOffset / 8)); } bool allInitialized() const { @@ -112,10 +98,18 @@ struct BitcastBuffer { return true; } - void pushData(const std::byte *data, size_t BitOffset, size_t BitWidth, - bool BigEndianTarget) { - Data.reserve(BitOffset + BitWidth); + bool atByteBoundary() const { return (Data.size() * 8) == SizeInBits; } + + void pushBit(bool Value) { + if (atByteBoundary()) + Data.push_back(std::byte{0}); + if (Value) + Data.back() |= (std::byte{1} << (SizeInBits % 8)); + ++SizeInBits; + } + + void pushData(const std::byte *data, size_t BitWidth, bool BigEndianTarget) { bool OnlyFullBytes = BitWidth % 8 == 0; unsigned NBytes = BitWidth / 8; @@ -125,7 +119,7 @@ struct BitcastBuffer { std::byte B = BigEndianTarget ? data[NBytes - OnlyFullBytes - I] : data[I]; for (unsigned X = 0; X != 8; ++X) { - Data.push_back(bitof(B, X)); + pushBit(bitof(B, X)); ++BitsHandled; } } @@ -137,7 +131,7 @@ struct BitcastBuffer { assert((BitWidth - BitsHandled) < 8); std::byte B = BigEndianTarget ? data[0] : data[NBytes]; for (size_t I = 0, E = (BitWidth - BitsHandled); I != E; ++I) { - Data.push_back(bitof(B, I)); + pushBit(bitof(B, I)); ++BitsHandled; } @@ -154,7 +148,7 @@ static bool enumerateData(const Pointer &P, const Context &Ctx, size_t Offset, // Primitives. if (FieldDesc->isPrimitive()) - return F(P, FieldDesc->getPrimType(), Offset); + return F(P, FieldDesc->getPrimType(), Offset, false); // Primitive arrays. if (FieldDesc->isPrimitiveArray()) { @@ -162,10 +156,12 @@ static bool enumerateData(const Pointer &P, const Context &Ctx, size_t Offset, QualType ElemType = FieldDesc->getElemQualType(); size_t ElemSizeInBits = Ctx.getASTContext().getTypeSize(ElemType); PrimType ElemT = *Ctx.classify(ElemType); + // Special case, since the bools here are packed. + bool PackedBools = FieldDesc->getType()->isExtVectorBoolType(); bool Ok = true; for (unsigned I = 0; I != FieldDesc->getNumElems(); ++I) { unsigned Index = BigEndianTarget ? (FieldDesc->getNumElems() - 1 - I) : I; - Ok = Ok && F(P.atIndex(Index), ElemT, Offset); + Ok = Ok && F(P.atIndex(Index), ElemT, Offset, PackedBools); Offset += ElemSizeInBits; } return Ok; @@ -309,7 +305,8 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr, return enumeratePointerFields( FromPtr, Ctx, - [&](const Pointer &P, PrimType T, size_t BitOffset) -> bool { + [&](const Pointer &P, PrimType T, size_t BitOffset, + bool PackedBools) -> bool { if (!P.isInitialized()) { assert(false && "Implement uninitialized value tracking"); return ReturnOnUninit; @@ -321,25 +318,42 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr, assert(false && "Implement casting to pointer types"); CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType()); - unsigned BitWidth; - if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) - BitWidth = FD->getBitWidthValue(ASTCtx); - else - BitWidth = ASTCtx.toBits(ObjectReprChars); - + unsigned BitWidth = ASTCtx.toBits(ObjectReprChars); llvm::SmallVector Buff(ObjectReprChars.getQuantity()); - BITCAST_TYPE_SWITCH_WITH_FLOAT(T, { - T Val = P.deref(); - Val.bitcastToMemory(Buff.data()); - }); - if (SwapData) - swapBytes(Buff.data(), ObjectReprChars.getQuantity()); + // Work around floating point types that contain unused padding bytes. + // This is really just `long double` on x86, which is the only + // fundamental type with padding bytes. + if (T == PT_Float) { + const Floating &F = P.deref(); + unsigned NumBits = + llvm::APFloatBase::getSizeInBits(F.getAPFloat().getSemantics()); + assert(NumBits % 8 == 0); + assert(NumBits <= (ObjectReprChars.getQuantity() * 8)); + F.bitcastToMemory(Buff.data()); + // Now, only (maybe) swap the actual size of the float, excluding the + // padding bits. + if (SwapData) + swapBytes(Buff.data(), NumBits / 8); + + } else { + if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) + BitWidth = FD->getBitWidthValue(ASTCtx); + else if (T == PT_Bool && PackedBools) + BitWidth = 1; + + BITCAST_TYPE_SWITCH(T, { + T Val = P.deref(); + Val.bitcastToMemory(Buff.data()); + }); + if (SwapData) + swapBytes(Buff.data(), ObjectReprChars.getQuantity()); + } if (BitWidth != (Buff.size() * 8) && BigEndianTarget) { Buffer.pushData(Buff.data() + (Buff.size() - 1 - (BitWidth / 8)), - BitOffset, BitWidth, BigEndianTarget); + BitWidth, BigEndianTarget); } else { - Buffer.pushData(Buff.data(), BitOffset, BitWidth, BigEndianTarget); + Buffer.pushData(Buff.data(), BitWidth, BigEndianTarget); } return true; }); @@ -363,5 +377,66 @@ bool clang::interp::DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, HasIndeterminateBits = !Buffer.allInitialized(); std::memcpy(Buff, Buffer.data(), BuffSize); + if (llvm::sys::IsBigEndianHost) + swapBytes(Buff, BuffSize); + + return Success; +} + +bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC, + const Pointer &FromPtr, Pointer &ToPtr) { + assert(FromPtr.isLive()); + assert(FromPtr.isBlockPointer()); + assert(ToPtr.isBlockPointer()); + + QualType FromType = FromPtr.getType(); + QualType ToType = ToPtr.getType(); + + if (!CheckBitcastType(S, OpPC, FromType, /*IsToType=*/false)) + return false; + + if (!CheckBitcastType(S, OpPC, ToType, /*IsToType=*/true)) + return false; + + BitcastBuffer Buffer; + readPointerToBuffer(S.getContext(), FromPtr, Buffer, + /*ReturnOnUninit=*/false); + + // Now read the values out of the buffer again and into ToPtr. + const ASTContext &ASTCtx = S.getASTContext(); + size_t BitOffset = 0; + bool Success = enumeratePointerFields( + ToPtr, S.getContext(), + [&](const Pointer &P, PrimType T, size_t _, bool PackedBools) -> bool { + if (T == PT_Float) { + CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType()); + const auto &Semantics = ASTCtx.getFloatTypeSemantics(P.getType()); + unsigned NumBits = llvm::APFloatBase::getSizeInBits(Semantics); + assert(NumBits % 8 == 0); + assert(NumBits <= ASTCtx.toBits(ObjectReprChars)); + std::byte *M = Buffer.getBytes(BitOffset); + + if (llvm::sys::IsBigEndianHost) + swapBytes(M, NumBits / 8); + + P.deref() = Floating::bitcastFromMemory(M, Semantics); + P.initialize(); + BitOffset += ASTCtx.toBits(ObjectReprChars); + return true; + } + + BITCAST_TYPE_SWITCH_FIXED_SIZE(T, { + std::byte *M = Buffer.getBytes(BitOffset); + + if (llvm::sys::IsBigEndianHost) + swapBytes(M, T::bitWidth() / 8); + + P.deref() = T::bitcastFromMemory(M, T::bitWidth()); + P.initialize(); + BitOffset += T::bitWidth(); + }); + return true; + }); + return Success; } diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h index 84ba784e95e23..494c0880a9c45 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h +++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.h @@ -19,6 +19,8 @@ class CodePtr; bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, std::byte *Buff, size_t BuffSize, bool &HasIndeterminateBits); +bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr, + Pointer &ToPtr); } // namespace interp } // namespace clang diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 480febd895a24..26d5f70b44396 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -847,3 +847,5 @@ def BitCast : Opcode { let Args = [ArgBool, ArgUint32, ArgFltSemantics]; let HasGroup = 1; } + +def BitCastPtr : Opcode; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 229721aeae811..6bf2908e667c0 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -43,6 +43,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -4774,7 +4775,10 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { ->getTemplateName() .getAsTemplateDecl()) if (auto *CTD = dyn_cast(templateDecl)) - return CTD->getTemplatedDecl()->hasAttr(); + return llvm::any_of( + CTD->redecls(), [](const RedeclarableTemplateDecl *RTD) { + return RTD->getTemplatedDecl()->hasAttr(); + }); return ResultIfUnknown; case Type::Builtin: @@ -4841,10 +4845,14 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { // For template specializations, look only at primary template attributes. // This is a consistent regardless of whether the instantiation is known. if (const auto *CTSD = dyn_cast(RD)) - return CTSD->getSpecializedTemplate() - ->getTemplatedDecl() - ->hasAttr(); - return RD->hasAttr(); + return llvm::any_of( + CTSD->getSpecializedTemplate()->redecls(), + [](const RedeclarableTemplateDecl *RTD) { + return RTD->getTemplatedDecl()->hasAttr(); + }); + return llvm::any_of(RD->redecls(), [](const TagDecl *RD) { + return RD->hasAttr(); + }); } // Non-pointer types. diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 30c7ac8d9c037..85e4bd920d853 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -310,8 +310,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo { // SPIR-V IDs are represented with a single 32-bit word. SizeType = TargetInfo::UnsignedInt; - resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-" - "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"); + resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-" + "v256:256-v512:512-v1024:1024-n8:16:32:64-G1"); } void getTargetDefines(const LangOptions &Opts, @@ -334,8 +334,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo { // SPIR-V has core support for atomic ops, and Int32 is always available; // we take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max(MaxAtomicInlineWidth, 32); - resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-" - "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"); + resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-" + "v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"); } void getTargetDefines(const LangOptions &Opts, @@ -358,8 +358,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo { // SPIR-V has core support for atomic ops, and Int64 is always available; // we take the maximum because it's possible the Host supports wider types. MaxAtomicInlineWidth = std::max(MaxAtomicInlineWidth, 64); - resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-" - "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"); + resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-" + "v256:256-v512:512-v1024:1024-n8:16:32:64-G1"); } void getTargetDefines(const LangOptions &Opts, @@ -384,8 +384,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64AMDGCNTargetInfo final PtrDiffType = IntPtrType = TargetInfo::SignedLong; AddrSpaceMap = &SPIRDefIsGenMap; - resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-" - "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1-P4-A0"); + resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-" + "v256:256-v512:512-v1024:1024-n32:64-S32-G1-P4-A0"); BFloat16Width = BFloat16Align = 16; BFloat16Format = &llvm::APFloat::BFloat(); diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index ae33554a66b6b..70035a5e069a9 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -674,7 +674,7 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts, // Ensure we lower KCFI operand bundles with -O0. PB.registerOptimizerLastEPCallback( - [&](ModulePassManager &MPM, OptimizationLevel Level) { + [&](ModulePassManager &MPM, OptimizationLevel Level, ThinOrFullLTOPhase) { if (Level == OptimizationLevel::O0 && LangOpts.Sanitize.has(SanitizerKind::KCFI)) MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass())); @@ -693,8 +693,8 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts, static void addSanitizers(const Triple &TargetTriple, const CodeGenOptions &CodeGenOpts, const LangOptions &LangOpts, PassBuilder &PB) { - auto SanitizersCallback = [&](ModulePassManager &MPM, - OptimizationLevel Level) { + auto SanitizersCallback = [&](ModulePassManager &MPM, OptimizationLevel Level, + ThinOrFullLTOPhase) { if (CodeGenOpts.hasSanitizeCoverage()) { auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts); MPM.addPass(SanitizerCoveragePass( @@ -778,9 +778,10 @@ static void addSanitizers(const Triple &TargetTriple, }; if (ClSanitizeOnOptimizerEarlyEP) { PB.registerOptimizerEarlyEPCallback( - [SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level) { + [SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level, + ThinOrFullLTOPhase Phase) { ModulePassManager NewMPM; - SanitizersCallback(NewMPM, Level); + SanitizersCallback(NewMPM, Level, Phase); if (!NewMPM.isEmpty()) { // Sanitizers can abandon. NewMPM.addPass(RequireAnalysisPass()); @@ -993,7 +994,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline( createModuleToFunctionPassAdaptor(ObjCARCExpandPass())); }); PB.registerPipelineEarlySimplificationEPCallback( - [](ModulePassManager &MPM, OptimizationLevel Level) { + [](ModulePassManager &MPM, OptimizationLevel Level, + ThinOrFullLTOPhase) { if (Level != OptimizationLevel::O0) MPM.addPass(ObjCARCAPElimPass()); }); @@ -1057,11 +1059,12 @@ void EmitAssemblyHelper::RunOptimizationPipeline( // TODO: Consider passing the MemoryProfileOutput to the pass builder via // the PGOOptions, and set this up there. if (!CodeGenOpts.MemoryProfileOutput.empty()) { - PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass())); - MPM.addPass(ModuleMemProfilerPass()); - }); + PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM, + OptimizationLevel Level, + ThinOrFullLTOPhase) { + MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass())); + MPM.addPass(ModuleMemProfilerPass()); + }); } if (CodeGenOpts.FatLTO) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index e90e8da3e9f1e..3388a6df466d4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1941,6 +1941,10 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty, cast(Value->getType())->getBitWidth() == 1) return false; + if (NeedsEnumCheck && + getContext().isTypeIgnoredBySanitizer(SanitizerKind::Enum, Ty)) + return false; + llvm::APInt Min, End; if (!getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool)) return true; diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 9e2c2ad5e0250..287d911e10ba5 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -197,6 +197,18 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) { if (!Op.mayHaveIntegerOverflow()) return true; + if (Op.Ty->isSignedIntegerType() && + Ctx.isTypeIgnoredBySanitizer(SanitizerKind::SignedIntegerOverflow, + Op.Ty)) { + return true; + } + + if (Op.Ty->isUnsignedIntegerType() && + Ctx.isTypeIgnoredBySanitizer(SanitizerKind::UnsignedIntegerOverflow, + Op.Ty)) { + return true; + } + const UnaryOperator *UO = dyn_cast(Op.E); if (UO && UO->getOpcode() == UO_Minus && @@ -1125,6 +1137,10 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType, if (!CGF.SanOpts.has(Check.second.second)) return; + // Does some SSCL ignore this type? + if (CGF.getContext().isTypeIgnoredBySanitizer(Check.second.second, DstType)) + return; + llvm::Constant *StaticArgs[] = { CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType), CGF.EmitCheckTypeDescriptor(DstType), @@ -1235,6 +1251,15 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType, // Because here sign change check is interchangeable with truncation check. return; } + // Does an SSCL have an entry for the DstType under its respective sanitizer + // section? + if (DstSigned && CGF.getContext().isTypeIgnoredBySanitizer( + SanitizerKind::ImplicitSignedIntegerTruncation, DstType)) + return; + if (!DstSigned && + CGF.getContext().isTypeIgnoredBySanitizer( + SanitizerKind::ImplicitUnsignedIntegerTruncation, DstType)) + return; // That's it. We can't rule out any more cases with the data we have. CodeGenFunction::SanitizerScope SanScope(&CGF); @@ -2784,10 +2809,11 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior( return Builder.CreateNSWAdd(InVal, Amount, Name); [[fallthrough]]; case LangOptions::SOB_Trapping: - if (!E->canOverflow()) + BinOpInfo Info = createBinOpInfoFromIncDec( + E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts())); + if (!E->canOverflow() || CanElideOverflowCheck(CGF.getContext(), Info)) return Builder.CreateNSWAdd(InVal, Amount, Name); - return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec( - E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts()))); + return EmitOverflowCheckedBinOp(Info); } llvm_unreachable("Unknown SignedOverflowBehaviorTy"); } @@ -2990,7 +3016,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, value = EmitIncDecConsiderOverflowBehavior(E, value, isInc); } else if (E->canOverflow() && type->isUnsignedIntegerType() && CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) && - !excludeOverflowPattern) { + !excludeOverflowPattern && + !CGF.getContext().isTypeIgnoredBySanitizer( + SanitizerKind::UnsignedIntegerOverflow, E->getType())) { value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec( E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts()))); } else { diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 47ea636c75643..7caf801d22e0b 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -365,7 +365,7 @@ class ObjCCommonTypesHelper { /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function. llvm::FunctionCallee getGcReadWeakFn() { // id objc_read_weak (id *) - llvm::Type *args[] = { ObjectPtrTy->getPointerTo() }; + llvm::Type *args[] = {CGM.UnqualPtrTy}; llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); @@ -374,7 +374,7 @@ class ObjCCommonTypesHelper { /// GcAssignWeakFn -- LLVM objc_assign_weak function. llvm::FunctionCallee getGcAssignWeakFn() { // id objc_assign_weak (id, id *) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; + llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy}; llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); @@ -383,7 +383,7 @@ class ObjCCommonTypesHelper { /// GcAssignGlobalFn -- LLVM objc_assign_global function. llvm::FunctionCallee getGcAssignGlobalFn() { // id objc_assign_global(id, id *) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; + llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy}; llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); @@ -392,7 +392,7 @@ class ObjCCommonTypesHelper { /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function. llvm::FunctionCallee getGcAssignThreadLocalFn() { // id objc_assign_threadlocal(id src, id * dest) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; + llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy}; llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal"); @@ -401,8 +401,7 @@ class ObjCCommonTypesHelper { /// GcAssignIvarFn -- LLVM objc_assign_ivar function. llvm::FunctionCallee getGcAssignIvarFn() { // id objc_assign_ivar(id, id *, ptrdiff_t) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(), - CGM.PtrDiffTy }; + llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy, CGM.PtrDiffTy}; llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); @@ -419,7 +418,7 @@ class ObjCCommonTypesHelper { /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. llvm::FunctionCallee getGcAssignStrongCastFn() { // id objc_assign_strongCast(id, id *) - llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; + llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy}; llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); @@ -554,7 +553,7 @@ class ObjCTypesHelper : public ObjCCommonTypesHelper { /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. llvm::FunctionCallee getExceptionTryEnterFn() { - llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; + llvm::Type *params[] = {CGM.UnqualPtrTy}; return CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGM.VoidTy, params, false), "objc_exception_try_enter"); @@ -562,7 +561,7 @@ class ObjCTypesHelper : public ObjCCommonTypesHelper { /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. llvm::FunctionCallee getExceptionTryExitFn() { - llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; + llvm::Type *params[] = {CGM.UnqualPtrTy}; return CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGM.VoidTy, params, false), "objc_exception_try_exit"); @@ -570,7 +569,7 @@ class ObjCTypesHelper : public ObjCCommonTypesHelper { /// ExceptionExtractFn - LLVM objc_exception_extract function. llvm::FunctionCallee getExceptionExtractFn() { - llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; + llvm::Type *params[] = {CGM.UnqualPtrTy}; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, params, false), "objc_exception_extract"); @@ -587,7 +586,7 @@ class ObjCTypesHelper : public ObjCCommonTypesHelper { /// SetJmpFn - LLVM _setjmp function. llvm::FunctionCallee getSetJmpFn() { // This is specifically the prototype for x86. - llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() }; + llvm::Type *params[] = {CGM.UnqualPtrTy}; return CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp", llvm::AttributeList::get(CGM.getLLVMContext(), @@ -6051,9 +6050,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul Int8PtrTy, PropertyListPtrTy); // ImpnfABITy - LLVM for id (*)(id, SEL, ...) - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; - ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false) - ->getPointerTo(); + ImpnfABITy = CGM.UnqualPtrTy; // struct _class_t { // struct _class_t *isa; @@ -6469,8 +6466,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_vtable"); else - ObjCEmptyVtableVar = - llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo()); + ObjCEmptyVtableVar = llvm::ConstantPointerNull::get(CGM.UnqualPtrTy); } // FIXME: Is this correct (that meta class size is never computed)? diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index 7dd5c518e7149..a48fe9d5f1ee9 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -52,6 +52,10 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo { unsigned getOpenCLKernelCallingConv() const override; llvm::Type *getOpenCLType(CodeGenModule &CGM, const Type *T) const override; + llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *Ty) const override; + llvm::Type *getSPIRVImageTypeFromHLSLResource( + const HLSLAttributedResourceType::Attributes &attributes, + llvm::Type *ElementType, llvm::LLVMContext &Ctx) const; }; class SPIRVTargetCodeGenInfo : public CommonSPIRTargetCodeGenInfo { public: @@ -323,6 +327,81 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getOpenCLType(CodeGenModule &CGM, return nullptr; } +llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM, + const Type *Ty) const { + auto *ResType = dyn_cast(Ty); + if (!ResType) + return nullptr; + + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + const HLSLAttributedResourceType::Attributes &ResAttrs = ResType->getAttrs(); + switch (ResAttrs.ResourceClass) { + case llvm::dxil::ResourceClass::UAV: + case llvm::dxil::ResourceClass::SRV: { + // TypedBuffer and RawBuffer both need element type + QualType ContainedTy = ResType->getContainedType(); + if (ContainedTy.isNull()) + return nullptr; + + assert(!ResAttrs.RawBuffer && + "Raw buffers handles are not implemented for SPIR-V yet"); + assert(!ResAttrs.IsROV && + "Rasterizer order views not implemented for SPIR-V yet"); + + // convert element type + llvm::Type *ElemType = CGM.getTypes().ConvertType(ContainedTy); + return getSPIRVImageTypeFromHLSLResource(ResAttrs, ElemType, Ctx); + } + case llvm::dxil::ResourceClass::CBuffer: + llvm_unreachable("CBuffer handles are not implemented for SPIR-V yet"); + break; + case llvm::dxil::ResourceClass::Sampler: + return llvm::TargetExtType::get(Ctx, "spirv.Sampler"); + } + return nullptr; +} + +llvm::Type *CommonSPIRTargetCodeGenInfo::getSPIRVImageTypeFromHLSLResource( + const HLSLAttributedResourceType::Attributes &attributes, + llvm::Type *ElementType, llvm::LLVMContext &Ctx) const { + + if (ElementType->isVectorTy()) + ElementType = ElementType->getScalarType(); + + assert((ElementType->isIntegerTy() || ElementType->isFloatingPointTy()) && + "The element type for a SPIR-V resource must be a scalar integer or " + "floating point type."); + + // These parameters correspond to the operands to the OpTypeImage SPIR-V + // instruction. See + // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage. + SmallVector IntParams(6, 0); + + // Dim + // For now we assume everything is a buffer. + IntParams[0] = 5; + + // Depth + // HLSL does not indicate if it is a depth texture or not, so we use unknown. + IntParams[1] = 2; + + // Arrayed + IntParams[2] = 0; + + // MS + IntParams[3] = 0; + + // Sampled + IntParams[4] = + attributes.ResourceClass == llvm::dxil::ResourceClass::UAV ? 2 : 1; + + // Image format. + // Setting to unknown for now. + IntParams[5] = 0; + + return llvm::TargetExtType::get(Ctx, "spirv.Image", {ElementType}, IntParams); +} + std::unique_ptr CodeGen::createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM) { return std::make_unique(CGM.getTypes()); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 083035dee4302..c5be122737051 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -149,13 +149,9 @@ static std::optional getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) { if (!Args.hasArg(options::OPT_offload_EQ)) { auto OffloadArchs = Args.getAllArgValues(options::OPT_offload_arch_EQ); - if (llvm::is_contained(OffloadArchs, "amdgcnspirv")) { - if (OffloadArchs.size() == 1) - return llvm::Triple("spirv64-amd-amdhsa"); - // Mixing specific & SPIR-V compilation is not supported for now. - D.Diag(diag::err_drv_only_one_offload_target_supported); - return std::nullopt; - } + if (llvm::is_contained(OffloadArchs, "amdgcnspirv") && + OffloadArchs.size() == 1) + return llvm::Triple("spirv64-amd-amdhsa"); return llvm::Triple("amdgcn-amd-amdhsa"); // Default HIP triple. } auto TT = getOffloadTargetTriple(D, Args); @@ -3477,9 +3473,11 @@ class OffloadingActionBuilder final { llvm::StringMap Features; // getHIPOffloadTargetTriple() is known to return valid value as it has // been called successfully in the CreateOffloadingDeviceToolChains(). - auto ArchStr = parseTargetID( - *getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs()), IdStr, - &Features); + auto T = + (IdStr == "amdgcnspirv") + ? llvm::Triple("spirv64-amd-amdhsa") + : *getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs()); + auto ArchStr = parseTargetID(T, IdStr, &Features); if (!ArchStr) { C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr; C.setContainsError(); @@ -4035,7 +4033,7 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() && LTOMode != LTOK_None && !Args.getLastArgValue(options::OPT_fuse_ld_EQ) - .equals_insensitive("lld")) + .starts_with_insensitive("lld")) Diag(clang::diag::err_drv_lto_without_lld); // If -dumpdir is not specified, give a default prefix derived from the link @@ -5755,7 +5753,7 @@ InputInfoList Driver::BuildJobsForActionNoCache( // We only have to generate a prefix for the host if this is not a top-level // action. std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix( - A->getOffloadingDeviceKind(), TC->getTriple().normalize(), + A->getOffloadingDeviceKind(), EffectiveTriple.normalize(), /*CreatePrefixForHost=*/isa(A) || !(A->getOffloadingHostActiveKinds() == Action::OFK_None || AtTopLevel)); diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index bdf3da0c96adc..9774d3fab741c 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1099,6 +1099,12 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, } case llvm::Triple::aarch64_32: return getTripleString(); + case llvm::Triple::amdgcn: { + llvm::Triple Triple = getTriple(); + if (Args.getLastArgValue(options::OPT_mcpu_EQ) == "amdgcnspirv") + Triple.setArch(llvm::Triple::ArchType::spirv64); + return Triple.getTriple(); + } case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp index bae05cc0bb735..4eb8c4f58923f 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.cpp +++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp @@ -205,7 +205,7 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (JA.getType() == types::TY_LLVM_BC) return constructLlvmLinkCommand(C, JA, Inputs, Output, Args); - if (getToolChain().getTriple().isSPIRV()) + if (getToolChain().getEffectiveTriple().isSPIRV()) return constructLinkAndEmitSpirvCommand(C, JA, Inputs, Output, Args); return constructLldCommand(C, JA, Inputs, Output, Args); @@ -264,12 +264,14 @@ void HIPAMDToolChain::addClangTargetOptions( CC1Args.push_back("-fapply-global-visibility-to-externs"); } - // For SPIR-V we embed the command-line into the generated binary, in order to - // retrieve it at JIT time and be able to do target specific compilation with - // options that match the user-supplied ones. - if (getTriple().isSPIRV() && - !DriverArgs.hasArg(options::OPT_fembed_bitcode_marker)) - CC1Args.push_back("-fembed-bitcode=marker"); + if (getEffectiveTriple().isSPIRV()) { + // For SPIR-V we embed the command-line into the generated binary, in order + // to retrieve it at JIT time and be able to do target specific compilation + // with options that match the user-supplied ones. + if (!DriverArgs.hasArg(options::OPT_fembed_bitcode_marker)) + CC1Args.push_back("-fembed-bitcode=marker"); + return; // No DeviceLibs for SPIR-V. + } for (auto BCFile : getDeviceLibs(DriverArgs)) { CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode" @@ -361,8 +363,7 @@ llvm::SmallVector HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const { llvm::SmallVector BCLibs; if (DriverArgs.hasArg(options::OPT_nogpulib) || - (getTriple().getArch() == llvm::Triple::spirv64 && - getTriple().getVendor() == llvm::Triple::AMD)) + getGPUArch(DriverArgs) == "amdgcnspirv") return {}; ArgStringList LibraryPaths; @@ -437,8 +438,8 @@ HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const { void HIPAMDToolChain::checkTargetID( const llvm::opt::ArgList &DriverArgs) const { auto PTID = getParsedTargetID(DriverArgs); - if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) { + if (PTID.OptionalTargetID && !PTID.OptionalGPUArch && + PTID.OptionalTargetID != "amdgcnspirv") getDriver().Diag(clang::diag::err_drv_bad_target_id) << *PTID.OptionalTargetID; - } } diff --git a/clang/lib/Driver/ToolChains/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp index 9fe4f1e0e2096..c8075cbfe36b3 100644 --- a/clang/lib/Driver/ToolChains/HIPUtility.cpp +++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp @@ -304,10 +304,14 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA, for (const auto &II : Inputs) { const auto *A = II.getAction(); auto ArchStr = llvm::StringRef(A->getOffloadingArch()); - BundlerTargetArg += - "," + OffloadKind + "-" + normalizeForBundler(TT, !ArchStr.empty()); + BundlerTargetArg += ',' + OffloadKind + '-'; + if (ArchStr == "amdgcnspirv") + BundlerTargetArg += + normalizeForBundler(llvm::Triple("spirv64-amd-amdhsa"), true); + else + BundlerTargetArg += normalizeForBundler(TT, !ArchStr.empty()); if (!ArchStr.empty()) - BundlerTargetArg += "-" + ArchStr.str(); + BundlerTargetArg += '-' + ArchStr.str(); } BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg)); diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp index 877cb4e7b1261..c5299d606f238 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -293,6 +293,16 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, "dead-reloc-in-nonalloc=.debug_ranges=0xfffffffffffffffe"); CmdArgs.push_back("-z"); CmdArgs.push_back("dead-reloc-in-nonalloc=.debug_loc=0xfffffffffffffffe"); + + // The PlayStation loader expects linked objects to be laid out in a + // particular way. This is achieved by linker scripts that are supplied + // with the SDK. The scripts are inside /target/lib, which is + // added as a search path elsewhere. + // "PRX" has long stood for "PlayStation Relocatable eXecutable". + CmdArgs.push_back("--default-script"); + CmdArgs.push_back(Static ? "static.script" + : Shared ? "prx.script" + : "main.script"); } if (Static) diff --git a/clang/lib/Driver/XRayArgs.cpp b/clang/lib/Driver/XRayArgs.cpp index d0bb5d4887c18..c270a94f216eb 100644 --- a/clang/lib/Driver/XRayArgs.cpp +++ b/clang/lib/Driver/XRayArgs.cpp @@ -67,8 +67,12 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) { false)) { XRayShared = true; - // DSO instrumentation is currently limited to x86_64 - if (Triple.getArch() != llvm::Triple::x86_64) { + // Certain targets support DSO instrumentation + switch (Triple.getArch()) { + case llvm::Triple::aarch64: + case llvm::Triple::x86_64: + break; + default: D.Diag(diag::err_drv_unsupported_opt_for_target) << "-fxray-shared" << Triple.str(); } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 13037b6d00604..269cbef272079 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1259,7 +1259,7 @@ class AnnotatingParser { bool parseConditional() { while (CurrentToken) { - if (CurrentToken->is(tok::colon)) { + if (CurrentToken->is(tok::colon) && CurrentToken->is(TT_Unknown)) { CurrentToken->setType(TT_ConditionalExpr); next(); return true; diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 3eef3dc9b0f34..b757e20f71ffc 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -323,84 +323,69 @@ void Preprocessor::dumpMacroInfo(const IdentifierInfo *II) { } } -/// RegisterBuiltinMacro - Register the specified identifier in the identifier -/// table and mark it as a builtin macro to be expanded. -static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){ - // Get the identifier. - IdentifierInfo *Id = PP.getIdentifierInfo(Name); - - // Mark it as being a macro that is builtin. - MacroInfo *MI = PP.AllocateMacroInfo(SourceLocation()); - MI->setIsBuiltinMacro(); - PP.appendDefMacroDirective(Id, MI); - return Id; -} - /// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the /// identifier table. void Preprocessor::RegisterBuiltinMacros() { - Ident__LINE__ = RegisterBuiltinMacro(*this, "__LINE__"); - Ident__FILE__ = RegisterBuiltinMacro(*this, "__FILE__"); - Ident__DATE__ = RegisterBuiltinMacro(*this, "__DATE__"); - Ident__TIME__ = RegisterBuiltinMacro(*this, "__TIME__"); - Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__"); - Ident_Pragma = RegisterBuiltinMacro(*this, "_Pragma"); - Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro(*this, "__FLT_EVAL_METHOD__"); + Ident__LINE__ = RegisterBuiltinMacro("__LINE__"); + Ident__FILE__ = RegisterBuiltinMacro("__FILE__"); + Ident__DATE__ = RegisterBuiltinMacro("__DATE__"); + Ident__TIME__ = RegisterBuiltinMacro("__TIME__"); + Ident__COUNTER__ = RegisterBuiltinMacro("__COUNTER__"); + Ident_Pragma = RegisterBuiltinMacro("_Pragma"); + Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro("__FLT_EVAL_METHOD__"); // C++ Standing Document Extensions. if (getLangOpts().CPlusPlus) - Ident__has_cpp_attribute = - RegisterBuiltinMacro(*this, "__has_cpp_attribute"); + Ident__has_cpp_attribute = RegisterBuiltinMacro("__has_cpp_attribute"); else Ident__has_cpp_attribute = nullptr; // GCC Extensions. - Ident__BASE_FILE__ = RegisterBuiltinMacro(*this, "__BASE_FILE__"); - Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__"); - Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__"); + Ident__BASE_FILE__ = RegisterBuiltinMacro("__BASE_FILE__"); + Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro("__INCLUDE_LEVEL__"); + Ident__TIMESTAMP__ = RegisterBuiltinMacro("__TIMESTAMP__"); // Microsoft Extensions. if (getLangOpts().MicrosoftExt) { - Ident__identifier = RegisterBuiltinMacro(*this, "__identifier"); - Ident__pragma = RegisterBuiltinMacro(*this, "__pragma"); + Ident__identifier = RegisterBuiltinMacro("__identifier"); + Ident__pragma = RegisterBuiltinMacro("__pragma"); } else { Ident__identifier = nullptr; Ident__pragma = nullptr; } // Clang Extensions. - Ident__FILE_NAME__ = RegisterBuiltinMacro(*this, "__FILE_NAME__"); - Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature"); - Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension"); - Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); + Ident__FILE_NAME__ = RegisterBuiltinMacro("__FILE_NAME__"); + Ident__has_feature = RegisterBuiltinMacro("__has_feature"); + Ident__has_extension = RegisterBuiltinMacro("__has_extension"); + Ident__has_builtin = RegisterBuiltinMacro("__has_builtin"); Ident__has_constexpr_builtin = - RegisterBuiltinMacro(*this, "__has_constexpr_builtin"); - Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute"); + RegisterBuiltinMacro("__has_constexpr_builtin"); + Ident__has_attribute = RegisterBuiltinMacro("__has_attribute"); if (!getLangOpts().CPlusPlus) - Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute"); + Ident__has_c_attribute = RegisterBuiltinMacro("__has_c_attribute"); else Ident__has_c_attribute = nullptr; - Ident__has_declspec = RegisterBuiltinMacro(*this, "__has_declspec_attribute"); - Ident__has_embed = RegisterBuiltinMacro(*this, "__has_embed"); - Ident__has_include = RegisterBuiltinMacro(*this, "__has_include"); - Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next"); - Ident__has_warning = RegisterBuiltinMacro(*this, "__has_warning"); - Ident__is_identifier = RegisterBuiltinMacro(*this, "__is_identifier"); - Ident__is_target_arch = RegisterBuiltinMacro(*this, "__is_target_arch"); - Ident__is_target_vendor = RegisterBuiltinMacro(*this, "__is_target_vendor"); - Ident__is_target_os = RegisterBuiltinMacro(*this, "__is_target_os"); + Ident__has_declspec = RegisterBuiltinMacro("__has_declspec_attribute"); + Ident__has_embed = RegisterBuiltinMacro("__has_embed"); + Ident__has_include = RegisterBuiltinMacro("__has_include"); + Ident__has_include_next = RegisterBuiltinMacro("__has_include_next"); + Ident__has_warning = RegisterBuiltinMacro("__has_warning"); + Ident__is_identifier = RegisterBuiltinMacro("__is_identifier"); + Ident__is_target_arch = RegisterBuiltinMacro("__is_target_arch"); + Ident__is_target_vendor = RegisterBuiltinMacro("__is_target_vendor"); + Ident__is_target_os = RegisterBuiltinMacro("__is_target_os"); Ident__is_target_environment = - RegisterBuiltinMacro(*this, "__is_target_environment"); - Ident__is_target_variant_os = - RegisterBuiltinMacro(*this, "__is_target_variant_os"); + RegisterBuiltinMacro("__is_target_environment"); + Ident__is_target_variant_os = RegisterBuiltinMacro("__is_target_variant_os"); Ident__is_target_variant_environment = - RegisterBuiltinMacro(*this, "__is_target_variant_environment"); + RegisterBuiltinMacro("__is_target_variant_environment"); // Modules. - Ident__building_module = RegisterBuiltinMacro(*this, "__building_module"); + Ident__building_module = RegisterBuiltinMacro("__building_module"); if (!getLangOpts().CurrentModule.empty()) - Ident__MODULE__ = RegisterBuiltinMacro(*this, "__MODULE__"); + Ident__MODULE__ = RegisterBuiltinMacro("__MODULE__"); else Ident__MODULE__ = nullptr; } diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index ce8564429b380..a8365448de724 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -14,8 +14,6 @@ #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" -#include "clang/Basic/AttrKinds.h" -#include "clang/Basic/HLSLRuntime.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" @@ -164,16 +162,7 @@ struct BuiltinTypeDeclBuilder { VD, false, NameInfo, Ty, VK_PRValue); } - static Expr *emitResourceClassExpr(ASTContext &AST, ResourceClass RC) { - return IntegerLiteral::Create( - AST, - llvm::APInt(AST.getIntWidth(AST.UnsignedCharTy), - static_cast(RC)), - AST.UnsignedCharTy, SourceLocation()); - } - - BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S, - ResourceClass RC) { + BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S) { if (Record->isCompleteDefinition()) return *this; ASTContext &AST = Record->getASTContext(); @@ -480,7 +469,7 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S, bool IsROV, bool RawBuffer) { return BuiltinTypeDeclBuilder(Decl) .addHandleMember(S, RC, RK, IsROV, RawBuffer) - .addDefaultHandleConstructor(S, RC); + .addDefaultHandleConstructor(S); } void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 2b51765e80864..c5d40870c9f44 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -687,6 +687,32 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E) { << FixItHint::CreateReplacement(E->getSourceRange(), "nullptr"); } +void Sema::DiagnoseAssignmentBoolContext(Expr* E,QualType Ty) { + if (Ty->isBooleanType()) { + // `bool(x=0)` and if (x=0){} emit: + // -ImplicitCastExpr bool IntegralToBoolean + // -- ImplicitCastExpr int LValueToRValue + // --- Assignment ... + // But should still emit this warning (at least gcc does), even if bool-cast is not directly followed by assignment + // NOTE: Is this robust enough or can there be other semantic expression until the assignment? + while (auto *ICE = dyn_cast(E)) { + // If there is another implicit cast to bool then this warning would have been already emitted + if (ICE->getType()->isBooleanType()) + return; + E = ICE->getSubExpr(); + } + + if (BinaryOperator* Op = dyn_cast(E)) { + // Should only be issued for regular assignment `=`, not for compound-assign like `+=`. + // NOTE: Might make sense to emit for all assignments even if gcc only does for regular assignment + if (Op->getOpcode() == BO_Assign) { + SourceLocation Loc = Op->getOperatorLoc(); + Diag(Loc,diag::warn_assignment_bool_context) << E->getSourceRange(); + } + } + } +} + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. /// If there is already an implicit cast, merge into the existing one. /// The result is of the given category. @@ -761,6 +787,14 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, } } + // FIXME: Doesn't include C89, so this warning isn't emitted when passing `std=c99`. + auto isC = getLangOpts().C99 || getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C23; + // Do not emit this warning for Objective-C, since it's a common idiom. + // NOTE: Are there other languages that this could affect besides C and C++? + // Ideally would check `getLangOpts().Cplusplus || getLangOpts().C` but there is no option for C (only C99 etc.). + if ((getLangOpts().CPlusPlus || isC) && !getLangOpts().ObjC) + DiagnoseAssignmentBoolContext(E,Ty); + if (ImplicitCastExpr *ImpCast = dyn_cast(E)) { if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { ImpCast->setType(Ty); diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index ec43a0def9c1e..edb4c19d59745 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -12,6 +12,7 @@ #include "clang/APINotes/APINotesReader.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" @@ -415,6 +416,13 @@ static void ProcessAPINotes(Sema &S, ParmVarDecl *D, return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo()); }); + if (auto Lifetimebound = Info.isLifetimebound()) + handleAPINotedAttribute( + S, D, *Lifetimebound, Metadata, [&] { + return new (S.Context) + LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo()); + }); + // Retain count convention handleAPINotedRetainCountConvention(S, D, Metadata, Info.getRetainCountConvention()); @@ -860,13 +868,12 @@ void Sema::ProcessAPINotes(Decl *D) { if (!D) return; + auto *DC = D->getDeclContext(); // Globals. - if (D->getDeclContext()->isFileContext() || - D->getDeclContext()->isNamespace() || - D->getDeclContext()->isExternCContext() || - D->getDeclContext()->isExternCXXContext()) { + if (DC->isFileContext() || DC->isNamespace() || DC->isExternCContext() || + DC->isExternCXXContext()) { std::optional APINotesContext = - UnwindNamespaceContext(D->getDeclContext(), APINotes); + UnwindNamespaceContext(DC, APINotes); // Global variables. if (auto VD = dyn_cast(D)) { for (auto Reader : APINotes.findAPINotes(D->getLocation())) { @@ -967,8 +974,8 @@ void Sema::ProcessAPINotes(Decl *D) { } // Enumerators. - if (D->getDeclContext()->getRedeclContext()->isFileContext() || - D->getDeclContext()->getRedeclContext()->isExternCContext()) { + if (DC->getRedeclContext()->isFileContext() || + DC->getRedeclContext()->isExternCContext()) { if (auto EnumConstant = dyn_cast(D)) { for (auto Reader : APINotes.findAPINotes(D->getLocation())) { auto Info = Reader->lookupEnumConstant(EnumConstant->getName()); @@ -979,7 +986,7 @@ void Sema::ProcessAPINotes(Decl *D) { } } - if (auto ObjCContainer = dyn_cast(D->getDeclContext())) { + if (auto ObjCContainer = dyn_cast(DC)) { // Location function that looks up an Objective-C context. auto GetContext = [&](api_notes::APINotesReader *Reader) -> std::optional { @@ -1063,7 +1070,7 @@ void Sema::ProcessAPINotes(Decl *D) { } } - if (auto TagContext = dyn_cast(D->getDeclContext())) { + if (auto TagContext = dyn_cast(DC)) { if (auto CXXMethod = dyn_cast(D)) { if (!isa(CXXMethod) && !isa(CXXMethod) && diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index dae271c1ff500..d78968179b1fd 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2212,7 +2212,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (CheckBuiltinTargetInSupported( *this, TheCall, {llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::arm, - llvm::Triple::thumb, llvm::Triple::aarch64, llvm::Triple::amdgcn})) + llvm::Triple::thumb, llvm::Triple::aarch64, llvm::Triple::amdgcn, + llvm::Triple::ppc, llvm::Triple::ppc64, llvm::Triple::ppcle, + llvm::Triple::ppc64le})) return ExprError(); break; diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index e36ee06221371..bc988001ea7e4 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -975,7 +975,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( std::optional ScopeForParameters; if (const NamedDecl *ND = DeclInfo.getDecl(); ND && ND->isFunctionOrFunctionTemplate()) { - ScopeForParameters.emplace(S); + ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true); const FunctionDecl *FD = ND->getAsFunction(); for (auto *PVD : FD->parameters()) { if (!PVD->isParameterPack()) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1aa3e8edfe1b1..00c8f871bbb38 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12094,6 +12094,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (LangOpts.OpenMP) OpenMP().ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(NewFD); + if (LangOpts.isSYCL() && NewFD->hasAttr()) + getASTContext().registerSYCLEntryPointFunction(NewFD); + // Semantic checking for this function declaration (in isolation). if (getLangOpts().CPlusPlus) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 601c6f2eef1d9..a90f8706fc008 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6620,6 +6620,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_SYCLKernel: S.SYCL().handleKernelAttr(D, AL); break; + case ParsedAttr::AT_SYCLKernelEntryPoint: + S.SYCL().handleKernelEntryPointAttr(D, AL); + break; case ParsedAttr::AT_SYCLSpecialClass: handleSimpleAttribute(S, D, AL); break; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7f3cff1054aee..fea00564b919a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -20276,7 +20276,11 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) { ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr) { - DiagnoseAssignmentAsCondition(E); + // This warning is already covered by `warn_assignment_bool_context` in C++. + // NOTE: Ideally both warnings would be combined + if (!getLangOpts().CPlusPlus || getLangOpts().ObjC) + DiagnoseAssignmentAsCondition(E); + if (ParenExpr *parenE = dyn_cast(E)) DiagnoseEqualityWithExtraParens(parenE); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 50c1b24fce6da..b44b273637389 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -18,6 +18,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp index 3fa326db06ee4..ab728f24d8a27 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -971,6 +971,7 @@ class Analyzer { PendingFunctionAnalysis &CurrentFunction; CallableInfo &CurrentCaller; ViolationSite VSite; + const Expr *TrailingRequiresClause = nullptr; FunctionBodyASTVisitor(Analyzer &Outer, PendingFunctionAnalysis &CurrentFunction, @@ -985,6 +986,9 @@ class Analyzer { if (auto *Dtor = dyn_cast(CurrentCaller.CDecl)) followDestructor(dyn_cast(Dtor->getParent()), Dtor); + if (auto *FD = dyn_cast(CurrentCaller.CDecl)) + TrailingRequiresClause = FD->getTrailingRequiresClause(); + // Do an AST traversal of the function/block body TraverseDecl(const_cast(CurrentCaller.CDecl)); } @@ -1259,6 +1263,17 @@ class Analyzer { return true; } + bool TraverseStmt(Stmt *Statement) { + // If this statement is a `requires` clause from the top-level function + // being traversed, ignore it, since it's not generating runtime code. + // We skip the traversal of lambdas (beyond their captures, see + // TraverseLambdaExpr below), so just caching this from our constructor + // should suffice. + if (Statement != TrailingRequiresClause) + return Base::TraverseStmt(Statement); + return true; + } + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { ViolationSite PrevVS = VSite; if (Init->isAnyMemberInitializer()) @@ -1297,6 +1312,7 @@ class Analyzer { } bool TraverseBlockExpr(BlockExpr * /*unused*/) { + // As with lambdas, don't traverse the block's body. // TODO: are the capture expressions (ctor call?) safe? return true; } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index e2a59f63ccf58..f13355bb93cbe 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2253,6 +2253,10 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, return FlexArrayDiag != diag::ext_flexible_array_init; } +static bool isInitializedStructuredList(const InitListExpr *StructuredList) { + return StructuredList && StructuredList->getNumInits() == 1U; +} + void InitListChecker::CheckStructUnionTypes( const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, CXXRecordDecl::base_class_const_range Bases, RecordDecl::field_iterator Field, @@ -2499,8 +2503,7 @@ void InitListChecker::CheckStructUnionTypes( StructuredList, StructuredIndex); InitializedSomething = true; InitializedFields.insert(*Field); - - if (RD->isUnion() && StructuredList) { + if (RD->isUnion() && isInitializedStructuredList(StructuredList)) { // Initialize the first field within the union. StructuredList->setInitializedFieldInUnion(*Field); } @@ -2585,7 +2588,7 @@ void InitListChecker::CheckStructUnionTypes( CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); - if (RD->isUnion() && StructuredList) { + if (RD->isUnion() && isInitializedStructuredList(StructuredList)) { // Initialize the first field within the union. StructuredList->setInitializedFieldInUnion(*Field); } diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index f2d13d456c25f..e7cecebae2580 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -198,3 +198,12 @@ void SemaSYCL::handleKernelAttr(Decl *D, const ParsedAttr &AL) { handleSimpleAttribute(*this, D, AL); } + +void SemaSYCL::handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL) { + ParsedType PT = AL.getTypeArg(); + TypeSourceInfo *TSI = nullptr; + (void)SemaRef.GetTypeFromParser(PT, &TSI); + assert(TSI && "no type source info for attribute argument"); + D->addAttr(::new (SemaRef.Context) + SYCLKernelEntryPointAttr(SemaRef.Context, AL, TSI)); +} diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d4e392dcc6bcd..20edd53598e5b 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1155,6 +1155,14 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { for (unsigned I = 0; I != NumParams; ++I) Params.push_back(readDeclAs()); FD->setParams(Reader.getContext(), Params); + + // If the declaration is a SYCL kernel entry point function as indicated by + // the presence of a sycl_kernel_entry_point attribute, register it so that + // associated metadata is recreated. + if (FD->hasAttr()) { + ASTContext &C = Reader.getContext(); + C.registerSYCLEntryPointFunction(FD); + } } void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 46819d5ca1205..487cde26012e5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -108,7 +108,8 @@ std::optional isRefCountable(const clang::CXXRecordDecl *R) { } std::optional isCheckedPtrCapable(const clang::CXXRecordDecl *R) { - return isSmartPtrCompatible(R, "incrementPtrCount", "decrementPtrCount"); + return isSmartPtrCompatible(R, "incrementCheckedPtrCount", + "decrementCheckedPtrCount"); } bool isRefType(const std::string &Name) { diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 1a5a7309a54f1..177c196127c7f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -96,7 +96,8 @@ class UncountedCallArgsChecker auto name = safeGetName(MD); if (name == "ref" || name == "deref") return; - if (name == "incrementPtrCount" || name == "decrementPtrCount") + if (name == "incrementCheckedPtrCount" || + name == "decrementCheckedPtrCount") return; } auto *E = MemberCallExpr->getImplicitObjectArgument(); diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp index 0832bcf66145f..90c95d5cf60d8 100644 --- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp +++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp @@ -115,19 +115,19 @@ static int initialize(Lang Language) { NSLen = 0; } - if (SymIndex >= 0 && - Mapping->SymbolNames[SymIndex].qualifiedName() == QName) { - // Not a new symbol, use the same index. + if (SymIndex > 0) { assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex), [&QName](const SymbolHeaderMapping::SymbolName &S) { return S.qualifiedName() == QName; }) && "The symbol has been added before, make sure entries in the .inc " "file are grouped by symbol name!"); - } else { + } + if (SymIndex < 0 || + Mapping->SymbolNames[SymIndex].qualifiedName() != QName) { // First symbol or new symbol, increment next available index. ++SymIndex; - } + } // Else use the same index. Mapping->SymbolNames[SymIndex] = { QName.data(), NSLen, static_cast(QName.size() - NSLen)}; if (!HeaderName.empty()) diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc index 4d466013eeac3..8f20ce98152f0 100644 --- a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc +++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc @@ -232,6 +232,38 @@ SYMBOL(ssize, std::, ) SYMBOL(ssize, std::, ) SYMBOL(ssize, std::, ) SYMBOL(ssize, std::, ) +// C++ [range.access.general]: ... the customization point objects +// in [range.access] are available when the header is included. +// (see https://eel.is/c++draft/range.access#general) +SYMBOL(begin, std::ranges::, ) +SYMBOL(begin, std::ranges::, ) +SYMBOL(end, std::ranges::, ) +SYMBOL(end, std::ranges::, ) +SYMBOL(cbegin, std::ranges::, ) +SYMBOL(cbegin, std::ranges::, ) +SYMBOL(cend, std::ranges::, ) +SYMBOL(cend, std::ranges::, ) +SYMBOL(rbegin, std::ranges::, ) +SYMBOL(rbegin, std::ranges::, ) +SYMBOL(rend, std::ranges::, ) +SYMBOL(rend, std::ranges::, ) +SYMBOL(crbegin, std::ranges::, ) +SYMBOL(crbegin, std::ranges::, ) +SYMBOL(crend, std::ranges::, ) +SYMBOL(crend, std::ranges::, ) +SYMBOL(size, std::ranges::, ) +SYMBOL(size, std::ranges::, ) +SYMBOL(ssize, std::ranges::, ) +SYMBOL(ssize, std::ranges::, ) +SYMBOL(empty, std::ranges::, ) +SYMBOL(empty, std::ranges::, ) +SYMBOL(data, std::ranges::, ) +SYMBOL(data, std::ranges::, ) +SYMBOL(cdata, std::ranges::, ) +SYMBOL(cdata, std::ranges::, ) + +// Ignore specializations +SYMBOL(hash, std::, ) // Add headers for generic integer-type abs. // Ignore other variants (std::complex, std::valarray, std::intmax_t) @@ -352,20 +384,23 @@ SYMBOL(get, std::, /*no headers*/) // providing the type. SYMBOL(make_error_code, std::, /*no headers*/) SYMBOL(make_error_condition, std::, /*no headers*/) +// Similar to std::get, has variants for multiple containers +// (vector, deque, list, etc.) +SYMBOL(erase, std::, /*no headers*/) +SYMBOL(erase_if, std::, /*no headers*/) // cppreference symbol index page was missing these symbols. // Remove them when the cppreference offline archive catches up. -SYMBOL(index_sequence, std::, ) -SYMBOL(index_sequence_for, std::, ) -SYMBOL(make_index_sequence, std::, ) -SYMBOL(make_integer_sequence, std::, ) +SYMBOL(regular_invocable, std::, ) // Symbols missing from the generated symbol map as reported by users. // Remove when the generator starts producing them. -SYMBOL(make_any, std::, ) -SYMBOL(any_cast, std::, ) SYMBOL(div, std::, ) SYMBOL(abort, std::, ) +SYMBOL(atomic_wait, std::, ) +SYMBOL(atomic_wait_explicit, std::, ) +SYMBOL(move_backward, std::, ) +SYMBOL(month_weekday, std::chrono::, ) SYMBOL(binary_search, std::ranges::, ) SYMBOL(equal_range, std::ranges::, ) diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc index b46bd2e4d7a4b..b4afd0228694f 100644 --- a/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc +++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc @@ -6,7 +6,7 @@ // This file was generated automatically by // clang/tools/include-mapping/gen_std.py, DO NOT EDIT! // -// Generated from cppreference offline HTML book (modified on 2022-07-30). +// Generated from cppreference offline HTML book (modified on 2024-06-10). //===----------------------------------------------------------------------===// SYMBOL(ATOMIC_BOOL_LOCK_FREE, None, ) @@ -598,7 +598,6 @@ SYMBOL(aligned_union_t, std::, ) SYMBOL(alignment_of, std::, ) SYMBOL(alignment_of_v, std::, ) SYMBOL(all_of, std::, ) -SYMBOL(allocate_at_least, std::, ) SYMBOL(allocate_shared, std::, ) SYMBOL(allocate_shared_for_overwrite, std::, ) SYMBOL(allocation_result, std::, ) @@ -607,6 +606,7 @@ SYMBOL(allocator_arg, std::, ) SYMBOL(allocator_arg_t, std::, ) SYMBOL(allocator_traits, std::, ) SYMBOL(any, std::, ) +SYMBOL(any_cast, std::, ) SYMBOL(any_of, std::, ) SYMBOL(apply, std::, ) SYMBOL(arg, std::, ) @@ -727,8 +727,6 @@ SYMBOL(atomic_signal_fence, std::, ) SYMBOL(atomic_store, std::, ) SYMBOL(atomic_store_explicit, std::, ) SYMBOL(atomic_thread_fence, std::, ) -SYMBOL(atomic_wait, std::, ) -SYMBOL(atomic_wait_explicit, std::, ) SYMBOL(atto, std::, ) SYMBOL(auto_ptr, std::, ) SYMBOL(back_insert_iterator, std::, ) @@ -738,6 +736,7 @@ SYMBOL(bad_any_cast, std::, ) SYMBOL(bad_array_new_length, std::, ) SYMBOL(bad_cast, std::, ) SYMBOL(bad_exception, std::, ) +SYMBOL(bad_expected_access, std::, ) SYMBOL(bad_function_call, std::, ) SYMBOL(bad_optional_access, std::, ) SYMBOL(bad_typeid, std::, ) @@ -745,12 +744,14 @@ SYMBOL(bad_variant_access, std::, ) SYMBOL(bad_weak_ptr, std::, ) SYMBOL(barrier, std::, ) SYMBOL(basic_common_reference, std::, ) +SYMBOL(basic_const_iterator, std::, ) SYMBOL(basic_filebuf, std::, ) SYMBOL(basic_filebuf, std::, ) SYMBOL(basic_format_arg, std::, ) SYMBOL(basic_format_args, std::, ) SYMBOL(basic_format_context, std::, ) SYMBOL(basic_format_parse_context, std::, ) +SYMBOL(basic_format_string, std::, ) SYMBOL(basic_fstream, std::, ) SYMBOL(basic_fstream, std::, ) SYMBOL(basic_ifstream, std::, ) @@ -932,11 +933,13 @@ SYMBOL(conditional_t, std::, ) SYMBOL(conj, std::, ) SYMBOL(conjunction, std::, ) SYMBOL(conjunction_v, std::, ) +SYMBOL(const_iterator, std::, ) SYMBOL(const_mem_fun1_ref_t, std::, ) SYMBOL(const_mem_fun1_t, std::, ) SYMBOL(const_mem_fun_ref_t, std::, ) SYMBOL(const_mem_fun_t, std::, ) SYMBOL(const_pointer_cast, std::, ) +SYMBOL(const_sentinel, std::, ) SYMBOL(construct_at, std::, ) SYMBOL(constructible_from, std::, ) SYMBOL(contiguous_iterator, std::, ) @@ -1019,6 +1022,7 @@ SYMBOL(deci, std::, ) SYMBOL(declare_no_pointers, std::, ) SYMBOL(declare_reachable, std::, ) SYMBOL(declval, std::, ) +SYMBOL(default_accessor, std::, ) SYMBOL(default_delete, std::, ) SYMBOL(default_initializable, std::, ) SYMBOL(default_random_engine, std::, ) @@ -1040,6 +1044,7 @@ SYMBOL(destroy_n, std::, ) SYMBOL(destroying_delete, std::, ) SYMBOL(destroying_delete_t, std::, ) SYMBOL(destructible, std::, ) +SYMBOL(dextents, std::, ) SYMBOL(difftime, std::, ) SYMBOL(difftime, None, ) SYMBOL(difftime, None, ) @@ -1084,8 +1089,6 @@ SYMBOL(equal_to, std::, ) SYMBOL(equality_comparable, std::, ) SYMBOL(equality_comparable_with, std::, ) SYMBOL(equivalence_relation, std::, ) -SYMBOL(erase, std::, ) -SYMBOL(erase_if, std::, ) SYMBOL(erf, std::, ) SYMBOL(erf, None, ) SYMBOL(erf, None, ) @@ -1128,6 +1131,7 @@ SYMBOL(exp2f, None, ) SYMBOL(exp2l, std::, ) SYMBOL(exp2l, None, ) SYMBOL(exp2l, None, ) +SYMBOL(expected, std::, ) SYMBOL(expf, std::, ) SYMBOL(expf, None, ) SYMBOL(expf, None, ) @@ -1149,6 +1153,7 @@ SYMBOL(expm1l, None, ) SYMBOL(exponential_distribution, std::, ) SYMBOL(extent, std::, ) SYMBOL(extent_v, std::, ) +SYMBOL(extents, std::, ) SYMBOL(extreme_value_distribution, std::, ) SYMBOL(fabs, std::, ) SYMBOL(fabs, None, ) @@ -1249,6 +1254,10 @@ SYMBOL(find_if_not, std::, ) SYMBOL(fisher_f_distribution, std::, ) SYMBOL(fixed, std::, ) SYMBOL(fixed, std::, ) +SYMBOL(flat_map, std::, ) +SYMBOL(flat_multimap, std::, ) +SYMBOL(flat_multiset, std::, ) +SYMBOL(flat_set, std::, ) SYMBOL(float_denorm_style, std::, ) SYMBOL(float_round_style, std::, ) SYMBOL(float_t, std::, ) @@ -1314,6 +1323,7 @@ SYMBOL(format_args, std::, ) SYMBOL(format_context, std::, ) SYMBOL(format_error, std::, ) SYMBOL(format_parse_context, std::, ) +SYMBOL(format_string, std::, ) SYMBOL(format_to, std::, ) SYMBOL(format_to_n, std::, ) SYMBOL(format_to_n_result, std::, ) @@ -1410,6 +1420,7 @@ SYMBOL(gcd, std::, ) SYMBOL(generate, std::, ) SYMBOL(generate_canonical, std::, ) SYMBOL(generate_n, std::, ) +SYMBOL(generator, std::, ) SYMBOL(generic_category, std::, ) SYMBOL(geometric_distribution, std::, ) SYMBOL(get_deleter, std::, ) @@ -1456,7 +1467,6 @@ SYMBOL(has_unique_object_representations, std::, ) SYMBOL(has_unique_object_representations_v, std::, ) SYMBOL(has_virtual_destructor, std::, ) SYMBOL(has_virtual_destructor_v, std::, ) -SYMBOL(hash, std::, ) SYMBOL(hecto, std::, ) SYMBOL(hermite, std::, ) SYMBOL(hermitef, std::, ) @@ -1510,6 +1520,8 @@ SYMBOL(inclusive_scan, std::, ) SYMBOL(incrementable, std::, ) SYMBOL(incrementable_traits, std::, ) SYMBOL(independent_bits_engine, std::, ) +SYMBOL(index_sequence, std::, ) +SYMBOL(index_sequence_for, std::, ) SYMBOL(indirect_array, std::, ) SYMBOL(indirect_binary_predicate, std::, ) SYMBOL(indirect_equivalence_relation, std::, ) @@ -1663,6 +1675,7 @@ SYMBOL(is_gt, std::, ) SYMBOL(is_gteq, std::, ) SYMBOL(is_heap, std::, ) SYMBOL(is_heap_until, std::, ) +SYMBOL(is_implicit_lifetime, std::, ) SYMBOL(is_integral, std::, ) SYMBOL(is_integral_v, std::, ) SYMBOL(is_invocable, std::, ) @@ -1781,6 +1794,7 @@ SYMBOL(is_void, std::, ) SYMBOL(is_void_v, std::, ) SYMBOL(is_volatile, std::, ) SYMBOL(is_volatile_v, std::, ) +SYMBOL(is_within_lifetime, std::, ) SYMBOL(isalnum, std::, ) SYMBOL(isalnum, None, ) SYMBOL(isalnum, None, ) @@ -1849,6 +1863,7 @@ SYMBOL(istreambuf_iterator, std::, ) SYMBOL(istringstream, std::, ) SYMBOL(istringstream, std::, ) SYMBOL(istrstream, std::, ) +SYMBOL(istrstream, std::, ) SYMBOL(isunordered, std::, ) SYMBOL(isunordered, None, ) SYMBOL(isunordered, None, ) @@ -1922,6 +1937,9 @@ SYMBOL(laguerrel, std::, ) SYMBOL(latch, std::, ) SYMBOL(launch, std::, ) SYMBOL(launder, std::, ) +SYMBOL(layout_left, std::, ) +SYMBOL(layout_right, std::, ) +SYMBOL(layout_stride, std::, ) SYMBOL(lcm, std::, ) SYMBOL(lconv, std::, ) SYMBOL(lconv, None, ) @@ -2071,10 +2089,15 @@ SYMBOL(lroundf, None, ) SYMBOL(lroundl, std::, ) SYMBOL(lroundl, None, ) SYMBOL(lroundl, None, ) +SYMBOL(make_any, std::, ) +SYMBOL(make_const_iterator, std::, ) +SYMBOL(make_const_sentinel, std::, ) SYMBOL(make_exception_ptr, std::, ) SYMBOL(make_format_args, std::, ) SYMBOL(make_from_tuple, std::, ) SYMBOL(make_heap, std::, ) +SYMBOL(make_index_sequence, std::, ) +SYMBOL(make_integer_sequence, std::, ) SYMBOL(make_move_iterator, std::, ) SYMBOL(make_obj_using_allocator, std::, ) SYMBOL(make_optional, std::, ) @@ -2131,6 +2154,7 @@ SYMBOL(mbstowcs, None, ) SYMBOL(mbtowc, std::, ) SYMBOL(mbtowc, None, ) SYMBOL(mbtowc, None, ) +SYMBOL(mdspan, std::, ) SYMBOL(mega, std::, ) SYMBOL(mem_fn, std::, ) SYMBOL(mem_fun, std::, ) @@ -2198,7 +2222,6 @@ SYMBOL(moneypunct, std::, ) SYMBOL(moneypunct_byname, std::, ) SYMBOL(monostate, std::, ) SYMBOL(movable, std::, ) -SYMBOL(move_backward, std::, ) SYMBOL(move_constructible, std::, ) SYMBOL(move_if_noexcept, std::, ) SYMBOL(move_iterator, std::, ) @@ -2302,6 +2325,7 @@ SYMBOL(oct, std::, ) SYMBOL(ofstream, std::, ) SYMBOL(ofstream, std::, ) SYMBOL(once_flag, std::, ) +SYMBOL(op, std::, ) SYMBOL(open_mode, std::, ) SYMBOL(open_mode, std::, ) SYMBOL(optional, std::, ) @@ -2316,6 +2340,7 @@ SYMBOL(ostreambuf_iterator, std::, ) SYMBOL(ostringstream, std::, ) SYMBOL(ostringstream, std::, ) SYMBOL(ostrstream, std::, ) +SYMBOL(ostrstream, std::, ) SYMBOL(osyncstream, std::, ) SYMBOL(osyncstream, std::, ) SYMBOL(out_of_range, std::, ) @@ -2365,9 +2390,11 @@ SYMBOL(predicate, std::, ) SYMBOL(preferred, std::, ) SYMBOL(prev, std::, ) SYMBOL(prev_permutation, std::, ) +SYMBOL(print, std::, ) SYMBOL(printf, std::, ) SYMBOL(printf, None, ) SYMBOL(printf, None, ) +SYMBOL(println, std::, ) SYMBOL(priority_queue, std::, ) SYMBOL(proj, std::, ) SYMBOL(projected, std::, ) @@ -2397,6 +2424,8 @@ SYMBOL(putwchar, None, ) SYMBOL(qsort, std::, ) SYMBOL(qsort, None, ) SYMBOL(qsort, None, ) +SYMBOL(quecto, std::, ) +SYMBOL(quetta, std::, ) SYMBOL(queue, std::, ) SYMBOL(quick_exit, std::, ) SYMBOL(quick_exit, None, ) @@ -2445,6 +2474,8 @@ SYMBOL(recursive_mutex, std::, ) SYMBOL(recursive_timed_mutex, std::, ) SYMBOL(reduce, std::, ) SYMBOL(ref, std::, ) +SYMBOL(reference_constructs_from_temporary, std::, ) +SYMBOL(reference_converts_from_temporary, std::, ) SYMBOL(reference_wrapper, std::, ) SYMBOL(regex, std::, ) SYMBOL(regex_error, std::, ) @@ -2455,9 +2486,9 @@ SYMBOL(regex_search, std::, ) SYMBOL(regex_token_iterator, std::, ) SYMBOL(regex_traits, std::, ) SYMBOL(regular, std::, ) -SYMBOL(regular_invocable, std::, ) SYMBOL(reinterpret_pointer_cast, std::, ) SYMBOL(relation, std::, ) +SYMBOL(relaxed, std::, ) SYMBOL(remainder, std::, ) SYMBOL(remainder, None, ) SYMBOL(remainder, None, ) @@ -2528,6 +2559,8 @@ SYMBOL(rintf, None, ) SYMBOL(rintl, std::, ) SYMBOL(rintl, None, ) SYMBOL(rintl, None, ) +SYMBOL(ronna, std::, ) +SYMBOL(ronto, std::, ) SYMBOL(rotate, std::, ) SYMBOL(rotate_copy, std::, ) SYMBOL(rotl, std::, ) @@ -2705,6 +2738,7 @@ SYMBOL(stable_sort, std::, ) SYMBOL(stack, std::, ) SYMBOL(stacktrace, std::, ) SYMBOL(stacktrace_entry, std::, ) +SYMBOL(start_lifetime_as, std::, ) SYMBOL(static_pointer_cast, std::, ) SYMBOL(stod, std::, ) SYMBOL(stof, std::, ) @@ -2785,6 +2819,8 @@ SYMBOL(strstr, std::, ) SYMBOL(strstr, None, ) SYMBOL(strstr, None, ) SYMBOL(strstream, std::, ) +SYMBOL(strstream, std::, ) +SYMBOL(strstreambuf, std::, ) SYMBOL(strstreambuf, std::, ) SYMBOL(strtod, std::, ) SYMBOL(strtod, None, ) @@ -3017,6 +3053,9 @@ SYMBOL(undeclare_reachable, std::, ) SYMBOL(underflow_error, std::, ) SYMBOL(underlying_type, std::, ) SYMBOL(underlying_type_t, std::, ) +SYMBOL(unexpect, std::, ) +SYMBOL(unexpect_t, std::, ) +SYMBOL(unexpected, std::, ) SYMBOL(unexpected_handler, std::, ) SYMBOL(ungetc, std::, ) SYMBOL(ungetc, None, ) @@ -3087,6 +3126,8 @@ SYMBOL(vfwscanf, None, ) SYMBOL(visit, std::, ) SYMBOL(visit_format_arg, std::, ) SYMBOL(void_t, std::, ) +SYMBOL(vprint_nonunicode, std::, ) +SYMBOL(vprint_unicode, std::, ) SYMBOL(vprintf, std::, ) SYMBOL(vprintf, None, ) SYMBOL(vprintf, None, ) @@ -3239,6 +3280,7 @@ SYMBOL(wfilebuf, std::, ) SYMBOL(wformat_args, std::, ) SYMBOL(wformat_context, std::, ) SYMBOL(wformat_parse_context, std::, ) +SYMBOL(wformat_string, std::, ) SYMBOL(wfstream, std::, ) SYMBOL(wfstream, std::, ) SYMBOL(wifstream, std::, ) @@ -3338,6 +3380,7 @@ SYMBOL(Tuesday, std::chrono::, ) SYMBOL(Wednesday, std::chrono::, ) SYMBOL(abs, std::chrono::, ) SYMBOL(ambiguous_local_time, std::chrono::, ) +SYMBOL(ceil, std::chrono::, ) SYMBOL(choose, std::chrono::, ) SYMBOL(clock_cast, std::chrono::, ) SYMBOL(clock_time_conversion, std::chrono::, ) @@ -3349,6 +3392,8 @@ SYMBOL(duration_values, std::chrono::, ) SYMBOL(file_clock, std::chrono::, ) SYMBOL(file_seconds, std::chrono::, ) SYMBOL(file_time, std::chrono::, ) +SYMBOL(floor, std::chrono::, ) +SYMBOL(from_stream, std::chrono::, ) SYMBOL(get_leap_second_info, std::chrono::, ) SYMBOL(gps_clock, std::chrono::, ) SYMBOL(gps_seconds, std::chrono::, ) @@ -3378,11 +3423,11 @@ SYMBOL(minutes, std::chrono::, ) SYMBOL(month, std::chrono::, ) SYMBOL(month_day, std::chrono::, ) SYMBOL(month_day_last, std::chrono::, ) -SYMBOL(month_weekday, std::chrono::, ) SYMBOL(month_weekday_last, std::chrono::, ) SYMBOL(nanoseconds, std::chrono::, ) SYMBOL(nonexistent_local_time, std::chrono::, ) SYMBOL(parse, std::chrono::, ) +SYMBOL(round, std::chrono::, ) SYMBOL(seconds, std::chrono::, ) SYMBOL(steady_clock, std::chrono::, ) SYMBOL(sys_days, std::chrono::, ) @@ -3425,6 +3470,7 @@ SYMBOL(sequenced_policy, std::execution::, ) SYMBOL(unseq, std::execution::, ) SYMBOL(unsequenced_policy, std::execution::, ) SYMBOL(absolute, std::filesystem::, ) +SYMBOL(begin, std::filesystem::, ) SYMBOL(canonical, std::filesystem::, ) SYMBOL(copy, std::filesystem::, ) SYMBOL(copy_file, std::filesystem::, ) @@ -3439,6 +3485,7 @@ SYMBOL(current_path, std::filesystem::, ) SYMBOL(directory_entry, std::filesystem::, ) SYMBOL(directory_iterator, std::filesystem::, ) SYMBOL(directory_options, std::filesystem::, ) +SYMBOL(end, std::filesystem::, ) SYMBOL(equivalent, std::filesystem::, ) SYMBOL(exists, std::filesystem::, ) SYMBOL(file_size, std::filesystem::, ) @@ -3539,21 +3586,22 @@ SYMBOL(wcmatch, std::pmr::, ) SYMBOL(wsmatch, std::pmr::, ) SYMBOL(wstring, std::pmr::, ) SYMBOL(adjacent_find, std::ranges::, ) +SYMBOL(adjacent_transform_view, std::ranges::, ) +SYMBOL(adjacent_view, std::ranges::, ) SYMBOL(advance, std::ranges::, ) SYMBOL(all_of, std::ranges::, ) SYMBOL(any_of, std::ranges::, ) SYMBOL(as_const_view, std::ranges::, ) SYMBOL(as_rvalue_view, std::ranges::, ) SYMBOL(basic_istream_view, std::ranges::, ) -SYMBOL(begin, std::ranges::, ) SYMBOL(bidirectional_range, std::ranges::, ) SYMBOL(binary_transform_result, std::ranges::, ) SYMBOL(borrowed_iterator_t, std::ranges::, ) SYMBOL(borrowed_range, std::ranges::, ) SYMBOL(borrowed_subrange_t, std::ranges::, ) -SYMBOL(cbegin, std::ranges::, ) -SYMBOL(cdata, std::ranges::, ) -SYMBOL(cend, std::ranges::, ) +SYMBOL(cartesian_product_view, std::ranges::, ) +SYMBOL(chunk_by_view, std::ranges::, ) +SYMBOL(chunk_view, std::ranges::, ) SYMBOL(clamp, std::ranges::, ) SYMBOL(common_range, std::ranges::, ) SYMBOL(common_view, std::ranges::, ) @@ -3573,10 +3621,7 @@ SYMBOL(copy_n_result, std::ranges::, ) SYMBOL(copy_result, std::ranges::, ) SYMBOL(count, std::ranges::, ) SYMBOL(count_if, std::ranges::, ) -SYMBOL(crbegin, std::ranges::, ) -SYMBOL(crend, std::ranges::, ) SYMBOL(dangling, std::ranges::, ) -SYMBOL(data, std::ranges::, ) SYMBOL(destroy, std::ranges::, ) SYMBOL(destroy_at, std::ranges::, ) SYMBOL(destroy_n, std::ranges::, ) @@ -3585,11 +3630,9 @@ SYMBOL(distance, std::ranges::, ) SYMBOL(drop_view, std::ranges::, ) SYMBOL(drop_while_view, std::ranges::, ) SYMBOL(elements_view, std::ranges::, ) -SYMBOL(empty, std::ranges::, ) SYMBOL(empty_view, std::ranges::, ) SYMBOL(enable_borrowed_range, std::ranges::, ) SYMBOL(enable_view, std::ranges::, ) -SYMBOL(end, std::ranges::, ) SYMBOL(ends_with, std::ranges::, ) SYMBOL(equal, std::ranges::, ) SYMBOL(equal_to, std::ranges::, ) @@ -3604,6 +3647,12 @@ SYMBOL(find_if_not, std::ranges::, ) SYMBOL(find_last, std::ranges::, ) SYMBOL(find_last_if, std::ranges::, ) SYMBOL(find_last_if_not, std::ranges::, ) +SYMBOL(fold_left, std::ranges::, ) +SYMBOL(fold_left_first, std::ranges::, ) +SYMBOL(fold_left_first_with_iter, std::ranges::, ) +SYMBOL(fold_left_with_iter, std::ranges::, ) +SYMBOL(fold_right, std::ranges::, ) +SYMBOL(fold_right_last, std::ranges::, ) SYMBOL(for_each, std::ranges::, ) SYMBOL(for_each_n, std::ranges::, ) SYMBOL(for_each_n_result, std::ranges::, ) @@ -3611,6 +3660,7 @@ SYMBOL(for_each_result, std::ranges::, ) SYMBOL(forward_range, std::ranges::, ) SYMBOL(generate, std::ranges::, ) SYMBOL(generate_n, std::ranges::, ) +SYMBOL(get, std::ranges::, ) SYMBOL(greater, std::ranges::, ) SYMBOL(greater_equal, std::ranges::, ) SYMBOL(in_found_result, std::ranges::, ) @@ -3684,13 +3734,13 @@ SYMBOL(prev_permutation_result, std::ranges::, ) SYMBOL(push_heap, std::ranges::, ) SYMBOL(random_access_range, std::ranges::, ) SYMBOL(range, std::ranges::, ) +SYMBOL(range_adaptor_closure, std::ranges::, ) SYMBOL(range_const_reference_t, std::ranges::, ) SYMBOL(range_difference_t, std::ranges::, ) SYMBOL(range_reference_t, std::ranges::, ) SYMBOL(range_rvalue_reference_t, std::ranges::, ) SYMBOL(range_size_t, std::ranges::, ) SYMBOL(range_value_t, std::ranges::, ) -SYMBOL(rbegin, std::ranges::, ) SYMBOL(ref_view, std::ranges::, ) SYMBOL(remove, std::ranges::, ) SYMBOL(remove_copy, std::ranges::, ) @@ -3698,7 +3748,7 @@ SYMBOL(remove_copy_if, std::ranges::, ) SYMBOL(remove_copy_if_result, std::ranges::, ) SYMBOL(remove_copy_result, std::ranges::, ) SYMBOL(remove_if, std::ranges::, ) -SYMBOL(rend, std::ranges::, ) +SYMBOL(repeat_view, std::ranges::, ) SYMBOL(replace, std::ranges::, ) SYMBOL(replace_copy, std::ranges::, ) SYMBOL(replace_copy_if, std::ranges::, ) @@ -3728,15 +3778,15 @@ SYMBOL(shift_left, std::ranges::, ) SYMBOL(shift_right, std::ranges::, ) SYMBOL(shuffle, std::ranges::, ) SYMBOL(single_view, std::ranges::, ) -SYMBOL(size, std::ranges::, ) SYMBOL(sized_range, std::ranges::, ) +SYMBOL(slide_view, std::ranges::, ) SYMBOL(sort, std::ranges::, ) SYMBOL(sort_heap, std::ranges::, ) SYMBOL(split_view, std::ranges::, ) -SYMBOL(ssize, std::ranges::, ) SYMBOL(stable_partition, std::ranges::, ) SYMBOL(stable_sort, std::ranges::, ) SYMBOL(starts_with, std::ranges::, ) +SYMBOL(stride_view, std::ranges::, ) SYMBOL(subrange, std::ranges::, ) SYMBOL(subrange_kind, std::ranges::, ) SYMBOL(swap, std::ranges::, ) @@ -3773,10 +3823,15 @@ SYMBOL(viewable_range, std::ranges::, ) SYMBOL(wistream_view, std::ranges::, ) SYMBOL(zip_transform_view, std::ranges::, ) SYMBOL(zip_view, std::ranges::, ) +SYMBOL(adjacent, std::ranges::views::, ) +SYMBOL(adjacent_transform, std::ranges::views::, ) SYMBOL(all, std::ranges::views::, ) SYMBOL(all_t, std::ranges::views::, ) SYMBOL(as_const, std::ranges::views::, ) SYMBOL(as_rvalue, std::ranges::views::, ) +SYMBOL(cartesian_product, std::ranges::views::, ) +SYMBOL(chunk, std::ranges::views::, ) +SYMBOL(chunk_by, std::ranges::views::, ) SYMBOL(common, std::ranges::views::, ) SYMBOL(counted, std::ranges::views::, ) SYMBOL(drop, std::ranges::views::, ) @@ -3791,9 +3846,14 @@ SYMBOL(join, std::ranges::views::, ) SYMBOL(join_with, std::ranges::views::, ) SYMBOL(keys, std::ranges::views::, ) SYMBOL(lazy_split, std::ranges::views::, ) +SYMBOL(pairwise, std::ranges::views::, ) +SYMBOL(pairwise_transform, std::ranges::views::, ) +SYMBOL(repeat, std::ranges::views::, ) SYMBOL(reverse, std::ranges::views::, ) SYMBOL(single, std::ranges::views::, ) +SYMBOL(slide, std::ranges::views::, ) SYMBOL(split, std::ranges::views::, ) +SYMBOL(stride, std::ranges::views::, ) SYMBOL(take, std::ranges::views::, ) SYMBOL(take_while, std::ranges::views::, ) SYMBOL(transform, std::ranges::views::, ) @@ -3844,10 +3904,15 @@ SYMBOL(get_id, std::this_thread::, ) SYMBOL(sleep_for, std::this_thread::, ) SYMBOL(sleep_until, std::this_thread::, ) SYMBOL(yield, std::this_thread::, ) +SYMBOL(adjacent, std::views::, ) +SYMBOL(adjacent_transform, std::views::, ) SYMBOL(all, std::views::, ) SYMBOL(all_t, std::views::, ) SYMBOL(as_const, std::views::, ) SYMBOL(as_rvalue, std::views::, ) +SYMBOL(cartesian_product, std::views::, ) +SYMBOL(chunk, std::views::, ) +SYMBOL(chunk_by, std::views::, ) SYMBOL(common, std::views::, ) SYMBOL(counted, std::views::, ) SYMBOL(drop, std::views::, ) @@ -3862,9 +3927,14 @@ SYMBOL(join, std::views::, ) SYMBOL(join_with, std::views::, ) SYMBOL(keys, std::views::, ) SYMBOL(lazy_split, std::views::, ) +SYMBOL(pairwise, std::views::, ) +SYMBOL(pairwise_transform, std::views::, ) +SYMBOL(repeat, std::views::, ) SYMBOL(reverse, std::views::, ) SYMBOL(single, std::views::, ) +SYMBOL(slide, std::views::, ) SYMBOL(split, std::views::, ) +SYMBOL(stride, std::views::, ) SYMBOL(take, std::views::, ) SYMBOL(take_while, std::views::, ) SYMBOL(transform, std::views::, ) diff --git a/clang/test/APINotes/Inputs/Headers/Lifetimebound.apinotes b/clang/test/APINotes/Inputs/Headers/Lifetimebound.apinotes new file mode 100644 index 0000000000000..d07d87cf02f02 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Lifetimebound.apinotes @@ -0,0 +1,14 @@ +--- +Name: Lifetimebound +Functions: + - Name: funcToAnnotate + Parameters: + - Position: 0 + Lifetimebound: true +Tags: +- Name: MyClass + Methods: + - Name: methodToAnnotate + Parameters: + - Position: 0 + Lifetimebound: true diff --git a/clang/test/APINotes/Inputs/Headers/Lifetimebound.h b/clang/test/APINotes/Inputs/Headers/Lifetimebound.h new file mode 100644 index 0000000000000..2ec302f7801a7 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Lifetimebound.h @@ -0,0 +1,8 @@ +int *funcToAnnotate(int *p); + +// TODO: support annotating ctors and 'this'. +struct MyClass { + MyClass(int*); + int *annotateThis(); + int *methodToAnnotate(int *p); +}; diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap index 7d304863398ec..31f7d36356d83 100644 --- a/clang/test/APINotes/Inputs/Headers/module.modulemap +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -17,6 +17,11 @@ module Fields { export * } +module Lifetimebound { + header "Lifetimebound.h" + export * +} + module HeaderLib { header "HeaderLib.h" } diff --git a/clang/test/APINotes/lifetimebound.cpp b/clang/test/APINotes/lifetimebound.cpp new file mode 100644 index 0000000000000..3e5ce9df895b7 --- /dev/null +++ b/clang/test/APINotes/lifetimebound.cpp @@ -0,0 +1,13 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Lifetimebound -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Lifetimebound -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter funcToAnnotate -x c++ | FileCheck --check-prefix=CHECK-PARAM %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Lifetimebound -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter methodToAnnotate -x c++ | FileCheck --check-prefix=CHECK-METHOD %s +#include "Lifetimebound.h" + +// CHECK-PARAM: FunctionDecl {{.+}} funcToAnnotate +// CHECK-PARAM-NEXT: ParmVarDecl {{.+}} p +// CHECK-PARAM-NEXT: LifetimeBoundAttr + +// CHECK-METHOD: CXXMethodDecl {{.+}} methodToAnnotate +// CHECK-METHOD-NEXT: ParmVarDecl {{.+}} p +// CHECK-METHOD-NEXT: LifetimeBoundAttr diff --git a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp new file mode 100644 index 0000000000000..0929f7cb70b74 --- /dev/null +++ b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s +// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char +// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s + +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s -fexperimental-new-constant-interpreter + +// both-no-diagnostics + +typedef decltype(nullptr) nullptr_t; +typedef __INTPTR_TYPE__ intptr_t; + +static_assert(sizeof(int) == 4); +static_assert(sizeof(long long) == 8); + +template +constexpr To bit_cast(const From &from) { + static_assert(sizeof(To) == sizeof(From)); + return __builtin_bit_cast(To, from); +} + +template +constexpr bool check_round_trip(const Init &init) { + return bit_cast(bit_cast(init)) == init; +} + +template +constexpr Init round_trip(const Init &init) { + return bit_cast(bit_cast(init)); +} + + + + +namespace test_long_double { +#if __x86_64 +#if 0 +constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // expected-error{{must be initialized by a constant expression}}\ + // expected-note{{in call}} +#endif +constexpr long double ld = 3.1425926539; + +struct bytes { + unsigned char d[16]; +}; + +static_assert(round_trip(ld), ""); + +static_assert(round_trip(10.0L)); + +#if 0 +constexpr bool f(bool read_uninit) { + bytes b = bit_cast(ld); + unsigned char ld_bytes[10] = { + 0x0, 0x48, 0x9f, 0x49, 0xf0, + 0x3c, 0x20, 0xc9, 0x0, 0x40, + }; + + for (int i = 0; i != 10; ++i) + if (ld_bytes[i] != b.d[i]) + return false; + + if (read_uninit && b.d[10]) // expected-note{{read of uninitialized object is not allowed in a constant expression}} + return false; + + return true; +} + +static_assert(f(/*read_uninit=*/false), ""); +static_assert(f(/*read_uninit=*/true), ""); // expected-error{{static assertion expression is not an integral constant expression}} \ + // expected-note{{in call to 'f(true)'}} +#endif +constexpr bytes ld539 = { + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xc0, 0x86, + 0x8, 0x40, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, +}; +constexpr long double fivehundredandthirtynine = 539.0; +static_assert(bit_cast(ld539) == fivehundredandthirtynine, ""); + +struct LD { + long double v; +}; + +constexpr LD ld2 = __builtin_bit_cast(LD, ld539.d); +constexpr long double five39 = __builtin_bit_cast(long double, ld539.d); +static_assert(ld2.v == five39); + +#else +static_assert(round_trip<__int128_t>(34.0L)); +#endif +} diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp index 0e86da9133b33..7d1fcbda10965 100644 --- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp +++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp @@ -38,6 +38,13 @@ constexpr Init round_trip(const Init &init) { return bit_cast(bit_cast(init)); } + +namespace Discarding { + struct S { int a; }; + constexpr int f = (__builtin_bit_cast(int, 2), 0); + constexpr int f2 = (__builtin_bit_cast(S, 2), 0); +} + namespace std { enum byte : unsigned char {}; } // namespace std @@ -74,8 +81,21 @@ constexpr bool operator==(const struct bits& lhs, const struct bits((__int128_t)34)); static_assert(check_round_trip<__int128_t>((__int128_t)-34)); + +constexpr unsigned char OneBit[] = { + 0x1, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, +}; +constexpr __int128_t One = 1; +constexpr __int128_t Expected = One << 120; +static_assert(__builtin_bit_cast(__int128_t, OneBit) == (LITTLE_END ? 1 : Expected)); + #endif +static_assert(check_round_trip(17.0)); + namespace simple { constexpr int A = __builtin_bit_cast(int, 10); @@ -108,7 +128,7 @@ namespace simple { static_assert(check_round_trip((int)0x12345678)); static_assert(check_round_trip((int)0x87654321)); static_assert(check_round_trip((int)0x0C05FEFE)); - // static_assert(round_trip((int)0x0C05FEFE)); + static_assert(round_trip((int)0x0C05FEFE)); /// This works in GCC and in the bytecode interpreter, but the current interpreter @@ -274,7 +294,7 @@ struct int_splicer { constexpr int_splicer splice(0x0C05FEFE, 0xCAFEBABE); -#if 0 +#if 1 static_assert(bit_cast(splice) == (LITTLE_END ? 0xCAFEBABE0C05FEFE : 0x0C05FEFECAFEBABE)); @@ -284,8 +304,8 @@ static_assert(bit_cast(0xCAFEBABE0C05FEFE).x == (LITTLE_END ? 0x0C05FEFE : 0xCAFEBABE)); -static_assert(round_trip(splice)); -static_assert(round_trip(splice)); +static_assert(check_round_trip(splice)); +static_assert(check_round_trip(splice)); #endif @@ -327,13 +347,12 @@ void test_record() { ? 0xCAFEBABE0C05FEFE : 0x0C05FEFECAFEBABE)); - /// FIXME: Bit casts to composite types. - // static_assert(bit_cast(0xCAFEBABE0C05FEFE).x == (LITTLE_END - // ? 0x0C05FEFE - // : 0xCAFEBABE)); + static_assert(bit_cast(0xCAFEBABE0C05FEFE).x == (LITTLE_END + ? 0x0C05FEFE + : 0xCAFEBABE)); - // static_assert(check_round_trip(splice)); - // static_assert(check_round_trip(splice)); + static_assert(check_round_trip(splice)); + static_assert(check_round_trip(splice)); struct base2 { }; @@ -355,13 +374,14 @@ void test_record() { z == other.z && doublez == other.doublez; } }; - // constexpr bases b = {{1, 2}, {}, {3}, 4}; - // constexpr tuple4 t4 = bit_cast(b); - // static_assert(t4 == tuple4{1, 2, 3, 4}); - // static_assert(round_trip(b)); - - // constexpr auto b2 = bit_cast(t4); - // static_assert(t4 == b2); + constexpr bases b = {{1, 2}, {}, {3}, 4}; + constexpr tuple4 t4 = bit_cast(b); + static_assert(t4 == tuple4{1, 2, 3, 4}); + static_assert(check_round_trip(b)); + + /// FIXME: We need to initialize the base pointers in the pointer we're bitcasting to. +// constexpr auto b2 = bit_cast(t4); +// static_assert(t4 == b2); } void test_partially_initialized() { @@ -398,16 +418,16 @@ void bad_types() { }; static_assert(__builtin_bit_cast(int, X{0}) == 0); // both-error {{not an integral constant expression}} \ // both-note {{bit_cast from a union type is not allowed in a constant expression}} -#if 0 +#if 1 struct G { int g; }; - // expected-error@+2 {{constexpr variable 'g' must be initialized by a constant expression}} - // expected-note@+1 {{bit_cast from a union type is not allowed in a constant expression}} + // both-error@+2 {{constexpr variable 'g' must be initialized by a constant expression}} + // both-note@+1 {{bit_cast from a union type is not allowed in a constant expression}} constexpr G g = __builtin_bit_cast(G, X{0}); - // expected-error@+2 {{constexpr variable 'x' must be initialized by a constant expression}} - // expected-note@+1 {{bit_cast to a union type is not allowed in a constant expression}} + // both-error@+2 {{constexpr variable 'x' must be initialized by a constant expression}} + // both-note@+1 {{bit_cast to a union type is not allowed in a constant expression}} constexpr X x = __builtin_bit_cast(X, G{0}); #endif struct has_pointer { @@ -454,3 +474,66 @@ struct ref_mem { // both-error@+2 {{constexpr variable 'run_ref_mem' must be initialized by a constant expression}} // both-note@+1 {{bit_cast from a type with a reference member is not allowed in a constant expression}} constexpr intptr_t run_ref_mem = __builtin_bit_cast(intptr_t, ref_mem{global_int}); + +namespace test_vector { + +typedef unsigned uint2 __attribute__((vector_size(2 * sizeof(unsigned)))); +typedef char byte8 __attribute__((vector_size(sizeof(unsigned long long)))); + +constexpr uint2 test_vector = { 0x0C05FEFE, 0xCAFEBABE }; + +static_assert(bit_cast(test_vector) == (LITTLE_END + ? 0xCAFEBABE0C05FEFE + : 0x0C05FEFECAFEBABE), ""); +static_assert(check_round_trip(0xCAFEBABE0C05FEFEULL), ""); +static_assert(check_round_trip(0xCAFEBABE0C05FEFEULL), ""); + +typedef bool bool8 __attribute__((ext_vector_type(8))); +typedef bool bool9 __attribute__((ext_vector_type(9))); +typedef bool bool16 __attribute__((ext_vector_type(16))); +typedef bool bool17 __attribute__((ext_vector_type(17))); +typedef bool bool32 __attribute__((ext_vector_type(32))); +typedef bool bool128 __attribute__((ext_vector_type(128))); + +static_assert(bit_cast(bool8{1,0,1,0,1,0,1,0}) == (LITTLE_END ? 0x55 : 0xAA), ""); +constexpr bool8 b8 = __builtin_bit_cast(bool8, 0x55); // both-error {{__builtin_bit_cast source size does not equal destination size (4 vs 1)}} +#if 0 +static_assert(check_round_trip(static_cast(0)), ""); +static_assert(check_round_trip(static_cast(1)), ""); +static_assert(check_round_trip(static_cast(0x55)), ""); + +static_assert(bit_cast(bool16{1,1,1,1,1,0,0,0, 1,1,1,1,0,1,0,0}) == (LITTLE_END ? 0x2F1F : 0xF8F4), ""); + +static_assert(check_round_trip(static_cast(0xCAFE)), ""); +static_assert(check_round_trip(static_cast(0xCAFEBABE)), ""); +static_assert(check_round_trip(static_cast<__int128_t>(0xCAFEBABE0C05FEFEULL)), ""); +#endif + +#if 0 +// expected-error@+2 {{constexpr variable 'bad_bool9_to_short' must be initialized by a constant expression}} +// expected-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(9)))' (vector of 9 'bool' values) is not allowed in a constant expression; element size 1 * element count 9 is not a multiple of the byte size 8}} +constexpr unsigned short bad_bool9_to_short = __builtin_bit_cast(unsigned short, bool9{1,1,0,1,0,1,0,1,0}); +// expected-error@+2 {{constexpr variable 'bad_short_to_bool9' must be initialized by a constant expression}} +// expected-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(9)))' (vector of 9 'bool' values) is not allowed in a constant expression; element size 1 * element count 9 is not a multiple of the byte size 8}} +constexpr bool9 bad_short_to_bool9 = __builtin_bit_cast(bool9, static_cast(0)); +// expected-error@+2 {{constexpr variable 'bad_int_to_bool17' must be initialized by a constant expression}} +// expected-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(17)))' (vector of 17 'bool' values) is not allowed in a constant expression; element size 1 * element count 17 is not a multiple of the byte size 8}} +constexpr bool17 bad_int_to_bool17 = __builtin_bit_cast(bool17, 0x0001CAFEU); +#endif +} + +namespace test_complex { + constexpr _Complex unsigned test_int_complex = { 0x0C05FEFE, 0xCAFEBABE }; + static_assert(round_trip<_Complex unsigned>(0xCAFEBABE0C05FEFEULL), ""); + static_assert(bit_cast(test_int_complex) == (LITTLE_END + ? 0xCAFEBABE0C05FEFE + : 0x0C05FEFECAFEBABE), ""); + static_assert(sizeof(double) == 2 * sizeof(float)); + struct TwoFloats { float A; float B; }; + constexpr _Complex float test_float_complex = {1.0f, 2.0f}; + constexpr TwoFloats TF = __builtin_bit_cast(TwoFloats, test_float_complex); + static_assert(TF.A == 1.0f && TF.B == 2.0f); + + constexpr double D = __builtin_bit_cast(double, test_float_complex); + constexpr int M = __builtin_bit_cast(int, test_int_complex); // both-error {{__builtin_bit_cast source size does not equal destination size}} +} diff --git a/clang/test/AST/HLSL/RWBuffer-AST.hlsl b/clang/test/AST/HLSL/RWBuffer-AST.hlsl index e6ce73dbd962f..ebddd72ddb1e0 100644 --- a/clang/test/AST/HLSL/RWBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RWBuffer-AST.hlsl @@ -15,7 +15,7 @@ // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWBuffer // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// There should be no more occurrances of RWBuffer +// There should be no more occurrences of RWBuffer // EMPTY-NOT: RWBuffer #ifndef EMPTY diff --git a/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl index f95d74b30acde..4104250225aec 100644 --- a/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl @@ -16,7 +16,7 @@ // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWStructuredBuffer // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// There should be no more occurrances of RWStructuredBuffer +// There should be no more occurrences of RWStructuredBuffer // EMPTY-NOT: {{[^[:alnum:]]}}RWStructuredBuffer #ifndef EMPTY diff --git a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl index 6c39be8ba519f..42a7d1b561739 100644 --- a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl @@ -16,7 +16,7 @@ // EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class StructuredBuffer // EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// There should be no more occurrances of StructuredBuffer +// There should be no more occurrences of StructuredBuffer // EMPTY-NOT: {{[^[:alnum:]]}}StructuredBuffer #ifndef EMPTY diff --git a/clang/test/ASTSYCL/ast-dump-sycl-kernel-entry-point.cpp b/clang/test/ASTSYCL/ast-dump-sycl-kernel-entry-point.cpp new file mode 100644 index 0000000000000..c351f3b7d03ea --- /dev/null +++ b/clang/test/ASTSYCL/ast-dump-sycl-kernel-entry-point.cpp @@ -0,0 +1,144 @@ +// Tests without serialization: +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-device \ +// RUN: -ast-dump %s \ +// RUN: | FileCheck --match-full-lines %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-host \ +// RUN: -ast-dump %s \ +// RUN: | FileCheck --match-full-lines %s +// +// Tests with serialization: +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-device \ +// RUN: -emit-pch -o %t %s +// RUN: %clang_cc1 -x c++ -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-device \ +// RUN: -include-pch %t -ast-dump-all /dev/null \ +// RUN: | sed -e "s/ //" -e "s/ imported//" \ +// RUN: | FileCheck --match-full-lines %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-host \ +// RUN: -emit-pch -o %t %s +// RUN: %clang_cc1 -x c++ -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-host \ +// RUN: -include-pch %t -ast-dump-all /dev/null \ +// RUN: | sed -e "s/ //" -e "s/ imported//" \ +// RUN: | FileCheck --match-full-lines %s + +// These tests validate the AST produced for functions declared with the +// sycl_kernel_entry_point attribute. + +// CHECK: TranslationUnitDecl {{.*}} + +// A unique kernel name type is required for each declared kernel entry point. +template struct KN; + +__attribute__((sycl_kernel_entry_point(KN<1>))) +void skep1() { +} +// CHECK: |-FunctionDecl {{.*}} skep1 'void ()' +// CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN<1> + +using KN2 = KN<2>; +__attribute__((sycl_kernel_entry_point(KN2))) +void skep2() { +} +// CHECK: |-FunctionDecl {{.*}} skep2 'void ()' +// CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN2 + +template using KNT = KN; +__attribute__((sycl_kernel_entry_point(KNT<3>))) +void skep3() { +} +// CHECK: |-FunctionDecl {{.*}} skep3 'void ()' +// CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KNT<3> + +template +[[clang::sycl_kernel_entry_point(KNT)]] +void skep4(F f) { + f(); +} +// CHECK: |-FunctionTemplateDecl {{.*}} skep4 +// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} KNT +// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} F +// CHECK-NEXT: | |-FunctionDecl {{.*}} skep4 'void (F)' +// CHECK: | | `-SYCLKernelEntryPointAttr {{.*}} KNT + +void test_skep4() { + skep4>([]{}); +} +// CHECK: | `-FunctionDecl {{.*}} used skep4 'void ((lambda at {{.*}}))' implicit_instantiation +// CHECK-NEXT: | |-TemplateArgument type 'KN<4>' +// CHECK: | |-TemplateArgument type '(lambda at {{.*}})' +// CHECK: | `-SYCLKernelEntryPointAttr {{.*}} struct KN<4> +// CHECK-NEXT: |-FunctionDecl {{.*}} test_skep4 'void ()' + +template +[[clang::sycl_kernel_entry_point(KNT)]] +void skep5(T) { +} +// CHECK: |-FunctionTemplateDecl {{.*}} skep5 +// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} KNT +// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} T +// CHECK-NEXT: | |-FunctionDecl {{.*}} skep5 'void (T)' +// CHECK: | | `-SYCLKernelEntryPointAttr {{.*}} KNT + +// Checks for the explicit template instantiation declaration below. +// CHECK: | `-FunctionDecl {{.*}} skep5 'void (int)' explicit_instantiation_definition +// CHECK-NEXT: | |-TemplateArgument type 'KN<5, 4>' +// CHECK: | |-TemplateArgument type 'int' +// CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN<5, 4> + +// FIXME: C++23 [temp.expl.spec]p12 states: +// FIXME: ... Similarly, attributes appearing in the declaration of a template +// FIXME: have no effect on an explicit specialization of that template. +// FIXME: Clang currently instantiates and propagates attributes from a function +// FIXME: template to its explicit specializations resulting in the following +// FIXME: explicit specialization having an attribute incorrectly attached. +template<> +void skep5>(short) { +} +// CHECK: |-FunctionDecl {{.*}} prev {{.*}} skep5 'void (short)' explicit_specialization +// CHECK-NEXT: | |-TemplateArgument type 'KN<5, 1>' +// CHECK: | |-TemplateArgument type 'short' +// CHECK: | `-SYCLKernelEntryPointAttr {{.*}} Inherited struct KN<5, 1> + +template<> +[[clang::sycl_kernel_entry_point(KN<5,2>)]] +void skep5>(long) { +} +// CHECK: |-FunctionDecl {{.*}} prev {{.*}} skep5 'void (long)' explicit_specialization +// CHECK-NEXT: | |-TemplateArgument type 'KN<5, 2>' +// CHECK: | |-TemplateArgument type 'long' +// CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN<5, 2> + +template<> +[[clang::sycl_kernel_entry_point(KN<5,3>)]] +void skep5>(long long) { +} +// CHECK: |-FunctionDecl {{.*}} prev {{.*}} skep5 'void (long long)' explicit_specialization +// CHECK-NEXT: | |-TemplateArgument type 'KN<5, -1>' +// CHECK: | |-TemplateArgument type 'long long' +// CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN<5, 3> + +template void skep5>(int); +// Checks are located with the primary template declaration above. + +// Ensure that matching attributes from multiple declarations are ok. +[[clang::sycl_kernel_entry_point(KN<6>)]] +void skep6(); +[[clang::sycl_kernel_entry_point(KN<6>)]] +void skep6() { +} +// CHECK: |-FunctionDecl {{.*}} skep6 'void ()' +// CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<6> +// CHECK-NEXT: |-FunctionDecl {{.*}} prev {{.*}} skep6 'void ()' +// CHECK-NEXT: | |-CompoundStmt {{.*}} +// CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<6> + +// Ensure that matching attributes from the same declaration are ok. +[[clang::sycl_kernel_entry_point(KN<7>), clang::sycl_kernel_entry_point(KN<7>)]] +void skep7() { +} +// CHECK: |-FunctionDecl {{.*}} skep7 'void ()' +// CHECK-NEXT: | |-CompoundStmt {{.*}} +// CHECK-NEXT: | |-SYCLKernelEntryPointAttr {{.*}} KN<7> +// CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<7> + +void the_end() {} +// CHECK: `-FunctionDecl {{.*}} the_end 'void ()' diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h b/clang/test/Analysis/Checkers/WebKit/mock-types.h index 8d95926e419be..9c9326f0f11cf 100644 --- a/clang/test/Analysis/Checkers/WebKit/mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h @@ -146,9 +146,9 @@ template struct CheckedRef { public: CheckedRef() : t{} {}; - CheckedRef(T &t) : t(&t) { t.incrementPtrCount(); } - CheckedRef(const CheckedRef &o) : t(o.t) { if (t) t->incrementPtrCount(); } - ~CheckedRef() { if (t) t->decrementPtrCount(); } + CheckedRef(T &t) : t(&t) { t.incrementCheckedPtrCount(); } + CheckedRef(const CheckedRef &o) : t(o.t) { if (t) t->incrementCheckedPtrCount(); } + ~CheckedRef() { if (t) t->decrementCheckedPtrCount(); } T &get() { return *t; } T *ptr() { return t; } T *operator->() { return t; } @@ -165,14 +165,14 @@ template struct CheckedPtr { CheckedPtr(T *t) : t(t) { if (t) - t->incrementPtrCount(); + t->incrementCheckedPtrCount(); } CheckedPtr(Ref &&o) : t(o.leakRef()) { } ~CheckedPtr() { if (t) - t->decrementPtrCount(); + t->decrementCheckedPtrCount(); } T *get() { return t; } T *operator->() { return t; } @@ -184,16 +184,16 @@ template struct CheckedPtr { class CheckedObj { public: - void incrementPtrCount(); - void decrementPtrCount(); + void incrementCheckedPtrCount(); + void decrementCheckedPtrCount(); void method(); int trivial() { return 123; } }; class RefCountableAndCheckable { public: - void incrementPtrCount() const; - void decrementPtrCount() const; + void incrementCheckedPtrCount() const; + void decrementCheckedPtrCount() const; void ref() const; void deref() const; void method(); diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c index 57f8561a74da6..f2f8975b5f0e2 100644 --- a/clang/test/Analysis/malloc.c +++ b/clang/test/Analysis/malloc.c @@ -1829,7 +1829,7 @@ void testConstEscapeThroughAnotherField(void) { } // no-warning // PR15623 -int testNoCheckerDataPropogationFromLogicalOpOperandToOpResult(void) { +int testNoCheckerDataPropagationFromLogicalOpOperandToOpResult(void) { char *param = malloc(10); char *value = malloc(10); int ok = (param && value); diff --git a/clang/test/CodeGen/builtin_set_flt_rounds.c b/clang/test/CodeGen/builtin_set_flt_rounds.c index fc483fcc232aa..c5c8e905dbd4f 100644 --- a/clang/test/CodeGen/builtin_set_flt_rounds.c +++ b/clang/test/CodeGen/builtin_set_flt_rounds.c @@ -2,6 +2,9 @@ // RUN: %clang_cc1 -triple x86_64-windows-msvc %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple aarch64-gnu-linux %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple aarch64-windows-msvc %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix %s -emit-llvm -o - | FileCheck %s void test_builtin_set_flt_rounds() { __builtin_set_flt_rounds(1); // CHECK: call void @llvm.set.rounding(i32 1) diff --git a/clang/test/CodeGen/target-data.c b/clang/test/CodeGen/target-data.c index 26a1bf2a1a574..2dc6ead54f5f3 100644 --- a/clang/test/CodeGen/target-data.c +++ b/clang/test/CodeGen/target-data.c @@ -271,4 +271,4 @@ // RUN: %clang_cc1 -triple spirv64-amd-amdhsa -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=AMDGPUSPIRV64 -// AMDGPUSPIRV64: target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1-P4-A0" +// AMDGPUSPIRV64: target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n32:64-S32-G1-P4-A0" diff --git a/clang/test/CodeGen/ubsan-type-ignorelist-category-2.test b/clang/test/CodeGen/ubsan-type-ignorelist-category-2.test new file mode 100644 index 0000000000000..4b4f87326dbe5 --- /dev/null +++ b/clang/test/CodeGen/ubsan-type-ignorelist-category-2.test @@ -0,0 +1,58 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-0.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-1.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-2.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-3.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-4.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-5.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-6.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-7.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s + +// The same type can appear multiple times within an ignorelist. This is a test +// to make sure "=sanitize" has priority regardless of the order in which +// duplicate type entries appear. This is a precautionary measure; we would +// much rather eagerly sanitize than silently forgo sanitization. + +//--- order-0.ignorelist +type:int +type:int=sanitize + +//--- order-1.ignorelist +type:int=sanitize +type:int + +//--- order-2.ignorelist +type:in* +type:int=sanitize + +//--- order-3.ignorelist +type:in*=sanitize +type:int + +//--- order-4.ignorelist +type:int +type:in*=sanitize + +//--- order-5.ignorelist +type:int=sanitize +type:in* + +//--- order-6.ignorelist +type:int=sanitize +type:in* + +//--- order-7.ignorelist +type:int +type:int=sanitize + + + + +//--- test.c +// CHECK-LABEL: @test +void test(int A) { +// CHECK: @llvm.sadd.with.overflow.i32 + ++A; +} diff --git a/clang/test/CodeGen/ubsan-type-ignorelist-category.test b/clang/test/CodeGen/ubsan-type-ignorelist-category.test new file mode 100644 index 0000000000000..500c58f2165c4 --- /dev/null +++ b/clang/test/CodeGen/ubsan-type-ignorelist-category.test @@ -0,0 +1,98 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// Verify ubsan doesn't emit checks for ignorelisted types +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/int.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/nosection.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/nosan-same-as-no-category.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/myty.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=MYTY +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=implicit-signed-integer-truncation,implicit-unsigned-integer-truncation -fsanitize-ignorelist=%t/trunc.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=TRUNC +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=implicit-signed-integer-truncation,implicit-unsigned-integer-truncation -fsanitize-ignorelist=%t/docs.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=TRUNC2 + +//--- int.ignorelist +[{unsigned-integer-overflow,signed-integer-overflow}] +type:int + +//--- nosection.ignorelist +type:int + +//--- nosan-same-as-no-category.ignorelist +type:int + +//--- myty.ignorelist +[{unsigned-integer-overflow,signed-integer-overflow}] +type:* +type:myty=sanitize + +//--- trunc.ignorelist +[{implicit-signed-integer-truncation,implicit-unsigned-integer-truncation}] +type:char +type:unsigned char + +//--- docs.ignorelist +[implicit-signed-integer-truncation] +type:* +type:T=sanitize + +//--- test.cpp +// INT-LABEL: ignore_int +void ignore_int(int A, int B, unsigned C, unsigned D, long E) { +// INT: llvm.uadd.with.overflow.i32 + (void)(C+D); +// INT-NOT: llvm.sadd.with.overflow.i32 + (void)(A+B); +// INT: llvm.sadd.with.overflow.i64 + (void)(++E); +} + + +typedef unsigned long myty; +typedef myty derivative; +// INT-LABEL: ignore_all_except_myty +// MYTY-LABEL: ignore_all_except_myty +void ignore_all_except_myty(myty A, myty B, int C, unsigned D, derivative E) { +// MYTY-NOT: llvm.sadd.with.overflow.i32 + (void)(++C); + +// MYTY-NOT: llvm.uadd.with.overflow.i32 + (void)(D+D); + +// MYTY-NOT: llvm.umul.with.overflow.i64 + (void)(E*2); + +// MYTY: llvm.uadd.with.overflow.i64 + (void)(A+B); +} + +// INT-LABEL: truncation +// MYTY-LABEL: truncation +// TRUNC-LABEL: truncation +void truncation(char A, int B, unsigned char C, short D) { +// TRUNC-NOT: %handler.implicit_conversion + A = B; +// TRUNC-NOT: %handler.implicit_conversion + A = C; +// TRUNC-NOT: %handler.implicit_conversion + C = B; + +// TRUNC: %handler.implicit_conversion + D = B; + + (void)A; + (void)D; +} + + +// Matches the example from clang/docs/SanitizerSpecialCaseList.rst +typedef char T; +typedef char U; +// TRUNC2-LABEL: docs_example +void docs_example(int toobig) { +// TRUNC2: %handler.implicit_conversion + T a = toobig; +// TRUNC2-NOT: %handler.implicit_conversion + U b = toobig; +// TRUNC2-NOT: %handler.implicit_conversion + char c = toobig; +} + diff --git a/clang/test/CodeGen/ubsan-type-ignorelist-enum.test b/clang/test/CodeGen/ubsan-type-ignorelist-enum.test new file mode 100644 index 0000000000000..d041c79bbcafd --- /dev/null +++ b/clang/test/CodeGen/ubsan-type-ignorelist-enum.test @@ -0,0 +1,33 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=enum -fsanitize-ignorelist=%t/ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --implicit-check-not="call void @__ubsan_handle" + +//--- ignorelist +[enum] +type:IgnoreEnum + +//--- test.cpp +enum IgnoreEnum { + A, + B, + C, +}; + +// CHECK-LABEL: define dso_local noundef i32 @_Z6ignore10IgnoreEnum +int ignore(IgnoreEnum v) { + return v; +} + + +enum CheckEnum { + X, + Y, + Z, +}; + +// CHECK-LABEL: define dso_local noundef i32 @_Z5check9CheckEnum +// CHECK: call void @__ubsan_handle_load_invalid_value_abort +int check(CheckEnum v) { + return v; +} diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl index 16120a44a9e4d..d737d76a9d8d9 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl @@ -1,22 +1,39 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL +// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPIRV // NOTE: The type name number and whether the struct is packed or not will mostly // likely change once subscript operators are properly implemented (llvm/llvm-project#95956) // and theinterim field of the contained type is removed. -// CHECK: %"class.hlsl::RWBuffer" = type <{ target("dx.TypedBuffer", i16, 1, 0, 1) -// CHECK: %"class.hlsl::RWBuffer.0" = type <{ target("dx.TypedBuffer", i16, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", i32, 1, 0, 1) -// CHECK: %"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i32, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 1) -// CHECK: %"class.hlsl::RWBuffer.5" = type { target("dx.TypedBuffer", i64, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.6" = type <{ target("dx.TypedBuffer", half, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.8" = type { target("dx.TypedBuffer", float, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.9" = type { target("dx.TypedBuffer", double, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.10" = type { target("dx.TypedBuffer", <4 x i16>, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.11" = type { target("dx.TypedBuffer", <3 x i32>, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.12" = type { target("dx.TypedBuffer", <2 x half>, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.13" = type { target("dx.TypedBuffer", <3 x float>, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer" = type <{ target("dx.TypedBuffer", i16, 1, 0, 1) +// DXIL: %"class.hlsl::RWBuffer.0" = type <{ target("dx.TypedBuffer", i16, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", i32, 1, 0, 1) +// DXIL: %"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i32, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 1) +// DXIL: %"class.hlsl::RWBuffer.5" = type { target("dx.TypedBuffer", i64, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.6" = type <{ target("dx.TypedBuffer", half, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.8" = type { target("dx.TypedBuffer", float, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.9" = type { target("dx.TypedBuffer", double, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.10" = type { target("dx.TypedBuffer", <4 x i16>, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.11" = type { target("dx.TypedBuffer", <3 x i32>, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.12" = type { target("dx.TypedBuffer", <2 x half>, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.13" = type { target("dx.TypedBuffer", <3 x float>, 1, 0, 0) + +// SPIRV: %"class.hlsl::RWBuffer" = type <{ target("spirv.Image", i16, 5, 2, 0, 0, 2, 0), i16, [6 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.0" = type <{ target("spirv.Image", i16, 5, 2, 0, 0, 2, 0), i16, [6 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.2" = type <{ target("spirv.Image", i32, 5, 2, 0, 0, 2, 0), i32, [4 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.4" = type <{ target("spirv.Image", i32, 5, 2, 0, 0, 2, 0), i32, [4 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.6" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 0), i64 } +// SPIRV: %"class.hlsl::RWBuffer.7" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 0), i64 } +// SPIRV: %"class.hlsl::RWBuffer.8" = type <{ target("spirv.Image", half, 5, 2, 0, 0, 2, 0), half, [6 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.10" = type <{ target("spirv.Image", float, 5, 2, 0, 0, 2, 0), float, [4 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.12" = type { target("spirv.Image", double, 5, 2, 0, 0, 2, 0), double } +// SPIRV: %"class.hlsl::RWBuffer.13" = type { target("spirv.Image", i16, 5, 2, 0, 0, 2, 0), <4 x i16> } +// SPIRV: %"class.hlsl::RWBuffer.14" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 0), <3 x i32> } +// SPIRV: %"class.hlsl::RWBuffer.15" = type <{ target("spirv.Image", half, 5, 2, 0, 0, 2, 0), <2 x half>, [4 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.17" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 0), <3 x float> } + + RWBuffer BufI16; RWBuffer BufU16; diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl index bf5f2971cf118..9132cc8a717e0 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl @@ -638,7 +638,7 @@ void test_get_workgroup_size(int d, global int *out) // CHECK-LABEL: @test_get_grid_size( // CHECK: {{.*}}call align 4 dereferenceable(64){{.*}} ptr addrspace(4) @llvm.amdgcn.dispatch.ptr() -// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 %.sink +// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 %{{.+}} // CHECK: load i32, ptr addrspace(4) %{{.*}}, align 4, !invariant.load void test_get_grid_size(int d, global int *out) { diff --git a/clang/test/Driver/XRay/xray-shared.cpp b/clang/test/Driver/XRay/xray-shared.cpp index e331fefed1e0c..820c5b363d2c6 100644 --- a/clang/test/Driver/XRay/xray-shared.cpp +++ b/clang/test/Driver/XRay/xray-shared.cpp @@ -1,15 +1,21 @@ +// Check supported targets // RUN: %clang -### --target=x86_64-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s +// RUN: %clang -### --target=aarch64-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s + +// Check unsupported targets +// RUN: not %clang -### --target=arm-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET +// RUN: not %clang -### --target=mips-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET +// RUN: not %clang -### --target=loongarch64-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET +// RUN: not %clang -### --target=hexagon-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET +// RUN: not %clang -### --target=powerpc64le-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET + +// Check PIC requirement // RUN: %clang -### --target=x86_64-unknown-linux-gnu -fpic -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fno-PIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-PIC // RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fno-pic -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-PIC - // On 64 bit darwin, PIC is always enabled // RUN: %clang -### --target=x86_64-apple-darwin -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s -// Check unsupported targets -// RUN: not %clang -### --target=aarch64-pc-freebsd -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET -// RUN: not %clang -### --target=arm64-apple-macos -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET - // CHECK: "-cc1" {{.*}}"-fxray-instrument" {{.*}}"-fxray-shared" // ERR-TARGET: error: unsupported option '-fxray-shared' for target // ERR-PIC: error: option '-fxray-shared' cannot be specified without '-fPIC' diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c index fd15552715cb3..2cfbe256bc745 100644 --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -606,6 +606,7 @@ // RUN: %clang -### -S -fjmc -g --target=x86_64-unknown-linux %s 2>&1 | FileCheck -check-prefix=CHECK_JMC %s // RUN: %clang -### -S -fjmc -g -fno-jmc --target=x86_64-unknown-linux %s 2>&1 | FileCheck -check-prefix=CHECK_NOJMC %s // RUN: %clang -### -fjmc -g -flto -fuse-ld=lld --target=x86_64-pc-windows-msvc %s 2>&1 | FileCheck -check-prefix=CHECK_NOJMC_LTO %s +// RUN: %clang -### -fjmc -g -flto -fuse-ld=lld-link --target=x86_64-pc-windows-msvc %s 2>&1 | FileCheck -check-prefix=CHECK_NOJMC_LTO %s // RUN: %clang -### -fjmc -g -flto --target=x86_64-unknown-linux %s 2>&1 | FileCheck -check-prefix=CHECK_JMC_LTO %s // RUN: %clang -### -fjmc -g -flto -fno-jmc --target=x86_64-unknown-linux %s 2>&1 | FileCheck -check-prefix=CHECK_NOJMC_LTO %s // CHECK_JMC_WARN: -fjmc requires debug info. Use -g or debug options that enable debugger's stepping function; option ignored diff --git a/clang/test/Driver/hip-toolchain-no-rdc.hip b/clang/test/Driver/hip-toolchain-no-rdc.hip index 0cdc82ead6540..4a91c9dbe7570 100644 --- a/clang/test/Driver/hip-toolchain-no-rdc.hip +++ b/clang/test/Driver/hip-toolchain-no-rdc.hip @@ -36,6 +36,11 @@ // RUN: %t/a.o %t/b.o \ // RUN: 2>&1 | FileCheck -check-prefixes=LKONLY %s +// RUN: %clang -### --target=x86_64-linux-gnu \ +// RUN: --offload-arch=amdgcnspirv --offload-arch=gfx900 \ +// RUN: %s -nogpuinc -nogpulib \ +// RUN: 2>&1 | FileCheck -check-prefixes=AMDGCNSPIRV %s + // // Compile device code in a.cu to code object for gfx803. // @@ -177,3 +182,16 @@ // LKONLY-NOT: {{".*/llc"}} // LKONLY: [[LD:".*ld.*"]] {{.*}} "{{.*/a.o}}" "{{.*/b.o}}" // LKONLY-NOT: "-T" "{{.*}}.lk" + +// +// Check mixed AMDGCNSPIRV and concrete GPU arch. +// + +// AMDGCNSPIRV: "-cc1" "-triple" "spirv64-amd-amdhsa" {{.*}}"-emit-obj" {{.*}} "-o" "[[AMDGCNSPV_OBJ:.*o]]" +// AMDGCNSPIRV: {{".*llvm-link.*"}} "-o" "[[AMDGCNSPV_TMP:.*out]]" "[[AMDGCNSPV_OBJ]]" +// AMDGCNSPIRV: {{".*llvm-spirv.*"}} "--spirv-max-version=1.6" "--spirv-ext=+all" {{.*}} "[[AMDGCNSPV_TMP]]" {{.*}}"-o" "[[AMDGCNSPV_CO:.*out]]" +// AMDGCNSPIRV: "-cc1" "-triple" "amdgcn-amd-amdhsa" {{.*}}"-emit-obj" {{.*}}"-target-cpu" "gfx900"{{.*}} "-o" "[[GFX900_OBJ:.*o]]" +// AMDGCNSPIRV: {{".*lld.*"}} {{.*}}"-plugin-opt=mcpu=gfx900" {{.*}} "-o" "[[GFX900_CO:.*out]]" {{.*}}"[[GFX900_OBJ]]" +// AMDGCNSPIRV: {{".*clang-offload-bundler.*"}} "-type=o" +// AMDGCNSPIRV-SAME: "-targets={{.*}}hipv4-spirv64-amd-amdhsa--amdgcnspirv,hipv4-amdgcn-amd-amdhsa--gfx900" +// AMDGCNSPIRV-SAME: "-input=[[AMDGCNSPV_CO]]" "-input=[[GFX900_CO]]" diff --git a/clang/test/Driver/ps5-linker.c b/clang/test/Driver/ps5-linker.c index 0fcc0f02f5a90..363c431b6937e 100644 --- a/clang/test/Driver/ps5-linker.c +++ b/clang/test/Driver/ps5-linker.c @@ -66,6 +66,19 @@ // CHECK-NO-EXE-NOT: "--unresolved-symbols // CHECK-NO-EXE-NOT: "-z" +// Test that an appropriate linker script is supplied by the driver. + +// RUN: %clang --target=x86_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-SCRIPT -DSCRIPT=main %s +// RUN: %clang --target=x86_64-sie-ps5 %s -shared -### 2>&1 | FileCheck --check-prefixes=CHECK-SCRIPT -DSCRIPT=prx %s +// RUN: %clang --target=x86_64-sie-ps5 %s -static -### 2>&1 | FileCheck --check-prefixes=CHECK-SCRIPT -DSCRIPT=static %s +// RUN: %clang --target=x86_64-sie-ps5 %s -r -### 2>&1 | FileCheck --check-prefixes=CHECK-NO-SCRIPT %s + +// CHECK-SCRIPT: {{ld(\.exe)?}}" +// CHECK-SCRIPT-SAME: "--default-script" "[[SCRIPT]].script" + +// CHECK-NO-SCRIPT: {{ld(\.exe)?}}" +// CHECK-NO-SCRIPT-NOT: "--default-script" + // Test that -static is forwarded to the linker // RUN: %clang --target=x86_64-sie-ps5 -static %s -### 2>&1 | FileCheck --check-prefixes=CHECK-STATIC %s diff --git a/clang/test/Driver/windows-lto.c b/clang/test/Driver/windows-lto.c new file mode 100644 index 0000000000000..f85b0438ee4b1 --- /dev/null +++ b/clang/test/Driver/windows-lto.c @@ -0,0 +1,9 @@ +// RUN: %clang --target=aarch64-pc-windows-msvc -O3 -flto -fuse-ld=lld -### %s 2>&1 | FileCheck %s +// RUN: %clang --target=aarch64-pc-windows-msvc -O3 -flto=thin -fuse-ld=lld -### %s 2>&1 | FileCheck %s + +// RUN: %clang --target=aarch64-pc-windows-msvc -O3 -flto -fuse-ld=lld-link -### %s 2>&1 | FileCheck %s +// RUN: %clang --target=aarch64-pc-windows-msvc -O3 -flto=thin -fuse-ld=lld-link -### %s 2>&1 | FileCheck %s + +// CHECK: "{{.*}}lld-link{{(.exe)?}}" "-out:a.exe" "-defaultlib:libcmt" "-defaultlib:oldnames" + +int main() { return 0; } diff --git a/clang/test/Headers/lasxintrin.c b/clang/test/Headers/lasxintrin.c index 6126c6350455c..08f71791bdf36 100644 --- a/clang/test/Headers/lasxintrin.c +++ b/clang/test/Headers/lasxintrin.c @@ -1,6 +1,5 @@ // RUN: %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lasx -// RUN: not %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lasx -flax-vector-conversions=none -// RUN: not %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lasx -flax-vector-conversions=none -fno-signed-char -// FIXME: "not" should be removed once we fix GH#110834. +// RUN: %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lasx -flax-vector-conversions=none +// RUN: %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lasx -flax-vector-conversions=none -fno-signed-char #include diff --git a/clang/test/Headers/lsxintrin.c b/clang/test/Headers/lsxintrin.c index 930d3efe62e54..83c9879eea967 100644 --- a/clang/test/Headers/lsxintrin.c +++ b/clang/test/Headers/lsxintrin.c @@ -1,6 +1,5 @@ // RUN: %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lsx -// RUN: not %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lsx -flax-vector-conversions=none -// RUN: not %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lsx -flax-vector-conversions=none -fno-signed-char -// FIXME: "not" should be removed once we fix GH#110834. +// RUN: %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lsx -flax-vector-conversions=none +// RUN: %clang_cc1 %s -fsyntax-only -triple loongarch64 -target-feature +lsx -flax-vector-conversions=none -fno-signed-char #include diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index e28b0775410c0..3f1977d4d408b 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -178,6 +178,7 @@ // CHECK-NEXT: ReturnTypestate (SubjectMatchRule_function, SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: ReturnsNonNull (SubjectMatchRule_objc_method, SubjectMatchRule_function) // CHECK-NEXT: ReturnsTwice (SubjectMatchRule_function) +// CHECK-NEXT: SYCLKernelEntryPoint (SubjectMatchRule_function) // CHECK-NEXT: SYCLSpecialClass (SubjectMatchRule_record) // CHECK-NEXT: ScopedLockable (SubjectMatchRule_record) // CHECK-NEXT: Section (SubjectMatchRule_function, SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property) diff --git a/clang/test/Sema/attr-nonblocking-constraints.cpp b/clang/test/Sema/attr-nonblocking-constraints.cpp index f23093d4dc8a9..19a4c3b7942b1 100644 --- a/clang/test/Sema/attr-nonblocking-constraints.cpp +++ b/clang/test/Sema/attr-nonblocking-constraints.cpp @@ -388,6 +388,51 @@ void nb26() [[clang::nonblocking]] { abort_wrapper(); // no diagnostic } +// --- Make sure we don't traverse a requires clause. --- + +// Apparently some requires clauses are able to be collapsed into a constant before the nonblocking +// analysis sees any function calls. This example (extracted from a real-world case where +// `operator&&` in , preceding the inclusion of ) is sufficiently complex +// to look like it contains function calls. There may be simpler examples. + +namespace ExpectedTest { + +template +inline constexpr bool is_copy_constructible_v = __is_constructible(_Tp, _Tp&); + +template +struct enable_if {}; +template +struct enable_if { + typedef _Tp type; +}; + +template +using enable_if_t = typename enable_if<_Bp, _Tp>::type; + +// Doesn't seem to matter whether the enable_if is true or false. +template > = 0> +inline bool operator&&(const E1& x, const E2& y); + +template +class expected { +public: + constexpr expected() + {} + + constexpr expected(const expected&) + requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err>) + = default; +}; + +void test() [[clang::nonblocking]] +{ + expected a; + auto b = a; +} + +} // namespace ExpectedTest + // --- nonblocking implies noexcept --- #pragma clang diagnostic warning "-Wperf-constraint-implies-noexcept" diff --git a/clang/test/SemaCXX/PR113855.cpp b/clang/test/SemaCXX/PR113855.cpp new file mode 100644 index 0000000000000..fb2a448eca045 --- /dev/null +++ b/clang/test/SemaCXX/PR113855.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct S {}; + +union U { + S x; + float y; +}; + +void f() { + new U{0,.y=1}; + // expected-warning@-1 {{mixture of designated and non-designated initializers in the same initializer list is a C99 extension}} + // expected-note@-2 {{first non-designated initializer is here}} + // expected-error@-3 {{initializer for aggregate with no elements requires explicit braces}} +} diff --git a/clang/test/SemaCXX/nullability_redecl.cpp b/clang/test/SemaCXX/nullability_redecl.cpp new file mode 100644 index 0000000000000..99bc521b89c13 --- /dev/null +++ b/clang/test/SemaCXX/nullability_redecl.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify -Wnullable-to-nonnull-conversion -I%S/Inputs + +class Foo; +using Foo1 = Foo _Nonnull; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'Foo'}} +class _Nullable Foo; +using Foo2 = Foo _Nonnull; +class Foo; +using Foo3 = Foo _Nonnull; + +template +class Bar; +using Bar1 = Bar _Nonnull; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'Bar'}} +template +class _Nullable Bar; +using Bar2 = Bar _Nonnull; +template +class Bar; +using Bar3 = Bar _Nonnull; + +namespace std { + template class unique_ptr; + using UP1 = unique_ptr _Nonnull; + class X { template friend class unique_ptr; }; + using UP2 = unique_ptr _Nonnull; + template class unique_ptr; + using UP3 = unique_ptr _Nonnull; +} diff --git a/clang/test/SemaCXX/warn-assignment-bool-context.cpp b/clang/test/SemaCXX/warn-assignment-bool-context.cpp new file mode 100644 index 0000000000000..136d5bc5e59c9 --- /dev/null +++ b/clang/test/SemaCXX/warn-assignment-bool-context.cpp @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wparentheses -verify %s +// RUN: %clang_cc1 -x c -fsyntax-only -Wparentheses -verify %s + +// INFO: This warning is only issued for C and C++. +// This file is executed 3 times once for each language mention in the run-command. + +#ifdef __cplusplus + +// Do not emit the warning for compound-assignments. +bool f(int x) { return x = 0; } // expected-warning {{suggest parentheses around assignment used as truth value}} +bool f2(int x) { return x += 0; } + +bool f3(bool x) { return x = 0; } + +void test() { + int x; + if (x = 0) {} // expected-warning {{suggest parentheses around assignment used as truth value}} + if (x = 4 && x){} // expected-warning {{suggest parentheses around assignment used as truth value}} + + (void)bool(x = 1); // expected-warning {{suggest parentheses around assignment used as truth value}} + (void)(bool)(x = 1); + + // This should still emit since the RHS is casted to `int` before being casted back to `bool`. + (void)bool(x = false); // expected-warning {{suggest parentheses around assignment used as truth value}} + + // Should only issue warning once, even if multiple implicit casts. + // FIXME: This only checks that warning occurs not how often. + (void)bool(bool(x = 1)); // expected-warning {{suggest parentheses around assignment used as truth value}} + (void)bool(int(bool(x = 1))); // expected-warning {{suggest parentheses around assignment used as truth value}} + (void)bool(int(x = 1)); + + bool _a = x = 3; // expected-warning {{suggest parentheses around assignment used as truth value}} + + // Shouldn't warn for above cases if parentheses were provided. + if ((x = 0)) {} + (void)bool((x = 1)); + bool _b= (x = 3); +} + +#elif defined(__OBJC__) + +// NOTE: This warning shouldn't affect Objective-C +#import + +BOOL f(int x) { return x = 0; } +BOOL f2(int x) { return x += 0; } + +BOOL f3(BOOL x) { return x = 0; } + +void test() { + int x; + + if (x = 0) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} + if (x = 4 && x){} // expected-warning {{using the result of an assignment as a condition without parentheses}} + + (void)(BOOL)(x = 1); + (void)(BOOL)(int)(x = 1); + + BOOL _a = x = 3; + + if ((x = 0)) {} + (void)BOOL((x = 1)); + BOOL _b= (x = 3); +} + +#else + +// NOTE: Don't know if tests allow includes. +#include + +// Do not emit the warning for compound-assignments. +bool f(int x) { return x = 0; } // expected-warning {{suggest parentheses around assignment used as truth value}} +bool f2(int x) { return x += 0; } + +bool f3(bool x) { return x = 0; } + +void test() { + int x; + + // This should emit the `warn_condition_is_assignment` warning since + // C doesn't do implicit conversion booleans for conditions + if (x = 0) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + // expected-note{{use '==' to turn this assignment into an equality comparison}} \ + // expected-note{{place parentheses around the assignment to silence this warning}} + if (x = 4 && x){} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + // expected-note{{use '==' to turn this assignment into an equality comparison}} \ + // expected-note{{place parentheses around the assignment to silence this warning}} + + (void)(bool)(x = 1); + (void)(bool)(int)(x = 1); + + + bool _a = x = 3; // expected-warning {{suggest parentheses around assignment used as truth value}} + + // Shouldn't warn for above cases if parentheses were provided. + if ((x = 0)) {} + bool _b = (x = 3); +} + +#endif diff --git a/clang/test/SemaSYCL/sycl-kernel-entry-point-attr-grammar.cpp b/clang/test/SemaSYCL/sycl-kernel-entry-point-attr-grammar.cpp new file mode 100644 index 0000000000000..c63d241163e61 --- /dev/null +++ b/clang/test/SemaSYCL/sycl-kernel-entry-point-attr-grammar.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -fsycl-is-device -verify %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 -fsyntax-only -fsycl-is-device -verify %s + +// These tests validate parsing of the sycl_kernel_entry_point argument list +// and that the single argument names a type. + +// Templates used to exercise class template specializations. +template struct ST; // #ST-decl +template using TTA = ST; // #TTA-decl + + +//////////////////////////////////////////////////////////////////////////////// +// Valid declarations. +//////////////////////////////////////////////////////////////////////////////// + +struct S1; +[[clang::sycl_kernel_entry_point(S1)]] void ok1(); + +typedef struct {} TA2; +[[clang::sycl_kernel_entry_point(TA2)]] void ok2(); + +using TA3 = struct {}; +[[clang::sycl_kernel_entry_point(TA3)]] void ok3(); + +[[clang::sycl_kernel_entry_point(ST<4>)]] void ok4(); + +[[clang::sycl_kernel_entry_point(TTA<5>)]] void ok5(); + +namespace NS6 { + struct NSS; +} +[[clang::sycl_kernel_entry_point(NS6::NSS)]] void ok6(); + +namespace { + struct UNSS7; +} +[[clang::sycl_kernel_entry_point(UNSS7)]] void ok7(); + +struct {} s; +[[clang::sycl_kernel_entry_point(decltype(s))]] void ok8(); + +template +[[clang::sycl_kernel_entry_point(KN)]] void ok9(); +void test_ok9() { + ok9(); +} + +template +[[clang::sycl_kernel_entry_point(KN)]] void ok10(); +void test_ok10() { + ok10<1, struct LS2>(); +} + +namespace NS11 { + struct NSS; +} +template +[[clang::sycl_kernel_entry_point(T)]] void ok11() {} +template<> +[[clang::sycl_kernel_entry_point(NS11::NSS)]] void ok11() {} + +struct S12; +[[clang::sycl_kernel_entry_point(S12)]] void ok12(); +[[clang::sycl_kernel_entry_point(S12)]] void ok12() {} + +template +[[clang::sycl_kernel_entry_point(T)]] void ok13(T k); +void test_ok13() { + ok13([]{}); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Invalid declarations. +//////////////////////////////////////////////////////////////////////////////// + +// expected-error@+1 {{'sycl_kernel_entry_point' attribute takes one argument}} +[[clang::sycl_kernel_entry_point]] void bad1(); + +// expected-error@+1 {{'sycl_kernel_entry_point' attribute takes one argument}} +[[clang::sycl_kernel_entry_point()]] void bad2(); + +struct B3; +// expected-error@+2 {{expected ')'}} +// expected-error@+1 {{expected ']'}} +[[clang::sycl_kernel_entry_point(B3,)]] void bad3(); + +struct B4; +// expected-error@+3 {{expected ')'}} +// expected-error@+2 {{expected ','}} +// expected-warning@+1 {{unknown attribute 'X' ignored}} +[[clang::sycl_kernel_entry_point(B4, X)]] void bad4(); + +// expected-error@+1 {{expected a type}} +[[clang::sycl_kernel_entry_point(1)]] void bad5(); + +void f6(); +// expected-error@+1 {{unknown type name 'f6'}} +[[clang::sycl_kernel_entry_point(f6)]] void bad6(); + +// expected-error@+2 {{use of class template 'ST' requires template arguments; argument deduction not allowed here}} +// expected-note@#ST-decl {{template is declared here}} +[[clang::sycl_kernel_entry_point(ST)]] void bad7(); + +// expected-error@+2 {{use of alias template 'TTA' requires template arguments; argument deduction not allowed here}} +// expected-note@#TTA-decl {{template is declared here}} +[[clang::sycl_kernel_entry_point(TTA)]] void bad8(); + +enum { + e9 +}; +// expected-error@+1 {{unknown type name 'e9'}} +[[clang::sycl_kernel_entry_point(e9)]] void bad9(); + +#if __cplusplus >= 202002L +template concept C = true; +// expected-error@+1 {{expected a type}} +[[clang::sycl_kernel_entry_point(C)]] void bad10(); + +// expected-error@+1 {{expected a type}} +[[clang::sycl_kernel_entry_point(C)]] void bad11(); +#endif + +struct B12; // #B12-decl +// FIXME: C++23 [temp.expl.spec]p12 states: +// FIXME: ... Similarly, attributes appearing in the declaration of a template +// FIXME: have no effect on an explicit specialization of that template. +// FIXME: Clang currently instantiates and propagates attributes from a function +// FIXME: template to its explicit specializations resulting in the following +// FIXME: spurious error. +// expected-error@+4 {{incomplete type 'B12' named in nested name specifier}} +// expected-note@+5 {{in instantiation of function template specialization 'bad12' requested here}} +// expected-note@#B12-decl {{forward declaration of 'B12'}} +template +[[clang::sycl_kernel_entry_point(typename T::not_found)]] void bad12() {} +template<> +void bad12() {} diff --git a/clang/test/SemaSYCL/sycl-kernel-entry-point-attr-ignored.cpp b/clang/test/SemaSYCL/sycl-kernel-entry-point-attr-ignored.cpp new file mode 100644 index 0000000000000..30de6ae0b0e6f --- /dev/null +++ b/clang/test/SemaSYCL/sycl-kernel-entry-point-attr-ignored.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only -verify %s + +// These tests validate that the sycl_kernel_entry_point attribute is ignored +// when SYCL support is not enabled. + +// A unique kernel name type is required for each declared kernel entry point. +template struct KN; + +// expected-warning@+1 {{'sycl_kernel_entry_point' attribute ignored}} +[[clang::sycl_kernel_entry_point(KN<1>)]] +void ok1(); + +// expected-warning@+2 {{'sycl_kernel_entry_point' attribute ignored}} +template +[[clang::sycl_kernel_entry_point(KNT)]] +void ok2() {} +template void ok2>(); diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp index fe8f74928fc37..dd518d283c83c 100644 --- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp +++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp @@ -702,3 +702,19 @@ class TTP; C v; } // namespace GH93099 + +namespace GH114685 { + +template struct ptr { + template + friend ptr make_item(auto &&args) + requires(sizeof(args) > 1); +}; + +template +ptr make_item(auto &&args) + requires(sizeof(args) > 1) {} + +ptr p; + +} // namespace GH114685 diff --git a/clang/tools/include-mapping/cppreference_parser.py b/clang/tools/include-mapping/cppreference_parser.py index f2ea55384fac8..9101f3dbff0f9 100644 --- a/clang/tools/include-mapping/cppreference_parser.py +++ b/clang/tools/include-mapping/cppreference_parser.py @@ -7,7 +7,7 @@ # # ===------------------------------------------------------------------------===# -from bs4 import BeautifulSoup, NavigableString +from bs4 import BeautifulSoup, NavigableString, Tag import collections import multiprocessing @@ -40,7 +40,7 @@ def _HasClass(tag, *classes): return False -def _ParseSymbolPage(symbol_page_html, symbol_name): +def _ParseSymbolPage(symbol_page_html, symbol_name, qual_name): """Parse symbol page and retrieve the include header defined in this page. The symbol page provides header for the symbol, specifically in "Defined in header
" section. An example: @@ -69,7 +69,9 @@ def _ParseSymbolPage(symbol_page_html, symbol_name): was_decl = True # Symbols are in the first cell. found_symbols = row.find("td").stripped_strings - if not symbol_name in found_symbols: + if not any( + sym == symbol_name or sym == qual_name for sym in found_symbols + ): continue headers.update(current_headers) elif _HasClass(row, "t-dsc-header"): @@ -89,6 +91,22 @@ def _ParseSymbolPage(symbol_page_html, symbol_name): return headers or all_headers +def _ParseSymbolVariant(caption): + if not (isinstance(caption, NavigableString) and "(" in caption): + return None + + if ")" in caption.text: # (locale), (algorithm), etc. + return caption.text.strip(" ()") + + second_part = caption.next_sibling + if isinstance(second_part, Tag) and second_part.name == "code": + # (std::complex), etc. + third_part = second_part.next_sibling + if isinstance(third_part, NavigableString) and third_part.text.startswith(")"): + return second_part.text + return None + + def _ParseIndexPage(index_page_html): """Parse index page. The index page lists all std symbols and hrefs to their detailed pages @@ -107,9 +125,7 @@ def _ParseIndexPage(index_page_html): # This accidentally accepts begin/end despite the (iterator) caption: the # (since C++11) note is first. They are good symbols, so the bug is unfixed. caption = symbol_href.next_sibling - variant = None - if isinstance(caption, NavigableString) and "(" in caption: - variant = caption.text.strip(" ()") + variant = _ParseSymbolVariant(caption) symbol_tt = symbol_href.find("tt") if symbol_tt: symbols.append( @@ -122,9 +138,9 @@ def _ParseIndexPage(index_page_html): return symbols -def _ReadSymbolPage(path, name): +def _ReadSymbolPage(path, name, qual_name): with open(path) as f: - return _ParseSymbolPage(f.read(), name) + return _ParseSymbolPage(f.read(), name, qual_name) def _GetSymbols(pool, root_dir, index_page_name, namespace, variants_to_accept): @@ -146,9 +162,8 @@ def _GetSymbols(pool, root_dir, index_page_name, namespace, variants_to_accept): for symbol_name, symbol_page_path, variant in _ParseIndexPage(f.read()): # Variant symbols (e.g. the std::locale version of isalpha) add ambiguity. # FIXME: use these as a fallback rather than ignoring entirely. - variants_for_symbol = variants_to_accept.get( - (namespace or "") + symbol_name, () - ) + qualified_symbol_name = (namespace or "") + symbol_name + variants_for_symbol = variants_to_accept.get(qualified_symbol_name, ()) if variant and variant not in variants_for_symbol: continue path = os.path.join(root_dir, symbol_page_path) @@ -156,7 +171,9 @@ def _GetSymbols(pool, root_dir, index_page_name, namespace, variants_to_accept): results.append( ( symbol_name, - pool.apply_async(_ReadSymbolPage, (path, symbol_name)), + pool.apply_async( + _ReadSymbolPage, (path, symbol_name, qualified_symbol_name) + ), ) ) else: @@ -192,6 +209,16 @@ def GetSymbols(parse_pages): variants_to_accept = { # std::remove<> has variant algorithm. "std::remove": ("algorithm"), + # These functions don't have a generic version, and all variants are defined in + "std::chrono::abs": ("std::chrono::duration"), + "std::chrono::ceil": ("std::chrono::duration"), + "std::chrono::floor": ("std::chrono::duration"), + "std::chrono::from_stream": ("std::chrono::day"), + "std::chrono::round": ("std::chrono::duration"), + # Same, but in + "std::filesystem::begin": ("std::filesystem::directory_iterator"), + "std::filesystem::end": ("std::filesystem::directory_iterator"), + "std::ranges::get": ("std::ranges::subrange"), } symbols = [] # Run many workers to process individual symbol pages under the symbol index. diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index cdb68b74ca79f..250e51b542166 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -24393,6 +24393,8 @@ TEST_F(FormatTest, DisableRegions) { TEST_F(FormatTest, DoNotCrashOnInvalidInput) { format("? ) ="); verifyNoCrash("#define a\\\n /**/}"); + verifyNoCrash(" tst %o5 ! are we doing the gray case?\n" + "LY52: ! [internal]"); } TEST_F(FormatTest, FormatsTableGenCode) { diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 3031d81b3df73..5a80c8c0b7ad3 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -2727,7 +2727,8 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS, } if (Header) - OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; + OS << "class CLANG_ABI " << R.getName() << "Attr : public " << SuperName + << " {\n"; else OS << "\n// " << R.getName() << "Attr implementation\n\n"; @@ -3185,7 +3186,8 @@ void clang::EmitClangAttrClass(const RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("Attribute classes' definitions", OS, Records); OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n"; - OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n"; + OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n"; + OS << "#include \"clang/Support/Compiler.h\"\n\n"; emitAttributes(Records, OS, true); diff --git a/cmake/Modules/HandleOutOfTreeLLVM.cmake b/cmake/Modules/HandleOutOfTreeLLVM.cmake deleted file mode 100644 index edffe572e091e..0000000000000 --- a/cmake/Modules/HandleOutOfTreeLLVM.cmake +++ /dev/null @@ -1,80 +0,0 @@ -if (NOT DEFINED LLVM_PATH) - set(LLVM_PATH ${CMAKE_CURRENT_LIST_DIR}/../../llvm CACHE PATH "" FORCE) -endif() - -if(NOT IS_DIRECTORY ${LLVM_PATH}) - message(FATAL_ERROR - "The provided LLVM_PATH (${LLVM_PATH}) is not a valid directory. Note that " - "building libc++ outside of the monorepo is not supported anymore. Please " - "use a Standalone build against the monorepo, a Runtimes build or a classic " - "monorepo build.") -endif() - -set(LLVM_INCLUDE_DIR ${LLVM_PATH}/include CACHE PATH "Path to llvm/include") -set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree") -set(LLVM_MAIN_SRC_DIR ${LLVM_PATH}) -set(LLVM_CMAKE_DIR "${LLVM_PATH}/cmake/modules") -set(LLVM_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) -set(LLVM_LIBRARY_OUTPUT_INTDIR "${CMAKE_CURRENT_BINARY_DIR}/lib") - -if (EXISTS "${LLVM_CMAKE_DIR}") - list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") -elseif (EXISTS "${LLVM_MAIN_SRC_DIR}/cmake/modules") - list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules") -else() - message(FATAL_ERROR "Neither ${LLVM_CMAKE_DIR} nor ${LLVM_MAIN_SRC_DIR}/cmake/modules found. " - "This is not a supported configuration.") -endif() - -message(STATUS "Configuring for standalone build.") - -# By default, we target the host, but this can be overridden at CMake invocation time. -include(GetHostTriple) -get_host_triple(LLVM_INFERRED_HOST_TRIPLE) -set(LLVM_HOST_TRIPLE "${LLVM_INFERRED_HOST_TRIPLE}" CACHE STRING "Host on which LLVM binaries will run") -set(LLVM_DEFAULT_TARGET_TRIPLE "${LLVM_HOST_TRIPLE}" CACHE STRING "Target triple used by default.") - -# Add LLVM Functions -------------------------------------------------------- -if (WIN32) - set(LLVM_ON_UNIX 0) - set(LLVM_ON_WIN32 1) -else() - set(LLVM_ON_UNIX 1) - set(LLVM_ON_WIN32 0) -endif() - -include(AddLLVM OPTIONAL) - -# LLVM Options -------------------------------------------------------------- -if (NOT DEFINED LLVM_INCLUDE_TESTS) - set(LLVM_INCLUDE_TESTS ON) -endif() -if (NOT DEFINED LLVM_INCLUDE_DOCS) - set(LLVM_INCLUDE_DOCS ON) -endif() -if (NOT DEFINED LLVM_ENABLE_SPHINX) - set(LLVM_ENABLE_SPHINX OFF) -endif() - -if (LLVM_INCLUDE_TESTS) - # Required LIT Configuration ------------------------------------------------ - # Define the default arguments to use with 'lit', and an option for the user - # to override. - set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py") - set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported") - if (MSVC OR XCODE) - set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") - endif() - set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") -endif() - -# Required doc configuration -if (LLVM_ENABLE_SPHINX) - find_package(Sphinx REQUIRED) -endif() - -if (LLVM_ON_UNIX AND NOT APPLE) - set(LLVM_HAVE_LINK_VERSION_SCRIPT 1) -else() - set(LLVM_HAVE_LINK_VERSION_SCRIPT 0) -endif() diff --git a/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/compiler-rt/cmake/Modules/AddCompilerRT.cmake index e3d81d241b105..bfa1834229baa 100644 --- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -690,7 +690,6 @@ macro(add_custom_libcxx name prefix) -DCMAKE_CXX_FLAGS=${LIBCXX_CXX_FLAGS} -DCMAKE_BUILD_TYPE=Release -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY - -DLLVM_PATH=${LLVM_MAIN_SRC_DIR} -DLLVM_ENABLE_RUNTIMES=libcxx|libcxxabi -DLIBCXXABI_USE_LLVM_UNWINDER=OFF -DLIBCXXABI_ENABLE_SHARED=OFF diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index fb4dfa7bd09df..b29ae179c2b4f 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -104,7 +104,7 @@ else() set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le ${HEXAGON} ${LOONGARCH64}) endif() -set(ALL_XRAY_DSO_SUPPORTED_ARCH ${X86_64}) +set(ALL_XRAY_DSO_SUPPORTED_ARCH ${X86_64} ${ARM64}) set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64}) if (UNIX) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 431f544e8ad6a..6d52eecc9a91f 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -37,7 +37,11 @@ check_c_compiler_flag(-nodefaultlibs C_SUPPORTS_NODEFAULTLIBS_FLAG) if (C_SUPPORTS_NODEFAULTLIBS_FLAG) set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs") if (COMPILER_RT_HAS_LIBC) - list(APPEND CMAKE_REQUIRED_LIBRARIES c) + if (HAIKU) + list(APPEND CMAKE_REQUIRED_LIBRARIES root) + else() + list(APPEND CMAKE_REQUIRED_LIBRARIES c) + endif() endif () if (COMPILER_RT_USE_BUILTINS_LIBRARY) # TODO: remote this check once we address PR51389. @@ -826,7 +830,7 @@ else() endif() if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX|WASI") + OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX|WASI|Haiku") set(COMPILER_RT_HAS_PROFILE TRUE) else() set(COMPILER_RT_HAS_PROFILE FALSE) diff --git a/compiler-rt/lib/asan/tests/CMakeLists.txt b/compiler-rt/lib/asan/tests/CMakeLists.txt index 0c4b0361ec493..998e0ff24efa4 100644 --- a/compiler-rt/lib/asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/asan/tests/CMakeLists.txt @@ -244,7 +244,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID) if(APPLE) darwin_filter_host_archs(ASAN_SUPPORTED_ARCH ASAN_TEST_ARCH) endif() - list(REMOVE_ITEM ASAN_TEST_ARCH sparc sparcv9) + list(REMOVE_ITEM ASAN_TEST_ARCH sparcv9) if(OS_NAME MATCHES "SunOS") list(REMOVE_ITEM ASAN_TEST_ARCH x86_64) endif() diff --git a/compiler-rt/lib/asan/tests/asan_oob_test.cpp b/compiler-rt/lib/asan/tests/asan_oob_test.cpp index 56f573c1fc482..ce4c90c23e84b 100644 --- a/compiler-rt/lib/asan/tests/asan_oob_test.cpp +++ b/compiler-rt/lib/asan/tests/asan_oob_test.cpp @@ -11,6 +11,13 @@ //===----------------------------------------------------------------------===// #include "asan_test_utils.h" +#ifdef __sparc__ +// Tests using unaligned accesses cannot work on strict-alignment targets. +#define SKIP_ON_STRICT_ALIGNMENT(x) DISABLED_##x +#else +#define SKIP_ON_STRICT_ALIGNMENT(x) x +#endif + NOINLINE void asan_write_sized_aligned(uint8_t *p, size_t size) { EXPECT_EQ(0U, ((uintptr_t)p % size)); if (size == 1) asan_write((uint8_t*)p); @@ -79,7 +86,7 @@ TEST(AddressSanitizer, OOB_char) { OOBTest(); } -TEST(AddressSanitizer, OOB_int) { +TEST(AddressSanitizer, SKIP_ON_STRICT_ALIGNMENT(OOB_int)) { OOBTest(); } diff --git a/compiler-rt/lib/asan/tests/asan_test.cpp b/compiler-rt/lib/asan/tests/asan_test.cpp index 827c2ae3a9cdc..09d71569f89bb 100644 --- a/compiler-rt/lib/asan/tests/asan_test.cpp +++ b/compiler-rt/lib/asan/tests/asan_test.cpp @@ -631,7 +631,7 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) { #if !defined(__ANDROID__) && !defined(__arm__) && !defined(__aarch64__) && \ !defined(__mips__) && !defined(__mips64) && !defined(__s390__) && \ - !defined(__riscv) && !defined(__loongarch__) + !defined(__riscv) && !defined(__loongarch__) && !defined(__sparc__) NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) { // create three red zones for these two stack objects. int a; diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index 077a536dd2a31..cfd92619a1e15 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -187,8 +187,12 @@ static uptr GetMmapGranularity() { return si.dwAllocationGranularity; } +UNUSED static uptr RoundDownTo(uptr size, uptr boundary) { + return size & ~(boundary - 1); +} + UNUSED static uptr RoundUpTo(uptr size, uptr boundary) { - return (size + boundary - 1) & ~(boundary - 1); + return RoundDownTo(size + boundary - 1, boundary); } // FIXME: internal_str* and internal_mem* functions should be moved from the @@ -285,8 +289,11 @@ static void WriteJumpInstruction(uptr from, uptr target) { static void WriteShortJumpInstruction(uptr from, uptr target) { sptr offset = target - from - kShortJumpInstructionLength; - if (offset < -128 || offset > 127) + if (offset < -128 || offset > 127) { + ReportError("interception_win: cannot write short jmp from %p to %p\n", + (void *)from, (void *)target); InterceptionFailed(); + } *(u8*)from = 0xEB; *(u8*)(from + 1) = (u8)offset; } @@ -340,32 +347,78 @@ struct TrampolineMemoryRegion { uptr max_size; }; -UNUSED static const uptr kTrampolineScanLimitRange = 1ull << 31; // 2 gig +UNUSED static const uptr kTrampolineRangeLimit = 1ull << 31; // 2 gig static const int kMaxTrampolineRegion = 1024; static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion]; -static void *AllocateTrampolineRegion(uptr image_address, size_t granularity) { -#if SANITIZER_WINDOWS64 - uptr address = image_address; - uptr scanned = 0; - while (scanned < kTrampolineScanLimitRange) { +static void *AllocateTrampolineRegion(uptr min_addr, uptr max_addr, + uptr func_addr, size_t granularity) { +# if SANITIZER_WINDOWS64 + // Clamp {min,max}_addr to the accessible address space. + SYSTEM_INFO system_info; + ::GetSystemInfo(&system_info); + uptr min_virtual_addr = + RoundUpTo((uptr)system_info.lpMinimumApplicationAddress, granularity); + uptr max_virtual_addr = + RoundDownTo((uptr)system_info.lpMaximumApplicationAddress, granularity); + if (min_addr < min_virtual_addr) + min_addr = min_virtual_addr; + if (max_addr > max_virtual_addr) + max_addr = max_virtual_addr; + + // This loop probes the virtual address space to find free memory in the + // [min_addr, max_addr] interval. The search starts from func_addr and + // proceeds "outwards" towards the interval bounds using two probes, lo_addr + // and hi_addr, for addresses lower/higher than func_addr. At each step, it + // considers the probe closest to func_addr. If that address is not free, the + // probe is advanced (lower or higher depending on the probe) to the next + // memory block and the search continues. + uptr lo_addr = RoundDownTo(func_addr, granularity); + uptr hi_addr = RoundUpTo(func_addr, granularity); + while (lo_addr >= min_addr || hi_addr <= max_addr) { + // Consider the in-range address closest to func_addr. + uptr addr; + if (lo_addr < min_addr) + addr = hi_addr; + else if (hi_addr > max_addr) + addr = lo_addr; + else + addr = (hi_addr - func_addr < func_addr - lo_addr) ? hi_addr : lo_addr; + MEMORY_BASIC_INFORMATION info; - if (!::VirtualQuery((void*)address, &info, sizeof(info))) + if (!::VirtualQuery((void *)addr, &info, sizeof(info))) { + ReportError( + "interception_win: VirtualQuery in AllocateTrampolineRegion failed " + "for %p\n", + (void *)addr); return nullptr; + } - // Check whether a region can be allocated at |address|. + // Check whether a region can be allocated at |addr|. if (info.State == MEM_FREE && info.RegionSize >= granularity) { - void *page = ::VirtualAlloc((void*)RoundUpTo(address, granularity), - granularity, - MEM_RESERVE | MEM_COMMIT, - PAGE_EXECUTE_READWRITE); + void *page = + ::VirtualAlloc((void *)addr, granularity, MEM_RESERVE | MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (page == nullptr) + ReportError( + "interception_win: VirtualAlloc in AllocateTrampolineRegion failed " + "for %p\n", + (void *)addr); return page; } - // Move to the next region. - address = (uptr)info.BaseAddress + info.RegionSize; - scanned += info.RegionSize; + if (addr == lo_addr) + lo_addr = + RoundDownTo((uptr)info.AllocationBase - granularity, granularity); + if (addr == hi_addr) + hi_addr = + RoundUpTo((uptr)info.BaseAddress + info.RegionSize, granularity); } + + ReportError( + "interception_win: AllocateTrampolineRegion failed to find free memory; " + "min_addr: %p, max_addr: %p, func_addr: %p, granularity: %zu\n", + (void *)min_addr, (void *)max_addr, granularity); return nullptr; #else return ::VirtualAlloc(nullptr, @@ -387,17 +440,17 @@ void TestOnlyReleaseTrampolineRegions() { } static uptr AllocateMemoryForTrampoline(uptr func_address, size_t size) { - uptr image_address = func_address; +# if SANITIZER_WINDOWS64 + uptr min_addr = func_address - kTrampolineRangeLimit; + uptr max_addr = func_address + kTrampolineRangeLimit - size; -#if SANITIZER_WINDOWS64 - // Allocate memory after the module (DLL or EXE file), but within 2GB - // of the start of the module so that any address within the module can be - // referenced with PC-relative operands. + // Allocate memory within 2GB of the module (DLL or EXE file) so that any + // address within the module can be referenced with PC-relative operands. // This allows us to not just jump to the trampoline with a PC-relative // offset, but to relocate any instructions that we copy to the trampoline // which have references to the original module. If we can't find the base // address of the module (e.g. if func_address is in mmap'ed memory), just - // use func_address as is. + // stay within 2GB of func_address. HMODULE module; if (::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, @@ -405,19 +458,32 @@ static uptr AllocateMemoryForTrampoline(uptr func_address, size_t size) { MODULEINFO module_info; if (::GetModuleInformation(::GetCurrentProcess(), module, &module_info, sizeof(module_info))) { - image_address = (uptr)module_info.lpBaseOfDll; + min_addr = (uptr)module_info.lpBaseOfDll + module_info.SizeOfImage - + kTrampolineRangeLimit; + max_addr = (uptr)module_info.lpBaseOfDll + kTrampolineRangeLimit - size; } } -#endif - // Find a region within 2G with enough space to allocate |size| bytes. + // Check for overflow. + if (min_addr > func_address) + min_addr = 0; + if (max_addr < func_address) + max_addr = ~(uptr)0; +# else + uptr min_addr = 0; + uptr max_addr = ~min_addr; +# endif + + // Find a region within [min_addr,max_addr] with enough space to allocate + // |size| bytes. TrampolineMemoryRegion *region = nullptr; for (size_t bucket = 0; bucket < kMaxTrampolineRegion; ++bucket) { TrampolineMemoryRegion* current = &TrampolineRegions[bucket]; if (current->content == 0) { // No valid region found, allocate a new region. size_t bucket_size = GetMmapGranularity(); - void *content = AllocateTrampolineRegion(image_address, bucket_size); + void *content = AllocateTrampolineRegion(min_addr, max_addr, func_address, + bucket_size); if (content == nullptr) return 0U; @@ -427,13 +493,9 @@ static uptr AllocateMemoryForTrampoline(uptr func_address, size_t size) { region = current; break; } else if (current->max_size - current->allocated_size > size) { -#if SANITIZER_WINDOWS64 - // In 64-bits, the memory space must be allocated within 2G boundary. - uptr next_address = current->content + current->allocated_size; - if (next_address < image_address || - next_address - image_address >= 0x7FFF0000) - continue; -#endif + uptr next_address = current->content + current->allocated_size; + if (next_address < min_addr || next_address > max_addr) + continue; // The space can be allocated in the current region. region = current; break; @@ -872,8 +934,14 @@ static bool CopyInstructions(uptr to, uptr from, size_t size) { // this will be untrue if relocated_offset \notin [-2**31, 2**31) s64 delta = to - from; s64 relocated_offset = *(s32 *)(to + cursor + rel_offset) - delta; - if (-0x8000'0000ll > relocated_offset || relocated_offset > 0x7FFF'FFFFll) + if (-0x8000'0000ll > relocated_offset || + relocated_offset > 0x7FFF'FFFFll) { + ReportError( + "interception_win: CopyInstructions relocated_offset %lld outside " + "32-bit range\n", + (long long)relocated_offset); return false; + } # else // on 32-bit, the relative offset will always be correct s32 delta = to - from; @@ -1167,19 +1235,27 @@ uptr InternalGetProcAddress(void *module, const char *func_name) { // exported directory. char function_name[256]; size_t funtion_name_length = _strlen(func); - if (funtion_name_length >= sizeof(function_name) - 1) + if (funtion_name_length >= sizeof(function_name) - 1) { + ReportError("interception_win: func too long: '%s'\n", func); InterceptionFailed(); + } _memcpy(function_name, func, funtion_name_length); function_name[funtion_name_length] = '\0'; char* separator = _strchr(function_name, '.'); - if (!separator) + if (!separator) { + ReportError("interception_win: no separator in '%s'\n", + function_name); InterceptionFailed(); + } *separator = '\0'; void* redirected_module = GetModuleHandleA(function_name); - if (!redirected_module) + if (!redirected_module) { + ReportError("interception_win: GetModuleHandleA failed for '%s'\n", + function_name); InterceptionFailed(); + } return InternalGetProcAddress(redirected_module, separator + 1); } diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c index e2c06d51e0c67..613cfb60857cf 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -8,7 +8,7 @@ #if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ (defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \ - defined(_AIX) || defined(__wasm__) + defined(_AIX) || defined(__wasm__) || defined(__HAIKU__) #if !defined(_AIX) && !defined(__wasm__) #include diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformOther.c b/compiler-rt/lib/profile/InstrProfilingPlatformOther.c index 52e82273f8aad..29e570b9fba92 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformOther.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformOther.c @@ -9,7 +9,7 @@ #if !defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__) && \ !defined(__Fuchsia__) && !(defined(__sun__) && defined(__svr4__)) && \ !defined(__NetBSD__) && !defined(_WIN32) && !defined(_AIX) && \ - !defined(__wasm__) + !defined(__wasm__) && !defined(__HAIKU__) #include #include diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp index a480ea23751d7..5524197216719 100644 --- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp @@ -15,12 +15,10 @@ #include "interception/interception.h" #include "sanitizer_common/sanitizer_allocator_dlsym.h" -#include "sanitizer_common/sanitizer_allocator_internal.h" #include "sanitizer_common/sanitizer_platform_interceptors.h" #include "interception/interception.h" #include "rtsan/rtsan.h" -#include "rtsan/rtsan_context.h" #if SANITIZER_APPLE @@ -33,11 +31,11 @@ extern "C" { typedef int32_t OSSpinLock; void OSSpinLockLock(volatile OSSpinLock *__lock); } -#endif +#endif // TARGET_OS_MAC #include #include -#endif +#endif // SANITIZER_APPLE #if SANITIZER_INTERCEPT_MEMALIGN || SANITIZER_INTERCEPT_PVALLOC #include @@ -504,6 +502,38 @@ INTERCEPTOR(void *, pvalloc, size_t size) { } #endif +INTERCEPTOR(void *, mmap, void *addr, size_t length, int prot, int flags, + int fd, off_t offset) { + __rtsan_notify_intercepted_call("mmap"); + return REAL(mmap)(addr, length, prot, flags, fd, offset); +} + +#if SANITIZER_INTERCEPT_MMAP64 +INTERCEPTOR(void *, mmap64, void *addr, size_t length, int prot, int flags, + int fd, off64_t offset) { + __rtsan_notify_intercepted_call("mmap64"); + return REAL(mmap64)(addr, length, prot, flags, fd, offset); +} +#define RTSAN_MAYBE_INTERCEPT_MMAP64 INTERCEPT_FUNCTION(mmap64) +#else +#define RTSAN_MAYBE_INTERCEPT_MMAP64 +#endif // SANITIZER_INTERCEPT_MMAP64 + +INTERCEPTOR(int, munmap, void *addr, size_t length) { + __rtsan_notify_intercepted_call("munmap"); + return REAL(munmap)(addr, length); +} + +INTERCEPTOR(int, shm_open, const char *name, int oflag, mode_t mode) { + __rtsan_notify_intercepted_call("shm_open"); + return REAL(shm_open)(name, oflag, mode); +} + +INTERCEPTOR(int, shm_unlink, const char *name) { + __rtsan_notify_intercepted_call("shm_unlink"); + return REAL(shm_unlink)(name); +} + // Sockets INTERCEPTOR(int, socket, int domain, int type, int protocol) { __rtsan_notify_intercepted_call("socket"); @@ -558,6 +588,11 @@ void __rtsan::InitializeInterceptors() { INTERCEPT_FUNCTION(valloc); RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC; INTERCEPT_FUNCTION(posix_memalign); + INTERCEPT_FUNCTION(mmap); + RTSAN_MAYBE_INTERCEPT_MMAP64; + INTERCEPT_FUNCTION(munmap); + INTERCEPT_FUNCTION(shm_open); + INTERCEPT_FUNCTION(shm_unlink); #if SANITIZER_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign); #endif diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp index 38274485c29f6..1850f4fa30f9c 100644 --- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp @@ -28,33 +28,18 @@ #include #endif -#include -#include -#include -#include - #include #include #include +#include #include #include #if _FILE_OFFSET_BITS == 64 && SANITIZER_GLIBC -const char *const kCreatFunctionName = "creat64"; -const char *const kFcntlFunctionName = "fcntl64"; -const char *const kFopenFunctionName = "fopen64"; -const char *const kOpenAtFunctionName = "openat64"; -const char *const kOpenFunctionName = "open64"; -const char *const kPreadFunctionName = "pread64"; -const char *const kPwriteFunctionName = "pwrite64"; +// Under these conditions, some system calls are `foo64` instead of `foo` +#define MAYBE_APPEND_64(func) func "64" #else -const char *const kCreatFunctionName = "creat"; -const char *const kFcntlFunctionName = "fcntl"; -const char *const kFopenFunctionName = "fopen"; -const char *const kOpenAtFunctionName = "openat"; -const char *const kOpenFunctionName = "open"; -const char *const kPreadFunctionName = "pread"; -const char *const kPwriteFunctionName = "pwrite"; +#define MAYBE_APPEND_64(func) func #endif using namespace testing; @@ -179,6 +164,37 @@ TEST(TestRtsanInterceptors, PvallocDiesWhenRealtime) { } #endif +TEST(TestRtsanInterceptors, MmapDiesWhenRealtime) { + auto Func = []() { + void *_ = mmap(nullptr, 8, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + }; + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("mmap")); + ExpectNonRealtimeSurvival(Func); +} + +TEST(TestRtsanInterceptors, MunmapDiesWhenRealtime) { + void *ptr = mmap(nullptr, 8, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + EXPECT_NE(ptr, nullptr); + auto Func = [ptr]() { munmap(ptr, 8); }; + printf("Right before death munmap\n"); + ExpectRealtimeDeath(Func, "munmap"); + ExpectNonRealtimeSurvival(Func); +} + +TEST(TestRtsanInterceptors, ShmOpenDiesWhenRealtime) { + auto Func = []() { shm_open("/rtsan_test_shm", O_CREAT | O_RDWR, 0); }; + ExpectRealtimeDeath(Func, "shm_open"); + ExpectNonRealtimeSurvival(Func); +} + +TEST(TestRtsanInterceptors, ShmUnlinkDiesWhenRealtime) { + auto Func = []() { shm_unlink("/rtsan_test_shm"); }; + ExpectRealtimeDeath(Func, "shm_unlink"); + ExpectNonRealtimeSurvival(Func); +} + /* Sleeping */ @@ -210,13 +226,13 @@ TEST(TestRtsanInterceptors, NanosleepDiesWhenRealtime) { TEST_F(RtsanFileTest, OpenDiesWhenRealtime) { auto Func = [this]() { open(GetTemporaryFilePath(), O_RDONLY); }; - ExpectRealtimeDeath(Func, kOpenFunctionName); + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("open")); ExpectNonRealtimeSurvival(Func); } TEST_F(RtsanFileTest, OpenatDiesWhenRealtime) { auto Func = [this]() { openat(0, GetTemporaryFilePath(), O_RDONLY); }; - ExpectRealtimeDeath(Func, kOpenAtFunctionName); + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("openat")); ExpectNonRealtimeSurvival(Func); } @@ -241,13 +257,13 @@ TEST_F(RtsanFileTest, OpenCreatesFileWithProperMode) { TEST_F(RtsanFileTest, CreatDiesWhenRealtime) { auto Func = [this]() { creat(GetTemporaryFilePath(), S_IWOTH | S_IROTH); }; - ExpectRealtimeDeath(Func, kCreatFunctionName); + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("creat")); ExpectNonRealtimeSurvival(Func); } TEST(TestRtsanInterceptors, FcntlDiesWhenRealtime) { auto Func = []() { fcntl(0, F_GETFL); }; - ExpectRealtimeDeath(Func, kFcntlFunctionName); + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fcntl")); ExpectNonRealtimeSurvival(Func); } @@ -266,7 +282,7 @@ TEST_F(RtsanFileTest, FcntlFlockDiesWhenRealtime) { ASSERT_THAT(fcntl(fd, F_GETLK, &lock), Eq(0)); ASSERT_THAT(lock.l_type, F_UNLCK); }; - ExpectRealtimeDeath(Func, kFcntlFunctionName); + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fcntl")); ExpectNonRealtimeSurvival(Func); close(fd); @@ -288,7 +304,7 @@ TEST_F(RtsanFileTest, FcntlSetFdDiesWhenRealtime) { ASSERT_THAT(fcntl(fd, F_GETFD), Eq(old_flags)); }; - ExpectRealtimeDeath(Func, kFcntlFunctionName); + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fcntl")); ExpectNonRealtimeSurvival(Func); close(fd); @@ -306,7 +322,7 @@ TEST_F(RtsanFileTest, FopenDiesWhenRealtime) { EXPECT_THAT(f, Ne(nullptr)); }; - ExpectRealtimeDeath(Func, kFopenFunctionName); + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fopen")); ExpectNonRealtimeSurvival(Func); } @@ -394,7 +410,7 @@ TEST_F(RtsanOpenedFileTest, PreadDiesWhenRealtime) { char c{}; pread(GetOpenFd(), &c, 1, 0); }; - ExpectRealtimeDeath(Func, kPreadFunctionName); + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("pread")); ExpectNonRealtimeSurvival(Func); } @@ -413,7 +429,7 @@ TEST_F(RtsanOpenedFileTest, PwriteDiesWhenRealtime) { char c = 'a'; pwrite(GetOpenFd(), &c, 1, 0); }; - ExpectRealtimeDeath(Func, kPwriteFunctionName); + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("pwrite")); ExpectNonRealtimeSurvival(Func); } diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp index 9db0eebd92369..e0e4c5b9d36cd 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp @@ -14,22 +14,22 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_APPLE -#include "interception/interception.h" -#include "tsan_interceptors.h" -#include "tsan_interface.h" -#include "tsan_interface_ann.h" -#include "tsan_spinlock_defs_mac.h" -#include "sanitizer_common/sanitizer_addrhashmap.h" - -#include -#include -#include -#include -#include - -#if defined(__has_include) && __has_include() -#include -#endif // #if defined(__has_include) && __has_include() +# include +# include +# include +# include +# include + +# include "interception/interception.h" +# include "sanitizer_common/sanitizer_addrhashmap.h" +# include "tsan_interceptors.h" +# include "tsan_interface.h" +# include "tsan_interface_ann.h" +# include "tsan_spinlock_defs_mac.h" + +# if defined(__has_include) && __has_include() +# include +# endif // #if defined(__has_include) && __has_include() typedef long long_t; @@ -49,55 +49,56 @@ static constexpr morder kMacOrderBarrier = mo_acq_rel; static constexpr morder kMacOrderNonBarrier = mo_acq_rel; static constexpr morder kMacFailureOrder = mo_relaxed; -#define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \ - TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \ - SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \ - return tsan_atomic_f((volatile tsan_t *)ptr, x, mo); \ - } +# define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \ + TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \ + SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \ + return tsan_atomic_f((volatile tsan_t *)ptr, x, mo); \ + } -#define OSATOMIC_INTERCEPTOR_PLUS_X(return_t, t, tsan_t, f, tsan_atomic_f, mo) \ - TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \ - SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \ - return tsan_atomic_f((volatile tsan_t *)ptr, x, mo) + x; \ - } +# define OSATOMIC_INTERCEPTOR_PLUS_X(return_t, t, tsan_t, f, tsan_atomic_f, \ + mo) \ + TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \ + SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \ + return tsan_atomic_f((volatile tsan_t *)ptr, x, mo) + x; \ + } -#define OSATOMIC_INTERCEPTOR_PLUS_1(return_t, t, tsan_t, f, tsan_atomic_f, mo) \ - TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \ - SCOPED_TSAN_INTERCEPTOR(f, ptr); \ - return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) + 1; \ - } +# define OSATOMIC_INTERCEPTOR_PLUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \ + mo) \ + TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \ + SCOPED_TSAN_INTERCEPTOR(f, ptr); \ + return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) + 1; \ + } -#define OSATOMIC_INTERCEPTOR_MINUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \ - mo) \ - TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \ - SCOPED_TSAN_INTERCEPTOR(f, ptr); \ - return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) - 1; \ - } +# define OSATOMIC_INTERCEPTOR_MINUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \ + mo) \ + TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \ + SCOPED_TSAN_INTERCEPTOR(f, ptr); \ + return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) - 1; \ + } -#define OSATOMIC_INTERCEPTORS_ARITHMETIC(f, tsan_atomic_f, m) \ - m(int32_t, int32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \ - kMacOrderNonBarrier) \ - m(int32_t, int32_t, a32, f##32##Barrier, __tsan_atomic32_##tsan_atomic_f, \ - kMacOrderBarrier) \ - m(int64_t, int64_t, a64, f##64, __tsan_atomic64_##tsan_atomic_f, \ - kMacOrderNonBarrier) \ - m(int64_t, int64_t, a64, f##64##Barrier, __tsan_atomic64_##tsan_atomic_f, \ - kMacOrderBarrier) - -#define OSATOMIC_INTERCEPTORS_BITWISE(f, tsan_atomic_f, m, m_orig) \ - m(int32_t, uint32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \ - kMacOrderNonBarrier) \ - m(int32_t, uint32_t, a32, f##32##Barrier, __tsan_atomic32_##tsan_atomic_f, \ - kMacOrderBarrier) \ - m_orig(int32_t, uint32_t, a32, f##32##Orig, __tsan_atomic32_##tsan_atomic_f, \ - kMacOrderNonBarrier) \ - m_orig(int32_t, uint32_t, a32, f##32##OrigBarrier, \ - __tsan_atomic32_##tsan_atomic_f, kMacOrderBarrier) - - -#pragma clang diagnostic push +# define OSATOMIC_INTERCEPTORS_ARITHMETIC(f, tsan_atomic_f, m) \ + m(int32_t, int32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \ + kMacOrderNonBarrier) \ + m(int32_t, int32_t, a32, f##32##Barrier, \ + __tsan_atomic32_##tsan_atomic_f, kMacOrderBarrier) \ + m(int64_t, int64_t, a64, f##64, __tsan_atomic64_##tsan_atomic_f, \ + kMacOrderNonBarrier) \ + m(int64_t, int64_t, a64, f##64##Barrier, \ + __tsan_atomic64_##tsan_atomic_f, kMacOrderBarrier) + +# define OSATOMIC_INTERCEPTORS_BITWISE(f, tsan_atomic_f, m, m_orig) \ + m(int32_t, uint32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \ + kMacOrderNonBarrier) \ + m(int32_t, uint32_t, a32, f##32##Barrier, \ + __tsan_atomic32_##tsan_atomic_f, kMacOrderBarrier) \ + m_orig(int32_t, uint32_t, a32, f##32##Orig, \ + __tsan_atomic32_##tsan_atomic_f, kMacOrderNonBarrier) \ + m_orig(int32_t, uint32_t, a32, f##32##OrigBarrier, \ + __tsan_atomic32_##tsan_atomic_f, kMacOrderBarrier) + +# pragma clang diagnostic push // OSAtomic* functions are deprecated. -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +# pragma clang diagnostic ignored "-Wdeprecated-declarations" OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicAdd, fetch_add, OSATOMIC_INTERCEPTOR_PLUS_X) OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicIncrement, fetch_add, @@ -111,25 +112,25 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicAnd, fetch_and, OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor, OSATOMIC_INTERCEPTOR_PLUS_X, OSATOMIC_INTERCEPTOR) -#define OSATOMIC_INTERCEPTORS_CAS(f, tsan_atomic_f, tsan_t, t) \ - TSAN_INTERCEPTOR(bool, f, t old_value, t new_value, t volatile *ptr) { \ - SCOPED_TSAN_INTERCEPTOR(f, old_value, new_value, ptr); \ - return tsan_atomic_f##_compare_exchange_strong( \ - (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ - kMacOrderNonBarrier, kMacFailureOrder); \ - } \ - \ - TSAN_INTERCEPTOR(bool, f##Barrier, t old_value, t new_value, \ - t volatile *ptr) { \ - SCOPED_TSAN_INTERCEPTOR(f##Barrier, old_value, new_value, ptr); \ - return tsan_atomic_f##_compare_exchange_strong( \ - (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ - kMacOrderBarrier, kMacFailureOrder); \ - } +# define OSATOMIC_INTERCEPTORS_CAS(f, tsan_atomic_f, tsan_t, t) \ + TSAN_INTERCEPTOR(bool, f, t old_value, t new_value, t volatile *ptr) { \ + SCOPED_TSAN_INTERCEPTOR(f, old_value, new_value, ptr); \ + return tsan_atomic_f##_compare_exchange_strong( \ + (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ + kMacOrderNonBarrier, kMacFailureOrder); \ + } \ + \ + TSAN_INTERCEPTOR(bool, f##Barrier, t old_value, t new_value, \ + t volatile *ptr) { \ + SCOPED_TSAN_INTERCEPTOR(f##Barrier, old_value, new_value, ptr); \ + return tsan_atomic_f##_compare_exchange_strong( \ + (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ + kMacOrderBarrier, kMacFailureOrder); \ + } -#pragma clang diagnostic push +# pragma clang diagnostic push // OSAtomicCompareAndSwap* functions are deprecated. -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +# pragma clang diagnostic ignored "-Wdeprecated-declarations" OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapInt, __tsan_atomic32, a32, int) OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapLong, __tsan_atomic64, a64, long_t) @@ -139,21 +140,21 @@ OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap32, __tsan_atomic32, a32, int32_t) OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap64, __tsan_atomic64, a64, int64_t) -#pragma clang diagnostic pop - -#define OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, mo) \ - TSAN_INTERCEPTOR(bool, f, uint32_t n, volatile void *ptr) { \ - SCOPED_TSAN_INTERCEPTOR(f, n, ptr); \ - volatile char *byte_ptr = ((volatile char *)ptr) + (n >> 3); \ - char bit = 0x80u >> (n & 7); \ - char mask = clear ? ~bit : bit; \ - char orig_byte = op((volatile a8 *)byte_ptr, mask, mo); \ - return orig_byte & bit; \ - } +# pragma clang diagnostic pop + +# define OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, mo) \ + TSAN_INTERCEPTOR(bool, f, uint32_t n, volatile void *ptr) { \ + SCOPED_TSAN_INTERCEPTOR(f, n, ptr); \ + volatile char *byte_ptr = ((volatile char *)ptr) + (n >> 3); \ + char bit = 0x80u >> (n & 7); \ + char mask = clear ? ~bit : bit; \ + char orig_byte = op((volatile a8 *)byte_ptr, mask, mo); \ + return orig_byte & bit; \ + } -#define OSATOMIC_INTERCEPTORS_BITOP(f, op, clear) \ - OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, kMacOrderNonBarrier) \ - OSATOMIC_INTERCEPTOR_BITOP(f##Barrier, op, clear, kMacOrderBarrier) +# define OSATOMIC_INTERCEPTORS_BITOP(f, op, clear) \ + OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, kMacOrderNonBarrier) \ + OSATOMIC_INTERCEPTOR_BITOP(f##Barrier, op, clear, kMacOrderBarrier) OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndSet, __tsan_atomic8_fetch_or, false) OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndClear, __tsan_atomic8_fetch_and, @@ -169,12 +170,13 @@ TSAN_INTERCEPTOR(void, OSAtomicEnqueue, OSQueueHead *list, void *item, TSAN_INTERCEPTOR(void *, OSAtomicDequeue, OSQueueHead *list, size_t offset) { SCOPED_TSAN_INTERCEPTOR(OSAtomicDequeue, list, offset); void *item = REAL(OSAtomicDequeue)(list, offset); - if (item) __tsan_acquire(item); + if (item) + __tsan_acquire(item); return item; } // OSAtomicFifoEnqueue and OSAtomicFifoDequeue are only on OS X. -#if !SANITIZER_IOS +# if !SANITIZER_IOS TSAN_INTERCEPTOR(void, OSAtomicFifoEnqueue, OSFifoQueueHead *list, void *item, size_t offset) { @@ -187,11 +189,12 @@ TSAN_INTERCEPTOR(void *, OSAtomicFifoDequeue, OSFifoQueueHead *list, size_t offset) { SCOPED_TSAN_INTERCEPTOR(OSAtomicFifoDequeue, list, offset); void *item = REAL(OSAtomicFifoDequeue)(list, offset); - if (item) __tsan_acquire(item); + if (item) + __tsan_acquire(item); return item; } -#endif +# endif TSAN_INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) { CHECK(!cur_thread()->is_dead); @@ -296,7 +299,7 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_unlock, os_unfair_lock_t lock) { REAL(os_unfair_lock_unlock)(lock); } -#if defined(__has_include) && __has_include() +# if defined(__has_include) && __has_include() TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler, xpc_connection_t connection, xpc_handler_t handler) { @@ -350,7 +353,7 @@ TSAN_INTERCEPTOR(void, xpc_connection_cancel, xpc_connection_t connection) { REAL(xpc_connection_cancel)(connection); } -#endif // #if defined(__has_include) && __has_include() +# endif // #if defined(__has_include) && __has_include() // Determines whether the Obj-C object pointer is a tagged pointer. Tagged // pointers encode the object data directly in their pointer bits and do not @@ -373,7 +376,7 @@ static uptr GetOrCreateSyncAddress(uptr addr, ThreadState *thr, uptr pc) { Map::Handle h(&Addresses, addr); if (h.created()) { ThreadIgnoreBegin(thr, pc); - *h = (uptr) user_alloc(thr, pc, /*size=*/1); + *h = (uptr)user_alloc(thr, pc, /*size=*/1); ThreadIgnoreEnd(thr); } return *h; @@ -391,7 +394,8 @@ static uptr SyncAddressForObjCObject(id obj, ThreadState *thr, uptr pc) { TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) { SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj); - if (!obj) return REAL(objc_sync_enter)(obj); + if (!obj) + return REAL(objc_sync_enter)(obj); uptr addr = SyncAddressForObjCObject(obj, thr, pc); MutexPreLock(thr, pc, addr, MutexFlagWriteReentrant); int result = REAL(objc_sync_enter)(obj); @@ -402,11 +406,13 @@ TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) { TSAN_INTERCEPTOR(int, objc_sync_exit, id obj) { SCOPED_TSAN_INTERCEPTOR(objc_sync_exit, obj); - if (!obj) return REAL(objc_sync_exit)(obj); + if (!obj) + return REAL(objc_sync_exit)(obj); uptr addr = SyncAddressForObjCObject(obj, thr, pc); MutexUnlock(thr, pc, addr); int result = REAL(objc_sync_exit)(obj); - if (result != OBJC_SYNC_SUCCESS) MutexInvalidAccess(thr, pc, addr); + if (result != OBJC_SYNC_SUCCESS) + MutexInvalidAccess(thr, pc, addr); return result; } @@ -437,7 +443,7 @@ TSAN_INTERCEPTOR(int, swapcontext, ucontext_t *oucp, const ucontext_t *ucp) { // On macOS, libc++ is always linked dynamically, so intercepting works the // usual way. -#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR +# define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR namespace { struct fake_shared_weak_count { diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface.h b/compiler-rt/lib/tsan/rtl/tsan_interface.h index 3731c90d45915..2b8a13ddb842c 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interface.h +++ b/compiler-rt/lib/tsan/rtl/tsan_interface.h @@ -16,8 +16,8 @@ #define TSAN_INTERFACE_H #include -using __sanitizer::uptr; using __sanitizer::tid_t; +using __sanitizer::uptr; // This header should NOT include any other headers. // All functions in this header are extern "C" and start with __tsan_. @@ -203,17 +203,18 @@ int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id, namespace __tsan { // These should match declarations from public tsan_interface_atomic.h header. -typedef unsigned char a8; +typedef unsigned char a8; typedef unsigned short a16; -typedef unsigned int a32; +typedef unsigned int a32; typedef unsigned long long a64; -#if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \ - || (__clang_major__ * 100 + __clang_minor__ >= 302)) && \ +#if !SANITIZER_GO && \ + (defined(__SIZEOF_INT128__) || \ + (__clang_major__ * 100 + __clang_minor__ >= 302)) && \ !defined(__mips64) && !defined(__s390x__) __extension__ typedef __int128 a128; -# define __TSAN_HAS_INT128 1 +# define __TSAN_HAS_INT128 1 #else -# define __TSAN_HAS_INT128 0 +# define __TSAN_HAS_INT128 0 #endif // Part of ABI, do not change. diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp index 2b5a2c6ef79b9..67106f59f6e7f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp @@ -18,9 +18,9 @@ // The following page contains more background information: // http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/ +#include "sanitizer_common/sanitizer_mutex.h" #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_stacktrace.h" -#include "sanitizer_common/sanitizer_mutex.h" #include "tsan_flags.h" #include "tsan_interface.h" #include "tsan_rtl.h" @@ -34,8 +34,8 @@ static StaticSpinMutex mutex128; #if SANITIZER_DEBUG static bool IsLoadOrder(morder mo) { - return mo == mo_relaxed || mo == mo_consume - || mo == mo_acquire || mo == mo_seq_cst; + return mo == mo_relaxed || mo == mo_consume || mo == mo_acquire || + mo == mo_seq_cst; } static bool IsStoreOrder(morder mo) { @@ -48,42 +48,49 @@ static bool IsReleaseOrder(morder mo) { } static bool IsAcquireOrder(morder mo) { - return mo == mo_consume || mo == mo_acquire - || mo == mo_acq_rel || mo == mo_seq_cst; + return mo == mo_consume || mo == mo_acquire || mo == mo_acq_rel || + mo == mo_seq_cst; } static bool IsAcqRelOrder(morder mo) { return mo == mo_acq_rel || mo == mo_seq_cst; } -template T func_xchg(volatile T *v, T op) { +template +T func_xchg(volatile T *v, T op) { T res = __sync_lock_test_and_set(v, op); // __sync_lock_test_and_set does not contain full barrier. __sync_synchronize(); return res; } -template T func_add(volatile T *v, T op) { +template +T func_add(volatile T *v, T op) { return __sync_fetch_and_add(v, op); } -template T func_sub(volatile T *v, T op) { +template +T func_sub(volatile T *v, T op) { return __sync_fetch_and_sub(v, op); } -template T func_and(volatile T *v, T op) { +template +T func_and(volatile T *v, T op) { return __sync_fetch_and_and(v, op); } -template T func_or(volatile T *v, T op) { +template +T func_or(volatile T *v, T op) { return __sync_fetch_and_or(v, op); } -template T func_xor(volatile T *v, T op) { +template +T func_xor(volatile T *v, T op) { return __sync_fetch_and_xor(v, op); } -template T func_nand(volatile T *v, T op) { +template +T func_nand(volatile T *v, T op) { // clang does not support __sync_fetch_and_nand. T cmp = *v; for (;;) { @@ -95,7 +102,8 @@ template T func_nand(volatile T *v, T op) { } } -template T func_cas(volatile T *v, T cmp, T xch) { +template +T func_cas(volatile T *v, T cmp, T xch) { return __sync_val_compare_and_swap(v, cmp, xch); } @@ -103,8 +111,8 @@ template T func_cas(volatile T *v, T cmp, T xch) { // Atomic ops are executed under tsan internal mutex, // here we assume that the atomic variables are not accessed // from non-instrumented code. -#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !SANITIZER_GO \ - && __TSAN_HAS_INT128 +#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !SANITIZER_GO && \ + __TSAN_HAS_INT128 a128 func_xchg(volatile a128 *v, a128 op) { SpinMutexLock lock(&mutex128); a128 cmp = *v; @@ -197,89 +205,24 @@ static atomic_uint64_t *to_atomic(const volatile a64 *a) { static memory_order to_mo(morder mo) { switch (mo) { - case mo_relaxed: return memory_order_relaxed; - case mo_consume: return memory_order_consume; - case mo_acquire: return memory_order_acquire; - case mo_release: return memory_order_release; - case mo_acq_rel: return memory_order_acq_rel; - case mo_seq_cst: return memory_order_seq_cst; + case mo_relaxed: + return memory_order_relaxed; + case mo_consume: + return memory_order_consume; + case mo_acquire: + return memory_order_acquire; + case mo_release: + return memory_order_release; + case mo_acq_rel: + return memory_order_acq_rel; + case mo_seq_cst: + return memory_order_seq_cst; } DCHECK(0); return memory_order_seq_cst; } -template -static T NoTsanAtomicLoad(const volatile T *a, morder mo) { - return atomic_load(to_atomic(a), to_mo(mo)); -} - -#if __TSAN_HAS_INT128 && !SANITIZER_GO -static a128 NoTsanAtomicLoad(const volatile a128 *a, morder mo) { - SpinMutexLock lock(&mutex128); - return *a; -} -#endif - -template -static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a, morder mo) { - DCHECK(IsLoadOrder(mo)); - // This fast-path is critical for performance. - // Assume the access is atomic. - if (!IsAcquireOrder(mo)) { - MemoryAccess(thr, pc, (uptr)a, AccessSize(), - kAccessRead | kAccessAtomic); - return NoTsanAtomicLoad(a, mo); - } - // Don't create sync object if it does not exist yet. For example, an atomic - // pointer is initialized to nullptr and then periodically acquire-loaded. - T v = NoTsanAtomicLoad(a, mo); - SyncVar *s = ctx->metamap.GetSyncIfExists((uptr)a); - if (s) { - SlotLocker locker(thr); - ReadLock lock(&s->mtx); - thr->clock.Acquire(s->clock); - // Re-read under sync mutex because we need a consistent snapshot - // of the value and the clock we acquire. - v = NoTsanAtomicLoad(a, mo); - } - MemoryAccess(thr, pc, (uptr)a, AccessSize(), kAccessRead | kAccessAtomic); - return v; -} - -template -static void NoTsanAtomicStore(volatile T *a, T v, morder mo) { - atomic_store(to_atomic(a), v, to_mo(mo)); -} - -#if __TSAN_HAS_INT128 && !SANITIZER_GO -static void NoTsanAtomicStore(volatile a128 *a, a128 v, morder mo) { - SpinMutexLock lock(&mutex128); - *a = v; -} -#endif - -template -static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v, - morder mo) { - DCHECK(IsStoreOrder(mo)); - MemoryAccess(thr, pc, (uptr)a, AccessSize(), kAccessWrite | kAccessAtomic); - // This fast-path is critical for performance. - // Assume the access is atomic. - // Strictly saying even relaxed store cuts off release sequence, - // so must reset the clock. - if (!IsReleaseOrder(mo)) { - NoTsanAtomicStore(a, v, mo); - return; - } - SlotLocker locker(thr); - { - auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false); - Lock lock(&s->mtx); - thr->clock.ReleaseStore(&s->clock); - NoTsanAtomicStore(a, v, mo); - } - IncrementEpoch(thr); -} +namespace { template static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) { @@ -303,166 +246,255 @@ static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) { return v; } -template -static T NoTsanAtomicExchange(volatile T *a, T v, morder mo) { - return func_xchg(a, v); -} +struct OpLoad { + template + static T NoTsanAtomic(morder mo, const volatile T *a) { + return atomic_load(to_atomic(a), to_mo(mo)); + } -template -static T NoTsanAtomicFetchAdd(volatile T *a, T v, morder mo) { - return func_add(a, v); -} +#if __TSAN_HAS_INT128 && !SANITIZER_GO + static a128 NoTsanAtomic(morder mo, const volatile a128 *a) { + SpinMutexLock lock(&mutex128); + return *a; + } +#endif -template -static T NoTsanAtomicFetchSub(volatile T *a, T v, morder mo) { - return func_sub(a, v); -} + template + static T Atomic(ThreadState *thr, uptr pc, morder mo, const volatile T *a) { + DCHECK(IsLoadOrder(mo)); + // This fast-path is critical for performance. + // Assume the access is atomic. + if (!IsAcquireOrder(mo)) { + MemoryAccess(thr, pc, (uptr)a, AccessSize(), + kAccessRead | kAccessAtomic); + return NoTsanAtomic(mo, a); + } + // Don't create sync object if it does not exist yet. For example, an atomic + // pointer is initialized to nullptr and then periodically acquire-loaded. + T v = NoTsanAtomic(mo, a); + SyncVar *s = ctx->metamap.GetSyncIfExists((uptr)a); + if (s) { + SlotLocker locker(thr); + ReadLock lock(&s->mtx); + thr->clock.Acquire(s->clock); + // Re-read under sync mutex because we need a consistent snapshot + // of the value and the clock we acquire. + v = NoTsanAtomic(mo, a); + } + MemoryAccess(thr, pc, (uptr)a, AccessSize(), + kAccessRead | kAccessAtomic); + return v; + } +}; -template -static T NoTsanAtomicFetchAnd(volatile T *a, T v, morder mo) { - return func_and(a, v); -} +struct OpStore { + template + static void NoTsanAtomic(morder mo, volatile T *a, T v) { + atomic_store(to_atomic(a), v, to_mo(mo)); + } -template -static T NoTsanAtomicFetchOr(volatile T *a, T v, morder mo) { - return func_or(a, v); -} +#if __TSAN_HAS_INT128 && !SANITIZER_GO + static void NoTsanAtomic(morder mo, volatile a128 *a, a128 v) { + SpinMutexLock lock(&mutex128); + *a = v; + } +#endif -template -static T NoTsanAtomicFetchXor(volatile T *a, T v, morder mo) { - return func_xor(a, v); -} + template + static void Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) { + DCHECK(IsStoreOrder(mo)); + MemoryAccess(thr, pc, (uptr)a, AccessSize(), + kAccessWrite | kAccessAtomic); + // This fast-path is critical for performance. + // Assume the access is atomic. + // Strictly saying even relaxed store cuts off release sequence, + // so must reset the clock. + if (!IsReleaseOrder(mo)) { + NoTsanAtomic(mo, a, v); + return; + } + SlotLocker locker(thr); + { + auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false); + Lock lock(&s->mtx); + thr->clock.ReleaseStore(&s->clock); + NoTsanAtomic(mo, a, v); + } + IncrementEpoch(thr); + } +}; -template -static T NoTsanAtomicFetchNand(volatile T *a, T v, morder mo) { - return func_nand(a, v); -} +struct OpExchange { + template + static T NoTsanAtomic(morder mo, volatile T *a, T v) { + return func_xchg(a, v); + } + template + static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) { + return AtomicRMW(thr, pc, a, v, mo); + } +}; -template -static T AtomicExchange(ThreadState *thr, uptr pc, volatile T *a, T v, - morder mo) { - return AtomicRMW(thr, pc, a, v, mo); -} +struct OpFetchAdd { + template + static T NoTsanAtomic(morder mo, volatile T *a, T v) { + return func_add(a, v); + } -template -static T AtomicFetchAdd(ThreadState *thr, uptr pc, volatile T *a, T v, - morder mo) { - return AtomicRMW(thr, pc, a, v, mo); -} + template + static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) { + return AtomicRMW(thr, pc, a, v, mo); + } +}; -template -static T AtomicFetchSub(ThreadState *thr, uptr pc, volatile T *a, T v, - morder mo) { - return AtomicRMW(thr, pc, a, v, mo); -} +struct OpFetchSub { + template + static T NoTsanAtomic(morder mo, volatile T *a, T v) { + return func_sub(a, v); + } -template -static T AtomicFetchAnd(ThreadState *thr, uptr pc, volatile T *a, T v, - morder mo) { - return AtomicRMW(thr, pc, a, v, mo); -} + template + static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) { + return AtomicRMW(thr, pc, a, v, mo); + } +}; -template -static T AtomicFetchOr(ThreadState *thr, uptr pc, volatile T *a, T v, - morder mo) { - return AtomicRMW(thr, pc, a, v, mo); -} +struct OpFetchAnd { + template + static T NoTsanAtomic(morder mo, volatile T *a, T v) { + return func_and(a, v); + } -template -static T AtomicFetchXor(ThreadState *thr, uptr pc, volatile T *a, T v, - morder mo) { - return AtomicRMW(thr, pc, a, v, mo); -} + template + static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) { + return AtomicRMW(thr, pc, a, v, mo); + } +}; -template -static T AtomicFetchNand(ThreadState *thr, uptr pc, volatile T *a, T v, - morder mo) { - return AtomicRMW(thr, pc, a, v, mo); -} +struct OpFetchOr { + template + static T NoTsanAtomic(morder mo, volatile T *a, T v) { + return func_or(a, v); + } -template -static bool NoTsanAtomicCAS(volatile T *a, T *c, T v, morder mo, morder fmo) { - return atomic_compare_exchange_strong(to_atomic(a), c, v, to_mo(mo)); -} + template + static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) { + return AtomicRMW(thr, pc, a, v, mo); + } +}; -#if __TSAN_HAS_INT128 -static bool NoTsanAtomicCAS(volatile a128 *a, a128 *c, a128 v, - morder mo, morder fmo) { - a128 old = *c; - a128 cur = func_cas(a, old, v); - if (cur == old) - return true; - *c = cur; - return false; -} -#endif +struct OpFetchXor { + template + static T NoTsanAtomic(morder mo, volatile T *a, T v) { + return func_xor(a, v); + } -template -static T NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) { - NoTsanAtomicCAS(a, &c, v, mo, fmo); - return c; -} + template + static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) { + return AtomicRMW(thr, pc, a, v, mo); + } +}; -template -static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v, - morder mo, morder fmo) { - // 31.7.2.18: "The failure argument shall not be memory_order_release - // nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic - // (mo_relaxed) when those are used. - DCHECK(IsLoadOrder(fmo)); +struct OpFetchNand { + template + static T NoTsanAtomic(morder mo, volatile T *a, T v) { + return func_nand(a, v); + } - MemoryAccess(thr, pc, (uptr)a, AccessSize(), kAccessWrite | kAccessAtomic); - if (LIKELY(mo == mo_relaxed && fmo == mo_relaxed)) { - T cc = *c; - T pr = func_cas(a, cc, v); - if (pr == cc) + template + static T Atomic(ThreadState *thr, uptr pc, morder mo, volatile T *a, T v) { + return AtomicRMW(thr, pc, a, v, mo); + } +}; + +struct OpCAS { + template + static bool NoTsanAtomic(morder mo, morder fmo, volatile T *a, T *c, T v) { + return atomic_compare_exchange_strong(to_atomic(a), c, v, to_mo(mo)); + } + +#if __TSAN_HAS_INT128 + static bool NoTsanAtomic(morder mo, morder fmo, volatile a128 *a, a128 *c, + a128 v) { + a128 old = *c; + a128 cur = func_cas(a, old, v); + if (cur == old) return true; - *c = pr; + *c = cur; return false; } - SlotLocker locker(thr); - bool release = IsReleaseOrder(mo); - bool success; - { - auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false); - RWLock lock(&s->mtx, release); - T cc = *c; - T pr = func_cas(a, cc, v); - success = pr == cc; - if (!success) { +#endif + + template + static T NoTsanAtomic(morder mo, morder fmo, volatile T *a, T c, T v) { + NoTsanAtomic(mo, fmo, a, &c, v); + return c; + } + + template + static bool Atomic(ThreadState *thr, uptr pc, morder mo, morder fmo, + volatile T *a, T *c, T v) { + // 31.7.2.18: "The failure argument shall not be memory_order_release + // nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic + // (mo_relaxed) when those are used. + DCHECK(IsLoadOrder(fmo)); + + MemoryAccess(thr, pc, (uptr)a, AccessSize(), + kAccessWrite | kAccessAtomic); + if (LIKELY(mo == mo_relaxed && fmo == mo_relaxed)) { + T cc = *c; + T pr = func_cas(a, cc, v); + if (pr == cc) + return true; *c = pr; - mo = fmo; + return false; } - if (success && IsAcqRelOrder(mo)) - thr->clock.ReleaseAcquire(&s->clock); - else if (success && IsReleaseOrder(mo)) - thr->clock.Release(&s->clock); - else if (IsAcquireOrder(mo)) - thr->clock.Acquire(s->clock); + SlotLocker locker(thr); + bool release = IsReleaseOrder(mo); + bool success; + { + auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false); + RWLock lock(&s->mtx, release); + T cc = *c; + T pr = func_cas(a, cc, v); + success = pr == cc; + if (!success) { + *c = pr; + mo = fmo; + } + if (success && IsAcqRelOrder(mo)) + thr->clock.ReleaseAcquire(&s->clock); + else if (success && IsReleaseOrder(mo)) + thr->clock.Release(&s->clock); + else if (IsAcquireOrder(mo)) + thr->clock.Acquire(s->clock); + } + if (success && release) + IncrementEpoch(thr); + return success; } - if (success && release) - IncrementEpoch(thr); - return success; -} -template -static T AtomicCAS(ThreadState *thr, uptr pc, - volatile T *a, T c, T v, morder mo, morder fmo) { - AtomicCAS(thr, pc, a, &c, v, mo, fmo); - return c; -} + template + static T Atomic(ThreadState *thr, uptr pc, morder mo, morder fmo, + volatile T *a, T c, T v) { + Atomic(thr, pc, mo, fmo, a, &c, v); + return c; + } +}; #if !SANITIZER_GO -static void NoTsanAtomicFence(morder mo) { - __sync_synchronize(); -} +struct OpFence { + static void NoTsanAtomic(morder mo) { __sync_synchronize(); } -static void AtomicFence(ThreadState *thr, uptr pc, morder mo) { - // FIXME(dvyukov): not implemented. - __sync_synchronize(); -} + static void Atomic(ThreadState *thr, uptr pc, morder mo) { + // FIXME(dvyukov): not implemented. + __sync_synchronize(); + } +}; #endif +} // namespace + // Interface functions follow. #if !SANITIZER_GO @@ -485,465 +517,470 @@ static morder convert_morder(morder mo) { return (morder)(mo & 0x7fff); } -# define ATOMIC_IMPL(func, ...) \ - ThreadState *const thr = cur_thread(); \ - ProcessPendingSignals(thr); \ - if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) \ - return NoTsanAtomic##func(__VA_ARGS__); \ - mo = convert_morder(mo); \ - return Atomic##func(thr, GET_CALLER_PC(), __VA_ARGS__); +# define ATOMIC_IMPL(func, mo, ...) \ + ThreadState *const thr = cur_thread(); \ + ProcessPendingSignals(thr); \ + if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) \ + return Op##func::NoTsanAtomic(mo, ##__VA_ARGS__); \ + return Op##func::Atomic(thr, GET_CALLER_PC(), convert_morder(mo), \ + ##__VA_ARGS__); extern "C" { SANITIZER_INTERFACE_ATTRIBUTE a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) { - ATOMIC_IMPL(Load, a, mo); + ATOMIC_IMPL(Load, mo, a); } SANITIZER_INTERFACE_ATTRIBUTE a16 __tsan_atomic16_load(const volatile a16 *a, morder mo) { - ATOMIC_IMPL(Load, a, mo); + ATOMIC_IMPL(Load, mo, a); } SANITIZER_INTERFACE_ATTRIBUTE a32 __tsan_atomic32_load(const volatile a32 *a, morder mo) { - ATOMIC_IMPL(Load, a, mo); + ATOMIC_IMPL(Load, mo, a); } SANITIZER_INTERFACE_ATTRIBUTE a64 __tsan_atomic64_load(const volatile a64 *a, morder mo) { - ATOMIC_IMPL(Load, a, mo); + ATOMIC_IMPL(Load, mo, a); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE a128 __tsan_atomic128_load(const volatile a128 *a, morder mo) { - ATOMIC_IMPL(Load, a, mo); + ATOMIC_IMPL(Load, mo, a); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo) { - ATOMIC_IMPL(Store, a, v, mo); + ATOMIC_IMPL(Store, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo) { - ATOMIC_IMPL(Store, a, v, mo); + ATOMIC_IMPL(Store, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo) { - ATOMIC_IMPL(Store, a, v, mo); + ATOMIC_IMPL(Store, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo) { - ATOMIC_IMPL(Store, a, v, mo); + ATOMIC_IMPL(Store, mo, a, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo) { - ATOMIC_IMPL(Store, a, v, mo); + ATOMIC_IMPL(Store, mo, a, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo) { - ATOMIC_IMPL(Exchange, a, v, mo); + ATOMIC_IMPL(Exchange, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo) { - ATOMIC_IMPL(Exchange, a, v, mo); + ATOMIC_IMPL(Exchange, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo) { - ATOMIC_IMPL(Exchange, a, v, mo); + ATOMIC_IMPL(Exchange, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo) { - ATOMIC_IMPL(Exchange, a, v, mo); + ATOMIC_IMPL(Exchange, mo, a, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo) { - ATOMIC_IMPL(Exchange, a, v, mo); + ATOMIC_IMPL(Exchange, mo, a, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo) { - ATOMIC_IMPL(FetchAdd, a, v, mo); + ATOMIC_IMPL(FetchAdd, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo) { - ATOMIC_IMPL(FetchAdd, a, v, mo); + ATOMIC_IMPL(FetchAdd, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo) { - ATOMIC_IMPL(FetchAdd, a, v, mo); + ATOMIC_IMPL(FetchAdd, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo) { - ATOMIC_IMPL(FetchAdd, a, v, mo); + ATOMIC_IMPL(FetchAdd, mo, a, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo) { - ATOMIC_IMPL(FetchAdd, a, v, mo); + ATOMIC_IMPL(FetchAdd, mo, a, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo) { - ATOMIC_IMPL(FetchSub, a, v, mo); + ATOMIC_IMPL(FetchSub, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo) { - ATOMIC_IMPL(FetchSub, a, v, mo); + ATOMIC_IMPL(FetchSub, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo) { - ATOMIC_IMPL(FetchSub, a, v, mo); + ATOMIC_IMPL(FetchSub, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo) { - ATOMIC_IMPL(FetchSub, a, v, mo); + ATOMIC_IMPL(FetchSub, mo, a, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo) { - ATOMIC_IMPL(FetchSub, a, v, mo); + ATOMIC_IMPL(FetchSub, mo, a, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo) { - ATOMIC_IMPL(FetchAnd, a, v, mo); + ATOMIC_IMPL(FetchAnd, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo) { - ATOMIC_IMPL(FetchAnd, a, v, mo); + ATOMIC_IMPL(FetchAnd, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo) { - ATOMIC_IMPL(FetchAnd, a, v, mo); + ATOMIC_IMPL(FetchAnd, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo) { - ATOMIC_IMPL(FetchAnd, a, v, mo); + ATOMIC_IMPL(FetchAnd, mo, a, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo) { - ATOMIC_IMPL(FetchAnd, a, v, mo); + ATOMIC_IMPL(FetchAnd, mo, a, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo) { - ATOMIC_IMPL(FetchOr, a, v, mo); + ATOMIC_IMPL(FetchOr, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo) { - ATOMIC_IMPL(FetchOr, a, v, mo); + ATOMIC_IMPL(FetchOr, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo) { - ATOMIC_IMPL(FetchOr, a, v, mo); + ATOMIC_IMPL(FetchOr, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo) { - ATOMIC_IMPL(FetchOr, a, v, mo); + ATOMIC_IMPL(FetchOr, mo, a, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo) { - ATOMIC_IMPL(FetchOr, a, v, mo); + ATOMIC_IMPL(FetchOr, mo, a, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo) { - ATOMIC_IMPL(FetchXor, a, v, mo); + ATOMIC_IMPL(FetchXor, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo) { - ATOMIC_IMPL(FetchXor, a, v, mo); + ATOMIC_IMPL(FetchXor, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo) { - ATOMIC_IMPL(FetchXor, a, v, mo); + ATOMIC_IMPL(FetchXor, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo) { - ATOMIC_IMPL(FetchXor, a, v, mo); + ATOMIC_IMPL(FetchXor, mo, a, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo) { - ATOMIC_IMPL(FetchXor, a, v, mo); + ATOMIC_IMPL(FetchXor, mo, a, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo) { - ATOMIC_IMPL(FetchNand, a, v, mo); + ATOMIC_IMPL(FetchNand, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo) { - ATOMIC_IMPL(FetchNand, a, v, mo); + ATOMIC_IMPL(FetchNand, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo) { - ATOMIC_IMPL(FetchNand, a, v, mo); + ATOMIC_IMPL(FetchNand, mo, a, v); } SANITIZER_INTERFACE_ATTRIBUTE a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo) { - ATOMIC_IMPL(FetchNand, a, v, mo); + ATOMIC_IMPL(FetchNand, mo, a, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo) { - ATOMIC_IMPL(FetchNand, a, v, mo); + ATOMIC_IMPL(FetchNand, mo, a, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE -int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); +int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, morder mo, + morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE -a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); +a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, morder mo, + morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } SANITIZER_INTERFACE_ATTRIBUTE a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } SANITIZER_INTERFACE_ATTRIBUTE a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } SANITIZER_INTERFACE_ATTRIBUTE a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } -#if __TSAN_HAS_INT128 +# if __TSAN_HAS_INT128 SANITIZER_INTERFACE_ATTRIBUTE a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v, - morder mo, morder fmo) { - ATOMIC_IMPL(CAS, a, c, v, mo, fmo); + morder mo, morder fmo) { + ATOMIC_IMPL(CAS, mo, fmo, a, c, v); } -#endif +# endif SANITIZER_INTERFACE_ATTRIBUTE void __tsan_atomic_thread_fence(morder mo) { ATOMIC_IMPL(Fence, mo); } SANITIZER_INTERFACE_ATTRIBUTE -void __tsan_atomic_signal_fence(morder mo) { -} +void __tsan_atomic_signal_fence(morder mo) {} } // extern "C" #else // #if !SANITIZER_GO // Go -# define ATOMIC(func, ...) \ - if (thr->ignore_sync) { \ - NoTsanAtomic##func(__VA_ARGS__); \ - } else { \ - FuncEntry(thr, cpc); \ - Atomic##func(thr, pc, __VA_ARGS__); \ - FuncExit(thr); \ +# define ATOMIC(func, ...) \ + if (thr->ignore_sync) { \ + Op##func::NoTsanAtomic(__VA_ARGS__); \ + } else { \ + FuncEntry(thr, cpc); \ + Op##func::Atomic(thr, pc, __VA_ARGS__); \ + FuncExit(thr); \ } -# define ATOMIC_RET(func, ret, ...) \ - if (thr->ignore_sync) { \ - (ret) = NoTsanAtomic##func(__VA_ARGS__); \ - } else { \ - FuncEntry(thr, cpc); \ - (ret) = Atomic##func(thr, pc, __VA_ARGS__); \ - FuncExit(thr); \ +# define ATOMIC_RET(func, ret, ...) \ + if (thr->ignore_sync) { \ + (ret) = Op##func::NoTsanAtomic(__VA_ARGS__); \ + } else { \ + FuncEntry(thr, cpc); \ + (ret) = Op##func::Atomic(thr, pc, __VA_ARGS__); \ + FuncExit(thr); \ } extern "C" { SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(Load, *(a32*)(a+8), *(a32**)a, mo_acquire); + ATOMIC_RET(Load, *(a32 *)(a + 8), mo_acquire, *(a32 **)a); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(Load, *(a64*)(a+8), *(a64**)a, mo_acquire); + ATOMIC_RET(Load, *(a64 *)(a + 8), mo_acquire, *(a64 **)a); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC(Store, *(a32**)a, *(a32*)(a+8), mo_release); + ATOMIC(Store, mo_release, *(a32 **)a, *(a32 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC(Store, *(a64**)a, *(a64*)(a+8), mo_release); + ATOMIC(Store, mo_release, *(a64 **)a, *(a64 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(FetchAdd, *(a32*)(a+16), *(a32**)a, *(a32*)(a+8), mo_acq_rel); + ATOMIC_RET(FetchAdd, *(a32 *)(a + 16), mo_acq_rel, *(a32 **)a, + *(a32 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(FetchAdd, *(a64*)(a+16), *(a64**)a, *(a64*)(a+8), mo_acq_rel); + ATOMIC_RET(FetchAdd, *(a64 *)(a + 16), mo_acq_rel, *(a64 **)a, + *(a64 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic32_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(FetchAnd, *(a32 *)(a + 16), *(a32 **)a, *(a32 *)(a + 8), - mo_acq_rel); + ATOMIC_RET(FetchAnd, *(a32 *)(a + 16), mo_acq_rel, *(a32 **)a, + *(a32 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic64_fetch_and(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(FetchAnd, *(a64 *)(a + 16), *(a64 **)a, *(a64 *)(a + 8), - mo_acq_rel); + ATOMIC_RET(FetchAnd, *(a64 *)(a + 16), mo_acq_rel, *(a64 **)a, + *(a64 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic32_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(FetchOr, *(a32 *)(a + 16), *(a32 **)a, *(a32 *)(a + 8), - mo_acq_rel); + ATOMIC_RET(FetchOr, *(a32 *)(a + 16), mo_acq_rel, *(a32 **)a, + *(a32 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic64_fetch_or(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(FetchOr, *(a64 *)(a + 16), *(a64 **)a, *(a64 *)(a + 8), - mo_acq_rel); + ATOMIC_RET(FetchOr, *(a64 *)(a + 16), mo_acq_rel, *(a64 **)a, + *(a64 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(Exchange, *(a32*)(a+16), *(a32**)a, *(a32*)(a+8), mo_acq_rel); + ATOMIC_RET(Exchange, *(a32 *)(a + 16), mo_acq_rel, *(a32 **)a, + *(a32 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) { - ATOMIC_RET(Exchange, *(a64*)(a+16), *(a64**)a, *(a64*)(a+8), mo_acq_rel); + ATOMIC_RET(Exchange, *(a64 *)(a + 16), mo_acq_rel, *(a64 **)a, + *(a64 *)(a + 8)); } SANITIZER_INTERFACE_ATTRIBUTE -void __tsan_go_atomic32_compare_exchange( - ThreadState *thr, uptr cpc, uptr pc, u8 *a) { +void __tsan_go_atomic32_compare_exchange(ThreadState *thr, uptr cpc, uptr pc, + u8 *a) { a32 cur = 0; - a32 cmp = *(a32*)(a+8); - ATOMIC_RET(CAS, cur, *(a32**)a, cmp, *(a32*)(a+12), mo_acq_rel, mo_acquire); - *(bool*)(a+16) = (cur == cmp); + a32 cmp = *(a32 *)(a + 8); + ATOMIC_RET(CAS, cur, mo_acq_rel, mo_acquire, *(a32 **)a, cmp, + *(a32 *)(a + 12)); + *(bool *)(a + 16) = (cur == cmp); } SANITIZER_INTERFACE_ATTRIBUTE -void __tsan_go_atomic64_compare_exchange( - ThreadState *thr, uptr cpc, uptr pc, u8 *a) { +void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc, + u8 *a) { a64 cur = 0; - a64 cmp = *(a64*)(a+8); - ATOMIC_RET(CAS, cur, *(a64**)a, cmp, *(a64*)(a+16), mo_acq_rel, mo_acquire); - *(bool*)(a+24) = (cur == cmp); + a64 cmp = *(a64 *)(a + 8); + ATOMIC_RET(CAS, cur, mo_acq_rel, mo_acquire, *(a64 **)a, cmp, + *(a64 *)(a + 16)); + *(bool *)(a + 24) = (cur == cmp); } } // extern "C" #endif // #if !SANITIZER_GO diff --git a/compiler-rt/lib/xray/CMakeLists.txt b/compiler-rt/lib/xray/CMakeLists.txt index f38c07420c9ab..633c2e3a402f5 100644 --- a/compiler-rt/lib/xray/CMakeLists.txt +++ b/compiler-rt/lib/xray/CMakeLists.txt @@ -56,6 +56,10 @@ set(aarch64_SOURCES xray_trampoline_AArch64.S ) +set(aarch64_DSO_SOURCES + xray_trampoline_AArch64.S + ) + set(loongarch64_SOURCES xray_loongarch64.cpp xray_trampoline_loongarch64.S diff --git a/compiler-rt/lib/xray/xray_trampoline_AArch64.S b/compiler-rt/lib/xray/xray_trampoline_AArch64.S index 536a79e0d150e..2586def04cbb1 100644 --- a/compiler-rt/lib/xray/xray_trampoline_AArch64.S +++ b/compiler-rt/lib/xray/xray_trampoline_AArch64.S @@ -26,6 +26,17 @@ ldp x1, x2, [sp], #16 .endm +.macro LOAD_HANDLER_ADDR reg handler +#if !defined(XRAY_PIC) + adrp \reg, ASM_SYMBOL(\handler) + ldr \reg, [\reg, :lo12:ASM_SYMBOL(\handler)] +#else + adrp \reg, :got:ASM_SYMBOL(\handler) + ldr \reg, [\reg, :got_lo12:ASM_SYMBOL(\handler)] + ldr \reg, [\reg] +#endif +.endm + .text .p2align 2 .global ASM_SYMBOL(__xray_FunctionEntry) @@ -42,8 +53,7 @@ ASM_SYMBOL(__xray_FunctionEntry): SAVE_REGISTERS // Load the handler function pointer. - adrp x2, ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE) - ldr x2, [x2, #:lo12:ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)] + LOAD_HANDLER_ADDR x2, _ZN6__xray19XRayPatchedFunctionE cbz x2, 1f // Set w0 to the function ID (w17). Set x1 to XRayEntryType::ENTRY = 0. mov w0, w17 @@ -69,8 +79,7 @@ ASM_SYMBOL(__xray_FunctionExit): SAVE_REGISTERS // Load the handler function pointer into x2. - adrp x2, ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE) - ldr x2, [x2, #:lo12:ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)] + LOAD_HANDLER_ADDR x2, _ZN6__xray19XRayPatchedFunctionE cbz x2, 1f // Set w0 to the function ID (w17). Set x1 to XRayEntryType::EXIT = 1. mov w0, w17 @@ -96,8 +105,7 @@ ASM_SYMBOL(__xray_FunctionTailExit): // Save the registers which may be modified by the handler function. SAVE_REGISTERS // Load the handler function pointer into x2. - adrp x2, ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE) - ldr x2, [x2, #:lo12:ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)] + LOAD_HANDLER_ADDR x2, _ZN6__xray19XRayPatchedFunctionE cbz x2, 1f // Set w0 to the function ID (w17). Set x1 to XRayEntryType::TAIL = 2. mov w0, w17 @@ -118,13 +126,11 @@ ASM_SYMBOL(__xray_ArgLoggerEntry): // Push the registers which may be modified by the handler function. SAVE_REGISTERS - adrp x8, ASM_SYMBOL(_ZN6__xray13XRayArgLoggerE) - ldr x8, [x8, #:lo12:ASM_SYMBOL(_ZN6__xray13XRayArgLoggerE)] + LOAD_HANDLER_ADDR x8, _ZN6__xray13XRayArgLoggerE cbnz x8, 2f // Load the handler function pointer. - adrp x8, ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE) - ldr x8, [x8, #:lo12:ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)] + LOAD_HANDLER_ADDR x8, _ZN6__xray19XRayPatchedFunctionE cbz x8, 1f 2: @@ -144,8 +150,7 @@ ASM_SIZE(__xray_ArgLoggerEntry) ASM_TYPE_FUNCTION(__xray_CustomEvent) ASM_SYMBOL(__xray_CustomEvent): SAVE_REGISTERS - adrp x8, ASM_SYMBOL(_ZN6__xray22XRayPatchedCustomEventE) - ldr x8, [x8, #:lo12:ASM_SYMBOL(_ZN6__xray22XRayPatchedCustomEventE)] + LOAD_HANDLER_ADDR x8, _ZN6__xray22XRayPatchedCustomEventE cbz x8, 1f blr x8 1: @@ -157,8 +162,7 @@ ASM_SIZE(__xray_CustomEvent) ASM_TYPE_FUNCTION(__xray_TypedEvent) ASM_SYMBOL(__xray_TypedEvent): SAVE_REGISTERS - adrp x8, ASM_SYMBOL(_ZN6__xray21XRayPatchedTypedEventE) - ldr x8, [x8, #:lo12:ASM_SYMBOL(_ZN6__xray21XRayPatchedTypedEventE)] + LOAD_HANDLER_ADDR x8, _ZN6__xray21XRayPatchedTypedEventE cbz x8, 1f blr x8 1: diff --git a/compiler-rt/test/asan/CMakeLists.txt b/compiler-rt/test/asan/CMakeLists.txt index fb9e81bbe8082..414a6cc9496ed 100644 --- a/compiler-rt/test/asan/CMakeLists.txt +++ b/compiler-rt/test/asan/CMakeLists.txt @@ -36,7 +36,7 @@ set(ASAN_TEST_ARCH ${ASAN_SUPPORTED_ARCH}) if(APPLE) darwin_filter_host_archs(ASAN_SUPPORTED_ARCH ASAN_TEST_ARCH) endif() -list(REMOVE_ITEM ASAN_TEST_ARCH sparc sparcv9) +list(REMOVE_ITEM ASAN_TEST_ARCH sparcv9) if(OS_NAME MATCHES "SunOS") list(REMOVE_ITEM ASAN_TEST_ARCH x86_64) endif() diff --git a/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp b/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp index 96ac4c7db291a..b98bb726dcebc 100644 --- a/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp +++ b/compiler-rt/test/asan/TestCases/alloca_vla_interact.cpp @@ -3,6 +3,9 @@ // // REQUIRES: stable-runtime +// See https://github.com/llvm/llvm-project/issues/110956 +// XFAIL: target=sparc{{.*}} + // This testcase checks correct interaction between VLAs and allocas. #include diff --git a/compiler-rt/test/asan/TestCases/zero_page_pc.cpp b/compiler-rt/test/asan/TestCases/zero_page_pc.cpp index 9a395ecdf37c8..a7d00ce9b6988 100644 --- a/compiler-rt/test/asan/TestCases/zero_page_pc.cpp +++ b/compiler-rt/test/asan/TestCases/zero_page_pc.cpp @@ -19,6 +19,6 @@ int main() { // the compiler is free to choose the order. As a result, the address is // either 0x4, 0xc or 0x14. The pc is still in main() because it has not // actually made the call when the faulting access occurs. - // CHECK: {{AddressSanitizer: (SEGV|access-violation).*(address|pc) 0x0*[4c]}} + // CHECK: {{AddressSanitizer: (SEGV|access-violation).*(address|pc) 0x0*[45c]}} return 0; } diff --git a/compiler-rt/test/builtins/Unit/ctor_dtor.c b/compiler-rt/test/builtins/Unit/ctor_dtor.c index 47560722a9f75..58dffba5338ea 100644 --- a/compiler-rt/test/builtins/Unit/ctor_dtor.c +++ b/compiler-rt/test/builtins/Unit/ctor_dtor.c @@ -1,7 +1,7 @@ // REQUIRES: crt // RUN: %clang -fno-use-init-array -g -c %s -o %t.o -// RUN: %clang -o %t -no-pie -nostdlib %crt1 %crti %crtbegin %t.o -lc %libgcc %crtend %crtn +// RUN: %clang -o %t -no-pie -nostdlib %crt1 %crti %crtbegin %t.o %libc %libgcc %crtend %crtn // RUN: %run %t 2>&1 | FileCheck %s #include diff --git a/compiler-rt/test/builtins/Unit/dso_handle.cpp b/compiler-rt/test/builtins/Unit/dso_handle.cpp index 796746992af94..183e29b8ac31a 100644 --- a/compiler-rt/test/builtins/Unit/dso_handle.cpp +++ b/compiler-rt/test/builtins/Unit/dso_handle.cpp @@ -2,8 +2,8 @@ // RUN: %clangxx -g -fno-exceptions -DCRT_SHARED -c %s -fPIC -o %tshared.o // RUN: %clangxx -g -fno-exceptions -c %s -fPIC -o %t.o -// RUN: %clangxx -g -shared -o %t.so -nostdlib %crti %crtbegin %tshared.o %libstdcxx -lc -lm %libgcc %crtend %crtn -// RUN: %clangxx -g -o %t -fno-pic -no-pie -nostdlib %crt1 %crti %crtbegin %t.o %libstdcxx -lc -lm %libgcc %t.so %crtend %crtn +// RUN: %clangxx -g -shared -o %t.so -nostdlib %crti %crtbegin %tshared.o %libstdcxx %libc -lm %libgcc %crtend %crtn +// RUN: %clangxx -g -o %t -fno-pic -no-pie -nostdlib %crt1 %crti %crtbegin %t.o %libstdcxx %libc -lm %libgcc %t.so %crtend %crtn // RUN: %run %t 2>&1 | FileCheck %s // UNSUPPORTED: target={{(arm|aarch64).*}} diff --git a/compiler-rt/test/builtins/Unit/lit.cfg.py b/compiler-rt/test/builtins/Unit/lit.cfg.py index c18c973d54c13..c030f89c66e42 100644 --- a/compiler-rt/test/builtins/Unit/lit.cfg.py +++ b/compiler-rt/test/builtins/Unit/lit.cfg.py @@ -104,7 +104,10 @@ def get_libgcc_file_name(): if sys.platform in ["win32"] and execute_external: # Don't pass dosish path separator to msys bash.exe. base_lib = base_lib.replace("\\", "/") - config.substitutions.append(("%librt ", base_lib + " -lc -lm ")) + if config.host_os == "Haiku": + config.substitutions.append(("%librt ", base_lib + " -lroot ")) + else: + config.substitutions.append(("%librt ", base_lib + " -lc -lm ")) builtins_build_crt = get_required_attr(config, "builtins_build_crt") if builtins_build_crt: @@ -123,6 +126,9 @@ def get_libgcc_file_name(): config.substitutions.append(("%crtn", get_library_path("crtn.o"))) config.substitutions.append(("%libgcc", get_libgcc_file_name())) + config.substitutions.append( + ("%libc", "-lroot" if sys.platform.startswith("haiku") else "-lc") + ) config.substitutions.append( ("%libstdcxx", "-l" + config.sanitizer_cxx_lib.lstrip("lib")) diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index 4bbce4c073666..c6f27748ccb76 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -82,6 +82,8 @@ def push_dynamic_library_lookup_path(config, new_path): dynamic_library_lookup_var = "PATH" elif platform.system() == "Darwin": dynamic_library_lookup_var = "DYLD_LIBRARY_PATH" + elif platform.system() == "Haiku": + dynamic_library_lookup_var = "LIBRARY_PATH" else: dynamic_library_lookup_var = "LD_LIBRARY_PATH" @@ -275,7 +277,6 @@ def push_dynamic_library_lookup_path(config, new_path): "COMPILER_PATH", "RC_DEBUG_OPTIONS", "CINDEXTEST_PREAMBLE_FILE", - "LIBRARY_PATH", "CPATH", "C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH", diff --git a/compiler-rt/test/profile/Posix/gcov-destructor.c b/compiler-rt/test/profile/Posix/gcov-destructor.c index bd1e0d2dde079..1f9412f095a0f 100644 --- a/compiler-rt/test/profile/Posix/gcov-destructor.c +++ b/compiler-rt/test/profile/Posix/gcov-destructor.c @@ -1,4 +1,5 @@ /// Test that destructors and destructors whose priorities are greater than 100 are tracked. +// XFAIL: target={{.*haiku.*}} // RUN: mkdir -p %t.dir && cd %t.dir // RUN: %clang --coverage %s -o %t -dumpdir ./ // RUN: rm -f gcov-destructor.gcda && %run %t diff --git a/compiler-rt/test/profile/Posix/gcov-dlopen.c b/compiler-rt/test/profile/Posix/gcov-dlopen.c index ceac6ac355ee6..72f11186e084c 100644 --- a/compiler-rt/test/profile/Posix/gcov-dlopen.c +++ b/compiler-rt/test/profile/Posix/gcov-dlopen.c @@ -1,5 +1,6 @@ /// atexit(3) not supported in dlopen(3)ed+dlclose(3)d DSO // XFAIL: target={{.*netbsd.*}} +// XFAIL: target={{.*haiku.*}} // RUN: mkdir -p %t.d && cd %t.d diff --git a/compiler-rt/test/profile/Posix/instrprof-dlopen-norpath.test b/compiler-rt/test/profile/Posix/instrprof-dlopen-norpath.test index 0d750185204ae..1c98969802817 100644 --- a/compiler-rt/test/profile/Posix/instrprof-dlopen-norpath.test +++ b/compiler-rt/test/profile/Posix/instrprof-dlopen-norpath.test @@ -1,3 +1,4 @@ +XFAIL: target={{.*haiku.*}} RUN: rm -rf %t && split-file %s %t && cd %t RUN: %clang_pgogen -fprofile-update=atomic -fPIC foo.c -c -Xclang -fprofile-instrument-path="default_foo_%m.profraw" RUN: %clang_pgogen -fprofile-update=atomic -fPIC foo2.c -c -Xclang -fprofile-instrument-path="default_foo2_%m.profraw" diff --git a/compiler-rt/test/profile/instrprof-error.c b/compiler-rt/test/profile/instrprof-error.c index 3297c9d8840ae..a49d238edf8fc 100644 --- a/compiler-rt/test/profile/instrprof-error.c +++ b/compiler-rt/test/profile/instrprof-error.c @@ -1,3 +1,4 @@ +// XFAIL: target={{.*haiku.*}} // RUN: %clang_profgen -o %t -O3 %s // RUN: env LLVM_PROFILE_FILE=%t/ %run %t 1 2>&1 | FileCheck %s diff --git a/compiler-rt/test/profile/lit.cfg.py b/compiler-rt/test/profile/lit.cfg.py index ca6df08ad0436..bb5e28d87bb0f 100644 --- a/compiler-rt/test/profile/lit.cfg.py +++ b/compiler-rt/test/profile/lit.cfg.py @@ -162,6 +162,7 @@ def exclude_unsupported_files_for_aix(dirname): "NetBSD", "SunOS", "AIX", + "Haiku", ]: config.unsupported = True diff --git a/compiler-rt/test/sanitizer_common/CMakeLists.txt b/compiler-rt/test/sanitizer_common/CMakeLists.txt index fa06b82acebd9..615666676f57a 100644 --- a/compiler-rt/test/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/test/sanitizer_common/CMakeLists.txt @@ -59,7 +59,7 @@ foreach(tool ${SUPPORTED_TOOLS}) darwin_filter_host_archs(${tool_toupper}_SUPPORTED_ARCH TEST_ARCH) endif() if(${tool} STREQUAL "asan") - list(REMOVE_ITEM TEST_ARCH sparc sparcv9) + list(REMOVE_ITEM TEST_ARCH sparcv9) endif() if(OS_NAME MATCHES "SunOS" AND ${tool} STREQUAL "asan") list(REMOVE_ITEM TEST_ARCH x86_64) diff --git a/compiler-rt/test/ubsan/CMakeLists.txt b/compiler-rt/test/ubsan/CMakeLists.txt index d95f9ad649ebf..9b7fbe3c8f926 100644 --- a/compiler-rt/test/ubsan/CMakeLists.txt +++ b/compiler-rt/test/ubsan/CMakeLists.txt @@ -51,10 +51,10 @@ foreach(arch ${UBSAN_TEST_ARCH}) if(COMPILER_RT_HAS_ASAN AND ";${ASAN_SUPPORTED_ARCH};" MATCHES ";${arch};") # TODO(wwchrome): Re-enable ubsan for asan win 64-bit when ready. # Disable ubsan with AddressSanitizer tests for Windows 64-bit, - # 64-bit Solaris/x86, and SPARC. + # 64-bit Solaris/x86 and 64-bit SPARC. if((NOT (OS_NAME MATCHES "Windows" AND CMAKE_SIZEOF_VOID_P EQUAL 8)) AND (NOT (OS_NAME MATCHES "SunOS" AND ${arch} MATCHES x86_64)) AND - (NOT ${arch} MATCHES sparc)) + (NOT ${arch} MATCHES sparcv9)) add_ubsan_testsuites("AddressSanitizer" asan ${arch}) endif() endif() diff --git a/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp b/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp index 31c615bd1f81b..d40dcd808bcba 100644 --- a/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp +++ b/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp @@ -8,7 +8,8 @@ // RUN: %llvm_xray account --format=csv --sort=funcid "`ls basic-mode-dso-* | head -1`" | FileCheck --check-prefix=ACCOUNT %s // RUN: rm basic-mode-dso-* -// REQUIRES: target=x86_64{{.*}} +// REQUIRES: target={{(aarch64|x86_64)-.*}} +// REQUIRES: built-in-llvm-tree //--- main.cpp diff --git a/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp b/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp index 0dd721571de9b..f36b64dd59f1a 100644 --- a/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp +++ b/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp @@ -6,7 +6,7 @@ // RUN: %clangxx -fxray-instrument %s -shared -o %t.so // RUN: llvm-nm %t.so | FileCheck %s --check-prefix DISABLED // -// REQUIRES: target=x86_64{{.*}} +// REQUIRES: target={{(aarch64|x86_64)-.*}} [[clang::xray_always_instrument]] int always_instrumented() { return 42; } diff --git a/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp b/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp index 9db411d5ff1c6..9567269e8ff1b 100644 --- a/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp +++ b/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp @@ -7,7 +7,7 @@ // // RUN: XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlib.so 2>&1 | FileCheck %s -// REQUIRES: target=x86_64{{.*}} +// REQUIRES: target={{(aarch64|x86_64)-.*}} //--- main.cpp diff --git a/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp b/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp index 89da2764c35ce..82cc127b521a6 100644 --- a/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp +++ b/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp @@ -17,7 +17,7 @@ // // RUN: XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlibd.so %t/testlibe.so 2>&1 | FileCheck %s -// REQUIRES: target=x86_64{{.*}} +// REQUIRES: target={{(aarch64|x86_64)-.*}} //--- main.cpp diff --git a/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp b/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp index 0708d0383439d..7bce653fe7233 100644 --- a/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp +++ b/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp @@ -6,7 +6,7 @@ // RUN: XRAY_OPTIONS="patch_premain=true,verbosity=1" %run %t/main.o 2>&1 | FileCheck %s -// REQUIRES: target=x86_64{{.*}} +// REQUIRES: target={{(aarch64|x86_64)-.*}} //--- main.cpp diff --git a/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp b/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp index d3e992dd49772..640cf9bcc1a34 100644 --- a/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp +++ b/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp @@ -8,7 +8,7 @@ // RUN: XRAY_OPTIONS="patch_premain=false" %run %t/main.o 2>&1 | FileCheck %s -// REQUIRES: target=x86_64{{.*}} +// REQUIRES: target={{(aarch64|x86_64)-.*}} //--- main.cpp diff --git a/flang/include/flang/Evaluate/check-expression.h b/flang/include/flang/Evaluate/check-expression.h index b711d289ba524..49b64468ffaa7 100644 --- a/flang/include/flang/Evaluate/check-expression.h +++ b/flang/include/flang/Evaluate/check-expression.h @@ -115,6 +115,10 @@ extern template std::optional IsContiguous( const CoarrayRef &, FoldingContext &); extern template std::optional IsContiguous( const Symbol &, FoldingContext &); +static inline std::optional IsContiguous( + const SymbolRef &s, FoldingContext &c) { + return IsContiguous(s.get(), c); +} template bool IsSimplyContiguous(const A &x, FoldingContext &context) { return IsContiguous(x, context).value_or(false); diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 67f7e1aac40ed..bfeb23de53539 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -510,6 +510,7 @@ class ParseTreeDumper { NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior) NODE_ENUM(OmpDefaultmapClause, VariableCategory) NODE(parser, OmpDependClause) + NODE(parser, OmpDetachClause) NODE(OmpDependClause, InOut) NODE(OmpDependClause, Sink) NODE(OmpDependClause, Source) @@ -524,6 +525,8 @@ class ParseTreeDumper { NODE(parser, OmpEndCriticalDirective) NODE(parser, OmpEndLoopDirective) NODE(parser, OmpEndSectionsDirective) + NODE(parser, OmpFromClause) + NODE_ENUM(OmpFromClause, Expectation) NODE(parser, OmpIfClause) NODE_ENUM(OmpIfClause, DirectiveNameModifier) NODE_ENUM(OmpLastprivateClause, LastprivateModifier) @@ -581,6 +584,9 @@ class ParseTreeDumper { NODE(parser, OmpSectionBlocks) NODE(parser, OmpSectionsDirective) NODE(parser, OmpSimpleStandaloneDirective) + NODE(parser, OmpToClause) + // No NODE_ENUM for OmpToClause::Expectation, because it's an alias + // for OmpFromClause::Expectation. NODE(parser, Only) NODE(parser, OpenACCAtomicConstruct) NODE(parser, OpenACCBlockConstruct) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 13c3353512208..2f66aade32ac6 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3582,6 +3582,26 @@ struct OmpDeviceTypeClause { WRAPPER_CLASS_BOILERPLATE(OmpDeviceTypeClause, Type); }; +// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168] +// +// from-clause -> +// FROM(locator-list) | +// FROM(mapper-modifier: locator-list) | // since 5.0 +// FROM(motion-modifier[,] ...: locator-list) // since 5.1 +// motion-modifier -> +// PRESENT | mapper-modifier | iterator-modifier +struct OmpFromClause { + ENUM_CLASS(Expectation, Present); + TUPLE_CLASS_BOILERPLATE(OmpFromClause); + + // As in the case of MAP, modifiers are parsed as lists, even if they + // are unique. These restrictions will be checked in semantic checks. + std::tuple>, + std::optional>, OmpObjectList, + bool> // were the modifiers comma-separated? + t; +}; + // OMP 5.2 12.6.1 grainsize-clause -> grainsize ([prescriptiveness :] value) struct OmpGrainsizeClause { TUPLE_CLASS_BOILERPLATE(OmpGrainsizeClause); @@ -3597,6 +3617,11 @@ struct OmpIfClause { std::tuple, ScalarLogicalExpr> t; }; +// OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle) +struct OmpDetachClause { + WRAPPER_CLASS_BOILERPLATE(OmpDetachClause, OmpObject); +}; + // OMP 5.0 2.19.5.6 in_reduction-clause -> IN_REDUCTION (reduction-identifier: // variable-name-list) struct OmpInReductionClause { @@ -3718,6 +3743,28 @@ struct OmpScheduleClause { t; }; +// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168] +// +// to-clause (in DECLARE TARGET) -> +// TO(extended-list) | // until 5.1 +// to-clause (in TARGET UPDATE) -> +// TO(locator-list) | +// TO(mapper-modifier: locator-list) | // since 5.0 +// TO(motion-modifier[,] ...: locator-list) // since 5.1 +// motion-modifier -> +// PRESENT | mapper-modifier | iterator-modifier +struct OmpToClause { + using Expectation = OmpFromClause::Expectation; + TUPLE_CLASS_BOILERPLATE(OmpToClause); + + // As in the case of MAP, modifiers are parsed as lists, even if they + // are unique. These restrictions will be checked in semantic checks. + std::tuple>, + std::optional>, OmpObjectList, + bool> // were the modifiers comma-separated? + t; +}; + // OMP 5.2 12.6.2 num_tasks-clause -> num_tasks ([prescriptiveness :] value) struct OmpNumTasksClause { TUPLE_CLASS_BOILERPLATE(OmpNumTasksClause); diff --git a/flang/include/flang/Runtime/CUDA/memory.h b/flang/include/flang/Runtime/CUDA/memory.h index 6d2e0c0f15942..51d6b8d4545f0 100644 --- a/flang/include/flang/Runtime/CUDA/memory.h +++ b/flang/include/flang/Runtime/CUDA/memory.h @@ -49,6 +49,10 @@ void RTDECL(CUFDataTransferPtrDesc)(void *dst, Descriptor *src, void RTDECL(CUFDataTransferDescDesc)(Descriptor *dst, Descriptor *src, unsigned mode, const char *sourceFile = nullptr, int sourceLine = 0); +/// Data transfer from a descriptor to a global descriptor. +void RTDECL(CUFDataTransferGlobalDescDesc)(Descriptor *dst, Descriptor *src, + unsigned mode, const char *sourceFile = nullptr, int sourceLine = 0); + } // extern "C" } // namespace Fortran::runtime::cuda #endif // FORTRAN_RUNTIME_CUDA_MEMORY_H_ diff --git a/flang/lib/Lower/DirectivesCommon.h b/flang/lib/Lower/DirectivesCommon.h index 421a44b128c01..88514b1674327 100644 --- a/flang/lib/Lower/DirectivesCommon.h +++ b/flang/lib/Lower/DirectivesCommon.h @@ -179,7 +179,11 @@ static inline void genOmpAccAtomicWriteStatement( fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Type varType = fir::unwrapRefType(lhsAddr.getType()); + // Create a conversion outside the capture block. + auto insertionPoint = firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPointAfter(rhsExpr.getDefiningOp()); rhsExpr = firOpBuilder.createConvert(loc, varType, rhsExpr); + firOpBuilder.restoreInsertionPoint(insertionPoint); processOmpAtomicTODO(varType, loc); @@ -410,10 +414,6 @@ void genOmpAccAtomicRead(Fortran::lower::AbstractConverter &converter, fir::getBase(converter.genExprAddr(fromExpr, stmtCtx)); mlir::Value toAddress = fir::getBase(converter.genExprAddr( *Fortran::semantics::GetExpr(assignmentStmtVariable), stmtCtx)); - fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - if (fromAddress.getType() != toAddress.getType()) - fromAddress = - builder.create(loc, toAddress.getType(), fromAddress); genOmpAccAtomicCaptureStatement(converter, fromAddress, toAddress, leftHandClauseList, rightHandClauseList, elementType, loc); @@ -497,23 +497,12 @@ void genOmpAccAtomicCapture(Fortran::lower::AbstractConverter &converter, // a `atomic.read`, `atomic.write`, or `atomic.update` operation // inside `atomic.capture` Fortran::lower::StatementContext stmtCtx; - mlir::Value stmt1LHSArg, stmt1RHSArg, stmt2LHSArg, stmt2RHSArg; - mlir::Type elementType; // LHS evaluations are common to all combinations of `atomic.capture` - stmt1LHSArg = fir::getBase(converter.genExprAddr(assign1.lhs, stmtCtx)); - stmt2LHSArg = fir::getBase(converter.genExprAddr(assign2.lhs, stmtCtx)); + mlir::Value stmt1LHSArg = + fir::getBase(converter.genExprAddr(assign1.lhs, stmtCtx)); + mlir::Value stmt2LHSArg = + fir::getBase(converter.genExprAddr(assign2.lhs, stmtCtx)); - // Operation specific RHS evaluations - if (Fortran::semantics::checkForSingleVariableOnRHS(stmt1)) { - // Atomic capture construct is of the form [capture-stmt, update-stmt] or - // of the form [capture-stmt, write-stmt] - stmt1RHSArg = fir::getBase(converter.genExprAddr(assign1.rhs, stmtCtx)); - stmt2RHSArg = fir::getBase(converter.genExprValue(assign2.rhs, stmtCtx)); - } else { - // Atomic capture construct is of the form [update-stmt, capture-stmt] - stmt1RHSArg = fir::getBase(converter.genExprValue(assign1.rhs, stmtCtx)); - stmt2RHSArg = fir::getBase(converter.genExprAddr(assign2.lhs, stmtCtx)); - } // Type information used in generation of `atomic.update` operation mlir::Type stmt1VarType = fir::getBase(converter.genExprValue(assign1.lhs, stmtCtx)).getType(); @@ -545,44 +534,46 @@ void genOmpAccAtomicCapture(Fortran::lower::AbstractConverter &converter, // Atomic capture construct is of the form [capture-stmt, update-stmt] const Fortran::semantics::SomeExpr &fromExpr = *Fortran::semantics::GetExpr(stmt1Expr); - elementType = converter.genType(fromExpr); + mlir::Type elementType = converter.genType(fromExpr); genOmpAccAtomicCaptureStatement( - converter, stmt1RHSArg, stmt1LHSArg, + converter, stmt2LHSArg, stmt1LHSArg, /*leftHandClauseList=*/nullptr, /*rightHandClauseList=*/nullptr, elementType, loc); genOmpAccAtomicUpdateStatement( - converter, stmt1RHSArg, stmt2VarType, stmt2Var, stmt2Expr, + converter, stmt2LHSArg, stmt2VarType, stmt2Var, stmt2Expr, /*leftHandClauseList=*/nullptr, /*rightHandClauseList=*/nullptr, loc, atomicCaptureOp); } else { // Atomic capture construct is of the form [capture-stmt, write-stmt] + firOpBuilder.setInsertionPoint(atomicCaptureOp); + mlir::Value stmt2RHSArg = + fir::getBase(converter.genExprValue(assign2.rhs, stmtCtx)); + firOpBuilder.setInsertionPointToStart(&block); const Fortran::semantics::SomeExpr &fromExpr = *Fortran::semantics::GetExpr(stmt1Expr); - elementType = converter.genType(fromExpr); + mlir::Type elementType = converter.genType(fromExpr); genOmpAccAtomicCaptureStatement( - converter, stmt1RHSArg, stmt1LHSArg, + converter, stmt2LHSArg, stmt1LHSArg, /*leftHandClauseList=*/nullptr, /*rightHandClauseList=*/nullptr, elementType, loc); genOmpAccAtomicWriteStatement( - converter, stmt1RHSArg, stmt2RHSArg, + converter, stmt2LHSArg, stmt2RHSArg, /*leftHandClauseList=*/nullptr, /*rightHandClauseList=*/nullptr, loc); } } else { // Atomic capture construct is of the form [update-stmt, capture-stmt] - firOpBuilder.setInsertionPointToEnd(&block); const Fortran::semantics::SomeExpr &fromExpr = *Fortran::semantics::GetExpr(stmt2Expr); - elementType = converter.genType(fromExpr); - genOmpAccAtomicCaptureStatement( - converter, stmt1LHSArg, stmt2LHSArg, - /*leftHandClauseList=*/nullptr, - /*rightHandClauseList=*/nullptr, elementType, loc); - firOpBuilder.setInsertionPointToStart(&block); + mlir::Type elementType = converter.genType(fromExpr); genOmpAccAtomicUpdateStatement( converter, stmt1LHSArg, stmt1VarType, stmt1Var, stmt1Expr, /*leftHandClauseList=*/nullptr, /*rightHandClauseList=*/nullptr, loc, atomicCaptureOp); + genOmpAccAtomicCaptureStatement( + converter, stmt1LHSArg, stmt2LHSArg, + /*leftHandClauseList=*/nullptr, + /*rightHandClauseList=*/nullptr, elementType, loc); } firOpBuilder.setInsertionPointToEnd(&block); if constexpr (std::is_same, omp::clause::To> ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; - processMapObjects(stmtCtx, clauseLocation, std::get(clause.t), - mapTypeBits, parentMemberIndices, result.mapVars, - mapSymbols); + processMapObjects(stmtCtx, clauseLocation, objects, mapTypeBits, + parentMemberIndices, result.mapVars, mapSymbols); }; bool clauseFound = findRepeatableClause(callbackFn); diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 45b89de023a4b..936d0d21997d5 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -635,8 +635,8 @@ Destroy make(const parser::OmpClause::Destroy &inp, Detach make(const parser::OmpClause::Detach &inp, semantics::SemanticsContext &semaCtx) { - // inp -> empty - llvm_unreachable("Empty: detach"); + // inp.v -> parser::OmpDetachClause + return Detach{makeObject(inp.v.v, semaCtx)}; } Device make(const parser::OmpClause::Device &inp, @@ -728,21 +728,51 @@ Firstprivate make(const parser::OmpClause::Firstprivate &inp, From make(const parser::OmpClause::From &inp, semantics::SemanticsContext &semaCtx) { - // inp.v -> parser::OmpObjectList - return From{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt, - /*Iterator=*/std::nullopt, - /*LocatorList=*/makeObjects(inp.v, semaCtx)}}; + // inp.v -> parser::OmpFromClause + using wrapped = parser::OmpFromClause; + + CLAUSET_ENUM_CONVERT( // + convert, parser::OmpFromClause::Expectation, From::Expectation, + // clang-format off + MS(Present, Present) + // clang-format on + ); + + auto &t0 = std::get>>(inp.v.t); + auto &t1 = + std::get>>(inp.v.t); + auto &t2 = std::get(inp.v.t); + + assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed"); + assert((!t1 || t1->size() == 1) && "Only one iterator modifier allowed"); + + auto expectation = [&]() -> std::optional { + if (t0) + return convert(t0->front()); + return std::nullopt; + }(); + + auto iterator = [&]() -> std::optional { + if (t1) + return makeIterator(t1->front(), semaCtx); + return std::nullopt; + }(); + + return From{{/*Expectation=*/std::move(expectation), /*Mapper=*/std::nullopt, + /*Iterator=*/std::move(iterator), + /*LocatorList=*/makeObjects(t2, semaCtx)}}; } // Full: empty Grainsize make(const parser::OmpClause::Grainsize &inp, - semantics::SemanticsContext &semaCtx) { + semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpGrainsizeClause using wrapped = parser::OmpGrainsizeClause; CLAUSET_ENUM_CONVERT( // - convert, parser::OmpGrainsizeClause::Prescriptiveness, Grainsize::Prescriptiveness, + convert, parser::OmpGrainsizeClause::Prescriptiveness, + Grainsize::Prescriptiveness, // clang-format off MS(Strict, Strict) // clang-format on @@ -1274,10 +1304,39 @@ ThreadLimit make(const parser::OmpClause::ThreadLimit &inp, To make(const parser::OmpClause::To &inp, semantics::SemanticsContext &semaCtx) { - // inp.v -> parser::OmpObjectList - return To{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt, - /*Iterator=*/std::nullopt, - /*LocatorList=*/makeObjects(inp.v, semaCtx)}}; + // inp.v -> parser::OmpToClause + using wrapped = parser::OmpToClause; + + CLAUSET_ENUM_CONVERT( // + convert, parser::OmpToClause::Expectation, To::Expectation, + // clang-format off + MS(Present, Present) + // clang-format on + ); + + auto &t0 = std::get>>(inp.v.t); + auto &t1 = + std::get>>(inp.v.t); + auto &t2 = std::get(inp.v.t); + + assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed"); + assert((!t1 || t1->size() == 1) && "Only one iterator modifier allowed"); + + auto expectation = [&]() -> std::optional { + if (t0) + return convert(t0->front()); + return std::nullopt; + }(); + + auto iterator = [&]() -> std::optional { + if (t1) + return makeIterator(t1->front(), semaCtx); + return std::nullopt; + }(); + + return To{{/*Expectation=*/std::move(expectation), /*Mapper=*/std::nullopt, + /*Iterator=*/std::move(iterator), + /*LocatorList=*/makeObjects(t2, semaCtx)}}; } // UnifiedAddress: empty diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 329cbf3d7539f..4f9e2347308aa 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -2246,12 +2246,6 @@ static void genCompositeDistributeParallelDoSimd( genSimdClauses(converter, semaCtx, simdItem->clauses, loc, simdClauseOps, simdReductionSyms); - // TODO: Remove this after omp.simd reductions on composite constructs are - // supported. - simdClauseOps.reductionVars.clear(); - simdClauseOps.reductionByref.clear(); - simdClauseOps.reductionSyms.clear(); - mlir::omp::LoopNestOperands loopNestClauseOps; llvm::SmallVector iv; genLoopNestClauses(converter, semaCtx, eval, simdItem->clauses, loc, @@ -2273,7 +2267,9 @@ static void genCompositeDistributeParallelDoSimd( wsloopOp.setComposite(/*val=*/true); EntryBlockArgs simdArgs; - // TODO: Add private and reduction syms and vars. + // TODO: Add private syms and vars. + simdArgs.reduction.syms = simdReductionSyms; + simdArgs.reduction.vars = simdClauseOps.reductionVars; auto simdOp = genWrapperOp(converter, loc, simdClauseOps, simdArgs); simdOp.setComposite(/*val=*/true); @@ -2366,12 +2362,6 @@ static void genCompositeDoSimd(lower::AbstractConverter &converter, genSimdClauses(converter, semaCtx, simdItem->clauses, loc, simdClauseOps, simdReductionSyms); - // TODO: Remove this after omp.simd reductions on composite constructs are - // supported. - simdClauseOps.reductionVars.clear(); - simdClauseOps.reductionByref.clear(); - simdClauseOps.reductionSyms.clear(); - // TODO: Support delayed privatization. DataSharingProcessor dsp(converter, semaCtx, simdItem->clauses, eval, /*shouldCollectPreDeterminedSymbols=*/true, @@ -2395,7 +2385,9 @@ static void genCompositeDoSimd(lower::AbstractConverter &converter, wsloopOp.setComposite(/*val=*/true); EntryBlockArgs simdArgs; - // TODO: Add private and reduction syms and vars. + // TODO: Add private syms and vars. + simdArgs.reduction.syms = simdReductionSyms; + simdArgs.reduction.vars = simdClauseOps.reductionVars; auto simdOp = genWrapperOp(converter, loc, simdClauseOps, simdArgs); simdOp.setComposite(/*val=*/true); diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp index 8b7918744017c..993d41633a079 100644 --- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp +++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp @@ -372,6 +372,29 @@ getAttrsFromVariable(fir::FortranVariableOpInterface var) { return attrs; } +template +static Value getPrivateArg(omp::BlockArgOpenMPOpInterface &argIface, + OMPTypeOp &op, DeclTypeOp &declOp) { + Value privateArg; + if (!op.getPrivateSyms().has_value()) + return privateArg; + for (auto [opSym, blockArg] : + llvm::zip_equal(*op.getPrivateSyms(), argIface.getPrivateBlockArgs())) { + if (blockArg == declOp.getMemref()) { + omp::PrivateClauseOp privateOp = + SymbolTable::lookupNearestSymbolFrom( + op, cast(opSym)); + privateOp.walk([&](omp::YieldOp yieldOp) { + llvm::TypeSwitch(yieldOp.getResults()[0].getDefiningOp()) + .template Case( + [&](auto declOp) { privateArg = declOp.getMemref(); }); + }); + return privateArg; + } + } + return privateArg; +} + AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, bool getInstantiationPoint) { auto *defOp = v.getDefiningOp(); @@ -470,20 +493,37 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, breakFromLoop = true; }) .Case([&](auto op) { - // If declare operation is inside omp target region, - // continue alias analysis outside the target region - if (auto targetOp = - llvm::dyn_cast(op->getParentOp())) { - auto argIface = cast(*targetOp); - for (auto [opArg, blockArg] : llvm::zip_equal( - targetOp.getMapVars(), argIface.getMapBlockArgs())) { - if (blockArg == op.getMemref()) { - omp::MapInfoOp mapInfo = - llvm::cast(opArg.getDefiningOp()); - v = mapInfo.getVarPtr(); - defOp = v.getDefiningOp(); - return; - } + if (omp::BlockArgOpenMPOpInterface argIface = + dyn_cast(op->getParentOp())) { + Value ompValArg; + llvm::TypeSwitch(op->getParentOp()) + .template Case([&](auto targetOp) { + // If declare operation is inside omp target region, + // continue alias analysis outside the target region + for (auto [opArg, blockArg] : llvm::zip_equal( + targetOp.getMapVars(), argIface.getMapBlockArgs())) { + if (blockArg == op.getMemref()) { + omp::MapInfoOp mapInfo = + llvm::cast(opArg.getDefiningOp()); + ompValArg = mapInfo.getVarPtr(); + break; + } + } + // If given operation does not reflect mapping item, + // check private clause + if (!ompValArg) + ompValArg = getPrivateArg(argIface, targetOp, op); + }) + .template Case( + [&](auto privateOp) { + ompValArg = getPrivateArg(argIface, privateOp, op); + }); + if (ompValArg) { + v = ompValArg; + defOp = ompValArg.getDefiningOp(); + return; } } auto varIf = llvm::cast(defOp); diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index 3c139f7e93405..a914407991591 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -264,10 +264,10 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, addNestedPassToAllTopLevelOperations(pm, fir::createAbstractResultOpt); fir::addCodeGenRewritePass( pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo)); - fir::addTargetRewritePass(pm); - fir::addCompilerGeneratedNamesConversionPass(pm); fir::addExternalNameConversionPass(pm, config.Underscoring); fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename); + fir::addTargetRewritePass(pm); + fir::addCompilerGeneratedNamesConversionPass(pm); if (config.VScaleMin != 0) pm.addPass(fir::createVScaleAttr({{config.VScaleMin, config.VScaleMax}})); diff --git a/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp index 4050064ebe95d..a28d0a562f2f0 100644 --- a/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp @@ -429,6 +429,16 @@ struct CUFFreeOpConversion : public mlir::OpRewritePattern { } }; +static bool isDstGlobal(cuf::DataTransferOp op) { + if (auto declareOp = op.getDst().getDefiningOp()) + if (declareOp.getMemref().getDefiningOp()) + return true; + if (auto declareOp = op.getDst().getDefiningOp()) + if (declareOp.getMemref().getDefiningOp()) + return true; + return false; +} + struct CUFDataTransferOpConversion : public mlir::OpRewritePattern { using OpRewritePattern::OpRewritePattern; @@ -522,8 +532,11 @@ struct CUFDataTransferOpConversion mlir::isa(dstTy)) { // Transfer between two descriptor. mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc( - loc, builder); + isDstGlobal(op) + ? fir::runtime::getRuntimeFunc(loc, builder) + : fir::runtime::getRuntimeFunc( + loc, builder); auto fTy = func.getFunctionType(); mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 6fde70fc5c387..0510b32a4c485 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -122,6 +122,40 @@ template struct MapModifiers { const Separator sep_; }; +// This is almost exactly the same thing as MapModifiers. It has the same +// issue (it expects modifiers in a specific order), and the fix for that +// will change how modifiers are parsed. Instead of making this code more +// generic, make it simple, and generalize after the fix is in place. +template struct MotionModifiers { + constexpr MotionModifiers(Separator sep) : sep_(sep) {} + constexpr MotionModifiers(const MotionModifiers &) = default; + constexpr MotionModifiers(MotionModifiers &&) = default; + + // Parsing of mappers if not implemented yet. + using ExpParser = Parser; + using IterParser = Parser; + using ModParser = ConcatSeparated; + + using resultType = typename ModParser::resultType; + + std::optional Parse(ParseState &state) const { + auto mp{ModParser(sep_, ExpParser{}, IterParser{})}; + auto mods{mp.Parse(state)}; + // The ModParser always "succeeds", i.e. even if the input is junk, it + // will return a tuple filled with nullopts. If any of the components + // is not a nullopt, expect a ":". + if (std::apply([](auto &&...opts) { return (... || !!opts); }, *mods)) { + if (!attempt(":"_tok).Parse(state)) { + return std::nullopt; + } + } + return std::move(mods); + } + +private: + const Separator sep_; +}; + // OpenMP Clauses // [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple | @@ -382,6 +416,31 @@ TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US, maybe(Parser{} / ","_tok), Parser{} / ":", Parser{}))) +TYPE_PARSER(construct( + "PRESENT" >> pure(OmpFromClause::Expectation::Present))) + +template +static inline MotionClause makeMotionClause( + std::tuple>, + std::optional>> &&mods, + OmpObjectList &&objs) { + auto &&[exp, iter] = std::move(mods); + return MotionClause( + std::move(exp), std::move(iter), std::move(objs), CommasEverywhere); +} + +TYPE_PARSER(construct( + applyFunction(makeMotionClause, + MotionModifiers(","_tok), Parser{}) || + applyFunction(makeMotionClause, + MotionModifiers(maybe(","_tok)), Parser{}))) + +TYPE_PARSER(construct( + applyFunction(makeMotionClause, + MotionModifiers(","_tok), Parser{}) || + applyFunction(makeMotionClause, + MotionModifiers(maybe(","_tok)), Parser{}))) + // 2.15.3.7 LINEAR (linear-list: linear-step) // linear-list -> list | modifier(list) // linear-modifier -> REF | VAL | UVAL @@ -398,6 +457,9 @@ TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US, construct(construct( nonemptyList(name), maybe(":" >> scalarIntConstantExpr))))) +// OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle) +TYPE_PARSER(construct(Parser{})) + // 2.8.1 ALIGNED (list: alignment) TYPE_PARSER(construct( Parser{}, maybe(":" >> scalarIntConstantExpr))) @@ -475,11 +537,11 @@ TYPE_PARSER( parenthesized(scalarIntExpr))) || "FINAL" >> construct(construct( parenthesized(scalarLogicalExpr))) || - "FULL" >> construct(construct()) || "FIRSTPRIVATE" >> construct(construct( parenthesized(Parser{}))) || "FROM" >> construct(construct( - parenthesized(Parser{}))) || + parenthesized(Parser{}))) || + "FULL" >> construct(construct()) || "GRAINSIZE" >> construct(construct( parenthesized(Parser{}))) || "HAS_DEVICE_ADDR" >> @@ -529,6 +591,8 @@ TYPE_PARSER( parenthesized(Parser{}))) || "IN_REDUCTION" >> construct(construct( parenthesized(Parser{}))) || + "DETACH" >> construct(construct( + parenthesized(Parser{}))) || "TASK_REDUCTION" >> construct(construct( parenthesized(Parser{}))) || @@ -554,7 +618,7 @@ TYPE_PARSER( "THREAD_LIMIT" >> construct(construct( parenthesized(scalarIntExpr))) || "TO" >> construct(construct( - parenthesized(Parser{}))) || + parenthesized(Parser{}))) || "USE_DEVICE_PTR" >> construct(construct( parenthesized(Parser{}))) || "USE_DEVICE_ADDR" >> diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 3b0824f80161f..bbb126dcdb6d5 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2138,6 +2138,27 @@ class UnparseVisitor { Put(","); Walk(std::get>(x.t)); } + void Unparse(const OmpFromClause &x) { + auto &expect{ + std::get>>(x.t)}; + auto &iter{std::get>>(x.t)}; + bool needComma{false}; + if (expect) { + Walk(*expect); + needComma = true; + } + if (iter) { + if (needComma) { + Put(", "); + } + Walk(*iter); + needComma = true; + } + if (needComma) { + Put(": "); + } + Walk(std::get(x.t)); + } void Unparse(const OmpIfClause &x) { Walk(std::get>(x.t), ":"); Walk(std::get(x.t)); @@ -2157,6 +2178,7 @@ class UnparseVisitor { Put(":"); Walk(std::get(x.t)); } + void Unparse(const OmpDetachClause &x) { Walk(x.v); } void Unparse(const OmpInReductionClause &x) { Walk(std::get(x.t)); Put(":"); @@ -2241,6 +2263,27 @@ class UnparseVisitor { Walk(":", std::get>(x.t)); } + void Unparse(const OmpToClause &x) { + auto &expect{ + std::get>>(x.t)}; + auto &iter{std::get>>(x.t)}; + bool needComma{false}; + if (expect) { + Walk(*expect); + needComma = true; + } + if (iter) { + if (needComma) { + Put(", "); + } + Walk(*iter); + needComma = true; + } + if (needComma) { + Put(": "); + } + Walk(std::get(x.t)); + } #define GEN_FLANG_CLAUSE_UNPARSE #include "llvm/Frontend/OpenMP/OMP.inc" void Unparse(const OmpLoopDirective &x) { @@ -2858,6 +2901,7 @@ class UnparseVisitor { WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE WALK_NESTED_ENUM( OmpReductionClause, ReductionModifier) // OMP reduction-modifier + WALK_NESTED_ENUM(OmpFromClause, Expectation) // OMP motion-expectation WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp index 623e31341a7c2..7afc285e7b9ae 100644 --- a/flang/lib/Semantics/check-acc-structure.cpp +++ b/flang/lib/Semantics/check-acc-structure.cpp @@ -674,26 +674,28 @@ void AccStructureChecker::Enter(const parser::AccClause::Reduction &reduction) { common::visitors{ [&](const parser::Designator &designator) { if (const auto *name = getDesignatorNameIfDataRef(designator)) { - const auto *type{name->symbol->GetType()}; - if (type->IsNumeric(TypeCategory::Integer) && - !reductionIntegerSet.test(op.v)) { - context_.Say(GetContext().clauseSource, - "reduction operator not supported for integer type"_err_en_US); - } else if (type->IsNumeric(TypeCategory::Real) && - !reductionRealSet.test(op.v)) { - context_.Say(GetContext().clauseSource, - "reduction operator not supported for real type"_err_en_US); - } else if (type->IsNumeric(TypeCategory::Complex) && - !reductionComplexSet.test(op.v)) { - context_.Say(GetContext().clauseSource, - "reduction operator not supported for complex type"_err_en_US); - } else if (type->category() == - Fortran::semantics::DeclTypeSpec::Category::Logical && - !reductionLogicalSet.test(op.v)) { - context_.Say(GetContext().clauseSource, - "reduction operator not supported for logical type"_err_en_US); + if (name->symbol) { + const auto *type{name->symbol->GetType()}; + if (type->IsNumeric(TypeCategory::Integer) && + !reductionIntegerSet.test(op.v)) { + context_.Say(GetContext().clauseSource, + "reduction operator not supported for integer type"_err_en_US); + } else if (type->IsNumeric(TypeCategory::Real) && + !reductionRealSet.test(op.v)) { + context_.Say(GetContext().clauseSource, + "reduction operator not supported for real type"_err_en_US); + } else if (type->IsNumeric(TypeCategory::Complex) && + !reductionComplexSet.test(op.v)) { + context_.Say(GetContext().clauseSource, + "reduction operator not supported for complex type"_err_en_US); + } else if (type->category() == + Fortran::semantics::DeclTypeSpec::Category::Logical && + !reductionLogicalSet.test(op.v)) { + context_.Say(GetContext().clauseSource, + "reduction operator not supported for logical type"_err_en_US); + } + // TODO: check composite type. } - // TODO: check composite type. } }, [&](const Fortran::parser::Name &name) { diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index c813100b4b16c..749d5887eaac0 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -8,6 +8,7 @@ #include "check-omp-structure.h" #include "definable.h" +#include "flang/Evaluate/check-expression.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" #include "flang/Semantics/tools.h" @@ -268,6 +269,56 @@ bool OmpStructureChecker::IsCloselyNestedRegion(const OmpDirectiveSet &set) { return false; } +namespace { +struct ContiguousHelper { + ContiguousHelper(SemanticsContext &context) + : fctx_(context.foldingContext()) {} + + template + std::optional Visit(const common::Indirection &x) { + return Visit(x.value()); + } + template + std::optional Visit(const common::Reference &x) { + return Visit(x.get()); + } + template std::optional Visit(const evaluate::Expr &x) { + return common::visit([&](auto &&s) { return Visit(s); }, x.u); + } + template + std::optional Visit(const evaluate::Designator &x) { + return common::visit( + [this](auto &&s) { return evaluate::IsContiguous(s, fctx_); }, x.u); + } + template std::optional Visit(const T &) { + // Everything else. + return std::nullopt; + } + +private: + evaluate::FoldingContext &fctx_; +}; +} // namespace + +std::optional OmpStructureChecker::IsContiguous( + const parser::OmpObject &object) { + return common::visit(common::visitors{ + [&](const parser::Name &x) { + // Any member of a common block must be contiguous. + return std::optional{true}; + }, + [&](const parser::Designator &x) { + evaluate::ExpressionAnalyzer ea{context_}; + if (MaybeExpr maybeExpr{ea.Analyze(x)}) { + return ContiguousHelper{context_}.Visit( + *maybeExpr); + } + return std::optional{}; + }, + }, + object.u); +} + void OmpStructureChecker::CheckMultipleOccurrence( semantics::UnorderedSymbolSet &listVars, const std::list &nameList, const parser::CharBlock &item, @@ -1466,9 +1517,10 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) { common::visitors{ [&](const parser::OmpClause::To &toClause) { toClauseFound = true; - CheckSymbolNames(dir.source, toClause.v); - CheckIsVarPartOfAnotherVar(dir.source, toClause.v); - CheckThreadprivateOrDeclareTargetVar(toClause.v); + auto &objList{std::get(toClause.v.t)}; + CheckSymbolNames(dir.source, objList); + CheckIsVarPartOfAnotherVar(dir.source, objList); + CheckThreadprivateOrDeclareTargetVar(objList); }, [&](const parser::OmpClause::Link &linkClause) { CheckSymbolNames(dir.source, linkClause.v); @@ -1647,21 +1699,25 @@ void OmpStructureChecker::CheckOrderedDependClause( } void OmpStructureChecker::CheckTargetUpdate() { - const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to); - const parser::OmpClause *fromClause = - FindClause(llvm::omp::Clause::OMPC_from); - if (!toClause && !fromClause) { + const parser::OmpClause *toWrapper{FindClause(llvm::omp::Clause::OMPC_to)}; + const parser::OmpClause *fromWrapper{ + FindClause(llvm::omp::Clause::OMPC_from)}; + if (!toWrapper && !fromWrapper) { context_.Say(GetContext().directiveSource, - "At least one motion-clause (TO/FROM) must be specified on TARGET UPDATE construct."_err_en_US); + "At least one motion-clause (TO/FROM) must be specified on " + "TARGET UPDATE construct."_err_en_US); } - if (toClause && fromClause) { + if (toWrapper && fromWrapper) { SymbolSourceMap toSymbols, fromSymbols; + auto &fromClause{std::get(fromWrapper->u).v}; + auto &toClause{std::get(toWrapper->u).v}; GetSymbolsInObjectList( - std::get(toClause->u).v, toSymbols); + std::get(fromClause.t), fromSymbols); GetSymbolsInObjectList( - std::get(fromClause->u).v, fromSymbols); + std::get(toClause.t), toSymbols); + for (auto &[symbol, source] : toSymbols) { - auto fromSymbol = fromSymbols.find(symbol); + auto fromSymbol{fromSymbols.find(symbol)}; if (fromSymbol != fromSymbols.end()) { context_.Say(source, "A list item ('%s') can only appear in a TO or FROM clause, but not in both."_err_en_US, @@ -2515,7 +2571,6 @@ CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule) CHECK_SIMPLE_CLAUSE(Exclusive, OMPC_exclusive) CHECK_SIMPLE_CLAUSE(Final, OMPC_final) CHECK_SIMPLE_CLAUSE(Flush, OMPC_flush) -CHECK_SIMPLE_CLAUSE(From, OMPC_from) CHECK_SIMPLE_CLAUSE(Full, OMPC_full) CHECK_SIMPLE_CLAUSE(Grainsize, OMPC_grainsize) CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint) @@ -3689,11 +3744,62 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Enter &x) { } } +void OmpStructureChecker::Enter(const parser::OmpClause::From &x) { + CheckAllowedClause(llvm::omp::Clause::OMPC_from); + unsigned version{context_.langOptions().OpenMPVersion}; + using ExpMod = parser::OmpFromClause::Expectation; + using IterMod = parser::OmpIteratorModifier; + + if (auto &expMod{std::get>>(x.v.t)}) { + unsigned allowedInVersion{51}; + if (version < allowedInVersion) { + context_.Say(GetContext().clauseSource, + "The PRESENT modifier is not supported in %s, %s"_warn_en_US, + ThisVersion(version), TryVersion(allowedInVersion)); + } + if (expMod->size() != 1) { + context_.Say(GetContext().clauseSource, + "Only one PRESENT modifier is allowed"_err_en_US); + } + } + + if (auto &iterMod{std::get>>(x.v.t)}) { + unsigned allowedInVersion{51}; + if (version < allowedInVersion) { + context_.Say(GetContext().clauseSource, + "Iterator modifiers are not supported in %s, %s"_warn_en_US, + ThisVersion(version), TryVersion(allowedInVersion)); + } + if (iterMod->size() != 1) { + context_.Say(GetContext().clauseSource, + "Only one iterator-modifier is allowed"_err_en_US); + } + CheckIteratorModifier(iterMod->front()); + } + + const auto &objList{std::get(x.v.t)}; + SymbolSourceMap symbols; + GetSymbolsInObjectList(objList, symbols); + for (const auto &[sym, source] : symbols) { + if (!IsVariableListItem(*sym)) { + context_.SayWithDecl( + *sym, source, "'%s' must be a variable"_err_en_US, sym->name()); + } + } + + // Ref: [4.5:109:19] + // If a list item is an array section it must specify contiguous storage. + if (version <= 45) { + for (const parser::OmpObject &object : objList.v) { + CheckIfContiguous(object); + } + } +} + void OmpStructureChecker::Enter(const parser::OmpClause::To &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_to); - if (dirContext_.empty()) { - return; - } + unsigned version{context_.langOptions().OpenMPVersion}; + // The "to" clause is only allowed on "declare target" (pre-5.1), and // "target update". In the former case it can take an extended list item, // in the latter a variable (a locator). @@ -3705,8 +3811,37 @@ void OmpStructureChecker::Enter(const parser::OmpClause::To &x) { return; } assert(GetContext().directive == llvm::omp::OMPD_target_update); + using ExpMod = parser::OmpFromClause::Expectation; + using IterMod = parser::OmpIteratorModifier; - const parser::OmpObjectList &objList{x.v}; + if (auto &expMod{std::get>>(x.v.t)}) { + unsigned allowedInVersion{51}; + if (version < allowedInVersion) { + context_.Say(GetContext().clauseSource, + "The PRESENT modifier is not supported in %s, %s"_warn_en_US, + ThisVersion(version), TryVersion(allowedInVersion)); + } + if (expMod->size() != 1) { + context_.Say(GetContext().clauseSource, + "Only one PRESENT modifier is allowed"_err_en_US); + } + } + + if (auto &iterMod{std::get>>(x.v.t)}) { + unsigned allowedInVersion{51}; + if (version < allowedInVersion) { + context_.Say(GetContext().clauseSource, + "Iterator modifiers are not supported in %s, %s"_warn_en_US, + ThisVersion(version), TryVersion(allowedInVersion)); + } + if (iterMod->size() != 1) { + context_.Say(GetContext().clauseSource, + "Only one iterator-modifier is allowed"_err_en_US); + } + CheckIteratorModifier(iterMod->front()); + } + + const auto &objList{std::get(x.v.t)}; SymbolSourceMap symbols; GetSymbolsInObjectList(objList, symbols); for (const auto &[sym, source] : symbols) { @@ -3715,6 +3850,14 @@ void OmpStructureChecker::Enter(const parser::OmpClause::To &x) { *sym, source, "'%s' must be a variable"_err_en_US, sym->name()); } } + + // Ref: [4.5:109:19] + // If a list item is an array section it must specify contiguous storage. + if (version <= 45) { + for (const parser::OmpObject &object : objList.v) { + CheckIfContiguous(object); + } + } } llvm::StringRef OmpStructureChecker::getClauseName(llvm::omp::Clause clause) { @@ -3981,21 +4124,64 @@ void OmpStructureChecker::CheckWorkshareBlockStmts( } } +void OmpStructureChecker::CheckIfContiguous(const parser::OmpObject &object) { + if (auto contig{IsContiguous(object)}; contig && !*contig) { + const parser::Name *name{GetObjectName(object)}; + assert(name && "Expecting name component"); + context_.Say(name->source, + "Reference to %s must be a contiguous object"_err_en_US, + name->ToString()); + } +} + +namespace { +struct NameHelper { + template + static const parser::Name *Visit(const common::Indirection &x) { + return Visit(x.value()); + } + static const parser::Name *Visit(const parser::Substring &x) { + return Visit(std::get(x.t)); + } + static const parser::Name *Visit(const parser::ArrayElement &x) { + return Visit(x.base); + } + static const parser::Name *Visit(const parser::Designator &x) { + return common::visit([](auto &&s) { return Visit(s); }, x.u); + } + static const parser::Name *Visit(const parser::DataRef &x) { + return common::visit([](auto &&s) { return Visit(s); }, x.u); + } + static const parser::Name *Visit(const parser::OmpObject &x) { + return common::visit([](auto &&s) { return Visit(s); }, x.u); + } + template static const parser::Name *Visit(T &&) { + return nullptr; + } + static const parser::Name *Visit(const parser::Name &x) { return &x; } +}; +} // namespace + +const parser::Name *OmpStructureChecker::GetObjectName( + const parser::OmpObject &object) { + return NameHelper::Visit(object); +} + const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList( const parser::OmpClause &clause) { // Clauses with OmpObjectList as its data member using MemberObjectListClauses = std::tuple; // Clauses with OmpObjectList in the tuple - using TupleObjectListClauses = std::tuple; + parser::OmpClause::Reduction, parser::OmpClause::To>; // TODO:: Generate the tuples using TableGen. // Handle other constructs with OmpObjectList such as OpenMPThreadprivate. diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index d5fd558cea237..5e26827934796 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -138,6 +138,7 @@ class OmpStructureChecker bool CheckAllowedClause(llvmOmpClause clause); bool IsVariableListItem(const Symbol &sym); bool IsExtendedListItem(const Symbol &sym); + std::optional IsContiguous(const parser::OmpObject &object); void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars, const std::list &nameList, const parser::CharBlock &item, const std::string &clauseName); @@ -221,6 +222,8 @@ class OmpStructureChecker const parser::Name &name, const llvm::omp::Clause clause); void CheckSharedBindingInOuterContext( const parser::OmpObjectList &ompObjectList); + void CheckIfContiguous(const parser::OmpObject &object); + const parser::Name *GetObjectName(const parser::OmpObject &object); const parser::OmpObjectList *GetOmpObjectList(const parser::OmpClause &); void CheckPredefinedAllocatorRestriction(const parser::CharBlock &source, const parser::OmpObjectList &ompObjectList); diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 359dac911b8c7..c2b5b9673239b 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -1930,7 +1930,8 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) { parser::Unwrap(spec.u)}) { for (const auto &clause : clauseList->v) { if (const auto *toClause{std::get_if(&clause.u)}) { - ResolveOmpObjectList(toClause->v, Symbol::Flag::OmpDeclareTarget); + auto &objList{std::get(toClause->v.t)}; + ResolveOmpObjectList(objList, Symbol::Flag::OmpDeclareTarget); } else if (const auto *linkClause{ std::get_if(&clause.u)}) { ResolveOmpObjectList(linkClause->v, Symbol::Flag::OmpDeclareTarget); diff --git a/flang/runtime/CUDA/memory.cpp b/flang/runtime/CUDA/memory.cpp index daf1db684a3d2..0e03c618663eb 100644 --- a/flang/runtime/CUDA/memory.cpp +++ b/flang/runtime/CUDA/memory.cpp @@ -9,6 +9,7 @@ #include "flang/Runtime/CUDA/memory.h" #include "../terminator.h" #include "flang/Runtime/CUDA/common.h" +#include "flang/Runtime/CUDA/descriptor.h" #include "flang/Runtime/assign.h" #include "cuda_runtime.h" @@ -111,17 +112,32 @@ void RTDEF(CUFDataTransferPtrDesc)(void *addr, Descriptor *desc, void RTDECL(CUFDataTransferDescDesc)(Descriptor *dstDesc, Descriptor *srcDesc, unsigned mode, const char *sourceFile, int sourceLine) { - Terminator terminator{sourceFile, sourceLine}; MemmoveFct memmoveFct; + Terminator terminator{sourceFile, sourceLine}; if (mode == kHostToDevice) { memmoveFct = &MemmoveHostToDevice; } else if (mode == kDeviceToHost) { memmoveFct = &MemmoveDeviceToHost; } else if (mode == kDeviceToDevice) { memmoveFct = &MemmoveDeviceToDevice; + } else { + terminator.Crash("host to host copy not supported"); } Fortran::runtime::Assign( *dstDesc, *srcDesc, terminator, MaybeReallocate, memmoveFct); } + +void RTDECL(CUFDataTransferGlobalDescDesc)(Descriptor *dstDesc, + Descriptor *srcDesc, unsigned mode, const char *sourceFile, + int sourceLine) { + RTNAME(CUFDataTransferDescDesc) + (dstDesc, srcDesc, mode, sourceFile, sourceLine); + if ((mode == kHostToDevice) || (mode == kDeviceToDevice)) { + void *deviceAddr{ + RTNAME(CUFGetDeviceAddress)((void *)dstDesc, sourceFile, sourceLine)}; + RTNAME(CUFDescriptorSync) + ((Descriptor *)deviceAddr, srcDesc, sourceFile, sourceLine); + } +} } } // namespace Fortran::runtime::cuda diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-teams-distribute-private-ptr.mlir b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-teams-distribute-private-ptr.mlir new file mode 100644 index 0000000000000..78207d21c45bf --- /dev/null +++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-teams-distribute-private-ptr.mlir @@ -0,0 +1,102 @@ +// Use --mlir-disable-threading so that the AA queries are serialized +// as well as its diagnostic output. +// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s + +// Fortran code: +// program main +// integer, target :: arrayA(10) +// integer, pointer, dimension(:) :: ptrA +// integer :: i +// ptrA => arrayA +// !$omp teams distribute parallel do firstprivate(ptrA) +// do i = 1, 10 +// arrayA(i) = arrayA(i) + ptrA(i); +// end do +// end program main + +// CHECK-LABEL: Testing : "_QQmain" +// CHECK-DAG: ptrA#0 <-> ArrayA#0: MayAlias + +omp.private {type = private} @_QFEi_private_ref_i32 : !fir.ref alloc { +^bb0(%arg0: !fir.ref): + %0 = fir.alloca i32 {bindc_name = "i", pinned, uniq_name = "_QFEi"} + %1:2 = hlfir.declare %0 {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + omp.yield(%1#0 : !fir.ref) +} +omp.private {type = firstprivate} @_QFEptra_firstprivate_ref_box_ptr_Uxi32 : !fir.ref>>> alloc { +^bb0(%arg0: !fir.ref>>>): + %0 = fir.alloca !fir.box>> {bindc_name = "ptra", pinned, uniq_name = "_QFEptra"} + %1:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEptra"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + omp.yield(%1#0 : !fir.ref>>>) +} copy { +^bb0(%arg0: !fir.ref>>>, %arg1: !fir.ref>>>): + %0 = fir.load %arg0 : !fir.ref>>> + fir.store %0 to %arg1 : !fir.ref>>> + omp.yield(%arg1 : !fir.ref>>>) +} +func.func @_QQmain() attributes {fir.bindc_name = "main"} { + %0 = fir.address_of(@_QFEarraya) : !fir.ref> + %c10 = arith.constant 10 : index + %1 = fir.shape %c10 : (index) -> !fir.shape<1> + %2:2 = hlfir.declare %0(%1) {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEarraya"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %3 = fir.address_of(@_QFEarrayb) : !fir.ref> + %c10_0 = arith.constant 10 : index + %4 = fir.shape %c10_0 : (index) -> !fir.shape<1> + %5:2 = hlfir.declare %3(%4) {uniq_name = "_QFEarrayb"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %6 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} + %7:2 = hlfir.declare %6 {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %8 = fir.address_of(@_QFEptra) : !fir.ref>>> + %9:2 = hlfir.declare %8 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEptra"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + %10 = fir.shape %c10 : (index) -> !fir.shape<1> + %11 = fir.embox %2#1(%10) : (!fir.ref>, !fir.shape<1>) -> !fir.box>> + fir.store %11 to %9#1 : !fir.ref>>> + omp.teams { + omp.parallel private(@_QFEptra_firstprivate_ref_box_ptr_Uxi32 %9#0 -> %arg0, @_QFEi_private_ref_i32 %7#0 -> %arg1 : !fir.ref>>>, !fir.ref) { + %12:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEptra"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + %13:2 = hlfir.declare %arg1 {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %c1_i32 = arith.constant 1 : i32 + %c10_i32 = arith.constant 10 : i32 + %c1_i32_1 = arith.constant 1 : i32 + omp.distribute { + omp.wsloop { + omp.loop_nest (%arg2) : i32 = (%c1_i32) to (%c10_i32) inclusive step (%c1_i32_1) { + fir.store %arg2 to %13#1 : !fir.ref + %14 = fir.load %13#0 : !fir.ref + %15 = fir.convert %14 : (i32) -> i64 + %16 = hlfir.designate %2#0 (%15) : (!fir.ref>, i64) -> !fir.ref + %17 = fir.load %16 : !fir.ref + %18 = fir.load %12#0 : !fir.ref>>> + %19 = fir.load %13#0 : !fir.ref + %20 = fir.convert %19 : (i32) -> i64 + %21 = hlfir.designate %18 (%20) {test.ptr = "ptrA" } : (!fir.box>>, i64) -> !fir.ref + %22 = fir.load %21 : !fir.ref + %23 = arith.addi %17, %22 : i32 + %24 = fir.load %13#0 : !fir.ref + %25 = fir.convert %24 : (i32) -> i64 + %26 = hlfir.designate %2#0 (%25) {test.ptr = "ArrayA"} : (!fir.ref>, i64) -> !fir.ref + hlfir.assign %23 to %26 : i32, !fir.ref + omp.yield + } + } {omp.composite} + } {omp.composite} + omp.terminator + } {omp.composite} + omp.terminator + } + return +} +fir.global internal @_QFEarraya target : !fir.array<10xi32> { + %0 = fir.zero_bits !fir.array<10xi32> + fir.has_value %0 : !fir.array<10xi32> +} +fir.global internal @_QFEarrayb : !fir.array<10xi32> { + %0 = fir.zero_bits !fir.array<10xi32> + fir.has_value %0 : !fir.array<10xi32> +} +fir.global internal @_QFEptra : !fir.box>> { + %0 = fir.zero_bits !fir.ptr> + %c0 = arith.constant 0 : index + %1 = fir.shape %c0 : (index) -> !fir.shape<1> + %2 = fir.embox %0(%1) : (!fir.ptr>, !fir.shape<1>) -> !fir.box>> + fir.has_value %2 : !fir.box>> +} diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-teams-distribute-private.mlir b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-teams-distribute-private.mlir new file mode 100644 index 0000000000000..4668b2c215c8c --- /dev/null +++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-omp-teams-distribute-private.mlir @@ -0,0 +1,121 @@ +// Use --mlir-disable-threading so that the AA queries are serialized +// as well as its diagnostic output. +// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s + +// Fortran code: +// +// program main +// integer :: arrayA(10,10) +// integer :: tmp(2) +// integer :: i,j +// !$omp teams distribute parallel do private(tmp) +// do j = 1, 10 +// do i = 1,10 +// tmp = [i,j] +// arrayA = tmp(1) +// end do +// end do +// end program main + +// CHECK-LABEL: Testing : "_QQmain" +// CHECK-DAG: tmp_private_array#0 <-> unnamed_array#0: NoAlias +// CHECK-DAG: tmp_private_array#1 <-> unnamed_array#0: NoAlias + +omp.private {type = private} @_QFEi_private_ref_i32 : !fir.ref alloc { +^bb0(%arg0: !fir.ref): + %0 = fir.alloca i32 {bindc_name = "i", pinned, uniq_name = "_QFEi"} + %1:2 = hlfir.declare %0 {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + omp.yield(%1#0 : !fir.ref) +} +omp.private {type = private} @_QFEj_private_ref_i32 : !fir.ref alloc { +^bb0(%arg0: !fir.ref): + %0 = fir.alloca i32 {bindc_name = "j", pinned, uniq_name = "_QFEj"} + %1:2 = hlfir.declare %0 {uniq_name = "_QFEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) + omp.yield(%1#0 : !fir.ref) +} +omp.private {type = private} @_QFEtmp_private_ref_2xi32 : !fir.ref> alloc { +^bb0(%arg0: !fir.ref>): + %c2 = arith.constant 2 : index + %0 = fir.alloca !fir.array<2xi32> {bindc_name = "tmp", pinned, uniq_name = "_QFEtmp"} + %1 = fir.shape %c2 : (index) -> !fir.shape<1> + %2:2 = hlfir.declare %0(%1) {uniq_name = "_QFEtmp"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + omp.yield(%2#0 : !fir.ref>) +} +func.func @_QQmain() attributes {fir.bindc_name = "main"} { + %0 = fir.address_of(@_QFEarraya) : !fir.ref> + %c10 = arith.constant 10 : index + %c10_0 = arith.constant 10 : index + %1 = fir.shape %c10, %c10_0 : (index, index) -> !fir.shape<2> + %2:2 = hlfir.declare %0(%1) {uniq_name = "_QFEarraya"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) + %3 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} + %4:2 = hlfir.declare %3 {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %5 = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFEj"} + %6:2 = hlfir.declare %5 {uniq_name = "_QFEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %c2 = arith.constant 2 : index + %7 = fir.alloca !fir.array<2xi32> {bindc_name = "tmp", uniq_name = "_QFEtmp"} + %8 = fir.shape %c2 : (index) -> !fir.shape<1> + %9:2 = hlfir.declare %7(%8) {uniq_name = "_QFEtmp"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + omp.teams { + omp.parallel private(@_QFEtmp_private_ref_2xi32 %9#0 -> %arg0, @_QFEj_private_ref_i32 %6#0 -> %arg1, @_QFEi_private_ref_i32 %4#0 -> %arg2 : !fir.ref>, !fir.ref, !fir.ref) { + %c2_1 = arith.constant 2 : index + %10 = fir.shape %c2_1 : (index) -> !fir.shape<1> + %11:2 = hlfir.declare %arg0(%10) {uniq_name = "_QFEtmp", test.ptr = "tmp_private_array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %12:2 = hlfir.declare %arg1 {uniq_name = "_QFEj"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %13:2 = hlfir.declare %arg2 {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %c1_i32 = arith.constant 1 : i32 + %c10_i32 = arith.constant 10 : i32 + %c1_i32_2 = arith.constant 1 : i32 + omp.distribute { + omp.wsloop { + omp.loop_nest (%arg3) : i32 = (%c1_i32) to (%c10_i32) inclusive step (%c1_i32_2) { + fir.store %arg3 to %12#1 : !fir.ref + %c1_i32_3 = arith.constant 1 : i32 + %14 = fir.convert %c1_i32_3 : (i32) -> index + %c10_i32_4 = arith.constant 10 : i32 + %15 = fir.convert %c10_i32_4 : (i32) -> index + %c1 = arith.constant 1 : index + %16 = fir.convert %14 : (index) -> i32 + %17:2 = fir.do_loop %arg4 = %14 to %15 step %c1 iter_args(%arg5 = %16) -> (index, i32) { + fir.store %arg5 to %13#1 : !fir.ref + %c2_5 = arith.constant 2 : index + %c1_6 = arith.constant 1 : index + %c1_7 = arith.constant 1 : index + %18 = fir.allocmem !fir.array<2xi32> {bindc_name = ".tmp.arrayctor", uniq_name = ""} + %19 = fir.shape %c2_5 : (index) -> !fir.shape<1> + %20:2 = hlfir.declare %18(%19) {uniq_name = ".tmp.arrayctor"} : (!fir.heap>, !fir.shape<1>) -> (!fir.heap>, !fir.heap>) + %21 = fir.load %13#0 : !fir.ref + %22 = arith.addi %c1_6, %c1_7 : index + %23 = hlfir.designate %20#0 (%c1_6) : (!fir.heap>, index) -> !fir.ref + hlfir.assign %21 to %23 : i32, !fir.ref + %24 = fir.load %12#0 : !fir.ref + %25 = hlfir.designate %20#0 (%22) : (!fir.heap>, index) -> !fir.ref + hlfir.assign %24 to %25 : i32, !fir.ref + %true = arith.constant true + %26 = hlfir.as_expr %20#0 move %true {test.ptr = "unnamed_array"} : (!fir.heap>, i1) -> !hlfir.expr<2xi32> + hlfir.assign %26 to %11#0 : !hlfir.expr<2xi32>, !fir.ref> + hlfir.destroy %26 : !hlfir.expr<2xi32> + %c1_8 = arith.constant 1 : index + %27 = hlfir.designate %11#0 (%c1_8) : (!fir.ref>, index) -> !fir.ref + %28 = fir.load %27 : !fir.ref + hlfir.assign %28 to %2#0 : i32, !fir.ref> + %29 = arith.addi %arg4, %c1 : index + %30 = fir.convert %c1 : (index) -> i32 + %31 = fir.load %13#1 : !fir.ref + %32 = arith.addi %31, %30 : i32 + fir.result %29, %32 : index, i32 + } + fir.store %17#1 to %13#1 : !fir.ref + omp.yield + } + } {omp.composite} + } {omp.composite} + omp.terminator + } {omp.composite} + omp.terminator + } + return +} +fir.global internal @_QFEarraya : !fir.array<10x10xi32> { + %0 = fir.zero_bits !fir.array<10x10xi32> + fir.has_value %0 : !fir.array<10x10xi32> +} diff --git a/flang/test/Driver/mlir-debug-pass-pipeline.f90 b/flang/test/Driver/mlir-debug-pass-pipeline.f90 index e44f4e62a7148..ab5ddedf5fc18 100644 --- a/flang/test/Driver/mlir-debug-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-debug-pass-pipeline.f90 @@ -111,10 +111,10 @@ ! ALL-NEXT: CodeGenRewrite ! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated -! ALL-NEXT: TargetRewrite -! ALL-NEXT: CompilerGeneratedNamesConversion ! ALL-NEXT: ExternalNameConversion ! DEBUG-NEXT: AddDebugInfo ! NO-DEBUG-NOT: AddDebugInfo +! ALL-NEXT: TargetRewrite +! ALL-NEXT: CompilerGeneratedNamesConversion ! ALL: FIRToLLVMLowering ! ALL-NOT: LLVMIRLoweringPass diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index 6c2829d3cc5c5..7d57135c5fee3 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -120,8 +120,8 @@ ! ALL-NEXT: CodeGenRewrite ! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated +! ALL-NEXT: ExternalNameConversion ! ALL-NEXT: TargetRewrite ! ALL-NEXT: CompilerGeneratedNamesConversion -! ALL-NEXT: ExternalNameConversion ! ALL-NEXT: FIRToLLVMLowering ! ALL-NOT: LLVMIRLoweringPass diff --git a/flang/test/Fir/CUDA/cuda-data-transfer.fir b/flang/test/Fir/CUDA/cuda-data-transfer.fir index cee3048e279cc..a760650d14358 100644 --- a/flang/test/Fir/CUDA/cuda-data-transfer.fir +++ b/flang/test/Fir/CUDA/cuda-data-transfer.fir @@ -224,4 +224,29 @@ func.func @_QPsub9() { // CHECK: %[[DST:.*]] = fir.call @_FortranACUFGetDeviceAddress(%[[HOST]], %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.ref, i32) -> !fir.llvm_ptr // CHECK: %[[SRC:.*]] = fir.convert %[[LOCAL]] : (!fir.ref>) -> !fir.llvm_ptr // CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%[[DST]], %[[SRC]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none + +fir.global @_QMmod1Ea {data_attr = #cuf.cuda} : !fir.box>> { + %c0 = arith.constant 0 : index + %0 = fir.zero_bits !fir.heap> + %1 = fir.shape %c0 : (index) -> !fir.shape<1> + %2 = fir.embox %0(%1) {allocator_idx = 2 : i32} : (!fir.heap>, !fir.shape<1>) -> !fir.box>> + fir.has_value %2 : !fir.box>> +} + +func.func @_QQdesc_global() attributes {fir.bindc_name = "host_sub"} { + %0 = fir.address_of(@_QMmod1Ea) : !fir.ref>>> + %1:2 = hlfir.declare %0 {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMmod1Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + %2 = fir.address_of(@_QFEahost) : !fir.ref>>> + %3:2 = hlfir.declare %2 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEahost"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + cuf.data_transfer %3#0 to %1#0 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>>>, !fir.ref>>> + return +} + +// CHECK-LABEL: func.func @_QQdesc_global() attributes {fir.bindc_name = "host_sub"} +// CHECK: %[[GLOBAL_ADDRESS:.*]] = fir.address_of(@_QMmod1Ea) : !fir.ref>>> +// CHECK: %[[GLOBAL_DECL:.*]]:2 = hlfir.declare %[[GLOBAL_ADDRESS]] {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMmod1Ea"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +// CHECK: %[[BOX_NONE:.*]] = fir.convert %[[GLOBAL_DECL:.*]]#0 : (!fir.ref>>>) -> !fir.ref> +// CHECK: fir.call @_FortranACUFDataTransferGlobalDescDesc(%[[BOX_NONE]],{{.*}}) : (!fir.ref>, !fir.ref>, i32, !fir.ref, i32) -> none + + } // end of module diff --git a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir index 168526518865b..184abe24fe967 100644 --- a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir +++ b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir @@ -781,11 +781,11 @@ func.func @_QPsimple_reduction(%arg0: !fir.ref>> // ----- // CHECK: llvm.func @_QPs -// CHECK: omp.atomic.read %{{.*}} = %{{.*}} : !llvm.ptr, !llvm.struct<(f32, f32)> +// CHECK: omp.atomic.read %{{.*}} = %{{.*}} : !llvm.ptr, !llvm.ptr, !llvm.struct<(f32, f32)> func.func @_QPs(%arg0: !fir.ref> {fir.bindc_name = "x"}) { %0 = fir.alloca complex {bindc_name = "v", uniq_name = "_QFsEv"} - omp.atomic.read %0 = %arg0 : !fir.ref>, complex + omp.atomic.read %0 = %arg0 : !fir.ref>, !fir.ref>, complex return } diff --git a/flang/test/Integration/debug-complex-2.f90 b/flang/test/Integration/debug-complex-2.f90 new file mode 100644 index 0000000000000..c5f46d7b270b6 --- /dev/null +++ b/flang/test/Integration/debug-complex-2.f90 @@ -0,0 +1,12 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +! Test that complex return type is correctly represented in debug. +complex function fn(a) + complex, intent(in) :: a + fn = a +end function + +! CHECK-DAG: ![[CMPLX:.*]] = !DIBasicType(name: "complex", size: 64, encoding: DW_ATE_complex_float) +! CHECK-DAG: ![[SR_TY:.*]] = !DISubroutineType(cc: DW_CC_normal, types: ![[TYPES:.*]]) +! CHECK-DAG: ![[TYPES]] = !{![[CMPLX]], ![[CMPLX]]} +! CHECK-DAG: !DISubprogram(name: "fn"{{.*}}type: ![[SR_TY]]{{.*}}) diff --git a/flang/test/Integration/debug-external-linkage-name.f90 b/flang/test/Integration/debug-external-linkage-name.f90 new file mode 100644 index 0000000000000..c7fdf846b7dd3 --- /dev/null +++ b/flang/test/Integration/debug-external-linkage-name.f90 @@ -0,0 +1,10 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +! Test that correct linkage name is generated in the debug info. +subroutine sub(a) + integer :: a + return a+1 +end + +!CHECK: !DISubprogram(name: "sub", linkageName: "sub_"{{.*}}) + diff --git a/flang/test/Lower/OpenACC/acc-atomic-capture.f90 b/flang/test/Lower/OpenACC/acc-atomic-capture.f90 index 373683386fda9..797d322ca7ef1 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-capture.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-capture.f90 @@ -11,7 +11,7 @@ program acc_atomic_capture_test !CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %2 {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[temp:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref !CHECK: acc.atomic.capture { -!CHECK: acc.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 : !fir.ref +!CHECK: acc.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 : !fir.ref, !fir.ref, i32 !CHECK: acc.atomic.update %[[Y_DECL]]#1 : !fir.ref { !CHECK: ^bb0(%[[ARG:.*]]: i32): !CHECK: %[[result:.*]] = arith.addi %[[temp]], %[[ARG]] : i32 @@ -32,7 +32,7 @@ program acc_atomic_capture_test !CHECK: %[[result:.*]] = arith.muli %[[temp]], %[[ARG]] : i32 !CHECK: acc.yield %[[result]] : i32 !CHECK: } -!CHECK: acc.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 : !fir.ref +!CHECK: acc.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 : !fir.ref, !fir.ref, i32 !CHECK: } !$acc atomic capture @@ -47,7 +47,7 @@ program acc_atomic_capture_test !CHECK: %[[result_noreassoc:.*]] = hlfir.no_reassoc %[[result]] : i32 !CHECK: %[[result:.*]] = arith.addi %[[constant_20]], %[[result_noreassoc]] : i32 !CHECK: acc.atomic.capture { -!CHECK: acc.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 : !fir.ref +!CHECK: acc.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 : !fir.ref, !fir.ref, i32 !CHECK: acc.atomic.write %[[Y_DECL]]#1 = %[[result]] : !fir.ref, i32 !CHECK: } @@ -82,7 +82,7 @@ subroutine pointers_in_atomic_capture() !CHECK: %[[result:.*]] = arith.addi %[[ARG]], %[[loaded_value]] : i32 !CHECK: acc.yield %[[result]] : i32 !CHECK: } -!CHECK: acc.atomic.read %[[loaded_B_addr]] = %[[loaded_A_addr]] : !fir.ptr, i32 +!CHECK: acc.atomic.read %[[loaded_B_addr]] = %[[loaded_A_addr]] : !fir.ptr, !fir.ptr, i32 !CHECK: } integer, pointer :: a, b integer, target :: c, d @@ -118,10 +118,99 @@ subroutine capture_with_convert_f32_to_i32() ! CHECK: %[[MUL:.*]] = arith.mulf %{{.*}}, %[[CST]] fastmath : f32 ! CHECK: %[[CONV:.*]] = fir.convert %[[MUL]] : (f32) -> i32 ! CHECK: acc.atomic.capture { -! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[K_DECL]]#1 : !fir.ref, i32 +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[K_DECL]]#1 : !fir.ref, !fir.ref, i32 ! CHECK: acc.atomic.write %[[K_DECL]]#1 = %[[CONV]] : !fir.ref, i32 ! CHECK: } +subroutine capture_with_convert_i32_to_f64() + real(8) :: x + integer :: v + x = 1.0 + v = 0 + !$acc atomic capture + v = x + x = v + !$acc end atomic +end subroutine capture_with_convert_i32_to_f64 + +! CHECK-LABEL: func.func @_QPcapture_with_convert_i32_to_f64() +! CHECK: %[[V:.*]] = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFcapture_with_convert_i32_to_f64Ev"} +! CHECK: %[[V_DECL:.*]]:2 = hlfir.declare %[[V]] {uniq_name = "_QFcapture_with_convert_i32_to_f64Ev"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[X:.*]] = fir.alloca f64 {bindc_name = "x", uniq_name = "_QFcapture_with_convert_i32_to_f64Ex"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFcapture_with_convert_i32_to_f64Ex"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[CST:.*]] = arith.constant 1.000000e+00 : f64 +! CHECK: hlfir.assign %[[CST]] to %[[X_DECL]]#0 : f64, !fir.ref +! CHECK: %c0_i32 = arith.constant 0 : i32 +! CHECK: hlfir.assign %c0_i32 to %[[V_DECL]]#0 : i32, !fir.ref +! CHECK: %[[LOAD:.*]] = fir.load %[[V_DECL]]#0 : !fir.ref +! CHECK: %[[CONV:.*]] = fir.convert %[[LOAD]] : (i32) -> f64 +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[X_DECL]]#1 : !fir.ref, !fir.ref, f64 +! CHECK: acc.atomic.write %[[X_DECL]]#1 = %[[CONV]] : !fir.ref, f64 +! CHECK: } + +subroutine capture_with_convert_f64_to_i32() + integer :: x + real(8) :: v + x = 1 + v = 0 + !$acc atomic capture + x = v * v + v = x + !$acc end atomic +end subroutine capture_with_convert_f64_to_i32 + +! CHECK-LABEL: func.func @_QPcapture_with_convert_f64_to_i32() +! CHECK: %[[V:.*]] = fir.alloca f64 {bindc_name = "v", uniq_name = "_QFcapture_with_convert_f64_to_i32Ev"} +! CHECK: %[[V_DECL:.*]]:2 = hlfir.declare %[[V]] {uniq_name = "_QFcapture_with_convert_f64_to_i32Ev"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFcapture_with_convert_f64_to_i32Ex"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFcapture_with_convert_f64_to_i32Ex"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %c1_i32 = arith.constant 1 : i32 +! CHECK: hlfir.assign %c1_i32 to %[[X_DECL]]#0 : i32, !fir.ref +! CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: hlfir.assign %[[CST]] to %[[V_DECL]]#0 : f64, !fir.ref +! CHECK: %[[LOAD:.*]] = fir.load %[[V_DECL]]#0 : !fir.ref +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.update %[[X_DECL]]#1 : !fir.ref { +! CHECK: ^bb0(%arg0: i32): +! CHECK: %[[MUL:.*]] = arith.mulf %[[LOAD]], %[[LOAD]] fastmath : f64 +! CHECK: %[[CONV:.*]] = fir.convert %[[MUL]] : (f64) -> i32 +! CHECK: acc.yield %[[CONV]] : i32 +! CHECK: } +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[X_DECL]]#1 : !fir.ref, !fir.ref, i32 +! CHECK: } + +subroutine capture_with_convert_i32_to_f32() + real(4) :: x + integer :: v + x = 1.0 + v = 0 + !$acc atomic capture + v = x + x = x + v + !$acc end atomic +end subroutine capture_with_convert_i32_to_f32 + +! CHECK-LABEL: func.func @_QPcapture_with_convert_i32_to_f32() +! CHECK: %[[V:.*]] = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFcapture_with_convert_i32_to_f32Ev"} +! CHECK: %[[V_DECL:.*]]:2 = hlfir.declare %[[V]] {uniq_name = "_QFcapture_with_convert_i32_to_f32Ev"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[X:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFcapture_with_convert_i32_to_f32Ex"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFcapture_with_convert_i32_to_f32Ex"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[CST:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[CST]] to %[[X_DECL]]#0 : f32, !fir.ref +! CHECK: %c0_i32 = arith.constant 0 : i32 +! CHECK: hlfir.assign %c0_i32 to %[[V_DECL]]#0 : i32, !fir.ref +! CHECK: %[[LOAD:.*]] = fir.load %[[V_DECL]]#0 : !fir.ref +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[X_DECL]]#1 : !fir.ref, !fir.ref, f32 +! CHECK: acc.atomic.update %[[X_DECL]]#1 : !fir.ref { +! CHECK: ^bb0(%arg0: f32): +! CHECK: %[[CONV:.*]] = fir.convert %[[LOAD]] : (i32) -> f32 +! CHECK: %[[ADD:.*]] = arith.addf %arg0, %[[CONV]] fastmath : f32 +! CHECK: acc.yield %[[ADD]] : f32 +! CHECK: } +! CHECK: } + subroutine array_ref_in_atomic_capture1 integer :: x(10), v !$acc atomic capture @@ -136,7 +225,7 @@ end subroutine array_ref_in_atomic_capture1 ! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]](%{{.*}}) {uniq_name = "_QFarray_ref_in_atomic_capture1Ex"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[X_REF:.*]] = hlfir.designate %[[X_DECL]]#0 (%{{.*}}) : (!fir.ref>, index) -> !fir.ref ! CHECK: acc.atomic.capture { -! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[X_REF]] : !fir.ref, i32 +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[X_REF]] : !fir.ref, !fir.ref, i32 ! CHECK: acc.atomic.update %[[X_REF]] : !fir.ref { ! CHECK: ^bb0(%[[VAL_7:.*]]: i32): ! CHECK: %[[VAL_8:.*]] = arith.addi %[[VAL_7]], %{{.*}} : i32 @@ -163,7 +252,7 @@ end subroutine array_ref_in_atomic_capture2 ! CHECK: %[[VAL_8:.*]] = arith.addi %[[VAL_7]], %{{.*}} : i32 ! CHECK: acc.yield %[[VAL_8]] : i32 ! CHECK: } -! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[X_REF]] : !fir.ref, i32 +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[X_REF]] : !fir.ref, !fir.ref, i32 ! CHECK: } subroutine comp_ref_in_atomic_capture1 @@ -184,7 +273,7 @@ end subroutine comp_ref_in_atomic_capture1 ! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFcomp_ref_in_atomic_capture1Ex"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[C:.*]] = hlfir.designate %[[X_DECL]]#0{"c"} : (!fir.ref>) -> !fir.ref ! CHECK: acc.atomic.capture { -! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[C]] : !fir.ref, i32 +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[C]] : !fir.ref, !fir.ref, i32 ! CHECK: acc.atomic.update %[[C]] : !fir.ref { ! CHECK: ^bb0(%[[VAL_5:.*]]: i32): ! CHECK: %[[VAL_6:.*]] = arith.addi %[[VAL_5]], %{{.*}} : i32 @@ -215,5 +304,5 @@ end subroutine comp_ref_in_atomic_capture2 ! CHECK: %[[VAL_6:.*]] = arith.addi %[[VAL_5]], %{{.*}} : i32 ! CHECK: acc.yield %[[VAL_6]] : i32 ! CHECK: } -! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[C]] : !fir.ref, i32 +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[C]] : !fir.ref, !fir.ref, i32 ! CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-atomic-read.f90 b/flang/test/Lower/OpenACC/acc-atomic-read.f90 index c1a97a9e5f74f..f2cbe6e45596a 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-read.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-read.f90 @@ -13,7 +13,7 @@ end program acc_atomic_test ! CHECK: %[[G_DECL:.*]]:2 = hlfir.declare %[[VAR_G]] {uniq_name = "_QFEg"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %[[VAR_H:.*]] = fir.alloca f32 {bindc_name = "h", uniq_name = "_QFEh"} ! CHECK: %[[H_DECL:.*]]:2 = hlfir.declare %[[VAR_H]] {uniq_name = "_QFEh"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: acc.atomic.read %[[G_DECL]]#1 = %[[H_DECL]]#1 : !fir.ref, f32 +! CHECK: acc.atomic.read %[[G_DECL]]#1 = %[[H_DECL]]#1 : !fir.ref, !fir.ref, f32 ! CHECK: return ! CHECK: } @@ -39,10 +39,10 @@ subroutine atomic_read_pointer() ! CHECK: %[[BOX_ADDR_X:.*]] = fir.box_addr %[[LOAD_X]] : (!fir.box>) -> !fir.ptr ! CHECK: %[[LOAD_Y:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref>> ! CHECK: %[[BOX_ADDR_Y:.*]] = fir.box_addr %[[LOAD_Y]] : (!fir.box>) -> !fir.ptr -! CHECK: acc.atomic.read %[[BOX_ADDR_Y]] = %[[BOX_ADDR_X]] : !fir.ptr, i32 +! CHECK: acc.atomic.read %[[BOX_ADDR_Y]] = %[[BOX_ADDR_X]] : !fir.ptr, !fir.ptr, i32 ! CHECK: } -subroutine atomic_read_with_convert() +subroutine atomic_read_with_cast() integer(4) :: x integer(8) :: y @@ -50,10 +50,9 @@ subroutine atomic_read_with_convert() y = x end -! CHECK-LABEL: func.func @_QPatomic_read_with_convert() { -! CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFatomic_read_with_convertEx"} -! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFatomic_read_with_convertEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: %[[Y:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFatomic_read_with_convertEy"} -! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFatomic_read_with_convertEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: %[[CONV:.*]] = fir.convert %[[X_DECL]]#1 : (!fir.ref) -> !fir.ref -! CHECK: acc.atomic.read %[[Y_DECL]]#1 = %[[CONV]] : !fir.ref, i32 +! CHECK-LABEL: func.func @_QPatomic_read_with_cast() { +! CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFatomic_read_with_castEx"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFatomic_read_with_castEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[Y:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFatomic_read_with_castEy"} +! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFatomic_read_with_castEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.atomic.read %[[Y_DECL]]#1 = %[[X_DECL]]#1 : !fir.ref, !fir.ref, i32 diff --git a/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 b/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 index eeb7ea2994086..f89a9ab457d49 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 @@ -45,7 +45,7 @@ subroutine atomic_read_array1(r, n, x) ! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_read_array1Ex"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) ! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_read_array1Er"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) ! CHECK: %[[DES:.*]] = hlfir.designate %[[DECL_R]]#0 (%{{.*}}) : (!fir.box>, i64) -> !fir.ref -! CHECK: acc.atomic.read %[[DECL_X]]#1 = %[[DES]] : !fir.ref, f32 +! CHECK: acc.atomic.read %[[DECL_X]]#1 = %[[DES]] : !fir.ref, !fir.ref, f32 subroutine atomic_write_array1(r, n, x) implicit none @@ -88,5 +88,5 @@ subroutine atomic_capture_array1(r, n, x, y) ! CHECK: %[[ADD:.*]] = arith.addf %[[ARG]], %[[LOAD]] fastmath : f32 ! CHECK: acc.yield %[[ADD]] : f32 ! CHECK: } -! CHECK: acc.atomic.read %[[DECL_Y]]#1 = %[[R_I]] : !fir.ref, f32 +! CHECK: acc.atomic.read %[[DECL_Y]]#1 = %[[R_I]] : !fir.ref, !fir.ref, f32 ! CHECK: } diff --git a/flang/test/Lower/OpenMP/Todo/from-expectation-modifier.f90 b/flang/test/Lower/OpenMP/Todo/from-expectation-modifier.f90 new file mode 100644 index 0000000000000..7be70ba9102e1 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/from-expectation-modifier.f90 @@ -0,0 +1,8 @@ +!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s +!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s + +!CHECK: not yet implemented: PRESENT modifier is not supported yet +subroutine f00(x) + integer :: x + !$omp target update from(present: x) +end diff --git a/flang/test/Lower/OpenMP/Todo/from-iterator-modifier.f90 b/flang/test/Lower/OpenMP/Todo/from-iterator-modifier.f90 new file mode 100644 index 0000000000000..973d1d1d76ba4 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/from-iterator-modifier.f90 @@ -0,0 +1,8 @@ +!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s +!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s + +!CHECK: not yet implemented: Iterator modifier is not supported yet +subroutine f00(x) + integer :: x(10) + !$omp target update from(iterator(i = 1:2): x(i)) +end diff --git a/flang/test/Lower/OpenMP/Todo/task_detach.f90 b/flang/test/Lower/OpenMP/Todo/task_detach.f90 new file mode 100644 index 0000000000000..6bc55e9e7cf64 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/task_detach.f90 @@ -0,0 +1,16 @@ +! REQUIRES: openmp_runtime +! RUN: %not_todo_cmd bbc -emit-fir %openmp_flags -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s +! RUN: %not_todo_cmd %flang_fc1 -emit-fir %openmp_flags -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s + +!=============================================================================== +! `detach` clause +!=============================================================================== + +! CHECK: not yet implemented: OpenMP Block construct clause +subroutine omp_task_detach() + use omp_lib + integer (kind=omp_event_handle_kind) :: event + !$omp task detach(event) + call foo() + !$omp end task +end subroutine omp_task_detach diff --git a/flang/test/Lower/OpenMP/Todo/to-expectation-modifier.f90 b/flang/test/Lower/OpenMP/Todo/to-expectation-modifier.f90 new file mode 100644 index 0000000000000..f29fb8fffb1eb --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/to-expectation-modifier.f90 @@ -0,0 +1,8 @@ +!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s +!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s + +!CHECK: not yet implemented: PRESENT modifier is not supported yet +subroutine f00(x) + integer :: x + !$omp target update to(present: x) +end diff --git a/flang/test/Lower/OpenMP/Todo/to-iterator-modifier.f90 b/flang/test/Lower/OpenMP/Todo/to-iterator-modifier.f90 new file mode 100644 index 0000000000000..a587373bf183a --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/to-iterator-modifier.f90 @@ -0,0 +1,8 @@ +!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s +!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s + +!CHECK: not yet implemented: Iterator modifier is not supported yet +subroutine f00(x) + integer :: x(10) + !$omp target update to(iterator(i = 1:2): x(i)) +end diff --git a/flang/test/Lower/OpenMP/atomic-capture.f90 b/flang/test/Lower/OpenMP/atomic-capture.f90 index af82e4b2a20eb..679d22d3d7063 100644 --- a/flang/test/Lower/OpenMP/atomic-capture.f90 +++ b/flang/test/Lower/OpenMP/atomic-capture.f90 @@ -22,7 +22,7 @@ program OmpAtomicCapture !CHECK: %[[TEMP:.*]] = arith.muli %[[VAL_Y_LOADED]], %[[ARG]] : i32 !CHECK: omp.yield(%[[TEMP]] : i32) !CHECK: } -!CHECK: omp.atomic.read %[[VAL_X_DECLARE]]#1 = %[[VAL_Y_DECLARE]]#1 : !fir.ref, i32 +!CHECK: omp.atomic.read %[[VAL_X_DECLARE]]#1 = %[[VAL_Y_DECLARE]]#1 : !fir.ref, !fir.ref, i32 !CHECK: } !$omp atomic hint(omp_sync_hint_uncontended) capture y = x * y @@ -36,7 +36,7 @@ program OmpAtomicCapture !CHECK: %[[NO_REASSOC:.*]] = hlfir.no_reassoc %[[SUB]] : i32 !CHECK: %[[ADD:.*]] = arith.addi %[[VAL_20]], %[[NO_REASSOC]] : i32 !CHECK: omp.atomic.capture hint(nonspeculative) memory_order(acquire) { -!CHECK: omp.atomic.read %[[VAL_X_DECLARE]]#1 = %[[VAL_Y_DECLARE]]#1 : !fir.ref, i32 +!CHECK: omp.atomic.read %[[VAL_X_DECLARE]]#1 = %[[VAL_Y_DECLARE]]#1 : !fir.ref, !fir.ref, i32 !CHECK: omp.atomic.write %[[VAL_Y_DECLARE]]#1 = %[[ADD]] : !fir.ref, i32 !CHECK: } !CHECK: return @@ -88,7 +88,7 @@ subroutine pointers_in_atomic_capture() !CHECK: %[[TEMP:.*]] = arith.addi %[[ARG]], %[[VAL_B]] : i32 !CHECK: omp.yield(%[[TEMP]] : i32) !CHECK: } -!CHECK: omp.atomic.read %[[VAL_B_BOX_ADDR]] = %[[VAL_A_BOX_ADDR]] : !fir.ptr, i32 +!CHECK: omp.atomic.read %[[VAL_B_BOX_ADDR]] = %[[VAL_A_BOX_ADDR]] : !fir.ptr, !fir.ptr, i32 !CHECK: } !CHECK: return !CHECK: } diff --git a/flang/test/Lower/OpenMP/atomic-read.f90 b/flang/test/Lower/OpenMP/atomic-read.f90 index c3270dd6c1d67..e9bea42252faa 100644 --- a/flang/test/Lower/OpenMP/atomic-read.f90 +++ b/flang/test/Lower/OpenMP/atomic-read.f90 @@ -25,12 +25,12 @@ !CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_REF]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) !CHECK: %[[Y_REF:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} !CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y_REF]] {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) -!CHECK: omp.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 hint(uncontended) memory_order(acquire) : !fir.ref, i32 -!CHECK: omp.atomic.read %[[A_DECL]]#1 = %[[B_DECL]]#1 memory_order(relaxed) : !fir.ref, i32 -!CHECK: omp.atomic.read %[[C_DECL]]#1 = %[[D_DECL]]#1 hint(contended) memory_order(seq_cst) : !fir.ref>, !fir.logical<4> -!CHECK: omp.atomic.read %[[E_DECL]]#1 = %[[F_DECL]]#1 hint(speculative) : !fir.ref, i32 -!CHECK: omp.atomic.read %[[G_DECL]]#1 = %[[H_DECL]]#1 hint(nonspeculative) : !fir.ref, f32 -!CHECK: omp.atomic.read %[[G_DECL]]#1 = %[[H_DECL]]#1 : !fir.ref, f32 +!CHECK: omp.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 hint(uncontended) memory_order(acquire) : !fir.ref, !fir.ref, i32 +!CHECK: omp.atomic.read %[[A_DECL]]#1 = %[[B_DECL]]#1 memory_order(relaxed) : !fir.ref, !fir.ref, i32 +!CHECK: omp.atomic.read %[[C_DECL]]#1 = %[[D_DECL]]#1 hint(contended) memory_order(seq_cst) : !fir.ref>, !fir.ref>, !fir.logical<4> +!CHECK: omp.atomic.read %[[E_DECL]]#1 = %[[F_DECL]]#1 hint(speculative) : !fir.ref, !fir.ref, i32 +!CHECK: omp.atomic.read %[[G_DECL]]#1 = %[[H_DECL]]#1 hint(nonspeculative) : !fir.ref, !fir.ref, f32 +!CHECK: omp.atomic.read %[[G_DECL]]#1 = %[[H_DECL]]#1 : !fir.ref, !fir.ref, f32 program OmpAtomic @@ -68,7 +68,7 @@ end program OmpAtomic !CHECK: %[[X_POINTEE_ADDR:.*]] = fir.box_addr %[[X_ADDR]] : (!fir.box>) -> !fir.ptr !CHECK: %[[Y_ADDR:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref>> !CHECK: %[[Y_POINTEE_ADDR:.*]] = fir.box_addr %[[Y_ADDR]] : (!fir.box>) -> !fir.ptr -!CHECK: omp.atomic.read %[[Y_POINTEE_ADDR]] = %[[X_POINTEE_ADDR]] : !fir.ptr, i32 +!CHECK: omp.atomic.read %[[Y_POINTEE_ADDR]] = %[[X_POINTEE_ADDR]] : !fir.ptr, !fir.ptr, i32 !CHECK: %[[Y_ADDR:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref>> !CHECK: %[[Y_POINTEE_ADDR:.*]] = fir.box_addr %[[Y_ADDR]] : (!fir.box>) -> !fir.ptr !CHECK: %[[Y_POINTEE_VAL:.*]] = fir.load %[[Y_POINTEE_ADDR]] : !fir.ptr diff --git a/flang/test/Lower/OpenMP/wsloop-simd.f90 b/flang/test/Lower/OpenMP/wsloop-simd.f90 index 899ab59714f14..49a9a523e11fe 100644 --- a/flang/test/Lower/OpenMP/wsloop-simd.f90 +++ b/flang/test/Lower/OpenMP/wsloop-simd.f90 @@ -45,3 +45,24 @@ subroutine do_simd_simdlen() end do !$omp end do simd end subroutine do_simd_simdlen + +! CHECK-LABEL: func.func @_QPdo_simd_reduction( +subroutine do_simd_reduction() + integer :: sum + sum = 0 + ! CHECK: omp.wsloop + ! CHECK-SAME: reduction(@[[RED_SYM:.*]] %{{.*}} -> %[[RED_OUTER:.*]] : !fir.ref) + ! CHECK-NEXT: omp.simd + ! CHECK-SAME: reduction(@[[RED_SYM]] %[[RED_OUTER]] -> %[[RED_INNER:.*]] : !fir.ref) + ! CHECK-NEXT: omp.loop_nest + ! CHECK: %[[RED_DECL:.*]]:2 = hlfir.declare %[[RED_INNER]] + ! CHECK: %[[RED:.*]] = fir.load %[[RED_DECL]]#0 : !fir.ref + ! CHECK: %[[RESULT:.*]] = arith.addi %[[RED]], %{{.*}} : i32 + ! CHECK: hlfir.assign %[[RESULT]] to %[[RED_DECL]]#0 : i32, !fir.ref + ! CHECK-NEXT: omp.yield + !$omp do simd reduction(+:sum) + do index_ = 1, 10 + sum = sum + 1 + end do + !$omp end do simd +end subroutine do_simd_reduction diff --git a/flang/test/Parser/OpenMP/declare-target-to-clause.f90 b/flang/test/Parser/OpenMP/declare-target-to-clause.f90 new file mode 100644 index 0000000000000..bcb23f821e403 --- /dev/null +++ b/flang/test/Parser/OpenMP/declare-target-to-clause.f90 @@ -0,0 +1,19 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=52 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck --check-prefix="PARSE-TREE" %s + +module m + integer :: x, y + + !$omp declare target to(x, y) +end + +!UNPARSE: MODULE m +!UNPARSE: INTEGER x, y +!UNPARSE: !$OMP DECLARE TARGET TO(x,y) +!UNPARSE: END MODULE + +!PARSE-TREE: OmpDeclareTargetSpecifier -> OmpDeclareTargetWithClause -> OmpClauseList -> OmpClause -> To -> OmpToClause +!PARSE-TREE: | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'y' +!PARSE-TREE: | bool = 'true' + diff --git a/flang/test/Parser/OpenMP/from-clause.f90 b/flang/test/Parser/OpenMP/from-clause.f90 new file mode 100644 index 0000000000000..1dcca0b611dfb --- /dev/null +++ b/flang/test/Parser/OpenMP/from-clause.f90 @@ -0,0 +1,91 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=52 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f00(x) + integer :: x + !$omp target update from(x) +end + +!UNPARSE: SUBROUTINE f00 (x) +!UNPARSE: INTEGER x +!UNPARSE: !$OMP TARGET UPDATE FROM(x) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update +!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause +!PARSE-TREE: | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | bool = 'true' + +subroutine f01(x) + integer :: x + !$omp target update from(present: x) +end + +!UNPARSE: SUBROUTINE f01 (x) +!UNPARSE: INTEGER x +!UNPARSE: !$OMP TARGET UPDATE FROM(PRESENT: x) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update +!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause +!PARSE-TREE: | Expectation = Present +!PARSE-TREE: | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | bool = 'true' + +subroutine f02(x) + integer :: x(10) + !$omp target update from(present iterator(i = 1:10): x(i)) +end + +!UNPARSE: SUBROUTINE f02 (x) +!UNPARSE: INTEGER x(10_4) +!UNPARSE: !$OMP TARGET UPDATE FROM(PRESENT, ITERATOR(INTEGER i = 1_4:10_4): x(i)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update +!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause +!PARSE-TREE: | Expectation = Present +!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | | TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'i' +!PARSE-TREE: | | SubscriptTriplet +!PARSE-TREE: | | | Scalar -> Integer -> Expr = '1_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | Scalar -> Integer -> Expr = '10_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '10' +!PARSE-TREE: | OmpObjectList -> OmpObject -> Designator -> DataRef -> ArrayElement +!PARSE-TREE: | | DataRef -> Name = 'x' +!PARSE-TREE: | | SectionSubscript -> Integer -> Expr = 'i' +!PARSE-TREE: | | | Designator -> DataRef -> Name = 'i' +!PARSE-TREE: | bool = 'false' + +subroutine f03(x) + integer :: x(10) + !$omp target update from(present, iterator(i = 1:10): x(i)) +end + +!UNPARSE: SUBROUTINE f03 (x) +!UNPARSE: INTEGER x(10_4) +!UNPARSE: !$OMP TARGET UPDATE FROM(PRESENT, ITERATOR(INTEGER i = 1_4:10_4): x(i)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update +!PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause +!PARSE-TREE: | Expectation = Present +!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | | TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'i' +!PARSE-TREE: | | SubscriptTriplet +!PARSE-TREE: | | | Scalar -> Integer -> Expr = '1_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | Scalar -> Integer -> Expr = '10_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '10' +!PARSE-TREE: | OmpObjectList -> OmpObject -> Designator -> DataRef -> ArrayElement +!PARSE-TREE: | | DataRef -> Name = 'x' +!PARSE-TREE: | | SectionSubscript -> Integer -> Expr = 'i' +!PARSE-TREE: | | | Designator -> DataRef -> Name = 'i' +!PARSE-TREE: | bool = 'true' diff --git a/flang/test/Parser/OpenMP/target-update-to-clause.f90 b/flang/test/Parser/OpenMP/target-update-to-clause.f90 new file mode 100644 index 0000000000000..2702575847924 --- /dev/null +++ b/flang/test/Parser/OpenMP/target-update-to-clause.f90 @@ -0,0 +1,91 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=52 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f00(x) + integer :: x + !$omp target update to(x) +end + +!UNPARSE: SUBROUTINE f00 (x) +!UNPARSE: INTEGER x +!UNPARSE: !$OMP TARGET UPDATE TO(x) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update +!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause +!PARSE-TREE: | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | bool = 'true' + +subroutine f01(x) + integer :: x + !$omp target update to(present: x) +end + +!UNPARSE: SUBROUTINE f01 (x) +!UNPARSE: INTEGER x +!UNPARSE: !$OMP TARGET UPDATE TO(PRESENT: x) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update +!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause +!PARSE-TREE: | Expectation = Present +!PARSE-TREE: | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | bool = 'true' + +subroutine f02(x) + integer :: x(10) + !$omp target update to(present iterator(i = 1:10): x(i)) +end + +!UNPARSE: SUBROUTINE f02 (x) +!UNPARSE: INTEGER x(10_4) +!UNPARSE: !$OMP TARGET UPDATE TO(PRESENT, ITERATOR(INTEGER i = 1_4:10_4): x(i)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update +!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause +!PARSE-TREE: | Expectation = Present +!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | | TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'i' +!PARSE-TREE: | | SubscriptTriplet +!PARSE-TREE: | | | Scalar -> Integer -> Expr = '1_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | Scalar -> Integer -> Expr = '10_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '10' +!PARSE-TREE: | OmpObjectList -> OmpObject -> Designator -> DataRef -> ArrayElement +!PARSE-TREE: | | DataRef -> Name = 'x' +!PARSE-TREE: | | SectionSubscript -> Integer -> Expr = 'i' +!PARSE-TREE: | | | Designator -> DataRef -> Name = 'i' +!PARSE-TREE: | bool = 'false' + +subroutine f03(x) + integer :: x(10) + !$omp target update to(present, iterator(i = 1:10): x(i)) +end + +!UNPARSE: SUBROUTINE f03 (x) +!UNPARSE: INTEGER x(10_4) +!UNPARSE: !$OMP TARGET UPDATE TO(PRESENT, ITERATOR(INTEGER i = 1_4:10_4): x(i)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update +!PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause +!PARSE-TREE: | Expectation = Present +!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | | TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'i' +!PARSE-TREE: | | SubscriptTriplet +!PARSE-TREE: | | | Scalar -> Integer -> Expr = '1_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | Scalar -> Integer -> Expr = '10_4' +!PARSE-TREE: | | | | LiteralConstant -> IntLiteralConstant = '10' +!PARSE-TREE: | OmpObjectList -> OmpObject -> Designator -> DataRef -> ArrayElement +!PARSE-TREE: | | DataRef -> Name = 'x' +!PARSE-TREE: | | SectionSubscript -> Integer -> Expr = 'i' +!PARSE-TREE: | | | Designator -> DataRef -> Name = 'i' +!PARSE-TREE: | bool = 'true' diff --git a/flang/test/Parser/OpenMP/task.f90 b/flang/test/Parser/OpenMP/task.f90 new file mode 100644 index 0000000000000..706deb3451f98 --- /dev/null +++ b/flang/test/Parser/OpenMP/task.f90 @@ -0,0 +1,17 @@ +! REQUIRES: openmp_runtime +! RUN: %flang_fc1 %openmp_flags -fdebug-dump-parse-tree -fopenmp -fopenmp-version=50 %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 %openmp_flags -fdebug-unparse -fopenmp -fopenmp-version=50 %s | FileCheck --ignore-case --check-prefix="CHECK-UNPARSE" %s + +!CHECK: OmpBlockDirective -> llvm::omp::Directive = task +!CHECK: OmpClauseList -> OmpClause -> Detach -> OmpDetachClause -> OmpObject -> Designator -> DataRef -> Name = 'event' + +!CHECK-UNPARSE: INTEGER(KIND=8_4) event +!CHECK-UNPARSE: !$OMP TASK DETACH(event) +!CHECK-UNPARSE: !$OMP END TASK +subroutine task_detach + use omp_lib + implicit none + integer(kind=omp_event_handle_kind) :: event + !$omp task detach(event) + !$omp end task +end subroutine diff --git a/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 b/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 index ccd009bffa2e2..cecc7e0f507b2 100644 --- a/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 +++ b/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 @@ -3,6 +3,7 @@ ! Check OpenACC reduction validity. program openacc_reduction_validity + implicit none integer :: i real :: r @@ -168,5 +169,9 @@ program openacc_reduction_validity !$acc parallel reduction(ieor:l) !$acc end parallel + !ERROR: No explicit type declared for 'xyz' + !$acc parallel reduction(+:xyz) + !$acc end parallel + end program diff --git a/flang/test/Semantics/OpenMP/from-clause-v45.f90 b/flang/test/Semantics/OpenMP/from-clause-v45.f90 new file mode 100644 index 0000000000000..9c418a400e548 --- /dev/null +++ b/flang/test/Semantics/OpenMP/from-clause-v45.f90 @@ -0,0 +1,32 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 + +subroutine f00(x) + integer :: x(10) +!ERROR: Reference to x must be a contiguous object + !$omp target update from(x(1:10:2)) +end + +subroutine f01(x) + integer :: x(10) +!WARNING: Iterator modifiers are not supported in OpenMP v4.5, try -fopenmp-version=51 + !$omp target update from(iterator(i = 1:5): x(i)) +end + +subroutine f02(x) + integer :: x(10) +!WARNING: The PRESENT modifier is not supported in OpenMP v4.5, try -fopenmp-version=51 +!WARNING: Iterator modifiers are not supported in OpenMP v4.5, try -fopenmp-version=51 + !$omp target update from(present, iterator(i = 1:5): x(i)) +end + +subroutine f03(x) + integer :: x(10) +!WARNING: The PRESENT modifier is not supported in OpenMP v4.5, try -fopenmp-version=51 +!ERROR: Only one PRESENT modifier is allowed + !$omp target update from(present, present: x) +end + +subroutine f04 +!ERROR: 'f04' must be a variable + !$omp target update from(f04) +end diff --git a/flang/test/Semantics/OpenMP/from-clause-v51.f90 b/flang/test/Semantics/OpenMP/from-clause-v51.f90 new file mode 100644 index 0000000000000..18139f04c35cf --- /dev/null +++ b/flang/test/Semantics/OpenMP/from-clause-v51.f90 @@ -0,0 +1,18 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51 + +subroutine f01(x) + integer :: x(10) +!ERROR: Only one iterator-modifier is allowed + !$omp target update from(iterator(i = 1:5), iterator(j = 1:5): x(i + j)) +end + +subroutine f03(x) + integer :: x(10) +!ERROR: Only one PRESENT modifier is allowed + !$omp target update from(present, present: x) +end + +subroutine f04 +!ERROR: 'f04' must be a variable + !$omp target update from(f04) +end diff --git a/flang/test/Semantics/OpenMP/to-clause-v45.f90 b/flang/test/Semantics/OpenMP/to-clause-v45.f90 new file mode 100644 index 0000000000000..39e842492ef08 --- /dev/null +++ b/flang/test/Semantics/OpenMP/to-clause-v45.f90 @@ -0,0 +1,32 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 + +subroutine f00(x) + integer :: x(10) +!ERROR: Reference to x must be a contiguous object + !$omp target update to(x(1:10:2)) +end + +subroutine f01(x) + integer :: x(10) +!WARNING: Iterator modifiers are not supported in OpenMP v4.5, try -fopenmp-version=51 + !$omp target update to(iterator(i = 1:5): x(i)) +end + +subroutine f02(x) + integer :: x(10) +!WARNING: The PRESENT modifier is not supported in OpenMP v4.5, try -fopenmp-version=51 +!WARNING: Iterator modifiers are not supported in OpenMP v4.5, try -fopenmp-version=51 + !$omp target update to(present, iterator(i = 1:5): x(i)) +end + +subroutine f03(x) + integer :: x(10) +!WARNING: The PRESENT modifier is not supported in OpenMP v4.5, try -fopenmp-version=51 +!ERROR: Only one PRESENT modifier is allowed + !$omp target update to(present, present: x) +end + +subroutine f04 +!ERROR: 'f04' must be a variable + !$omp target update to(f04) +end diff --git a/flang/test/Semantics/OpenMP/to-clause-v51.f90 b/flang/test/Semantics/OpenMP/to-clause-v51.f90 new file mode 100644 index 0000000000000..d4f5f15efeb97 --- /dev/null +++ b/flang/test/Semantics/OpenMP/to-clause-v51.f90 @@ -0,0 +1,18 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51 + +subroutine f01(x) + integer :: x(10) +!ERROR: Only one iterator-modifier is allowed + !$omp target update to(iterator(i = 1:5), iterator(j = 1:5): x(i + j)) +end + +subroutine f03(x) + integer :: x(10) +!ERROR: Only one PRESENT modifier is allowed + !$omp target update to(present, present: x) +end + +subroutine f04 +!ERROR: 'f04' must be a variable + !$omp target update to(f04) +end diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index b3f94a581c8ad..3e263b50327f2 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -356,6 +356,14 @@ if(LLVM_LIBC_INCLUDE_SCUDO) endif() set(TARGET_LIBM_ENTRYPOINTS + # complex.h entrypoints + libc.src.complex.creal + libc.src.complex.crealf + libc.src.complex.creall + libc.src.complex.cimag + libc.src.complex.cimagf + libc.src.complex.cimagl + # fenv.h entrypoints libc.src.fenv.feclearexcept libc.src.fenv.fedisableexcept @@ -603,6 +611,10 @@ set(TARGET_LIBM_ENTRYPOINTS if(LIBC_TYPES_HAS_FLOAT16) list(APPEND TARGET_LIBM_ENTRYPOINTS + # complex.h C23 _Complex _Float16 entrypoints + # libc.src.complex.crealf16 + # libc.src.complex.cimagf16 + # math.h C23 _Float16 entrypoints libc.src.math.canonicalizef16 libc.src.math.ceilf16 @@ -704,6 +716,10 @@ endif() if(LIBC_TYPES_HAS_FLOAT128) list(APPEND TARGET_LIBM_ENTRYPOINTS + # complex.h C23 _Complex _Float128 entrypoints + libc.src.complex.crealf128 + libc.src.complex.cimagf128 + # math.h C23 _Float128 entrypoints libc.src.math.canonicalizef128 libc.src.math.ceilf128 diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 2ddb7aeefe48e..383bf8c8e5280 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -197,6 +197,14 @@ if(LLVM_LIBC_INCLUDE_SCUDO) endif() set(TARGET_LIBM_ENTRYPOINTS + # complex.h entrypoints + libc.src.complex.creal + libc.src.complex.crealf + libc.src.complex.creall + libc.src.complex.cimag + libc.src.complex.cimagf + libc.src.complex.cimagl + # fenv.h entrypoints libc.src.fenv.feclearexcept libc.src.fenv.fedisableexcept diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 5c09edf7cfb26..c47a4662d1ac7 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -355,6 +355,14 @@ if(LLVM_LIBC_INCLUDE_SCUDO) endif() set(TARGET_LIBM_ENTRYPOINTS + # complex.h entrypoints + libc.src.complex.creal + libc.src.complex.crealf + libc.src.complex.creall + libc.src.complex.cimag + libc.src.complex.cimagf + libc.src.complex.cimagl + # fenv.h entrypoints libc.src.fenv.feclearexcept libc.src.fenv.fedisableexcept @@ -606,6 +614,10 @@ set(TARGET_LIBM_ENTRYPOINTS if(LIBC_TYPES_HAS_FLOAT128) list(APPEND TARGET_LIBM_ENTRYPOINTS + # complex.h C23 _Complex _Float128 entrypoints + libc.src.complex.crealf128 + libc.src.complex.cimagf128 + # math.h C23 _Float128 entrypoints libc.src.math.canonicalizef128 libc.src.math.ceilf128 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index a2fb97d04584d..3ed77c76709da 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -355,6 +355,14 @@ if(LLVM_LIBC_INCLUDE_SCUDO) endif() set(TARGET_LIBM_ENTRYPOINTS + # complex.h entrypoints + libc.src.complex.creal + libc.src.complex.crealf + libc.src.complex.creall + libc.src.complex.cimag + libc.src.complex.cimagf + libc.src.complex.cimagl + # fenv.h entrypoints libc.src.fenv.feclearexcept libc.src.fenv.fedisableexcept @@ -606,6 +614,10 @@ set(TARGET_LIBM_ENTRYPOINTS if(LIBC_TYPES_HAS_FLOAT16) list(APPEND TARGET_LIBM_ENTRYPOINTS + # complex.h C23 _Complex _Float16 entrypoints + libc.src.complex.crealf16 + libc.src.complex.cimagf16 + # math.h C23 _Float16 entrypoints libc.src.math.canonicalizef16 libc.src.math.ceilf16 @@ -709,6 +721,10 @@ endif() if(LIBC_TYPES_HAS_FLOAT128) list(APPEND TARGET_LIBM_ENTRYPOINTS + # complex.h C23 _Complex _Float128 entrypoints + # libc.src.complex.crealf128 + # libc.src.complex.cimagf128 + # math.h C23 _Float128 entrypoints libc.src.math.canonicalizef128 libc.src.math.ceilf128 diff --git a/libc/docs/complex.rst b/libc/docs/complex.rst index 09fbdd7c6179e..1e74f16b60e66 100644 --- a/libc/docs/complex.rst +++ b/libc/docs/complex.rst @@ -55,11 +55,11 @@ Functions +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | carg | | | | | | 7.3.9.1 | N/A | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ -| cimag | | | | | | 7.3.9.2 | N/A | +| cimag | |check| | |check| | |check| | |check| | |check| | 7.3.9.2 | N/A | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | conj | | | | | | 7.3.9.4 | N/A | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | cproj | | | | | | 7.3.9.5 | N/A | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ -| creal | | | | | | 7.3.9.6 | N/A | +| creal | |check| | |check| | |check| | |check| | |check| | 7.3.9.6 | N/A | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ diff --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt index c63eadab6f5d7..93da271f5e040 100644 --- a/libc/hdr/CMakeLists.txt +++ b/libc/hdr/CMakeLists.txt @@ -81,6 +81,8 @@ add_proxy_header_library( libc.include.signal ) +add_header_library(stdlib_overlay HDRS stdlib_overlay.h) + add_proxy_header_library( stdlib_macros HDRS @@ -193,3 +195,4 @@ add_proxy_header_library( ) add_subdirectory(types) +add_subdirectory(func) diff --git a/libc/hdr/func/CMakeLists.txt b/libc/hdr/func/CMakeLists.txt new file mode 100644 index 0000000000000..714b7ec9b4880 --- /dev/null +++ b/libc/hdr/func/CMakeLists.txt @@ -0,0 +1,52 @@ +add_proxy_header_library( + aligned_alloc + HDRS + aligned_alloc.h + DEPENDS + libc.hdr.stdlib_overlay + FULL_BUILD_DEPENDS + libc.include.stdlib + libc.hdr.types.size_t +) + +add_proxy_header_library( + malloc + HDRS + malloc.h + DEPENDS + libc.hdr.stdlib_overlay + FULL_BUILD_DEPENDS + libc.include.stdlib + libc.hdr.types.size_t +) + +add_proxy_header_library( + realloc + HDRS + realloc.h + DEPENDS + libc.hdr.stdlib_overlay + FULL_BUILD_DEPENDS + libc.include.stdlib + libc.hdr.types.size_t +) + +add_proxy_header_library( + free + HDRS + free.h + DEPENDS + libc.hdr.stdlib_overlay + FULL_BUILD_DEPENDS + libc.include.stdlib +) + +add_proxy_header_library( + _Exit + HDRS + _Exit.h + DEPENDS + libc.hdr.stdlib_overlay + FULL_BUILD_DEPENDS + libc.include.stdlib +) diff --git a/libc/hdr/func/_Exit.h b/libc/hdr/func/_Exit.h new file mode 100644 index 0000000000000..e024a651a50bc --- /dev/null +++ b/libc/hdr/func/_Exit.h @@ -0,0 +1,22 @@ +//===-- Definition of the _Exit proxy -------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_HDR_FUNC_EXIT_H +#define LLVM_LIBC_HDR_FUNC_EXIT_H + +#ifdef LIBC_FULL_BUILD +// We will use the `_Exit` declaration from our generated stdlib.h +#include + +#else // Overlay mode + +#include "hdr/stdlib_overlay.h" + +#endif + +#endif // LLVM_LIBC_HDR_EXIT_H diff --git a/libc/hdr/func/aligned_alloc.h b/libc/hdr/func/aligned_alloc.h new file mode 100644 index 0000000000000..b3436dfee1f23 --- /dev/null +++ b/libc/hdr/func/aligned_alloc.h @@ -0,0 +1,22 @@ +//===-- Definition of the aligned_alloc.h proxy ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_HDR_FUNC_ALIGNED_ALLOC_H +#define LLVM_LIBC_HDR_FUNC_ALIGNED_ALLOC_H + +#ifdef LIBC_FULL_BUILD +#include "hdr/types/size_t.h" +extern "C" void *aligned_alloc(size_t, size_t); + +#else // Overlay mode + +#include "hdr/stdlib_overlay.h" + +#endif + +#endif diff --git a/libc/hdr/func/free.h b/libc/hdr/func/free.h new file mode 100644 index 0000000000000..b1190a777da32 --- /dev/null +++ b/libc/hdr/func/free.h @@ -0,0 +1,21 @@ +//===-- Definition of the free.h proxy ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_HDR_FUNC_FREE_H +#define LLVM_LIBC_HDR_FUNC_FREE_H + +#ifdef LIBC_FULL_BUILD +extern "C" void free(void *); + +#else // Overlay mode + +#include "hdr/stdlib_overlay.h" + +#endif + +#endif diff --git a/libc/hdr/func/malloc.h b/libc/hdr/func/malloc.h new file mode 100644 index 0000000000000..b395f41f2bce2 --- /dev/null +++ b/libc/hdr/func/malloc.h @@ -0,0 +1,22 @@ +//===-- Definition of the malloc.h proxy ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_HDR_FUNC_MALLOC_H +#define LLVM_LIBC_HDR_FUNC_MALLOC_H + +#ifdef LIBC_FULL_BUILD +#include "hdr/types/size_t.h" +extern "C" void *malloc(size_t); + +#else // Overlay mode + +#include "hdr/stdlib_overlay.h" + +#endif + +#endif diff --git a/libc/hdr/func/realloc.h b/libc/hdr/func/realloc.h new file mode 100644 index 0000000000000..0096045e8330b --- /dev/null +++ b/libc/hdr/func/realloc.h @@ -0,0 +1,22 @@ +//===-- Definition of the realloc.h proxy ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_HDR_FUNC_REALLOC_H +#define LLVM_LIBC_HDR_FUNC_REALLOC_H + +#ifdef LIBC_FULL_BUILD +#include "hdr/types/size_t.h" +extern "C" void *realloc(void *ptr, size_t new_size); + +#else // Overlay mode + +#include "hdr/stdlib_overlay.h" + +#endif + +#endif diff --git a/libc/hdr/types/atexithandler_t.h b/libc/hdr/types/atexithandler_t.h index 4275e44073674..6d829fe60d271 100644 --- a/libc/hdr/types/atexithandler_t.h +++ b/libc/hdr/types/atexithandler_t.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_HDR_ATEXITHANDLER_T_H -#define LLVM_LIBC_HDR_ATEXITHANDLER_T_H +#ifndef LLVM_LIBC_HDR_TYPES_ATEXITHANDLER_T_H +#define LLVM_LIBC_HDR_TYPES_ATEXITHANDLER_T_H #ifdef LIBC_FULL_BUILD @@ -19,4 +19,4 @@ #endif // LLVM_LIBC_FULL_BUILD -#endif // LLVM_LIBC_HDR_ATEXITHANDLER_T_H +#endif // LLVM_LIBC_HDR_TYPES_ATEXITHANDLER_T_H diff --git a/libc/hdr/types/fenv_t.h b/libc/hdr/types/fenv_t.h index dc2dd0217a16f..ddfb08c027bfc 100644 --- a/libc/hdr/types/fenv_t.h +++ b/libc/hdr/types/fenv_t.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_HDR_FENV_T_H -#define LLVM_LIBC_HDR_FENV_T_H +#ifndef LLVM_LIBC_HDR_TYPES_FENV_T_H +#define LLVM_LIBC_HDR_TYPES_FENV_T_H #ifdef LIBC_FULL_BUILD @@ -19,4 +19,4 @@ #endif // LLVM_LIBC_FULL_BUILD -#endif // LLVM_LIBC_HDR_FENV_T_H +#endif // LLVM_LIBC_HDR_TYPES_FENV_T_H diff --git a/libc/hdr/types/fexcept_t.h b/libc/hdr/types/fexcept_t.h index 7a6702516f0a3..761f125ae8cfb 100644 --- a/libc/hdr/types/fexcept_t.h +++ b/libc/hdr/types/fexcept_t.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_HDR_FEXCEPT_T_H -#define LLVM_LIBC_HDR_FEXCEPT_T_H +#ifndef LLVM_LIBC_HDR_TYPES_FEXCEPT_T_H +#define LLVM_LIBC_HDR_TYPES_FEXCEPT_T_H #ifdef LIBC_FULL_BUILD @@ -19,4 +19,4 @@ #endif // LLVM_LIBC_FULL_BUILD -#endif // LLVM_LIBC_HDR_FENV_T_H +#endif // LLVM_LIBC_HDR_TYPES_FEXCEPT_T_H diff --git a/libc/hdr/types/jmp_buf.h b/libc/hdr/types/jmp_buf.h index 943764739f69a..3fa1de816d703 100644 --- a/libc/hdr/types/jmp_buf.h +++ b/libc/hdr/types/jmp_buf.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_HDR_JMP_BUF_H -#define LLVM_LIBC_HDR_JMP_BUF_H +#ifndef LLVM_LIBC_HDR_TYPES_JMP_BUF_H +#define LLVM_LIBC_HDR_TYPES_JMP_BUF_H #ifdef LIBC_FULL_BUILD diff --git a/libc/hdr/types/locale_t.h b/libc/hdr/types/locale_t.h index 485258b461696..be12d12b4070b 100644 --- a/libc/hdr/types/locale_t.h +++ b/libc/hdr/types/locale_t.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_HDR_LOCALE_T_H -#define LLVM_LIBC_HDR_LOCALE_T_H +#ifndef LLVM_LIBC_HDR_TYPES_LOCALE_T_H +#define LLVM_LIBC_HDR_TYPES_LOCALE_T_H #ifdef LIBC_FULL_BUILD @@ -19,4 +19,4 @@ #endif // LLVM_LIBC_FULL_BUILD -#endif // LLVM_LIBC_HDR_LOCALE_T_H +#endif // LLVM_LIBC_HDR_TYPES_LOCALE_T_H diff --git a/libc/hdr/types/mode_t.h b/libc/hdr/types/mode_t.h index abbbdb0a09d7b..3f36a1961e624 100644 --- a/libc/hdr/types/mode_t.h +++ b/libc/hdr/types/mode_t.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_HDR_MODE_T_H -#define LLVM_LIBC_HDR_MODE_T_H +#ifndef LLVM_LIBC_HDR_TYPES_MODE_T_H +#define LLVM_LIBC_HDR_TYPES_MODE_T_H #ifdef LIBC_FULL_BUILD @@ -19,4 +19,4 @@ #endif // LLVM_LIBC_FULL_BUILD -#endif // LLVM_LIBC_HDR_MODE_T_H +#endif // LLVM_LIBC_HDR_TYPES_MODE_T_H diff --git a/libc/hdr/types/sighandler_t.h b/libc/hdr/types/sighandler_t.h index b18f8e856c5b6..bc40dd8b4c8f4 100644 --- a/libc/hdr/types/sighandler_t.h +++ b/libc/hdr/types/sighandler_t.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_HDR_SIGHANDLER_T_H -#define LLVM_LIBC_HDR_SIGHANDLER_T_H +#ifndef LLVM_LIBC_HDR_TYPES_SIGHANDLER_T_H +#define LLVM_LIBC_HDR_TYPES_SIGHANDLER_T_H #ifdef LIBC_FULL_BUILD diff --git a/libc/hdr/types/stack_t.h b/libc/hdr/types/stack_t.h index 9c0f707a7f6d9..42dad3aa80c16 100644 --- a/libc/hdr/types/stack_t.h +++ b/libc/hdr/types/stack_t.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_HDR_STACK_T_H -#define LLVM_LIBC_HDR_STACK_T_H +#ifndef LLVM_LIBC_HDR_TYPES_STACK_T_H +#define LLVM_LIBC_HDR_TYPES_STACK_T_H #ifdef LIBC_FULL_BUILD diff --git a/libc/hdr/types/suseconds_t.h b/libc/hdr/types/suseconds_t.h index 72e54a965f750..f60168c59fb89 100644 --- a/libc/hdr/types/suseconds_t.h +++ b/libc/hdr/types/suseconds_t.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_HDR_TIMES_SUSECONDS_T_H -#define LLVM_LIBC_HDR_TIMES_SUSECONDS_T_H +#ifndef LLVM_LIBC_HDR_TYPES_SUSECONDS_T_H +#define LLVM_LIBC_HDR_TYPES_SUSECONDS_T_H #ifdef LIBC_FULL_BUILD @@ -19,4 +19,4 @@ #endif // LLVM_LIBC_FULL_BUILD -#endif // #ifndef LLVM_LIBC_HDR_TIMES_SUSECONDS_T_H +#endif // #ifndef LLVM_LIBC_HDR_TYPES_SUSECONDS_T_H diff --git a/libc/include/__llvm-libc-common.h b/libc/include/__llvm-libc-common.h index 3af0b08e9e866..e0e29bbbd5f87 100644 --- a/libc/include/__llvm-libc-common.h +++ b/libc/include/__llvm-libc-common.h @@ -17,6 +17,12 @@ #undef __END_C_DECLS #define __END_C_DECLS } +// Standard C++ doesn't have C99 restrict but GNU C++ has it with __ spelling. +#undef __restrict +#ifndef __GNUC__ +#define __restrict +#endif + #undef _Noreturn #define _Noreturn [[noreturn]] diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt index d554c12fb1ec8..02c193e635362 100644 --- a/libc/src/CMakeLists.txt +++ b/libc/src/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(__support) +add_subdirectory(complex) add_subdirectory(ctype) add_subdirectory(dlfcn) add_subdirectory(errno) diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 14a3acff8fae9..c44e333645e22 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -209,6 +209,12 @@ add_header_library( libc.src.__support.CPP.limits ) +add_header_library( + complex_type + HDRS + complex_type.h +) + add_header_library( integer_operations HDRS @@ -236,6 +242,9 @@ add_header_library( HDRS char_vector.h DEPENDS + libc.hdr.func.free + libc.hdr.func.malloc + libc.hdr.func.realloc libc.src.__support.common ) diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt index 774668be42e56..15fad9de0ed6d 100644 --- a/libc/src/__support/CPP/CMakeLists.txt +++ b/libc/src/__support/CPP/CMakeLists.txt @@ -80,8 +80,10 @@ add_header_library( HDRS string.h DEPENDS - libc.include.stdlib .string_view + libc.hdr.func.free + libc.hdr.func.malloc + libc.hdr.func.realloc libc.src.__support.common libc.src.__support.integer_to_string libc.src.string.memory_utils.inline_memcpy @@ -199,7 +201,9 @@ add_object_library( HDRS new.h DEPENDS - libc.include.stdlib + libc.hdr.func.free + libc.hdr.func.malloc + libc.hdr.func.aligned_alloc libc.src.__support.common libc.src.__support.macros.properties.os ) diff --git a/libc/src/__support/CPP/new.cpp b/libc/src/__support/CPP/new.cpp index 8316329fb10b0..65f80de373485 100644 --- a/libc/src/__support/CPP/new.cpp +++ b/libc/src/__support/CPP/new.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "new.h" -#include // For free, etc +#include "hdr/func/free.h" void operator delete(void *mem) noexcept { ::free(mem); } diff --git a/libc/src/__support/CPP/new.h b/libc/src/__support/CPP/new.h index c1b6b95033f84..8694d9c475507 100644 --- a/libc/src/__support/CPP/new.h +++ b/libc/src/__support/CPP/new.h @@ -9,12 +9,14 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_NEW_H #define LLVM_LIBC_SRC___SUPPORT_CPP_NEW_H +#include "hdr/func/aligned_alloc.h" +#include "hdr/func/free.h" +#include "hdr/func/malloc.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/os.h" #include // For size_t -#include // For malloc, free etc. // Defining members in the std namespace is not preferred. But, we do it here // so that we can use it to define the operator new which takes std::align_val_t diff --git a/libc/src/__support/CPP/string.h b/libc/src/__support/CPP/string.h index 64d4c276e8428..dbc0ae04e5e6f 100644 --- a/libc/src/__support/CPP/string.h +++ b/libc/src/__support/CPP/string.h @@ -9,6 +9,9 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_H #define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_H +#include "hdr/func/free.h" +#include "hdr/func/malloc.h" +#include "hdr/func/realloc.h" #include "src/__support/CPP/string_view.h" #include "src/__support/integer_to_string.h" // IntegerToString #include "src/__support/macros/config.h" @@ -17,7 +20,6 @@ #include "src/string/string_utils.h" // string_length #include // size_t -#include // malloc, free namespace LIBC_NAMESPACE_DECL { namespace cpp { diff --git a/libc/src/__support/File/CMakeLists.txt b/libc/src/__support/File/CMakeLists.txt index 1b390a12424d0..5a4af5e70e289 100644 --- a/libc/src/__support/File/CMakeLists.txt +++ b/libc/src/__support/File/CMakeLists.txt @@ -18,6 +18,7 @@ add_object_library( libc.src.__support.error_or libc.hdr.types.off_t libc.hdr.stdio_macros + libc.hdr.func.realloc ) add_object_library( diff --git a/libc/src/__support/File/file.cpp b/libc/src/__support/File/file.cpp index 51811a27c1acd..972249fef96bc 100644 --- a/libc/src/__support/File/file.cpp +++ b/libc/src/__support/File/file.cpp @@ -8,6 +8,7 @@ #include "file.h" +#include "hdr/func/realloc.h" #include "hdr/stdio_macros.h" #include "hdr/types/off_t.h" #include "src/__support/CPP/new.h" diff --git a/libc/src/__support/char_vector.h b/libc/src/__support/char_vector.h index df109da5d8127..d0837a8af3f46 100644 --- a/libc/src/__support/char_vector.h +++ b/libc/src/__support/char_vector.h @@ -9,11 +9,13 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_CHARVECTOR_H #define LLVM_LIBC_SRC___SUPPORT_CHARVECTOR_H +#include "hdr/func/free.h" +#include "hdr/func/malloc.h" +#include "hdr/func/realloc.h" #include "src/__support/common.h" // LIBC_INLINE #include "src/__support/macros/config.h" #include // size_t -#include // malloc, realloc, free namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/__support/complex_type.h b/libc/src/__support/complex_type.h new file mode 100644 index 0000000000000..d6b5eec8fd6b2 --- /dev/null +++ b/libc/src/__support/complex_type.h @@ -0,0 +1,20 @@ +//===-- complex type --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_COMPLEX_TYPE_H +#define LLVM_LIBC_SRC___SUPPORT_COMPLEX_TYPE_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { +template struct Complex { + T real; + T imag; +}; +} // namespace LIBC_NAMESPACE_DECL +#endif // LLVM_LIBC_SRC___SUPPORT_COMPLEX_TYPE_H diff --git a/libc/src/complex/CMakeLists.txt b/libc/src/complex/CMakeLists.txt new file mode 100644 index 0000000000000..289cce5455af7 --- /dev/null +++ b/libc/src/complex/CMakeLists.txt @@ -0,0 +1,26 @@ +add_subdirectory(generic) + +function(add_complex_entrypoint_object name) + get_fq_target_name("generic.${name}" fq_generic_target_name) + if(TARGET ${fq_generic_target_name}) + add_entrypoint_object( + ${name} + ALIAS + DEPENDS + .generic.${name} + ) + return() + endif() +endfunction() + +add_complex_entrypoint_object(creal) +add_complex_entrypoint_object(crealf) +add_complex_entrypoint_object(creall) +add_complex_entrypoint_object(crealf16) +add_complex_entrypoint_object(crealf128) + +add_complex_entrypoint_object(cimag) +add_complex_entrypoint_object(cimagf) +add_complex_entrypoint_object(cimagl) +add_complex_entrypoint_object(cimagf16) +add_complex_entrypoint_object(cimagf128) diff --git a/libc/src/complex/cimag.h b/libc/src/complex/cimag.h new file mode 100644 index 0000000000000..29c9b22a78b05 --- /dev/null +++ b/libc/src/complex/cimag.h @@ -0,0 +1,20 @@ +//===-- Implementation header for cimag -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_COMPLEX_CIMAG_H +#define LLVM_LIBC_SRC_COMPLEX_CIMAG_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +double cimag(_Complex double x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CIMAG_H diff --git a/libc/src/complex/cimagf.h b/libc/src/complex/cimagf.h new file mode 100644 index 0000000000000..577b6ca114559 --- /dev/null +++ b/libc/src/complex/cimagf.h @@ -0,0 +1,20 @@ +//===-- Implementation header for cimagf ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_COMPLEX_CIMAGF_H +#define LLVM_LIBC_SRC_COMPLEX_CIMAGF_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +float cimagf(_Complex float x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CIMAGF_H diff --git a/libc/src/complex/cimagf128.h b/libc/src/complex/cimagf128.h new file mode 100644 index 0000000000000..ab8f9ac7da58c --- /dev/null +++ b/libc/src/complex/cimagf128.h @@ -0,0 +1,27 @@ +//===-- Implementation header for cimagf128 ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/macros/properties/complex_types.h" +#include "src/__support/macros/properties/types.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT128) + +#ifndef LLVM_LIBC_SRC_COMPLEX_CIMAGF128_H +#define LLVM_LIBC_SRC_COMPLEX_CIMAGF128_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +float128 cimagf128(cfloat128 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CIMAGF128_H + +#endif // LIBC_TYPES_HAS_CFLOAT128 diff --git a/libc/src/complex/cimagf16.h b/libc/src/complex/cimagf16.h new file mode 100644 index 0000000000000..5c5de2eb1bcf2 --- /dev/null +++ b/libc/src/complex/cimagf16.h @@ -0,0 +1,27 @@ +//===-- Implementation header for cimagf16 ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/macros/properties/complex_types.h" +#include "src/__support/macros/properties/types.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT16) + +#ifndef LLVM_LIBC_SRC_COMPLEX_CIMAGF16_H +#define LLVM_LIBC_SRC_COMPLEX_CIMAGF16_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +float16 cimagf16(cfloat16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CIMAGF16_H + +#endif // LIBC_TYPES_HAS_CFLOAT16 diff --git a/libc/src/complex/cimagl.h b/libc/src/complex/cimagl.h new file mode 100644 index 0000000000000..966aee0ef3f74 --- /dev/null +++ b/libc/src/complex/cimagl.h @@ -0,0 +1,20 @@ +//===-- Implementation header for cimagl ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_COMPLEX_CIMAGL_H +#define LLVM_LIBC_SRC_COMPLEX_CIMAGL_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +long double cimagl(_Complex long double x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CIMAGL_H diff --git a/libc/src/complex/creal.h b/libc/src/complex/creal.h new file mode 100644 index 0000000000000..3ec5dd049b975 --- /dev/null +++ b/libc/src/complex/creal.h @@ -0,0 +1,20 @@ +//===-- Implementation header for creal -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_COMPLEX_CREAL_H +#define LLVM_LIBC_SRC_COMPLEX_CREAL_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +double creal(_Complex double x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CREAL_H diff --git a/libc/src/complex/crealf.h b/libc/src/complex/crealf.h new file mode 100644 index 0000000000000..79dafc1c3758d --- /dev/null +++ b/libc/src/complex/crealf.h @@ -0,0 +1,20 @@ +//===-- Implementation header for crealf ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_COMPLEX_CREALF_H +#define LLVM_LIBC_SRC_COMPLEX_CREALF_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +float crealf(_Complex float x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CREALF_H diff --git a/libc/src/complex/crealf128.h b/libc/src/complex/crealf128.h new file mode 100644 index 0000000000000..4922ae78cb238 --- /dev/null +++ b/libc/src/complex/crealf128.h @@ -0,0 +1,27 @@ +//===-- Implementation header for crealf128 ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/macros/properties/complex_types.h" +#include "src/__support/macros/properties/types.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT128) + +#ifndef LLVM_LIBC_SRC_COMPLEX_CREALF128_H +#define LLVM_LIBC_SRC_COMPLEX_CREALF128_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +float128 crealf128(cfloat128 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CREALF128_H + +#endif // LIBC_TYPES_HAS_CFLOAT128 diff --git a/libc/src/complex/crealf16.h b/libc/src/complex/crealf16.h new file mode 100644 index 0000000000000..e6098a218d092 --- /dev/null +++ b/libc/src/complex/crealf16.h @@ -0,0 +1,27 @@ +//===-- Implementation header for crealf16 ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/macros/properties/complex_types.h" +#include "src/__support/macros/properties/types.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT16) + +#ifndef LLVM_LIBC_SRC_COMPLEX_CREALF16_H +#define LLVM_LIBC_SRC_COMPLEX_CREALF16_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +float16 crealf16(cfloat16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CREALF16_H + +#endif // LIBC_TYPES_HAS_CFLOAT16 diff --git a/libc/src/complex/creall.h b/libc/src/complex/creall.h new file mode 100644 index 0000000000000..2a8245f63d671 --- /dev/null +++ b/libc/src/complex/creall.h @@ -0,0 +1,20 @@ +//===-- Implementation header for creall ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_COMPLEX_CREALL_H +#define LLVM_LIBC_SRC_COMPLEX_CREALL_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +long double creall(_Complex long double x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_COMPLEX_CREALL_H diff --git a/libc/src/complex/generic/CMakeLists.txt b/libc/src/complex/generic/CMakeLists.txt new file mode 100644 index 0000000000000..a63871b32afbf --- /dev/null +++ b/libc/src/complex/generic/CMakeLists.txt @@ -0,0 +1,137 @@ +add_entrypoint_object( + creal + SRCS + creal.cpp + HDRS + ../creal.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type +) + +add_entrypoint_object( + crealf + SRCS + crealf.cpp + HDRS + ../crealf.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type +) + +add_entrypoint_object( + creall + SRCS + creall.cpp + HDRS + ../creall.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type +) + +add_entrypoint_object( + crealf16 + SRCS + crealf16.cpp + HDRS + ../crealf16.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type + libc.src.__support.macros.properties.types + libc.src.__support.macros.properties.complex_types +) + +add_entrypoint_object( + crealf128 + SRCS + crealf128.cpp + HDRS + ../crealf128.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type + libc.src.__support.macros.properties.types + libc.src.__support.macros.properties.complex_types +) + +add_entrypoint_object( + cimag + SRCS + cimag.cpp + HDRS + ../cimag.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type +) + +add_entrypoint_object( + cimagf + SRCS + cimagf.cpp + HDRS + ../cimagf.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type +) + +add_entrypoint_object( + cimagl + SRCS + cimagl.cpp + HDRS + ../cimagl.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type +) + +add_entrypoint_object( + cimagf16 + SRCS + cimagf16.cpp + HDRS + ../cimagf16.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type + libc.src.__support.macros.properties.types + libc.src.__support.macros.properties.complex_types +) + +add_entrypoint_object( + cimagf128 + SRCS + cimagf128.cpp + HDRS + ../cimagf128.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.CPP.bit + libc.src.__support.complex_type + libc.src.__support.macros.properties.types + libc.src.__support.macros.properties.complex_types +) diff --git a/libc/src/complex/generic/cimag.cpp b/libc/src/complex/generic/cimag.cpp new file mode 100644 index 0000000000000..6aa5de4c2e78a --- /dev/null +++ b/libc/src/complex/generic/cimag.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of cimag function ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/cimag.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(double, cimag, (_Complex double x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.imag; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/complex/generic/cimagf.cpp b/libc/src/complex/generic/cimagf.cpp new file mode 100644 index 0000000000000..f61808c812077 --- /dev/null +++ b/libc/src/complex/generic/cimagf.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of cimagf function ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/cimagf.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(float, cimagf, (_Complex float x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.imag; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/complex/generic/cimagf128.cpp b/libc/src/complex/generic/cimagf128.cpp new file mode 100644 index 0000000000000..c21bd7f4602cc --- /dev/null +++ b/libc/src/complex/generic/cimagf128.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of cimagf128 function ------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/cimagf128.h" +#if defined(LIBC_TYPES_HAS_CFLOAT128) + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(float128, cimagf128, (cfloat128 x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.imag; +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_CFLOAT128 diff --git a/libc/src/complex/generic/cimagf16.cpp b/libc/src/complex/generic/cimagf16.cpp new file mode 100644 index 0000000000000..361687984067b --- /dev/null +++ b/libc/src/complex/generic/cimagf16.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of cimagf16 function -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/cimagf16.h" +#if defined(LIBC_TYPES_HAS_CFLOAT16) + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(float16, cimagf16, (cfloat16 x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.imag; +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_CFLOAT16 diff --git a/libc/src/complex/generic/cimagl.cpp b/libc/src/complex/generic/cimagl.cpp new file mode 100644 index 0000000000000..1f63ad3a95736 --- /dev/null +++ b/libc/src/complex/generic/cimagl.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of cimagl function ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/cimagl.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(long double, cimagl, (_Complex long double x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.imag; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/complex/generic/creal.cpp b/libc/src/complex/generic/creal.cpp new file mode 100644 index 0000000000000..e97e1dac2473d --- /dev/null +++ b/libc/src/complex/generic/creal.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of creal function ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/creal.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(double, creal, (_Complex double x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.real; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/complex/generic/crealf.cpp b/libc/src/complex/generic/crealf.cpp new file mode 100644 index 0000000000000..304c743d5922a --- /dev/null +++ b/libc/src/complex/generic/crealf.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of crealf function ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/crealf.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(float, crealf, (_Complex float x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.real; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/complex/generic/crealf128.cpp b/libc/src/complex/generic/crealf128.cpp new file mode 100644 index 0000000000000..e72a778216010 --- /dev/null +++ b/libc/src/complex/generic/crealf128.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of crealf128 function ------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/crealf128.h" +#if defined(LIBC_TYPES_HAS_CFLOAT128) + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(float128, crealf128, (cfloat128 x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.real; +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_CFLOAT128 diff --git a/libc/src/complex/generic/crealf16.cpp b/libc/src/complex/generic/crealf16.cpp new file mode 100644 index 0000000000000..35142071f0536 --- /dev/null +++ b/libc/src/complex/generic/crealf16.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of crealf16 function -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/crealf16.h" +#if defined(LIBC_TYPES_HAS_CFLOAT16) + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(float16, crealf16, (cfloat16 x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.real; +} + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LIBC_TYPES_HAS_CFLOAT16 diff --git a/libc/src/complex/generic/creall.cpp b/libc/src/complex/generic/creall.cpp new file mode 100644 index 0000000000000..9d43f977cf300 --- /dev/null +++ b/libc/src/complex/generic/creall.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of creall function ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/complex/creall.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/complex_type.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(long double, creall, (_Complex long double x)) { + Complex x_c = cpp::bit_cast>(x); + return x_c.real; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt index 8172fda1e866e..9eaffe2f7ed62 100644 --- a/libc/src/stdio/printf_core/CMakeLists.txt +++ b/libc/src/stdio/printf_core/CMakeLists.txt @@ -129,11 +129,12 @@ add_header_library( HDRS vasprintf_internal.h DEPENDS + libc.hdr.func.malloc + libc.hdr.func.free + libc.hdr.func.realloc libc.src.__support.arg_list libc.src.stdio.printf_core.printf_main libc.src.stdio.printf_core.writer - libc.src.stdlib.malloc - libc.src.stdlib.realloc ) if(NOT (TARGET libc.src.__support.File.file) AND LLVM_LIBC_FULL_BUILD) diff --git a/libc/src/stdio/printf_core/vasprintf_internal.h b/libc/src/stdio/printf_core/vasprintf_internal.h index e3448eebd302b..0e446f856e438 100644 --- a/libc/src/stdio/printf_core/vasprintf_internal.h +++ b/libc/src/stdio/printf_core/vasprintf_internal.h @@ -6,12 +6,14 @@ // //===----------------------------------------------------------------------===// +#include "hdr/func/free.h" +#include "hdr/func/malloc.h" +#include "hdr/func/realloc.h" #include "src/__support/arg_list.h" #include "src/stdio/printf.h" #include "src/stdio/printf_core/core_structs.h" #include "src/stdio/printf_core/printf_main.h" #include "src/stdio/printf_core/writer.h" -#include // malloc, realloc, free namespace LIBC_NAMESPACE_DECL { namespace printf_core { diff --git a/libc/test/integration/src/stdio/CMakeLists.txt b/libc/test/integration/src/stdio/CMakeLists.txt index 51c5ee25a6b26..aca22daf653b8 100644 --- a/libc/test/integration/src/stdio/CMakeLists.txt +++ b/libc/test/integration/src/stdio/CMakeLists.txt @@ -6,20 +6,23 @@ add_dependencies(libc-integration-tests stdio-integration-tests) # These tests are not for correctness testing, but are instead a convenient way # to generate hermetic binaries for comparitive binary size testing. -add_integration_test( - sprintf_size_test - SUITE - stdio-integration-tests - SRCS - sprintf_size_test.cpp - DEPENDS - libc.src.stdio.sprintf - ARGS - "%s %c %d" - "First arg" - "a" - "0" -) +# FIXME: This test fails on AMDGPU so we disable it temporarily. +if(NOT LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) + add_integration_test( + sprintf_size_test + SUITE + stdio-integration-tests + SRCS + sprintf_size_test.cpp + DEPENDS + libc.src.stdio.sprintf + ARGS + "%s %c %d" + "First arg" + "a" + "0" + ) +endif() add_integration_test( sprintf_size_test_no_sprintf @@ -35,4 +38,3 @@ add_integration_test( COMPILE_OPTIONS -DINTEGRATION_DISABLE_PRINTF ) - diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt index ddc6a5c7f6965..e121555bd60a9 100644 --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -47,6 +47,7 @@ function(add_fp_unittest name) endfunction(add_fp_unittest) add_subdirectory(__support) +add_subdirectory(complex) add_subdirectory(ctype) add_subdirectory(errno) add_subdirectory(fenv) diff --git a/libc/test/src/complex/CImagTest.h b/libc/test/src/complex/CImagTest.h new file mode 100644 index 0000000000000..6d2f935002669 --- /dev/null +++ b/libc/test/src/complex/CImagTest.h @@ -0,0 +1,74 @@ +//===-- Utility class to test different flavors of cimag --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_TEST_SRC_COMPLEX_CIMAGTEST_H +#define LLVM_LIBC_TEST_SRC_COMPLEX_CIMAGTEST_H + +#include "test/UnitTest/FEnvSafeTest.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +#include "hdr/math_macros.h" + +template +class CImagTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { + + DECLARE_SPECIAL_CONSTANTS(FPT) + +public: + typedef FPT (*CImagFunc)(CFPT); + + void testSpecialNumbers(CImagFunc func) { + EXPECT_FP_EQ(func(CFPT(67.123 + aNaN * 1.0i)), aNaN); + EXPECT_FP_EQ(func(CFPT(78.319 + neg_aNaN * 1.0i)), neg_aNaN); + EXPECT_FP_EQ(func(CFPT(7813.131 + sNaN * 1.0i)), sNaN); + EXPECT_FP_EQ(func(CFPT(7824.152 + neg_sNaN * 1.0i)), neg_sNaN); + EXPECT_FP_EQ(func(CFPT(9024.2442 + inf * 1.0i)), inf); + EXPECT_FP_EQ(func(CFPT(8923.124 + neg_inf * 1.0i)), neg_inf); + EXPECT_FP_EQ(func(CFPT(782.124 + min_normal * 1.0i)), min_normal); + EXPECT_FP_EQ(func(CFPT(2141.2352 + max_normal * 1.0i)), max_normal); + EXPECT_FP_EQ(func(CFPT(341.134 + neg_max_normal * 1.0i)), neg_max_normal); + EXPECT_FP_EQ(func(CFPT(781.142 + min_denormal * 1.0i)), min_denormal); + EXPECT_FP_EQ(func(CFPT(781.134 + neg_min_denormal * 1.0i)), + neg_min_denormal); + EXPECT_FP_EQ(func(CFPT(1241.112 + max_denormal * 1.0i)), max_denormal); + EXPECT_FP_EQ(func(CFPT(121.121 + zero * 1.0i)), zero); + EXPECT_FP_EQ(func(CFPT(neg_zero + zero * 1.0i)), zero); + EXPECT_FP_EQ(func(CFPT(neg_zero + neg_zero * 1.0i)), neg_zero); + EXPECT_FP_EQ(func(CFPT(zero + neg_zero * 1.0i)), neg_zero); + } + + void testRoundedNumbers(CImagFunc func) { + EXPECT_FP_EQ(func((CFPT)(4523.1413 + 12413.1414i)), (FPT)(12413.1414)); + EXPECT_FP_EQ(func((CFPT)(-4523.1413 + 12413.1414i)), (FPT)(12413.1414)); + EXPECT_FP_EQ(func((CFPT)(4523.1413 - 12413.1414i)), (FPT)(-12413.1414)); + EXPECT_FP_EQ(func((CFPT)(-4523.1413 - 12413.1414i)), (FPT)(-12413.1414)); + + EXPECT_FP_EQ(func((CFPT)(3210.5678 + 9876.5432i)), (FPT)(9876.5432)); + EXPECT_FP_EQ(func((CFPT)(-3210.5678 + 9876.5432i)), (FPT)(9876.5432)); + EXPECT_FP_EQ(func((CFPT)(3210.5678 - 9876.5432i)), (FPT)(-9876.5432)); + EXPECT_FP_EQ(func((CFPT)(-3210.5678 - 9876.5432i)), (FPT)(-9876.5432)); + + EXPECT_FP_EQ(func((CFPT)(1234.4321 + 4321.1234i)), (FPT)(4321.1234)); + EXPECT_FP_EQ(func((CFPT)(-1234.4321 + 4321.1234i)), (FPT)(4321.1234)); + EXPECT_FP_EQ(func((CFPT)(1234.4321 - 4321.1234i)), (FPT)(-4321.1234)); + EXPECT_FP_EQ(func((CFPT)(-1234.4321 - 4321.1234i)), (FPT)(-4321.1234)); + + EXPECT_FP_EQ(func((CFPT)(6789.1234 + 8765.6789i)), (FPT)(8765.6789)); + EXPECT_FP_EQ(func((CFPT)(-6789.1234 + 8765.6789i)), (FPT)(8765.6789)); + EXPECT_FP_EQ(func((CFPT)(6789.1234 - 8765.6789i)), (FPT)(-8765.6789)); + EXPECT_FP_EQ(func((CFPT)(-6789.1234 - 8765.6789i)), (FPT)(-8765.6789)); + } +}; + +#define LIST_CIMAG_TESTS(U, T, func) \ + using LlvmLibcCImagTest = CImagTest; \ + TEST_F(LlvmLibcCImagTest, SpecialNumbers) { testSpecialNumbers(&func); } \ + TEST_F(LlvmLibcCImagTest, RoundedNumbers) { testRoundedNumbers(&func); } + +#endif // LLVM_LIBC_TEST_SRC_COMPLEX_CIMAGTEST_H diff --git a/libc/test/src/complex/CMakeLists.txt b/libc/test/src/complex/CMakeLists.txt new file mode 100644 index 0000000000000..8f49e6d79e179 --- /dev/null +++ b/libc/test/src/complex/CMakeLists.txt @@ -0,0 +1,121 @@ +add_custom_target(libc-complex-unittests) + +add_libc_test( + creal_test + SUITE + libc-complex-unittests + SRCS + creal_test.cpp + DEPENDS + libc.src.complex.creal + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + crealf_test + SUITE + libc-complex-unittests + SRCS + crealf_test.cpp + DEPENDS + libc.src.complex.crealf + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + creall_test + SUITE + libc-complex-unittests + SRCS + creall_test.cpp + DEPENDS + libc.src.complex.creall + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + crealf16_test + SUITE + libc-complex-unittests + SRCS + crealf16_test.cpp + DEPENDS + libc.src.complex.crealf16 + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + crealf128_test + SUITE + libc-complex-unittests + SRCS + crealf128_test.cpp + DEPENDS + libc.src.complex.crealf128 + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + cimag_test + SUITE + libc-complex-unittests + SRCS + cimag_test.cpp + DEPENDS + libc.src.complex.cimag + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + cimagf_test + SUITE + libc-complex-unittests + SRCS + cimagf_test.cpp + DEPENDS + libc.src.complex.cimagf + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + cimagl_test + SUITE + libc-complex-unittests + SRCS + cimagl_test.cpp + DEPENDS + libc.src.complex.cimagl + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + cimagf16_test + SUITE + libc-complex-unittests + SRCS + cimagf16_test.cpp + DEPENDS + libc.src.complex.cimagf16 + LINK_LIBRARIES + LibcFPTestHelpers +) + +add_libc_test( + cimagf128_test + SUITE + libc-complex-unittests + SRCS + cimagf128_test.cpp + DEPENDS + libc.src.complex.cimagf128 + LINK_LIBRARIES + LibcFPTestHelpers +) diff --git a/libc/test/src/complex/CRealTest.h b/libc/test/src/complex/CRealTest.h new file mode 100644 index 0000000000000..a25555b506e22 --- /dev/null +++ b/libc/test/src/complex/CRealTest.h @@ -0,0 +1,72 @@ +//===-- Utility class to test different flavors of creal --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_TEST_SRC_COMPLEX_CREALTEST_H +#define LLVM_LIBC_TEST_SRC_COMPLEX_CREALTEST_H + +#include "test/UnitTest/FEnvSafeTest.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +#include "hdr/math_macros.h" + +template +class CRealTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { + + DECLARE_SPECIAL_CONSTANTS(FPT) + +public: + typedef FPT (*CRealFunc)(CFPT); + + void testSpecialNumbers(CRealFunc func) { + EXPECT_FP_EQ(func(CFPT(aNaN + 67.123i)), aNaN); + EXPECT_FP_EQ(func(CFPT(neg_aNaN + 78.319i)), neg_aNaN); + EXPECT_FP_EQ(func(CFPT(sNaN + 7813.131i)), sNaN); + EXPECT_FP_EQ(func(CFPT(neg_sNaN + 7824.152i)), neg_sNaN); + EXPECT_FP_EQ(func(CFPT(inf + 9024.2442i)), inf); + EXPECT_FP_EQ(func(CFPT(neg_inf + 8923.124i)), neg_inf); + EXPECT_FP_EQ(func(CFPT(min_normal + 782.124i)), min_normal); + EXPECT_FP_EQ(func(CFPT(max_normal + 2141.2352i)), max_normal); + EXPECT_FP_EQ(func(CFPT(neg_max_normal + 341.134i)), neg_max_normal); + EXPECT_FP_EQ(func(CFPT(min_denormal + 781.142i)), min_denormal); + EXPECT_FP_EQ(func(CFPT(neg_min_denormal + 781.134i)), neg_min_denormal); + EXPECT_FP_EQ(func(CFPT(max_denormal + 1241.112i)), max_denormal); + EXPECT_FP_EQ(func(CFPT(zero + 121.121i)), zero); + EXPECT_FP_EQ(func(CFPT(neg_zero + neg_zero * 1.0i)), neg_zero); + EXPECT_FP_EQ(func(CFPT(neg_zero + zero * 1.0i)), zero); + } + + void testRoundedNumbers(CRealFunc func) { + EXPECT_FP_EQ(func((CFPT)(4523.1413 + 12413.1414i)), (FPT)(4523.1413)); + EXPECT_FP_EQ(func((CFPT)(-4523.1413 + 12413.1414i)), (FPT)(-4523.1413)); + EXPECT_FP_EQ(func((CFPT)(4523.1413 - 12413.1414i)), (FPT)(4523.1413)); + EXPECT_FP_EQ(func((CFPT)(-4523.1413 - 12413.1414i)), (FPT)(-4523.1413)); + + EXPECT_FP_EQ(func((CFPT)(3210.5678 + 9876.5432i)), (FPT)(3210.5678)); + EXPECT_FP_EQ(func((CFPT)(-3210.5678 + 9876.5432i)), (FPT)(-3210.5678)); + EXPECT_FP_EQ(func((CFPT)(3210.5678 - 9876.5432i)), (FPT)(3210.5678)); + EXPECT_FP_EQ(func((CFPT)(-3210.5678 - 9876.5432i)), (FPT)(-3210.5678)); + + EXPECT_FP_EQ(func((CFPT)(1234.4321 + 4321.1234i)), (FPT)(1234.4321)); + EXPECT_FP_EQ(func((CFPT)(-1234.4321 + 4321.1234i)), (FPT)(-1234.4321)); + EXPECT_FP_EQ(func((CFPT)(1234.4321 - 4321.1234i)), (FPT)(1234.4321)); + EXPECT_FP_EQ(func((CFPT)(-1234.4321 - 4321.1234i)), (FPT)(-1234.4321)); + + EXPECT_FP_EQ(func((CFPT)(6789.1234 + 8765.6789i)), (FPT)(6789.1234)); + EXPECT_FP_EQ(func((CFPT)(-6789.1234 + 8765.6789i)), (FPT)(-6789.1234)); + EXPECT_FP_EQ(func((CFPT)(6789.1234 - 8765.6789i)), (FPT)(6789.1234)); + EXPECT_FP_EQ(func((CFPT)(-6789.1234 - 8765.6789i)), (FPT)(-6789.1234)); + } +}; + +#define LIST_CREAL_TESTS(U, T, func) \ + using LlvmLibcCRealTest = CRealTest; \ + TEST_F(LlvmLibcCRealTest, SpecialNumbers) { testSpecialNumbers(&func); } \ + TEST_F(LlvmLibcCRealTest, RoundedNumbers) { testRoundedNumbers(&func); } + +#endif // LLVM_LIBC_TEST_SRC_COMPLEX_CREALTEST_H diff --git a/libc/test/src/complex/cimag_test.cpp b/libc/test/src/complex/cimag_test.cpp new file mode 100644 index 0000000000000..706f54422b3cf --- /dev/null +++ b/libc/test/src/complex/cimag_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for cimag -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CImagTest.h" + +#include "src/complex/cimag.h" + +LIST_CIMAG_TESTS(_Complex double, double, LIBC_NAMESPACE::cimag) diff --git a/libc/test/src/complex/cimagf128_test.cpp b/libc/test/src/complex/cimagf128_test.cpp new file mode 100644 index 0000000000000..50ddc0ab06166 --- /dev/null +++ b/libc/test/src/complex/cimagf128_test.cpp @@ -0,0 +1,17 @@ +//===-- Unittests for cimagf128 -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CImagTest.h" + +#include "src/complex/cimagf128.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT128) + +LIST_CIMAG_TESTS(cfloat128, float128, LIBC_NAMESPACE::cimagf128) + +#endif // LIBC_TYPES_HAS_CFLOAT128 diff --git a/libc/test/src/complex/cimagf16_test.cpp b/libc/test/src/complex/cimagf16_test.cpp new file mode 100644 index 0000000000000..65a69787ddbd6 --- /dev/null +++ b/libc/test/src/complex/cimagf16_test.cpp @@ -0,0 +1,17 @@ +//===-- Unittests for cimagf16 --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CImagTest.h" + +#include "src/complex/cimagf16.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT16) + +LIST_CIMAG_TESTS(cfloat16, float16, LIBC_NAMESPACE::cimagf16) + +#endif // LIBC_TYPES_HAS_CFLOAT16 diff --git a/libc/test/src/complex/cimagf_test.cpp b/libc/test/src/complex/cimagf_test.cpp new file mode 100644 index 0000000000000..abc9225031e13 --- /dev/null +++ b/libc/test/src/complex/cimagf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for cimagf ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CImagTest.h" + +#include "src/complex/cimagf.h" + +LIST_CIMAG_TESTS(_Complex float, float, LIBC_NAMESPACE::cimagf) diff --git a/libc/test/src/complex/cimagl_test.cpp b/libc/test/src/complex/cimagl_test.cpp new file mode 100644 index 0000000000000..156e4c6bc852d --- /dev/null +++ b/libc/test/src/complex/cimagl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for cimagl ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CImagTest.h" + +#include "src/complex/cimagl.h" + +LIST_CIMAG_TESTS(_Complex long double, long double, LIBC_NAMESPACE::cimagl) diff --git a/libc/test/src/complex/creal_test.cpp b/libc/test/src/complex/creal_test.cpp new file mode 100644 index 0000000000000..14dc550932d7d --- /dev/null +++ b/libc/test/src/complex/creal_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for creal -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CRealTest.h" + +#include "src/complex/creal.h" + +LIST_CREAL_TESTS(_Complex double, double, LIBC_NAMESPACE::creal) diff --git a/libc/test/src/complex/crealf128_test.cpp b/libc/test/src/complex/crealf128_test.cpp new file mode 100644 index 0000000000000..7626eeebca278 --- /dev/null +++ b/libc/test/src/complex/crealf128_test.cpp @@ -0,0 +1,17 @@ +//===-- Unittests for crealf128 -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CRealTest.h" + +#include "src/complex/crealf128.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT128) + +LIST_CREAL_TESTS(cfloat128, float128, LIBC_NAMESPACE::crealf128) + +#endif // LIBC_TYPES_HAS_CFLOAT128 diff --git a/libc/test/src/complex/crealf16_test.cpp b/libc/test/src/complex/crealf16_test.cpp new file mode 100644 index 0000000000000..97346aad615f7 --- /dev/null +++ b/libc/test/src/complex/crealf16_test.cpp @@ -0,0 +1,17 @@ +//===-- Unittests for crealf16 --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CRealTest.h" + +#include "src/complex/crealf16.h" + +#if defined(LIBC_TYPES_HAS_CFLOAT16) + +LIST_CREAL_TESTS(cfloat16, float16, LIBC_NAMESPACE::crealf16) + +#endif // LIBC_TYPES_HAS_CFLOAT16 diff --git a/libc/test/src/complex/crealf_test.cpp b/libc/test/src/complex/crealf_test.cpp new file mode 100644 index 0000000000000..aa54f54793e2a --- /dev/null +++ b/libc/test/src/complex/crealf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for crealf ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CRealTest.h" + +#include "src/complex/crealf.h" + +LIST_CREAL_TESTS(_Complex float, float, LIBC_NAMESPACE::crealf) diff --git a/libc/test/src/complex/creall_test.cpp b/libc/test/src/complex/creall_test.cpp new file mode 100644 index 0000000000000..6985dbc2590a7 --- /dev/null +++ b/libc/test/src/complex/creall_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for creall ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CRealTest.h" + +#include "src/complex/creall.h" + +LIST_CREAL_TESTS(_Complex long double, long double, LIBC_NAMESPACE::creall) diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt index 2683eefd032b7..4ea894cf48724 100644 --- a/libc/test/src/stdlib/CMakeLists.txt +++ b/libc/test/src/stdlib/CMakeLists.txt @@ -382,7 +382,7 @@ if(LLVM_LIBC_FULL_BUILD) SRCS atexit_test.cpp DEPENDS - libc.include.stdlib + libc.hdr.func._Exit libc.src.stdlib._Exit libc.src.stdlib.exit libc.src.stdlib.atexit @@ -398,6 +398,7 @@ if(LLVM_LIBC_FULL_BUILD) SRCS at_quick_exit_test.cpp DEPENDS + libc.hdr.func._Exit libc.src.stdlib.quick_exit libc.src.stdlib.at_quick_exit libc.src.__support.CPP.array diff --git a/libc/test/src/stdlib/at_quick_exit_test.cpp b/libc/test/src/stdlib/at_quick_exit_test.cpp index e0a258d9fb2d9..8049fe58d29bd 100644 --- a/libc/test/src/stdlib/at_quick_exit_test.cpp +++ b/libc/test/src/stdlib/at_quick_exit_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "hdr/func/_Exit.h" #include "src/__support/CPP/array.h" #include "src/__support/CPP/utility.h" #include "src/stdlib/at_quick_exit.h" diff --git a/libc/test/src/stdlib/atexit_test.cpp b/libc/test/src/stdlib/atexit_test.cpp index 8a785ccb8cce2..9e19423f73086 100644 --- a/libc/test/src/stdlib/atexit_test.cpp +++ b/libc/test/src/stdlib/atexit_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "hdr/func/_Exit.h" #include "src/__support/CPP/array.h" #include "src/__support/CPP/utility.h" #include "src/stdlib/atexit.h" diff --git a/libclc/amdgcn/lib/integer/popcount.cl b/libclc/amdgcn/lib/integer/popcount.cl index ebd167d04da7c..3b493fbd146f0 100644 --- a/libclc/amdgcn/lib/integer/popcount.cl +++ b/libclc/amdgcn/lib/integer/popcount.cl @@ -1,5 +1,5 @@ #include -#include +#include #include #define __CLC_BODY "popcount.inc" diff --git a/libclc/amdgcn/lib/math/fmax.cl b/libclc/amdgcn/lib/math/fmax.cl index cb79616101082..4407d4a87f9ea 100644 --- a/libclc/amdgcn/lib/math/fmax.cl +++ b/libclc/amdgcn/lib/math/fmax.cl @@ -1,6 +1,5 @@ #include - -#include "../../../generic/lib/clcmacro.h" +#include _CLC_DEF _CLC_OVERLOAD float fmax(float x, float y) { diff --git a/libclc/amdgcn/lib/math/fmin.cl b/libclc/amdgcn/lib/math/fmin.cl index 35dea8bc975f7..4d02a47babdab 100644 --- a/libclc/amdgcn/lib/math/fmin.cl +++ b/libclc/amdgcn/lib/math/fmin.cl @@ -1,6 +1,5 @@ #include - -#include "../../../generic/lib/clcmacro.h" +#include _CLC_DEF _CLC_OVERLOAD float fmin(float x, float y) { diff --git a/libclc/amdgcn/lib/math/ldexp.cl b/libclc/amdgcn/lib/math/ldexp.cl index 9713e4daee0e7..d46d2dc606818 100644 --- a/libclc/amdgcn/lib/math/ldexp.cl +++ b/libclc/amdgcn/lib/math/ldexp.cl @@ -21,8 +21,7 @@ */ #include - -#include "../../../generic/lib/clcmacro.h" +#include #ifdef __HAS_LDEXPF__ #define BUILTINF __builtin_amdgcn_ldexpf diff --git a/libclc/amdgpu/lib/math/half_native_unary.inc b/libclc/amdgpu/lib/math/half_native_unary.inc index 0f99ba5e52163..bdc380600501a 100644 --- a/libclc/amdgpu/lib/math/half_native_unary.inc +++ b/libclc/amdgpu/lib/math/half_native_unary.inc @@ -1,4 +1,4 @@ -#include +#include #define __CLC_HALF_FUNC(x) __CLC_CONCAT(half_, x) #define __CLC_NATIVE_FUNC(x) __CLC_CONCAT(native_, x) diff --git a/libclc/amdgpu/lib/math/nextafter.cl b/libclc/amdgpu/lib/math/nextafter.cl index b290da0e417dd..6dc117b8cdd64 100644 --- a/libclc/amdgpu/lib/math/nextafter.cl +++ b/libclc/amdgpu/lib/math/nextafter.cl @@ -1,5 +1,5 @@ #include -#include "../lib/clcmacro.h" +#include #include _CLC_DEFINE_BINARY_BUILTIN(float, nextafter, __clc_nextafter, float, float) diff --git a/libclc/amdgpu/lib/math/sqrt.cl b/libclc/amdgpu/lib/math/sqrt.cl index 556260033169b..17d77e50d44d3 100644 --- a/libclc/amdgpu/lib/math/sqrt.cl +++ b/libclc/amdgpu/lib/math/sqrt.cl @@ -20,9 +20,9 @@ * THE SOFTWARE. */ -#include -#include "../../../generic/lib/clcmacro.h" #include "math/clc_sqrt.h" +#include +#include _CLC_DEFINE_UNARY_BUILTIN(float, sqrt, __clc_sqrt, float) diff --git a/libclc/generic/lib/clcmacro.h b/libclc/clc/include/clc/clcmacro.h similarity index 55% rename from libclc/generic/lib/clcmacro.h rename to libclc/clc/include/clc/clcmacro.h index f655368967c9e..244239284ecab 100644 --- a/libclc/generic/lib/clcmacro.h +++ b/libclc/clc/include/clc/clcmacro.h @@ -1,91 +1,105 @@ -#include - -#define _CLC_UNARY_VECTORIZE(DECLSPEC, RET_TYPE, FUNCTION, ARG1_TYPE) \ - DECLSPEC RET_TYPE##2 FUNCTION(ARG1_TYPE##2 x) { \ - return (RET_TYPE##2)(FUNCTION(x.x), FUNCTION(x.y)); \ - } \ -\ - DECLSPEC RET_TYPE##3 FUNCTION(ARG1_TYPE##3 x) { \ - return (RET_TYPE##3)(FUNCTION(x.x), FUNCTION(x.y), FUNCTION(x.z)); \ - } \ -\ - DECLSPEC RET_TYPE##4 FUNCTION(ARG1_TYPE##4 x) { \ - return (RET_TYPE##4)(FUNCTION(x.lo), FUNCTION(x.hi)); \ - } \ -\ - DECLSPEC RET_TYPE##8 FUNCTION(ARG1_TYPE##8 x) { \ - return (RET_TYPE##8)(FUNCTION(x.lo), FUNCTION(x.hi)); \ - } \ -\ - DECLSPEC RET_TYPE##16 FUNCTION(ARG1_TYPE##16 x) { \ - return (RET_TYPE##16)(FUNCTION(x.lo), FUNCTION(x.hi)); \ +#ifndef __CLC_CLCMACRO_H__ +#define __CLC_CLCMACRO_H__ + +#include +#include + +#define _CLC_UNARY_VECTORIZE(DECLSPEC, RET_TYPE, FUNCTION, ARG1_TYPE) \ + DECLSPEC RET_TYPE##2 FUNCTION(ARG1_TYPE##2 x) { \ + return (RET_TYPE##2)(FUNCTION(x.x), FUNCTION(x.y)); \ + } \ + \ + DECLSPEC RET_TYPE##3 FUNCTION(ARG1_TYPE##3 x) { \ + return (RET_TYPE##3)(FUNCTION(x.x), FUNCTION(x.y), FUNCTION(x.z)); \ + } \ + \ + DECLSPEC RET_TYPE##4 FUNCTION(ARG1_TYPE##4 x) { \ + return (RET_TYPE##4)(FUNCTION(x.lo), FUNCTION(x.hi)); \ + } \ + \ + DECLSPEC RET_TYPE##8 FUNCTION(ARG1_TYPE##8 x) { \ + return (RET_TYPE##8)(FUNCTION(x.lo), FUNCTION(x.hi)); \ + } \ + \ + DECLSPEC RET_TYPE##16 FUNCTION(ARG1_TYPE##16 x) { \ + return (RET_TYPE##16)(FUNCTION(x.lo), FUNCTION(x.hi)); \ } -#define _CLC_BINARY_VECTORIZE(DECLSPEC, RET_TYPE, FUNCTION, ARG1_TYPE, ARG2_TYPE) \ - DECLSPEC RET_TYPE##2 FUNCTION(ARG1_TYPE##2 x, ARG2_TYPE##2 y) { \ - return (RET_TYPE##2)(FUNCTION(x.x, y.x), FUNCTION(x.y, y.y)); \ - } \ -\ - DECLSPEC RET_TYPE##3 FUNCTION(ARG1_TYPE##3 x, ARG2_TYPE##3 y) { \ - return (RET_TYPE##3)(FUNCTION(x.x, y.x), FUNCTION(x.y, y.y), \ - FUNCTION(x.z, y.z)); \ - } \ -\ - DECLSPEC RET_TYPE##4 FUNCTION(ARG1_TYPE##4 x, ARG2_TYPE##4 y) { \ - return (RET_TYPE##4)(FUNCTION(x.lo, y.lo), FUNCTION(x.hi, y.hi)); \ - } \ -\ - DECLSPEC RET_TYPE##8 FUNCTION(ARG1_TYPE##8 x, ARG2_TYPE##8 y) { \ - return (RET_TYPE##8)(FUNCTION(x.lo, y.lo), FUNCTION(x.hi, y.hi)); \ - } \ -\ - DECLSPEC RET_TYPE##16 FUNCTION(ARG1_TYPE##16 x, ARG2_TYPE##16 y) { \ - return (RET_TYPE##16)(FUNCTION(x.lo, y.lo), FUNCTION(x.hi, y.hi)); \ +#define _CLC_BINARY_VECTORIZE(DECLSPEC, RET_TYPE, FUNCTION, ARG1_TYPE, \ + ARG2_TYPE) \ + DECLSPEC RET_TYPE##2 FUNCTION(ARG1_TYPE##2 x, ARG2_TYPE##2 y) { \ + return (RET_TYPE##2)(FUNCTION(x.x, y.x), FUNCTION(x.y, y.y)); \ + } \ + \ + DECLSPEC RET_TYPE##3 FUNCTION(ARG1_TYPE##3 x, ARG2_TYPE##3 y) { \ + return (RET_TYPE##3)(FUNCTION(x.x, y.x), FUNCTION(x.y, y.y), \ + FUNCTION(x.z, y.z)); \ + } \ + \ + DECLSPEC RET_TYPE##4 FUNCTION(ARG1_TYPE##4 x, ARG2_TYPE##4 y) { \ + return (RET_TYPE##4)(FUNCTION(x.lo, y.lo), FUNCTION(x.hi, y.hi)); \ + } \ + \ + DECLSPEC RET_TYPE##8 FUNCTION(ARG1_TYPE##8 x, ARG2_TYPE##8 y) { \ + return (RET_TYPE##8)(FUNCTION(x.lo, y.lo), FUNCTION(x.hi, y.hi)); \ + } \ + \ + DECLSPEC RET_TYPE##16 FUNCTION(ARG1_TYPE##16 x, ARG2_TYPE##16 y) { \ + return (RET_TYPE##16)(FUNCTION(x.lo, y.lo), FUNCTION(x.hi, y.hi)); \ } -#define _CLC_V_S_V_VECTORIZE(DECLSPEC, RET_TYPE, FUNCTION, ARG1_TYPE, ARG2_TYPE) \ - DECLSPEC RET_TYPE##2 FUNCTION(ARG1_TYPE x, ARG2_TYPE##2 y) { \ - return (RET_TYPE##2)(FUNCTION(x, y.lo), FUNCTION(x, y.hi)); \ - } \ -\ - DECLSPEC RET_TYPE##3 FUNCTION(ARG1_TYPE x, ARG2_TYPE##3 y) { \ - return (RET_TYPE##3)(FUNCTION(x, y.x), FUNCTION(x, y.y), \ - FUNCTION(x, y.z)); \ - } \ -\ - DECLSPEC RET_TYPE##4 FUNCTION(ARG1_TYPE x, ARG2_TYPE##4 y) { \ - return (RET_TYPE##4)(FUNCTION(x, y.lo), FUNCTION(x, y.hi)); \ - } \ -\ - DECLSPEC RET_TYPE##8 FUNCTION(ARG1_TYPE x, ARG2_TYPE##8 y) { \ - return (RET_TYPE##8)(FUNCTION(x, y.lo), FUNCTION(x, y.hi)); \ - } \ -\ - DECLSPEC RET_TYPE##16 FUNCTION(ARG1_TYPE x, ARG2_TYPE##16 y) { \ - return (RET_TYPE##16)(FUNCTION(x, y.lo), FUNCTION(x, y.hi)); \ - } \ -\ - -#define _CLC_TERNARY_VECTORIZE(DECLSPEC, RET_TYPE, FUNCTION, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ - DECLSPEC RET_TYPE##2 FUNCTION(ARG1_TYPE##2 x, ARG2_TYPE##2 y, ARG3_TYPE##2 z) { \ - return (RET_TYPE##2)(FUNCTION(x.x, y.x, z.x), FUNCTION(x.y, y.y, z.y)); \ - } \ -\ - DECLSPEC RET_TYPE##3 FUNCTION(ARG1_TYPE##3 x, ARG2_TYPE##3 y, ARG3_TYPE##3 z) { \ - return (RET_TYPE##3)(FUNCTION(x.x, y.x, z.x), FUNCTION(x.y, y.y, z.y), \ - FUNCTION(x.z, y.z, z.z)); \ - } \ -\ - DECLSPEC RET_TYPE##4 FUNCTION(ARG1_TYPE##4 x, ARG2_TYPE##4 y, ARG3_TYPE##4 z) { \ - return (RET_TYPE##4)(FUNCTION(x.lo, y.lo, z.lo), FUNCTION(x.hi, y.hi, z.hi)); \ - } \ -\ - DECLSPEC RET_TYPE##8 FUNCTION(ARG1_TYPE##8 x, ARG2_TYPE##8 y, ARG3_TYPE##8 z) { \ - return (RET_TYPE##8)(FUNCTION(x.lo, y.lo, z.lo), FUNCTION(x.hi, y.hi, z.hi)); \ - } \ -\ - DECLSPEC RET_TYPE##16 FUNCTION(ARG1_TYPE##16 x, ARG2_TYPE##16 y, ARG3_TYPE##16 z) { \ - return (RET_TYPE##16)(FUNCTION(x.lo, y.lo, z.lo), FUNCTION(x.hi, y.hi, z.hi)); \ +#define _CLC_V_S_V_VECTORIZE(DECLSPEC, RET_TYPE, FUNCTION, ARG1_TYPE, \ + ARG2_TYPE) \ + DECLSPEC RET_TYPE##2 FUNCTION(ARG1_TYPE x, ARG2_TYPE##2 y) { \ + return (RET_TYPE##2)(FUNCTION(x, y.lo), FUNCTION(x, y.hi)); \ + } \ + \ + DECLSPEC RET_TYPE##3 FUNCTION(ARG1_TYPE x, ARG2_TYPE##3 y) { \ + return (RET_TYPE##3)(FUNCTION(x, y.x), FUNCTION(x, y.y), \ + FUNCTION(x, y.z)); \ + } \ + \ + DECLSPEC RET_TYPE##4 FUNCTION(ARG1_TYPE x, ARG2_TYPE##4 y) { \ + return (RET_TYPE##4)(FUNCTION(x, y.lo), FUNCTION(x, y.hi)); \ + } \ + \ + DECLSPEC RET_TYPE##8 FUNCTION(ARG1_TYPE x, ARG2_TYPE##8 y) { \ + return (RET_TYPE##8)(FUNCTION(x, y.lo), FUNCTION(x, y.hi)); \ + } \ + \ + DECLSPEC RET_TYPE##16 FUNCTION(ARG1_TYPE x, ARG2_TYPE##16 y) { \ + return (RET_TYPE##16)(FUNCTION(x, y.lo), FUNCTION(x, y.hi)); \ + } + +#define _CLC_TERNARY_VECTORIZE(DECLSPEC, RET_TYPE, FUNCTION, ARG1_TYPE, \ + ARG2_TYPE, ARG3_TYPE) \ + DECLSPEC RET_TYPE##2 FUNCTION(ARG1_TYPE##2 x, ARG2_TYPE##2 y, \ + ARG3_TYPE##2 z) { \ + return (RET_TYPE##2)(FUNCTION(x.x, y.x, z.x), FUNCTION(x.y, y.y, z.y)); \ + } \ + \ + DECLSPEC RET_TYPE##3 FUNCTION(ARG1_TYPE##3 x, ARG2_TYPE##3 y, \ + ARG3_TYPE##3 z) { \ + return (RET_TYPE##3)(FUNCTION(x.x, y.x, z.x), FUNCTION(x.y, y.y, z.y), \ + FUNCTION(x.z, y.z, z.z)); \ + } \ + \ + DECLSPEC RET_TYPE##4 FUNCTION(ARG1_TYPE##4 x, ARG2_TYPE##4 y, \ + ARG3_TYPE##4 z) { \ + return (RET_TYPE##4)(FUNCTION(x.lo, y.lo, z.lo), \ + FUNCTION(x.hi, y.hi, z.hi)); \ + } \ + \ + DECLSPEC RET_TYPE##8 FUNCTION(ARG1_TYPE##8 x, ARG2_TYPE##8 y, \ + ARG3_TYPE##8 z) { \ + return (RET_TYPE##8)(FUNCTION(x.lo, y.lo, z.lo), \ + FUNCTION(x.hi, y.hi, z.hi)); \ + } \ + \ + DECLSPEC RET_TYPE##16 FUNCTION(ARG1_TYPE##16 x, ARG2_TYPE##16 y, \ + ARG3_TYPE##16 z) { \ + return (RET_TYPE##16)(FUNCTION(x.lo, y.lo, z.lo), \ + FUNCTION(x.hi, y.hi, z.hi)); \ } #define _CLC_V_S_S_V_VECTORIZE(DECLSPEC, RET_TYPE, FUNCTION, ARG1_TYPE, \ @@ -160,21 +174,24 @@ ARG2_TYPE, 8) *)((ADDR_SPACE ARG2_TYPE *)y + 8))); \ } -#define _CLC_DEFINE_BINARY_BUILTIN(RET_TYPE, FUNCTION, BUILTIN, ARG1_TYPE, ARG2_TYPE) \ -_CLC_DEF _CLC_OVERLOAD RET_TYPE FUNCTION(ARG1_TYPE x, ARG2_TYPE y) { \ - return BUILTIN(x, y); \ -} \ -_CLC_BINARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, RET_TYPE, FUNCTION, ARG1_TYPE, ARG2_TYPE) +#define _CLC_DEFINE_BINARY_BUILTIN(RET_TYPE, FUNCTION, BUILTIN, ARG1_TYPE, \ + ARG2_TYPE) \ + _CLC_DEF _CLC_OVERLOAD RET_TYPE FUNCTION(ARG1_TYPE x, ARG2_TYPE y) { \ + return BUILTIN(x, y); \ + } \ + _CLC_BINARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, RET_TYPE, FUNCTION, ARG1_TYPE, \ + ARG2_TYPE) -#define _CLC_DEFINE_BINARY_BUILTIN_WITH_SCALAR_SECOND_ARG(RET_TYPE, FUNCTION, BUILTIN, ARG1_TYPE, ARG2_TYPE) \ -_CLC_DEFINE_BINARY_BUILTIN(RET_TYPE, FUNCTION, BUILTIN, ARG1_TYPE, ARG2_TYPE) \ -_CLC_BINARY_VECTORIZE_SCALAR_SECOND_ARG(_CLC_OVERLOAD _CLC_DEF, RET_TYPE, FUNCTION, ARG1_TYPE, ARG2_TYPE) +#define _CLC_DEFINE_BINARY_BUILTIN_WITH_SCALAR_SECOND_ARG( \ + RET_TYPE, FUNCTION, BUILTIN, ARG1_TYPE, ARG2_TYPE) \ + _CLC_DEFINE_BINARY_BUILTIN(RET_TYPE, FUNCTION, BUILTIN, ARG1_TYPE, \ + ARG2_TYPE) \ + _CLC_BINARY_VECTORIZE_SCALAR_SECOND_ARG(_CLC_OVERLOAD _CLC_DEF, RET_TYPE, \ + FUNCTION, ARG1_TYPE, ARG2_TYPE) -#define _CLC_DEFINE_UNARY_BUILTIN(RET_TYPE, FUNCTION, BUILTIN, ARG1_TYPE) \ -_CLC_DEF _CLC_OVERLOAD RET_TYPE FUNCTION(ARG1_TYPE x) { \ - return BUILTIN(x); \ -} \ -_CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, RET_TYPE, FUNCTION, ARG1_TYPE) +#define _CLC_DEFINE_UNARY_BUILTIN(RET_TYPE, FUNCTION, BUILTIN, ARG1_TYPE) \ + _CLC_DEF _CLC_OVERLOAD RET_TYPE FUNCTION(ARG1_TYPE x) { return BUILTIN(x); } \ + _CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, RET_TYPE, FUNCTION, ARG1_TYPE) #ifdef cl_khr_fp16 @@ -198,3 +215,5 @@ _CLC_UNARY_VECTORIZE(_CLC_OVERLOAD _CLC_DEF, RET_TYPE, FUNCTION, ARG1_TYPE) #define _CLC_DEFINE_BINARY_BUILTIN_FP16(FUNCTION) #endif + +#endif // __CLC_CLCMACRO_H__ diff --git a/libclc/clc/include/clc/math/clc_ceil.h b/libclc/clc/include/clc/math/clc_ceil.h new file mode 100644 index 0000000000000..66590687c3422 --- /dev/null +++ b/libclc/clc/include/clc/math/clc_ceil.h @@ -0,0 +1,19 @@ +#ifndef __CLC_MATH_CLC_CEIL_H__ +#define __CLC_MATH_CLC_CEIL_H__ + +#if defined(CLC_CLSPV) || defined(CLC_SPIRV) +// clspv and spir-v targets provide their own OpenCL-compatible ceil +#define __clc_ceil ceil +#else + +// Map the function to an LLVM intrinsic +#define __CLC_FUNCTION __clc_ceil +#define __CLC_INTRINSIC "llvm.ceil" +#include + +#undef __CLC_INTRINSIC +#undef __CLC_FUNCTION + +#endif + +#endif // __CLC_MATH_CLC_CEIL_H__ diff --git a/libclc/clc/include/clc/math/clc_fabs.h b/libclc/clc/include/clc/math/clc_fabs.h new file mode 100644 index 0000000000000..93367b5731371 --- /dev/null +++ b/libclc/clc/include/clc/math/clc_fabs.h @@ -0,0 +1,19 @@ +#ifndef __CLC_MATH_CLC_FABS_H__ +#define __CLC_MATH_CLC_FABS_H__ + +#if defined(CLC_CLSPV) || defined(CLC_SPIRV) +// clspv and spir-v targets provide their own OpenCL-compatible fabs +#define __clc_fabs fabs +#else + +// Map the function to an LLVM intrinsic +#define __CLC_FUNCTION __clc_fabs +#define __CLC_INTRINSIC "llvm.fabs" +#include + +#undef __CLC_INTRINSIC +#undef __CLC_FUNCTION + +#endif + +#endif // __CLC_MATH_CLC_FABS_H__ diff --git a/libclc/clc/include/clc/math/clc_floor.h b/libclc/clc/include/clc/math/clc_floor.h new file mode 100644 index 0000000000000..9919872ec633c --- /dev/null +++ b/libclc/clc/include/clc/math/clc_floor.h @@ -0,0 +1,19 @@ +#ifndef __CLC_MATH_CLC_FLOOR_H__ +#define __CLC_MATH_CLC_FLOOR_H__ + +#if defined(CLC_CLSPV) || defined(CLC_SPIRV) +// clspv and spir-v targets provide their own OpenCL-compatible floor +#define __clc_floor floor +#else + +// Map the function to an LLVM intrinsic +#define __CLC_FUNCTION __clc_floor +#define __CLC_INTRINSIC "llvm.floor" +#include + +#undef __CLC_INTRINSIC +#undef __CLC_FUNCTION + +#endif + +#endif // __CLC_MATH_CLC_FLOOR_H__ diff --git a/libclc/clc/include/clc/math/clc_rint.h b/libclc/clc/include/clc/math/clc_rint.h new file mode 100644 index 0000000000000..3761407ad326d --- /dev/null +++ b/libclc/clc/include/clc/math/clc_rint.h @@ -0,0 +1,19 @@ +#ifndef __CLC_MATH_CLC_RINT_H__ +#define __CLC_MATH_CLC_RINT_H__ + +#if defined(CLC_CLSPV) || defined(CLC_SPIRV) +// clspv and spir-v targets provide their own OpenCL-compatible rint +#define __clc_rint rint +#else + +// Map the function to an LLVM intrinsic +#define __CLC_FUNCTION __clc_rint +#define __CLC_INTRINSIC "llvm.rint" +#include + +#undef __CLC_INTRINSIC +#undef __CLC_FUNCTION + +#endif + +#endif // __CLC_MATH_CLC_RINT_H__ diff --git a/libclc/clc/include/clc/math/clc_trunc.h b/libclc/clc/include/clc/math/clc_trunc.h new file mode 100644 index 0000000000000..c78c8899d8523 --- /dev/null +++ b/libclc/clc/include/clc/math/clc_trunc.h @@ -0,0 +1,19 @@ +#ifndef __CLC_MATH_CLC_TRUNC_H__ +#define __CLC_MATH_CLC_TRUNC_H__ + +#if defined(CLC_CLSPV) || defined(CLC_SPIRV) +// clspv and spir-v targets provide their own OpenCL-compatible trunc +#define __clc_trunc trunc +#else + +// Map the function to an LLVM intrinsic +#define __CLC_FUNCTION __clc_trunc +#define __CLC_INTRINSIC "llvm.trunc" +#include + +#undef __CLC_INTRINSIC +#undef __CLC_FUNCTION + +#endif + +#endif // __CLC_MATH_CLC_TRUNC_H__ diff --git a/libclc/generic/include/clc/math/unary_decl.inc b/libclc/clc/include/clc/math/unary_decl.inc similarity index 100% rename from libclc/generic/include/clc/math/unary_decl.inc rename to libclc/clc/include/clc/math/unary_decl.inc diff --git a/libclc/generic/include/math/unary_intrin.inc b/libclc/clc/include/clc/math/unary_intrin.inc similarity index 88% rename from libclc/generic/include/math/unary_intrin.inc rename to libclc/clc/include/clc/math/unary_intrin.inc index 532bb1f9d2615..c331d3ff08a61 100644 --- a/libclc/generic/include/math/unary_intrin.inc +++ b/libclc/clc/include/clc/math/unary_intrin.inc @@ -3,7 +3,8 @@ _CLC_OVERLOAD float2 __CLC_FUNCTION(float2 f) __asm(__CLC_INTRINSIC ".v2f32"); _CLC_OVERLOAD float3 __CLC_FUNCTION(float3 f) __asm(__CLC_INTRINSIC ".v3f32"); _CLC_OVERLOAD float4 __CLC_FUNCTION(float4 f) __asm(__CLC_INTRINSIC ".v4f32"); _CLC_OVERLOAD float8 __CLC_FUNCTION(float8 f) __asm(__CLC_INTRINSIC ".v8f32"); -_CLC_OVERLOAD float16 __CLC_FUNCTION(float16 f) __asm(__CLC_INTRINSIC ".v16f32"); +_CLC_OVERLOAD float16 __CLC_FUNCTION(float16 f) __asm(__CLC_INTRINSIC + ".v16f32"); #ifdef cl_khr_fp64 #pragma OPENCL EXTENSION cl_khr_fp64 : enable @@ -12,11 +13,12 @@ _CLC_OVERLOAD double2 __CLC_FUNCTION(double2 d) __asm(__CLC_INTRINSIC ".v2f64"); _CLC_OVERLOAD double3 __CLC_FUNCTION(double3 d) __asm(__CLC_INTRINSIC ".v3f64"); _CLC_OVERLOAD double4 __CLC_FUNCTION(double4 d) __asm(__CLC_INTRINSIC ".v4f64"); _CLC_OVERLOAD double8 __CLC_FUNCTION(double8 d) __asm(__CLC_INTRINSIC ".v8f64"); -_CLC_OVERLOAD double16 __CLC_FUNCTION(double16 d) __asm(__CLC_INTRINSIC ".v16f64"); +_CLC_OVERLOAD double16 __CLC_FUNCTION(double16 d) __asm(__CLC_INTRINSIC + ".v16f64"); #endif #ifdef cl_khr_fp16 -#pragma OPENCL EXTENSION cl_khr_fp16: enable +#pragma OPENCL EXTENSION cl_khr_fp16 : enable _CLC_OVERLOAD half __CLC_FUNCTION(half d) __asm(__CLC_INTRINSIC ".f16"); _CLC_OVERLOAD half2 __CLC_FUNCTION(half2 d) __asm(__CLC_INTRINSIC ".v2f16"); _CLC_OVERLOAD half3 __CLC_FUNCTION(half3 d) __asm(__CLC_INTRINSIC ".v3f16"); diff --git a/libclc/generic/include/utils.h b/libclc/clc/include/clc/utils.h similarity index 50% rename from libclc/generic/include/utils.h rename to libclc/clc/include/clc/utils.h index 018a7b31f8ff3..b53b6a39c615c 100644 --- a/libclc/generic/include/utils.h +++ b/libclc/clc/include/clc/utils.h @@ -1,10 +1,10 @@ -#ifndef __CLC_UTILS_H_ -#define __CLC_UTILS_H_ +#ifndef __CLC_UTILS_H__ +#define __CLC_UTILS_H__ -#define __CLC_CONCAT(x, y) x ## y +#define __CLC_CONCAT(x, y) x##y #define __CLC_XCONCAT(x, y) __CLC_CONCAT(x, y) #define __CLC_STR(x) #x #define __CLC_XSTR(x) __CLC_STR(x) -#endif +#endif // __CLC_UTILS_H__ diff --git a/libclc/clspv/lib/math/fma.cl b/libclc/clspv/lib/math/fma.cl index 3ffca28bd3bef..e6251db4e92db 100644 --- a/libclc/clspv/lib/math/fma.cl +++ b/libclc/clspv/lib/math/fma.cl @@ -24,9 +24,9 @@ // (__clc_sw_fma), but avoids the use of ulong in favor of uint2. The logic has // been updated as appropriate. -#include -#include "../../../generic/lib/clcmacro.h" #include "../../../generic/lib/math/math.h" +#include +#include struct fp { uint2 mantissa; diff --git a/libclc/generic/include/clc/clc.h b/libclc/generic/include/clc/clc.h index 171b06ac60696..94fca681f8cda 100644 --- a/libclc/generic/include/clc/clc.h +++ b/libclc/generic/include/clc/clc.h @@ -1,3 +1,6 @@ +#ifndef __CLC_CLC_H__ +#define __CLC_CLC_H__ + #ifndef cl_clang_storage_class_specifiers #error Implementation requires cl_clang_storage_class_specifiers extension! #endif @@ -286,3 +289,5 @@ #include #pragma OPENCL EXTENSION all : disable + +#endif // __CLC_CLC_H__ diff --git a/libclc/generic/include/clc/clcmacros.h b/libclc/generic/include/clc/clcmacros.h index 2282d361d791e..041c1cf424382 100644 --- a/libclc/generic/include/clc/clcmacros.h +++ b/libclc/generic/include/clc/clcmacros.h @@ -1,3 +1,6 @@ +#ifndef __CLC_CLCMACROS_H__ +#define __CLC_CLCMACROS_H__ + /* 6.9 Preprocessor Directives and Macros * Some of these are handled by clang or passed by clover */ #if __OPENCL_VERSION__ >= 110 @@ -9,10 +12,12 @@ #define CLC_VERSION_1_2 120 #endif -#define NULL ((void*)0) +#define NULL ((void *)0) -#define __kernel_exec(X, typen) __kernel \ - __attribute__((work_group_size_hint(X, 1, 1))) \ - __attribute__((vec_type_hint(typen))) +#define __kernel_exec(X, typen) \ + __kernel __attribute__((work_group_size_hint(X, 1, 1))) \ + __attribute__((vec_type_hint(typen))) #define kernel_exec(X, typen) __kernel_exec(X, typen) + +#endif // __CLC_CLCMACROS_H__ diff --git a/libclc/generic/include/math/clc_sqrt.h b/libclc/generic/include/math/clc_sqrt.h index 60e183ff66a5c..90a7c575c9bad 100644 --- a/libclc/generic/include/math/clc_sqrt.h +++ b/libclc/generic/include/math/clc_sqrt.h @@ -1,3 +1,6 @@ +#include +#include + #define __CLC_FUNCTION __clc_sqrt #define __CLC_BODY #include diff --git a/libclc/generic/lib/atom_int32_binary.inc b/libclc/generic/lib/atom_int32_binary.inc index 3af4c4bb0ae80..5d3b33fcc1edf 100644 --- a/libclc/generic/lib/atom_int32_binary.inc +++ b/libclc/generic/lib/atom_int32_binary.inc @@ -1,5 +1,5 @@ #include -#include "utils.h" +#include #define __CLC_ATOM_IMPL(AS, TYPE) \ _CLC_OVERLOAD _CLC_DEF TYPE __CLC_XCONCAT(atom_, __CLC_ATOMIC_OP) (volatile AS TYPE *p, TYPE val) { \ diff --git a/libclc/generic/lib/common/degrees.cl b/libclc/generic/lib/common/degrees.cl index 5de56f86c4ca9..cf49b190c76b3 100644 --- a/libclc/generic/lib/common/degrees.cl +++ b/libclc/generic/lib/common/degrees.cl @@ -21,8 +21,7 @@ */ #include - -#include "../clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF float degrees(float radians) { // 180/pi = ~57.29577951308232087685 or 0x1.ca5dc1a63c1f8p+5 or 0x1.ca5dc2p+5F diff --git a/libclc/generic/lib/common/radians.cl b/libclc/generic/lib/common/radians.cl index 3838dd6cde60f..645a30549afed 100644 --- a/libclc/generic/lib/common/radians.cl +++ b/libclc/generic/lib/common/radians.cl @@ -21,8 +21,7 @@ */ #include - -#include "../clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF float radians(float degrees) { // pi/180 = ~0.01745329251994329577 or 0x1.1df46a2529d39p-6 or 0x1.1df46ap-6F diff --git a/libclc/generic/lib/common/sign.cl b/libclc/generic/lib/common/sign.cl index 7b6b793be79c1..ad8f7405e0cb3 100644 --- a/libclc/generic/lib/common/sign.cl +++ b/libclc/generic/lib/common/sign.cl @@ -1,5 +1,5 @@ #include -#include "../clcmacro.h" +#include #define SIGN(TYPE, F) \ _CLC_DEF _CLC_OVERLOAD TYPE sign(TYPE x) { \ diff --git a/libclc/generic/lib/common/smoothstep.cl b/libclc/generic/lib/common/smoothstep.cl index 1b6a74b89d2c2..4cdecfc4abe26 100644 --- a/libclc/generic/lib/common/smoothstep.cl +++ b/libclc/generic/lib/common/smoothstep.cl @@ -21,8 +21,7 @@ */ #include - -#include "../clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF float smoothstep(float edge0, float edge1, float x) { float t = clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); diff --git a/libclc/generic/lib/common/step.cl b/libclc/generic/lib/common/step.cl index 8155b469fb210..3d9bc53c2e146 100644 --- a/libclc/generic/lib/common/step.cl +++ b/libclc/generic/lib/common/step.cl @@ -21,8 +21,7 @@ */ #include - -#include "../clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF float step(float edge, float x) { return x < edge ? 0.0f : 1.0f; diff --git a/libclc/generic/lib/integer/add_sat.cl b/libclc/generic/lib/integer/add_sat.cl index 252dce9775bfa..11a4a331fbd02 100644 --- a/libclc/generic/lib/integer/add_sat.cl +++ b/libclc/generic/lib/integer/add_sat.cl @@ -1,5 +1,5 @@ #include -#include "../clcmacro.h" +#include // From add_sat.ll _CLC_DECL char __clc_add_sat_s8(char, char); diff --git a/libclc/generic/lib/integer/clz.cl b/libclc/generic/lib/integer/clz.cl index e2080b5dd18ba..904d027d37613 100644 --- a/libclc/generic/lib/integer/clz.cl +++ b/libclc/generic/lib/integer/clz.cl @@ -1,5 +1,5 @@ #include -#include "../clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF char clz(char x) { return clz((ushort)(uchar)x) - 8; diff --git a/libclc/generic/lib/integer/mad_sat.cl b/libclc/generic/lib/integer/mad_sat.cl index 1708b29efffc5..2372eaacd6da8 100644 --- a/libclc/generic/lib/integer/mad_sat.cl +++ b/libclc/generic/lib/integer/mad_sat.cl @@ -1,5 +1,5 @@ #include -#include "../clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF char mad_sat(char x, char y, char z) { return clamp((short)mad24((short)x, (short)y, (short)z), (short)CHAR_MIN, (short) CHAR_MAX); diff --git a/libclc/generic/lib/integer/sub_sat.cl b/libclc/generic/lib/integer/sub_sat.cl index 2fbc31664e711..e6beef787c036 100644 --- a/libclc/generic/lib/integer/sub_sat.cl +++ b/libclc/generic/lib/integer/sub_sat.cl @@ -1,5 +1,5 @@ #include -#include "../clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF char sub_sat(char x, char y) { short r = x - y; diff --git a/libclc/generic/lib/math/acos.cl b/libclc/generic/lib/math/acos.cl index af59f443e8717..aeb72872da342 100644 --- a/libclc/generic/lib/math/acos.cl +++ b/libclc/generic/lib/math/acos.cl @@ -20,9 +20,9 @@ * THE SOFTWARE. */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float acos(float x) { // Computes arccos(x). diff --git a/libclc/generic/lib/math/acosh.cl b/libclc/generic/lib/math/acosh.cl index 6e8dd78c3c00c..4656f14457d42 100644 --- a/libclc/generic/lib/math/acosh.cl +++ b/libclc/generic/lib/math/acosh.cl @@ -21,10 +21,10 @@ */ #include +#include #include "ep_log.h" #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float acosh(float x) { uint ux = as_uint(x); diff --git a/libclc/generic/lib/math/acospi.cl b/libclc/generic/lib/math/acospi.cl index 7ebf802b5fbc5..83a47eb27e836 100644 --- a/libclc/generic/lib/math/acospi.cl +++ b/libclc/generic/lib/math/acospi.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float acospi(float x) { // Computes arccos(x). diff --git a/libclc/generic/lib/math/asin.cl b/libclc/generic/lib/math/asin.cl index 43ce9055564cf..443dec830eb2f 100644 --- a/libclc/generic/lib/math/asin.cl +++ b/libclc/generic/lib/math/asin.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float asin(float x) { // Computes arcsin(x). diff --git a/libclc/generic/lib/math/asinh.cl b/libclc/generic/lib/math/asinh.cl index 9f8ddad873af0..f7637ade227ee 100644 --- a/libclc/generic/lib/math/asinh.cl +++ b/libclc/generic/lib/math/asinh.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "ep_log.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float asinh(float x) { uint ux = as_uint(x); diff --git a/libclc/generic/lib/math/asinpi.cl b/libclc/generic/lib/math/asinpi.cl index 511d74ec589fc..18dc53000b034 100644 --- a/libclc/generic/lib/math/asinpi.cl +++ b/libclc/generic/lib/math/asinpi.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float asinpi(float x) { // Computes arcsin(x). diff --git a/libclc/generic/lib/math/atan.cl b/libclc/generic/lib/math/atan.cl index 2fa6e8d116cc3..28eaaf7b2ae72 100644 --- a/libclc/generic/lib/math/atan.cl +++ b/libclc/generic/lib/math/atan.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float atan(float x) { diff --git a/libclc/generic/lib/math/atan2.cl b/libclc/generic/lib/math/atan2.cl index d260338b83ec7..98b457a69a0e2 100644 --- a/libclc/generic/lib/math/atan2.cl +++ b/libclc/generic/lib/math/atan2.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "tables.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float atan2(float y, float x) { diff --git a/libclc/generic/lib/math/atan2pi.cl b/libclc/generic/lib/math/atan2pi.cl index ad2eda3dec87c..ad41b11bd3741 100644 --- a/libclc/generic/lib/math/atan2pi.cl +++ b/libclc/generic/lib/math/atan2pi.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "tables.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float atan2pi(float y, float x) { const float pi = 0x1.921fb6p+1f; diff --git a/libclc/generic/lib/math/atanh.cl b/libclc/generic/lib/math/atanh.cl index 524af025b0b58..f2298a2624e84 100644 --- a/libclc/generic/lib/math/atanh.cl +++ b/libclc/generic/lib/math/atanh.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float atanh(float x) { uint ux = as_uint(x); diff --git a/libclc/generic/lib/math/atanpi.cl b/libclc/generic/lib/math/atanpi.cl index 625af12ba8518..9e6b3ece7f325 100644 --- a/libclc/generic/lib/math/atanpi.cl +++ b/libclc/generic/lib/math/atanpi.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float atanpi(float x) { const float pi = 3.1415926535897932f; diff --git a/libclc/generic/lib/math/cbrt.cl b/libclc/generic/lib/math/cbrt.cl index 2f5ff9516ed76..8462f5f6e14bb 100644 --- a/libclc/generic/lib/math/cbrt.cl +++ b/libclc/generic/lib/math/cbrt.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "tables.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float cbrt(float x) { diff --git a/libclc/generic/lib/math/ceil.cl b/libclc/generic/lib/math/ceil.cl index 9f7154c6e6e47..e02789e694e06 100644 --- a/libclc/generic/lib/math/ceil.cl +++ b/libclc/generic/lib/math/ceil.cl @@ -1,10 +1,6 @@ #include -#include "../clcmacro.h" - -// Map the llvm intrinsic to an OpenCL function. -#define __CLC_FUNCTION __clc_ceil -#define __CLC_INTRINSIC "llvm.ceil" -#include "math/unary_intrin.inc" +#include +#include #undef __CLC_FUNCTION #define __CLC_FUNCTION ceil diff --git a/libclc/generic/lib/math/clc_exp10.cl b/libclc/generic/lib/math/clc_exp10.cl index c6a9476939b56..01e6fd652004a 100644 --- a/libclc/generic/lib/math/clc_exp10.cl +++ b/libclc/generic/lib/math/clc_exp10.cl @@ -21,11 +21,11 @@ */ #include +#include #include "config.h" #include "math.h" #include "tables.h" -#include "../clcmacro.h" // Algorithm: // diff --git a/libclc/generic/lib/math/clc_fma.cl b/libclc/generic/lib/math/clc_fma.cl index dee90e999c398..609981ac3624b 100644 --- a/libclc/generic/lib/math/clc_fma.cl +++ b/libclc/generic/lib/math/clc_fma.cl @@ -21,138 +21,142 @@ */ #include +#include #include "config.h" #include "math.h" -#include "../clcmacro.h" struct fp { - ulong mantissa; - int exponent; - uint sign; + ulong mantissa; + int exponent; + uint sign; }; -_CLC_DEF _CLC_OVERLOAD float __clc_sw_fma(float a, float b, float c) -{ - /* special cases */ - if (isnan(a) || isnan(b) || isnan(c) || isinf(a) || isinf(b)) - return mad(a, b, c); +_CLC_DEF _CLC_OVERLOAD float __clc_sw_fma(float a, float b, float c) { + /* special cases */ + if (isnan(a) || isnan(b) || isnan(c) || isinf(a) || isinf(b)) + return mad(a, b, c); - /* If only c is inf, and both a,b are regular numbers, the result is c*/ - if (isinf(c)) - return c; + /* If only c is inf, and both a,b are regular numbers, the result is c*/ + if (isinf(c)) + return c; - a = __clc_flush_denormal_if_not_supported(a); - b = __clc_flush_denormal_if_not_supported(b); - c = __clc_flush_denormal_if_not_supported(c); + a = __clc_flush_denormal_if_not_supported(a); + b = __clc_flush_denormal_if_not_supported(b); + c = __clc_flush_denormal_if_not_supported(c); - if (c == 0) - return a * b; + if (c == 0) + return a * b; - struct fp st_a, st_b, st_c; + struct fp st_a, st_b, st_c; - st_a.exponent = a == .0f ? 0 : ((as_uint(a) & 0x7f800000) >> 23) - 127; - st_b.exponent = b == .0f ? 0 : ((as_uint(b) & 0x7f800000) >> 23) - 127; - st_c.exponent = c == .0f ? 0 : ((as_uint(c) & 0x7f800000) >> 23) - 127; + st_a.exponent = a == .0f ? 0 : ((as_uint(a) & 0x7f800000) >> 23) - 127; + st_b.exponent = b == .0f ? 0 : ((as_uint(b) & 0x7f800000) >> 23) - 127; + st_c.exponent = c == .0f ? 0 : ((as_uint(c) & 0x7f800000) >> 23) - 127; - st_a.mantissa = a == .0f ? 0 : (as_uint(a) & 0x7fffff) | 0x800000; - st_b.mantissa = b == .0f ? 0 : (as_uint(b) & 0x7fffff) | 0x800000; - st_c.mantissa = c == .0f ? 0 : (as_uint(c) & 0x7fffff) | 0x800000; + st_a.mantissa = a == .0f ? 0 : (as_uint(a) & 0x7fffff) | 0x800000; + st_b.mantissa = b == .0f ? 0 : (as_uint(b) & 0x7fffff) | 0x800000; + st_c.mantissa = c == .0f ? 0 : (as_uint(c) & 0x7fffff) | 0x800000; - st_a.sign = as_uint(a) & 0x80000000; - st_b.sign = as_uint(b) & 0x80000000; - st_c.sign = as_uint(c) & 0x80000000; + st_a.sign = as_uint(a) & 0x80000000; + st_b.sign = as_uint(b) & 0x80000000; + st_c.sign = as_uint(c) & 0x80000000; - // Multiplication. - // Move the product to the highest bits to maximize precision - // mantissa is 24 bits => product is 48 bits, 2bits non-fraction. - // Add one bit for future addition overflow, - // add another bit to detect subtraction underflow - struct fp st_mul; - st_mul.sign = st_a.sign ^ st_b.sign; - st_mul.mantissa = (st_a.mantissa * st_b.mantissa) << 14ul; - st_mul.exponent = st_mul.mantissa ? st_a.exponent + st_b.exponent : 0; + // Multiplication. + // Move the product to the highest bits to maximize precision + // mantissa is 24 bits => product is 48 bits, 2bits non-fraction. + // Add one bit for future addition overflow, + // add another bit to detect subtraction underflow + struct fp st_mul; + st_mul.sign = st_a.sign ^ st_b.sign; + st_mul.mantissa = (st_a.mantissa * st_b.mantissa) << 14ul; + st_mul.exponent = st_mul.mantissa ? st_a.exponent + st_b.exponent : 0; - // FIXME: Detecting a == 0 || b == 0 above crashed GCN isel - if (st_mul.exponent == 0 && st_mul.mantissa == 0) - return c; + // FIXME: Detecting a == 0 || b == 0 above crashed GCN isel + if (st_mul.exponent == 0 && st_mul.mantissa == 0) + return c; // Mantissa is 23 fractional bits, shift it the same way as product mantissa #define C_ADJUST 37ul - // both exponents are bias adjusted - int exp_diff = st_mul.exponent - st_c.exponent; - - st_c.mantissa <<= C_ADJUST; - ulong cutoff_bits = 0; - ulong cutoff_mask = (1ul << abs(exp_diff)) - 1ul; - if (exp_diff > 0) { - cutoff_bits = exp_diff >= 64 ? st_c.mantissa : (st_c.mantissa & cutoff_mask); - st_c.mantissa = exp_diff >= 64 ? 0 : (st_c.mantissa >> exp_diff); - } else { - cutoff_bits = -exp_diff >= 64 ? st_mul.mantissa : (st_mul.mantissa & cutoff_mask); - st_mul.mantissa = -exp_diff >= 64 ? 0 : (st_mul.mantissa >> -exp_diff); - } - - struct fp st_fma; - st_fma.sign = st_mul.sign; - st_fma.exponent = max(st_mul.exponent, st_c.exponent); - if (st_c.sign == st_mul.sign) { - st_fma.mantissa = st_mul.mantissa + st_c.mantissa; - } else { - // cutoff bits borrow one - st_fma.mantissa = st_mul.mantissa - st_c.mantissa - (cutoff_bits && (st_mul.exponent > st_c.exponent) ? 1 : 0); - } - - // underflow: st_c.sign != st_mul.sign, and magnitude switches the sign - if (st_fma.mantissa > LONG_MAX) { - st_fma.mantissa = 0 - st_fma.mantissa; - st_fma.sign = st_mul.sign ^ 0x80000000; - } - - // detect overflow/underflow - int overflow_bits = 3 - clz(st_fma.mantissa); - - // adjust exponent - st_fma.exponent += overflow_bits; - - // handle underflow - if (overflow_bits < 0) { - st_fma.mantissa <<= -overflow_bits; - overflow_bits = 0; - } - - // rounding - ulong trunc_mask = (1ul << (C_ADJUST + overflow_bits)) - 1; - ulong trunc_bits = (st_fma.mantissa & trunc_mask) | (cutoff_bits != 0); - ulong last_bit = st_fma.mantissa & (1ul << (C_ADJUST + overflow_bits)); - ulong grs_bits = (0x4ul << (C_ADJUST - 3 + overflow_bits)); - - // round to nearest even - if ((trunc_bits > grs_bits) || - (trunc_bits == grs_bits && last_bit != 0)) - st_fma.mantissa += (1ul << (C_ADJUST + overflow_bits)); - - // Shift mantissa back to bit 23 - st_fma.mantissa = (st_fma.mantissa >> (C_ADJUST + overflow_bits)); - - // Detect rounding overflow - if (st_fma.mantissa > 0xffffff) { - ++st_fma.exponent; - st_fma.mantissa >>= 1; - } - - if (st_fma.mantissa == 0) - return .0f; - - // Flating point range limit - if (st_fma.exponent > 127) - return as_float(as_uint(INFINITY) | st_fma.sign); - - // Flush denormals - if (st_fma.exponent <= -127) - return as_float(st_fma.sign); - - return as_float(st_fma.sign | ((st_fma.exponent + 127) << 23) | ((uint)st_fma.mantissa & 0x7fffff)); + // both exponents are bias adjusted + int exp_diff = st_mul.exponent - st_c.exponent; + + st_c.mantissa <<= C_ADJUST; + ulong cutoff_bits = 0; + ulong cutoff_mask = (1ul << abs(exp_diff)) - 1ul; + if (exp_diff > 0) { + cutoff_bits = + exp_diff >= 64 ? st_c.mantissa : (st_c.mantissa & cutoff_mask); + st_c.mantissa = exp_diff >= 64 ? 0 : (st_c.mantissa >> exp_diff); + } else { + cutoff_bits = + -exp_diff >= 64 ? st_mul.mantissa : (st_mul.mantissa & cutoff_mask); + st_mul.mantissa = -exp_diff >= 64 ? 0 : (st_mul.mantissa >> -exp_diff); + } + + struct fp st_fma; + st_fma.sign = st_mul.sign; + st_fma.exponent = max(st_mul.exponent, st_c.exponent); + if (st_c.sign == st_mul.sign) { + st_fma.mantissa = st_mul.mantissa + st_c.mantissa; + } else { + // cutoff bits borrow one + st_fma.mantissa = + st_mul.mantissa - st_c.mantissa - + (cutoff_bits && (st_mul.exponent > st_c.exponent) ? 1 : 0); + } + + // underflow: st_c.sign != st_mul.sign, and magnitude switches the sign + if (st_fma.mantissa > LONG_MAX) { + st_fma.mantissa = 0 - st_fma.mantissa; + st_fma.sign = st_mul.sign ^ 0x80000000; + } + + // detect overflow/underflow + int overflow_bits = 3 - clz(st_fma.mantissa); + + // adjust exponent + st_fma.exponent += overflow_bits; + + // handle underflow + if (overflow_bits < 0) { + st_fma.mantissa <<= -overflow_bits; + overflow_bits = 0; + } + + // rounding + ulong trunc_mask = (1ul << (C_ADJUST + overflow_bits)) - 1; + ulong trunc_bits = (st_fma.mantissa & trunc_mask) | (cutoff_bits != 0); + ulong last_bit = st_fma.mantissa & (1ul << (C_ADJUST + overflow_bits)); + ulong grs_bits = (0x4ul << (C_ADJUST - 3 + overflow_bits)); + + // round to nearest even + if ((trunc_bits > grs_bits) || (trunc_bits == grs_bits && last_bit != 0)) + st_fma.mantissa += (1ul << (C_ADJUST + overflow_bits)); + + // Shift mantissa back to bit 23 + st_fma.mantissa = (st_fma.mantissa >> (C_ADJUST + overflow_bits)); + + // Detect rounding overflow + if (st_fma.mantissa > 0xffffff) { + ++st_fma.exponent; + st_fma.mantissa >>= 1; + } + + if (st_fma.mantissa == 0) + return .0f; + + // Flating point range limit + if (st_fma.exponent > 127) + return as_float(as_uint(INFINITY) | st_fma.sign); + + // Flush denormals + if (st_fma.exponent <= -127) + return as_float(st_fma.sign); + + return as_float(st_fma.sign | ((st_fma.exponent + 127) << 23) | + ((uint)st_fma.mantissa & 0x7fffff)); } -_CLC_TERNARY_VECTORIZE(_CLC_DEF _CLC_OVERLOAD, float, __clc_sw_fma, float, float, float) +_CLC_TERNARY_VECTORIZE(_CLC_DEF _CLC_OVERLOAD, float, __clc_sw_fma, float, + float, float) diff --git a/libclc/generic/lib/math/clc_fmod.cl b/libclc/generic/lib/math/clc_fmod.cl index ea9f0e47e7aa0..3a179879e6249 100644 --- a/libclc/generic/lib/math/clc_fmod.cl +++ b/libclc/generic/lib/math/clc_fmod.cl @@ -21,9 +21,11 @@ */ #include +#include +#include +#include #include -#include "../clcmacro.h" #include "config.h" #include "math.h" @@ -119,7 +121,7 @@ _CLC_DEF _CLC_OVERLOAD double __clc_fmod(double x, double y) for (i = 0; i < ntimes; i++) { // Compute integral multiplier - t = trunc(dx / w); + t = __clc_trunc(dx / w); // Compute w * t in quad precision p = w * t; @@ -138,7 +140,7 @@ _CLC_DEF _CLC_OVERLOAD double __clc_fmod(double x, double y) // One more time // Variable todd says whether the integer t is odd or not - t = floor(dx / w); + t = __clc_floor(dx / w); long lt = (long)t; int todd = lt & 1; diff --git a/libclc/generic/lib/math/clc_hypot.cl b/libclc/generic/lib/math/clc_hypot.cl index ce88f276cf2f2..7ab39bcd67a97 100644 --- a/libclc/generic/lib/math/clc_hypot.cl +++ b/libclc/generic/lib/math/clc_hypot.cl @@ -21,12 +21,12 @@ */ #include +#include #include #include #include "config.h" #include "math.h" -#include "../clcmacro.h" // Returns sqrt(x*x + y*y) with no overflow or underflow unless the result // warrants it diff --git a/libclc/generic/lib/math/clc_ldexp.cl b/libclc/generic/lib/math/clc_ldexp.cl index 438c31835a364..ccb37631706b8 100644 --- a/libclc/generic/lib/math/clc_ldexp.cl +++ b/libclc/generic/lib/math/clc_ldexp.cl @@ -20,10 +20,10 @@ * THE SOFTWARE. */ -#include "../clcmacro.h" #include "config.h" #include "math.h" #include +#include #include _CLC_DEF _CLC_OVERLOAD float __clc_ldexp(float x, int n) { diff --git a/libclc/generic/lib/math/clc_nextafter.cl b/libclc/generic/lib/math/clc_nextafter.cl index d32ef7079e115..ccb7624d20c56 100644 --- a/libclc/generic/lib/math/clc_nextafter.cl +++ b/libclc/generic/lib/math/clc_nextafter.cl @@ -1,5 +1,5 @@ #include -#include "../clcmacro.h" +#include // This file provides OpenCL C implementations of nextafter for // targets that don't support the clang builtin. diff --git a/libclc/generic/lib/math/clc_pow.cl b/libclc/generic/lib/math/clc_pow.cl index 02063a2e6b3e5..2e2dade0d6b8f 100644 --- a/libclc/generic/lib/math/clc_pow.cl +++ b/libclc/generic/lib/math/clc_pow.cl @@ -21,11 +21,12 @@ */ #include +#include +#include #include "config.h" #include "math.h" #include "tables.h" -#include "../clcmacro.h" /* compute pow using log and exp @@ -80,7 +81,7 @@ _CLC_DEF _CLC_OVERLOAD float __clc_pow(float x, float y) * First handle case that x is close to 1 */ float r = 1.0f - as_float(ax); - int near1 = fabs(r) < 0x1.0p-4f; + int near1 = __clc_fabs(r) < 0x1.0p-4f; float r2 = r*r; /* Coefficients are just 1/3, 1/4, 1/5 and 1/6 */ diff --git a/libclc/generic/lib/math/clc_pown.cl b/libclc/generic/lib/math/clc_pown.cl index 1a1e2acec6eda..031bf9b25e6a1 100644 --- a/libclc/generic/lib/math/clc_pown.cl +++ b/libclc/generic/lib/math/clc_pown.cl @@ -21,11 +21,12 @@ */ #include +#include +#include #include "config.h" #include "math.h" #include "tables.h" -#include "../clcmacro.h" // compute pow using log and exp // x^y = exp(y * log(x)) @@ -78,7 +79,7 @@ _CLC_DEF _CLC_OVERLOAD float __clc_pown(float x, int ny) // Extra precise log calculation // First handle case that x is close to 1 float r = 1.0f - as_float(ax); - int near1 = fabs(r) < 0x1.0p-4f; + int near1 = __clc_fabs(r) < 0x1.0p-4f; float r2 = r*r; // Coefficients are just 1/3, 1/4, 1/5 and 1/6 diff --git a/libclc/generic/lib/math/clc_powr.cl b/libclc/generic/lib/math/clc_powr.cl index ef97d3c322bd6..c431f529f3b97 100644 --- a/libclc/generic/lib/math/clc_powr.cl +++ b/libclc/generic/lib/math/clc_powr.cl @@ -21,11 +21,12 @@ */ #include +#include +#include #include "config.h" #include "math.h" #include "tables.h" -#include "../clcmacro.h" // compute pow using log and exp // x^y = exp(y * log(x)) @@ -76,7 +77,7 @@ _CLC_DEF _CLC_OVERLOAD float __clc_powr(float x, float y) // Extra precise log calculation // First handle case that x is close to 1 float r = 1.0f - as_float(ax); - int near1 = fabs(r) < 0x1.0p-4f; + int near1 = __clc_fabs(r) < 0x1.0p-4f; float r2 = r*r; // Coefficients are just 1/3, 1/4, 1/5 and 1/6 diff --git a/libclc/generic/lib/math/clc_remainder.cl b/libclc/generic/lib/math/clc_remainder.cl index ba50ee345191d..aef2ee973a1fe 100644 --- a/libclc/generic/lib/math/clc_remainder.cl +++ b/libclc/generic/lib/math/clc_remainder.cl @@ -21,9 +21,11 @@ */ #include +#include +#include +#include #include -#include "../clcmacro.h" #include "config.h" #include "math.h" @@ -129,7 +131,7 @@ _CLC_DEF _CLC_OVERLOAD double __clc_remainder(double x, double y) for (i = 0; i < ntimes; i++) { // Compute integral multiplier - t = trunc(dx / w); + t = __clc_trunc(dx / w); // Compute w * t in quad precision p = w * t; @@ -148,7 +150,7 @@ _CLC_DEF _CLC_OVERLOAD double __clc_remainder(double x, double y) // One more time // Variable todd says whether the integer t is odd or not - t = floor(dx / w); + t = __clc_floor(dx / w); long lt = (long)t; int todd = lt & 1; diff --git a/libclc/generic/lib/math/clc_remquo.cl b/libclc/generic/lib/math/clc_remquo.cl index edf4422610f4f..003f8a1227f12 100644 --- a/libclc/generic/lib/math/clc_remquo.cl +++ b/libclc/generic/lib/math/clc_remquo.cl @@ -21,9 +21,11 @@ */ #include +#include +#include +#include #include -#include "../clcmacro.h" #include "config.h" #include "math.h" @@ -154,7 +156,7 @@ _CLC_DEF _CLC_OVERLOAD double __clc_remquo(double x, double y, __private int *pq for (i = 0; i < ntimes; i++) { // Compute integral multiplier - t = trunc(dx / w); + t = __clc_trunc(dx / w); // Compute w * t in quad precision p = w * t; @@ -173,7 +175,7 @@ _CLC_DEF _CLC_OVERLOAD double __clc_remquo(double x, double y, __private int *pq // One more time // Variable todd says whether the integer t is odd or not - t = floor(dx / w); + t = __clc_floor(dx / w); long lt = (long)t; int todd = lt & 1; diff --git a/libclc/generic/lib/math/clc_rootn.cl b/libclc/generic/lib/math/clc_rootn.cl index 040b614f5feb4..eee9c9fcaa2d4 100644 --- a/libclc/generic/lib/math/clc_rootn.cl +++ b/libclc/generic/lib/math/clc_rootn.cl @@ -21,11 +21,12 @@ */ #include +#include +#include #include "config.h" #include "math.h" #include "tables.h" -#include "../clcmacro.h" // compute pow using log and exp // x^y = exp(y * log(x)) @@ -78,7 +79,7 @@ _CLC_DEF _CLC_OVERLOAD float __clc_rootn(float x, int ny) // Extra precise log calculation // First handle case that x is close to 1 float r = 1.0f - as_float(ax); - int near1 = fabs(r) < 0x1.0p-4f; + int near1 = __clc_fabs(r) < 0x1.0p-4f; float r2 = r*r; // Coefficients are just 1/3, 1/4, 1/5 and 1/6 diff --git a/libclc/generic/lib/math/clc_sqrt.cl b/libclc/generic/lib/math/clc_sqrt.cl index 14a48aa82f23e..92c7f6e73b11e 100644 --- a/libclc/generic/lib/math/clc_sqrt.cl +++ b/libclc/generic/lib/math/clc_sqrt.cl @@ -25,7 +25,7 @@ // Map the llvm sqrt intrinsic to an OpenCL function. #define __CLC_FUNCTION __clc_llvm_intr_sqrt #define __CLC_INTRINSIC "llvm.sqrt" -#include +#include #undef __CLC_FUNCTION #undef __CLC_INTRINSIC diff --git a/libclc/generic/lib/math/clc_sw_binary.inc b/libclc/generic/lib/math/clc_sw_binary.inc index 5cf15a21f7805..b701d78878c6a 100644 --- a/libclc/generic/lib/math/clc_sw_binary.inc +++ b/libclc/generic/lib/math/clc_sw_binary.inc @@ -1,4 +1,4 @@ -#include +#include #define __CLC_SW_FUNC(x) __CLC_CONCAT(__clc_, x) diff --git a/libclc/generic/lib/math/clc_sw_unary.inc b/libclc/generic/lib/math/clc_sw_unary.inc index 9b908aee87a18..0cf242dfeb366 100644 --- a/libclc/generic/lib/math/clc_sw_unary.inc +++ b/libclc/generic/lib/math/clc_sw_unary.inc @@ -1,4 +1,4 @@ -#include +#include #define __CLC_SW_FUNC(x) __CLC_CONCAT(__clc_, x) diff --git a/libclc/generic/lib/math/clc_tan.cl b/libclc/generic/lib/math/clc_tan.cl index ebba36a0d257e..d14ab71740501 100644 --- a/libclc/generic/lib/math/clc_tan.cl +++ b/libclc/generic/lib/math/clc_tan.cl @@ -20,52 +20,52 @@ * THE SOFTWARE. */ #include +#include +#include #include "math.h" #include "sincos_helpers.h" -#include "../clcmacro.h" #include "tables.h" -_CLC_DEF _CLC_OVERLOAD float __clc_tan(float x) -{ - int ix = as_int(x); - int ax = ix & 0x7fffffff; - float dx = as_float(ax); +_CLC_DEF _CLC_OVERLOAD float __clc_tan(float x) { + int ix = as_int(x); + int ax = ix & 0x7fffffff; + float dx = as_float(ax); - float r0, r1; - int regn = __clc_argReductionS(&r0, &r1, dx); + float r0, r1; + int regn = __clc_argReductionS(&r0, &r1, dx); - float t = __clc_tanf_piby4(r0 + r1, regn); - t = as_float(as_int(t) ^ (ix ^ ax)); + float t = __clc_tanf_piby4(r0 + r1, regn); + t = as_float(as_int(t) ^ (ix ^ ax)); - t = ax >= PINFBITPATT_SP32 ? as_float(QNANBITPATT_SP32) : t; - //Take care of subnormals - t = (x == 0.0f) ? x : t; - return t; + t = ax >= PINFBITPATT_SP32 ? as_float(QNANBITPATT_SP32) : t; + // Take care of subnormals + t = (x == 0.0f) ? x : t; + return t; } _CLC_UNARY_VECTORIZE(_CLC_DEF _CLC_OVERLOAD, float, __clc_tan, float); #ifdef cl_khr_fp64 #include "sincosD_piby4.h" -_CLC_DEF _CLC_OVERLOAD double __clc_tan(double x) -{ - double y = fabs(x); +_CLC_DEF _CLC_OVERLOAD double __clc_tan(double x) { + double y = __clc_fabs(x); - double r, rr; - int regn; + double r, rr; + int regn; - if (y < 0x1.0p+30) - __clc_remainder_piby2_medium(y, &r, &rr, ®n); - else - __clc_remainder_piby2_large(y, &r, &rr, ®n); + if (y < 0x1.0p+30) + __clc_remainder_piby2_medium(y, &r, &rr, ®n); + else + __clc_remainder_piby2_large(y, &r, &rr, ®n); - double2 tt = __clc_tan_piby4(r, rr); + double2 tt = __clc_tan_piby4(r, rr); - int2 t = as_int2(regn & 1 ? tt.y : tt.x); - t.hi ^= (x < 0.0) << 31; + int2 t = as_int2(regn & 1 ? tt.y : tt.x); + t.hi ^= (x < 0.0) << 31; - return isnan(x) || isinf(x) ? as_double(QNANBITPATT_DP64) : as_double(t); + return isnan(x) || isinf(x) ? as_double(QNANBITPATT_DP64) : as_double(t); } _CLC_UNARY_VECTORIZE(_CLC_DEF _CLC_OVERLOAD, double, __clc_tan, double); + #endif diff --git a/libclc/generic/lib/math/clc_tanpi.cl b/libclc/generic/lib/math/clc_tanpi.cl index d57c3ce3eb240..65d1984593706 100644 --- a/libclc/generic/lib/math/clc_tanpi.cl +++ b/libclc/generic/lib/math/clc_tanpi.cl @@ -20,10 +20,10 @@ * THE SOFTWARE. */ #include +#include #include "math.h" #include "sincos_helpers.h" -#include "../clcmacro.h" #include "tables.h" _CLC_DEF _CLC_OVERLOAD float __clc_tanpi(float x) diff --git a/libclc/generic/lib/math/copysign.cl b/libclc/generic/lib/math/copysign.cl index df65e9d7fece1..08045bebf88a1 100644 --- a/libclc/generic/lib/math/copysign.cl +++ b/libclc/generic/lib/math/copysign.cl @@ -1,5 +1,5 @@ #include -#include "../clcmacro.h" +#include _CLC_DEFINE_BINARY_BUILTIN(float, copysign, __builtin_copysignf, float, float) diff --git a/libclc/generic/lib/math/cos.cl b/libclc/generic/lib/math/cos.cl index 0af7aa67ba009..42192895151a3 100644 --- a/libclc/generic/lib/math/cos.cl +++ b/libclc/generic/lib/math/cos.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "sincos_helpers.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float cos(float x) { diff --git a/libclc/generic/lib/math/cosh.cl b/libclc/generic/lib/math/cosh.cl index 0987d1f921692..1f58d7acd2b55 100644 --- a/libclc/generic/lib/math/cosh.cl +++ b/libclc/generic/lib/math/cosh.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "tables.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float cosh(float x) { diff --git a/libclc/generic/lib/math/cospi.cl b/libclc/generic/lib/math/cospi.cl index d6ab27ba021e2..0e69f7885faa1 100644 --- a/libclc/generic/lib/math/cospi.cl +++ b/libclc/generic/lib/math/cospi.cl @@ -21,11 +21,11 @@ */ #include +#include #include "math.h" #include "sincos_helpers.h" #include "sincospiF_piby4.h" -#include "../clcmacro.h" #ifdef cl_khr_fp64 #include "sincosD_piby4.h" #endif diff --git a/libclc/generic/lib/math/erf.cl b/libclc/generic/lib/math/erf.cl index 2c395ce1a7526..ae8b6ab784558 100644 --- a/libclc/generic/lib/math/erf.cl +++ b/libclc/generic/lib/math/erf.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" /* * ==================================================== diff --git a/libclc/generic/lib/math/erfc.cl b/libclc/generic/lib/math/erfc.cl index cd35ea8def7b6..c4d34ea85e98b 100644 --- a/libclc/generic/lib/math/erfc.cl +++ b/libclc/generic/lib/math/erfc.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" /* * ==================================================== diff --git a/libclc/generic/lib/math/exp.cl b/libclc/generic/lib/math/exp.cl index cc7b7f39bf1db..1e37d76f3ac8e 100644 --- a/libclc/generic/lib/math/exp.cl +++ b/libclc/generic/lib/math/exp.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float exp(float x) { diff --git a/libclc/generic/lib/math/exp2.cl b/libclc/generic/lib/math/exp2.cl index 1ddccbd3ee653..8d718311f896f 100644 --- a/libclc/generic/lib/math/exp2.cl +++ b/libclc/generic/lib/math/exp2.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float exp2(float x) { diff --git a/libclc/generic/lib/math/expm1.cl b/libclc/generic/lib/math/expm1.cl index 9a0aa37ac333b..fbb9f0d087c89 100644 --- a/libclc/generic/lib/math/expm1.cl +++ b/libclc/generic/lib/math/expm1.cl @@ -1,8 +1,8 @@ #include +#include #include "math.h" #include "tables.h" -#include "../clcmacro.h" /* Refer to the exp routine for the underlying algorithm */ diff --git a/libclc/generic/lib/math/fabs.cl b/libclc/generic/lib/math/fabs.cl index 0a7037088b2e7..9644369d4a095 100644 --- a/libclc/generic/lib/math/fabs.cl +++ b/libclc/generic/lib/math/fabs.cl @@ -1,10 +1,6 @@ #include -#include "../clcmacro.h" - -// Map the llvm intrinsic to an OpenCL function. -#define __CLC_FUNCTION __clc_fabs -#define __CLC_INTRINSIC "llvm.fabs" -#include "math/unary_intrin.inc" +#include +#include #undef __CLC_FUNCTION #define __CLC_FUNCTION fabs diff --git a/libclc/generic/lib/math/floor.cl b/libclc/generic/lib/math/floor.cl index de215e437474b..f5c36b73862a4 100644 --- a/libclc/generic/lib/math/floor.cl +++ b/libclc/generic/lib/math/floor.cl @@ -1,10 +1,6 @@ #include -#include "../clcmacro.h" - -// Map the llvm intrinsic to an OpenCL function. -#define __CLC_FUNCTION __clc_floor -#define __CLC_INTRINSIC "llvm.floor" -#include "math/unary_intrin.inc" +#include +#include #undef __CLC_FUNCTION #define __CLC_FUNCTION floor diff --git a/libclc/generic/lib/math/fmax.cl b/libclc/generic/lib/math/fmax.cl index 5c269ceccdda3..c42fe4f54a9e6 100644 --- a/libclc/generic/lib/math/fmax.cl +++ b/libclc/generic/lib/math/fmax.cl @@ -1,6 +1,5 @@ #include - -#include "../clcmacro.h" +#include _CLC_DEFINE_BINARY_BUILTIN(float, fmax, __builtin_fmaxf, float, float); diff --git a/libclc/generic/lib/math/fmin.cl b/libclc/generic/lib/math/fmin.cl index 45c112d991ff9..55575d0486b60 100644 --- a/libclc/generic/lib/math/fmin.cl +++ b/libclc/generic/lib/math/fmin.cl @@ -1,6 +1,5 @@ #include - -#include "../clcmacro.h" +#include _CLC_DEFINE_BINARY_BUILTIN(float, fmin, __builtin_fminf, float, float); diff --git a/libclc/generic/lib/math/frexp.cl b/libclc/generic/lib/math/frexp.cl index cd2c717815112..75a9158ff318f 100644 --- a/libclc/generic/lib/math/frexp.cl +++ b/libclc/generic/lib/math/frexp.cl @@ -1,5 +1,5 @@ #include -#include +#include #define __CLC_BODY #define __CLC_ADDRESS_SPACE private diff --git a/libclc/generic/lib/math/frexp.inc b/libclc/generic/lib/math/frexp.inc index e6e2af49235a4..0d938d23c26a1 100644 --- a/libclc/generic/lib/math/frexp.inc +++ b/libclc/generic/lib/math/frexp.inc @@ -21,7 +21,7 @@ * THE SOFTWARE. */ -#include "../clcmacro.h" +#include #define __CLC_AS_GENTYPE __CLC_XCONCAT(as_, __CLC_GENTYPE) #define __CLC_AS_INTN __CLC_XCONCAT(as_, __CLC_INTN) diff --git a/libclc/generic/lib/math/half_binary.inc b/libclc/generic/lib/math/half_binary.inc index f831b530b4b53..2dc48e512e097 100644 --- a/libclc/generic/lib/math/half_binary.inc +++ b/libclc/generic/lib/math/half_binary.inc @@ -1,4 +1,4 @@ -#include +#include #define __CLC_HALF_FUNC(x) __CLC_CONCAT(half_, x) diff --git a/libclc/generic/lib/math/half_unary.inc b/libclc/generic/lib/math/half_unary.inc index a68f91a70beb5..aac668a6f0059 100644 --- a/libclc/generic/lib/math/half_unary.inc +++ b/libclc/generic/lib/math/half_unary.inc @@ -1,4 +1,4 @@ -#include +#include #define __CLC_HALF_FUNC(x) __CLC_CONCAT(half_, x) diff --git a/libclc/generic/lib/math/ilogb.cl b/libclc/generic/lib/math/ilogb.cl index d085e8608b01a..f16b4404fbebe 100644 --- a/libclc/generic/lib/math/ilogb.cl +++ b/libclc/generic/lib/math/ilogb.cl @@ -21,9 +21,9 @@ * THE SOFTWARE. */ -#include -#include "../clcmacro.h" #include "math.h" +#include +#include _CLC_OVERLOAD _CLC_DEF int ilogb(float x) { uint ux = as_uint(x); diff --git a/libclc/generic/lib/math/ldexp.cl b/libclc/generic/lib/math/ldexp.cl index 190a4d5f5fc34..a999c63902ce8 100644 --- a/libclc/generic/lib/math/ldexp.cl +++ b/libclc/generic/lib/math/ldexp.cl @@ -20,11 +20,11 @@ * THE SOFTWARE. */ -#include #include "config.h" -#include "../clcmacro.h" #include "math.h" #include "math/clc_ldexp.h" +#include +#include _CLC_DEFINE_BINARY_BUILTIN(float, ldexp, __clc_ldexp, float, int) diff --git a/libclc/generic/lib/math/lgamma.cl b/libclc/generic/lib/math/lgamma.cl index 024894f2f304f..ca7b9610a31b3 100644 --- a/libclc/generic/lib/math/lgamma.cl +++ b/libclc/generic/lib/math/lgamma.cl @@ -22,7 +22,7 @@ */ #include -#include "../clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF float lgamma(float x) { int s; diff --git a/libclc/generic/lib/math/lgamma_r.cl b/libclc/generic/lib/math/lgamma_r.cl index fe28e420d1286..bd68a76068ec5 100644 --- a/libclc/generic/lib/math/lgamma_r.cl +++ b/libclc/generic/lib/math/lgamma_r.cl @@ -22,8 +22,8 @@ */ #include +#include -#include "../clcmacro.h" #include "math.h" /* diff --git a/libclc/generic/lib/math/log.cl b/libclc/generic/lib/math/log.cl index ec1faa12606aa..336c8016a6ed8 100644 --- a/libclc/generic/lib/math/log.cl +++ b/libclc/generic/lib/math/log.cl @@ -1,5 +1,5 @@ #include -#include "../clcmacro.h" +#include /* *log(x) = log2(x) * (1/log2(e)) diff --git a/libclc/generic/lib/math/log10.cl b/libclc/generic/lib/math/log10.cl index e669f3148f9c0..3abb14a28d8ad 100644 --- a/libclc/generic/lib/math/log10.cl +++ b/libclc/generic/lib/math/log10.cl @@ -20,9 +20,9 @@ * THE SOFTWARE. */ -#include -#include "../clcmacro.h" #include "tables.h" +#include +#include #ifdef cl_khr_fp64 #pragma OPENCL EXTENSION cl_khr_fp64 : enable diff --git a/libclc/generic/lib/math/log1p.cl b/libclc/generic/lib/math/log1p.cl index 42fd9d3a23f34..a371995a08492 100644 --- a/libclc/generic/lib/math/log1p.cl +++ b/libclc/generic/lib/math/log1p.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "tables.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float log1p(float x) { diff --git a/libclc/generic/lib/math/log2.cl b/libclc/generic/lib/math/log2.cl index 64463557e3f6d..a6f9692881bb8 100644 --- a/libclc/generic/lib/math/log2.cl +++ b/libclc/generic/lib/math/log2.cl @@ -20,9 +20,9 @@ * THE SOFTWARE. */ -#include -#include "../clcmacro.h" #include "tables.h" +#include +#include #ifdef cl_khr_fp64 #pragma OPENCL EXTENSION cl_khr_fp64 : enable diff --git a/libclc/generic/lib/math/logb.cl b/libclc/generic/lib/math/logb.cl index c0c2b5de40ebc..7a7111d5bc84d 100644 --- a/libclc/generic/lib/math/logb.cl +++ b/libclc/generic/lib/math/logb.cl @@ -1,6 +1,6 @@ -#include #include "math.h" -#include "../clcmacro.h" +#include +#include _CLC_OVERLOAD _CLC_DEF float logb(float x) { int ax = as_int(x) & EXSIGNBIT_SP32; diff --git a/libclc/generic/lib/math/maxmag.cl b/libclc/generic/lib/math/maxmag.cl index 7b5902d8a8e56..12d22ae039388 100644 --- a/libclc/generic/lib/math/maxmag.cl +++ b/libclc/generic/lib/math/maxmag.cl @@ -1,5 +1,5 @@ #include -#include +#include #define __CLC_BODY #include diff --git a/libclc/generic/lib/math/minmag.cl b/libclc/generic/lib/math/minmag.cl index 0d89882060972..e9c9c82f29900 100644 --- a/libclc/generic/lib/math/minmag.cl +++ b/libclc/generic/lib/math/minmag.cl @@ -1,5 +1,5 @@ #include -#include +#include #define __CLC_BODY #include diff --git a/libclc/generic/lib/math/nan.cl b/libclc/generic/lib/math/nan.cl index 03752ab2d238b..8f89e8e760de8 100644 --- a/libclc/generic/lib/math/nan.cl +++ b/libclc/generic/lib/math/nan.cl @@ -1,5 +1,5 @@ #include -#include "utils.h" +#include #define __CLC_AS_GENTYPE __CLC_XCONCAT(as_, __CLC_GENTYPE) #define __CLC_BODY diff --git a/libclc/generic/lib/math/native_unary_intrinsic.inc b/libclc/generic/lib/math/native_unary_intrinsic.inc index 5640141ed6193..c0a3efdc8b9a3 100644 --- a/libclc/generic/lib/math/native_unary_intrinsic.inc +++ b/libclc/generic/lib/math/native_unary_intrinsic.inc @@ -20,14 +20,14 @@ * THE SOFTWARE. */ -#include +#include #ifdef __CLC_SCALAR #define __CLC_FUNCTION __CLC_XCONCAT(__clc_native_, __CLC_NATIVE_INTRINSIC) #define __CLC_INTRINSIC "llvm." __CLC_XSTR(__CLC_NATIVE_INTRINSIC) #undef cl_khr_fp64 -#include +#include #endif diff --git a/libclc/generic/lib/math/rint.cl b/libclc/generic/lib/math/rint.cl index 5d9f4b119af85..185bbbbf8c91d 100644 --- a/libclc/generic/lib/math/rint.cl +++ b/libclc/generic/lib/math/rint.cl @@ -1,9 +1,5 @@ #include - -// Map the llvm intrinsic to an OpenCL function. -#define __CLC_FUNCTION __clc_rint -#define __CLC_INTRINSIC "llvm.rint" -#include "math/unary_intrin.inc" +#include #undef __CLC_FUNCTION #define __CLC_FUNCTION rint diff --git a/libclc/generic/lib/math/round.cl b/libclc/generic/lib/math/round.cl index 17c72c985fef9..285328aaa5d56 100644 --- a/libclc/generic/lib/math/round.cl +++ b/libclc/generic/lib/math/round.cl @@ -3,7 +3,7 @@ // Map the llvm intrinsic to an OpenCL function. #define __CLC_FUNCTION __clc_round #define __CLC_INTRINSIC "llvm.round" -#include "math/unary_intrin.inc" +#include #undef __CLC_FUNCTION #define __CLC_FUNCTION round diff --git a/libclc/generic/lib/math/rsqrt.cl b/libclc/generic/lib/math/rsqrt.cl index 131ffc194a90f..b38d4a1c3cc82 100644 --- a/libclc/generic/lib/math/rsqrt.cl +++ b/libclc/generic/lib/math/rsqrt.cl @@ -1,6 +1,5 @@ #include - -#include "../clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF float rsqrt(float x) { diff --git a/libclc/generic/lib/math/sin.cl b/libclc/generic/lib/math/sin.cl index 689c3a1dbd0c8..30638a57f59b5 100644 --- a/libclc/generic/lib/math/sin.cl +++ b/libclc/generic/lib/math/sin.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "sincos_helpers.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float sin(float x) { diff --git a/libclc/generic/lib/math/sinh.cl b/libclc/generic/lib/math/sinh.cl index a7a092f1f547d..3de0792361c2f 100644 --- a/libclc/generic/lib/math/sinh.cl +++ b/libclc/generic/lib/math/sinh.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "tables.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float sinh(float x) { diff --git a/libclc/generic/lib/math/sinpi.cl b/libclc/generic/lib/math/sinpi.cl index c8a1031df0216..520bba5415c7c 100644 --- a/libclc/generic/lib/math/sinpi.cl +++ b/libclc/generic/lib/math/sinpi.cl @@ -21,10 +21,10 @@ */ #include +#include #include "math.h" #include "sincospiF_piby4.h" -#include "../clcmacro.h" #ifdef cl_khr_fp64 #include "sincosD_piby4.h" #endif diff --git a/libclc/generic/lib/math/tables.h b/libclc/generic/lib/math/tables.h index 8045242b89ce4..ea5221e1f72b0 100644 --- a/libclc/generic/lib/math/tables.h +++ b/libclc/generic/lib/math/tables.h @@ -20,6 +20,8 @@ * THE SOFTWARE. */ +#include + #define TABLE_SPACE __constant #define TABLE_MANGLE(NAME) __clc_##NAME diff --git a/libclc/generic/lib/math/tanh.cl b/libclc/generic/lib/math/tanh.cl index 6a6810cec1138..e558bb93a5596 100644 --- a/libclc/generic/lib/math/tanh.cl +++ b/libclc/generic/lib/math/tanh.cl @@ -21,9 +21,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float tanh(float x) { diff --git a/libclc/generic/lib/math/tgamma.cl b/libclc/generic/lib/math/tgamma.cl index 29c069fc925bb..314ffda4ec9d5 100644 --- a/libclc/generic/lib/math/tgamma.cl +++ b/libclc/generic/lib/math/tgamma.cl @@ -22,9 +22,9 @@ */ #include +#include #include "math.h" -#include "../clcmacro.h" _CLC_OVERLOAD _CLC_DEF float tgamma(float x) { const float pi = 3.1415926535897932384626433832795f; diff --git a/libclc/generic/lib/math/trunc.cl b/libclc/generic/lib/math/trunc.cl index 62c7b18bdaa70..00c2a4a80015f 100644 --- a/libclc/generic/lib/math/trunc.cl +++ b/libclc/generic/lib/math/trunc.cl @@ -1,9 +1,5 @@ #include - -// Map the llvm intrinsic to an OpenCL function. -#define __CLC_FUNCTION __clc_trunc -#define __CLC_INTRINSIC "llvm.trunc" -#include "math/unary_intrin.inc" +#include #undef __CLC_FUNCTION #define __CLC_FUNCTION trunc diff --git a/libclc/generic/lib/math/unary_builtin.inc b/libclc/generic/lib/math/unary_builtin.inc index 4e7ca5ba9b98e..6405c3fb32f89 100644 --- a/libclc/generic/lib/math/unary_builtin.inc +++ b/libclc/generic/lib/math/unary_builtin.inc @@ -1,5 +1,5 @@ -#include "../clcmacro.h" -#include "utils.h" +#include +#include #ifndef __CLC_BUILTIN #define __CLC_BUILTIN __CLC_XCONCAT(__clc_, __CLC_FUNCTION) diff --git a/libclc/generic/lib/relational/bitselect.cl b/libclc/generic/lib/relational/bitselect.cl index af4e70ccbdd6b..d2a7a92060678 100644 --- a/libclc/generic/lib/relational/bitselect.cl +++ b/libclc/generic/lib/relational/bitselect.cl @@ -21,8 +21,7 @@ */ #include - -#include "../clcmacro.h" +#include #define __CLC_BODY #include diff --git a/libclc/generic/lib/relational/select.cl b/libclc/generic/lib/relational/select.cl index dc2e273c852b4..094f4f9f29fa9 100644 --- a/libclc/generic/lib/relational/select.cl +++ b/libclc/generic/lib/relational/select.cl @@ -1,5 +1,5 @@ #include -#include +#include #define __CLC_BODY #include diff --git a/libclc/ptx/lib/math/nextafter.cl b/libclc/ptx/lib/math/nextafter.cl index 5b4521d21c26a..809eecac53d8c 100644 --- a/libclc/ptx/lib/math/nextafter.cl +++ b/libclc/ptx/lib/math/nextafter.cl @@ -1,5 +1,5 @@ #include -#include "../lib/clcmacro.h" +#include #include _CLC_DEFINE_BINARY_BUILTIN(float, nextafter, __clc_nextafter, float, float) diff --git a/libclc/r600/lib/math/fmax.cl b/libclc/r600/lib/math/fmax.cl index e4b9e4c821fb2..a43530fc7507e 100644 --- a/libclc/r600/lib/math/fmax.cl +++ b/libclc/r600/lib/math/fmax.cl @@ -1,6 +1,6 @@ #include +#include -#include "../../../generic/lib/clcmacro.h" #include "../../../generic/lib/math/math.h" _CLC_DEF _CLC_OVERLOAD float fmax(float x, float y) diff --git a/libclc/r600/lib/math/fmin.cl b/libclc/r600/lib/math/fmin.cl index 09f1e4c7faad3..a43655da13845 100644 --- a/libclc/r600/lib/math/fmin.cl +++ b/libclc/r600/lib/math/fmin.cl @@ -1,6 +1,6 @@ #include +#include -#include "../../../generic/lib/clcmacro.h" #include "../../../generic/lib/math/math.h" _CLC_DEF _CLC_OVERLOAD float fmin(float x, float y) diff --git a/libclc/r600/lib/math/native_rsqrt.cl b/libclc/r600/lib/math/native_rsqrt.cl index edf473e8409c6..78871f3823a51 100644 --- a/libclc/r600/lib/math/native_rsqrt.cl +++ b/libclc/r600/lib/math/native_rsqrt.cl @@ -1,6 +1,5 @@ #include - -#include "../../../generic/lib/clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF float native_rsqrt(float x) { diff --git a/libclc/r600/lib/math/rsqrt.cl b/libclc/r600/lib/math/rsqrt.cl index 37a8037902c28..53f7d4040463f 100644 --- a/libclc/r600/lib/math/rsqrt.cl +++ b/libclc/r600/lib/math/rsqrt.cl @@ -1,6 +1,5 @@ #include - -#include "../../../generic/lib/clcmacro.h" +#include _CLC_OVERLOAD _CLC_DEF float rsqrt(float x) { diff --git a/libcxx/cmake/caches/AMDGPU.cmake b/libcxx/cmake/caches/AMDGPU.cmake index 1a6bfd85a50be..49abb6475fc41 100644 --- a/libcxx/cmake/caches/AMDGPU.cmake +++ b/libcxx/cmake/caches/AMDGPU.cmake @@ -27,6 +27,10 @@ set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") set(LIBCXXABI_ENABLE_THREADS OFF CACHE BOOL "") set(LIBCXXABI_USE_LLVM_UNWINDER OFF CACHE BOOL "") +# Test configuration. +set(LIBCXX_TEST_CONFIG "amdgpu-libc++-shared.cfg.in" CACHE STRING "") +set(LIBCXX_TEST_PARAMS "optimization=none;long_tests=False;executor=amdhsa-loader" CACHE STRING "") + # Necessary compile flags for AMDGPU. set(LIBCXX_ADDITIONAL_COMPILE_FLAGS "-nogpulib;-flto;-fconvergent-functions;SHELL:-Xclang -mcode-object-version=none" CACHE STRING "") diff --git a/libcxx/cmake/caches/NVPTX.cmake b/libcxx/cmake/caches/NVPTX.cmake index 231b457d3017e..b6ec6c04ea700 100644 --- a/libcxx/cmake/caches/NVPTX.cmake +++ b/libcxx/cmake/caches/NVPTX.cmake @@ -27,6 +27,10 @@ set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") set(LIBCXXABI_ENABLE_THREADS OFF CACHE BOOL "") set(LIBCXXABI_USE_LLVM_UNWINDER OFF CACHE BOOL "") +# Test configuration. +set(LIBCXX_TEST_CONFIG "nvptx-libc++-shared.cfg.in" CACHE STRING "") +set(LIBCXX_TEST_PARAMS "optimization=none;long_tests=False;executor=nvptx-loader" CACHE STRING "") + # Necessary compile flags for NVPTX. set(LIBCXX_ADDITIONAL_COMPILE_FLAGS "-nogpulib;-flto;-fconvergent-functions;--cuda-feature=+ptx63" CACHE STRING "") diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index db24b65caca6c..3c4a13332661e 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -278,7 +278,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_shift`` ``201806L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_smart_ptr_for_overwrite`` *unimplemented* + ``__cpp_lib_smart_ptr_for_overwrite`` ``202002L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_source_location`` ``201907L`` ---------------------------------------------------------- ----------------- diff --git a/libcxx/docs/Hardening.rst b/libcxx/docs/Hardening.rst index 67791a5e55ac7..fd0f3af5ef2f9 100644 --- a/libcxx/docs/Hardening.rst +++ b/libcxx/docs/Hardening.rst @@ -341,6 +341,16 @@ Vendors can use the following ABI options to enable additional hardening checks: ABI impact: changes the iterator type of ``vector`` (except ``vector``). +- ``_LIBCPP_ABI_BOUNDED_UNIQUE_PTR``` -- tracks the bounds of the array stored inside + a ``std::unique_ptr``, allowing it to trap when accessed out-of-bounds. This + requires the ``std::unique_ptr`` to be created using an API like ``std::make_unique`` + or ``std::make_unique_for_overwrite``, otherwise the bounds information is not available + to the library. + + ABI impact: changes the layout of ``std::unique_ptr``, and the representation + of a few library types that use ``std::unique_ptr`` internally, such as + the unordered containers. + ABI tags -------- diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst index bf3aafe6139ee..905fd81cd6faa 100644 --- a/libcxx/docs/ReleaseNotes/20.rst +++ b/libcxx/docs/ReleaseNotes/20.rst @@ -62,6 +62,10 @@ Improvements and New Features compile times and smaller debug information as well as better code generation if optimizations are disabled. The Chromium project measured a 5% reduction in object file and debug information size. +- The ``_LIBCPP_ABI_BOUNDED_UNIQUE_PTR`` ABI configuration was added, which allows ``std::unique_ptr`` to + detect out-of-bounds accesses in certain circumstances. ``std::unique_ptr`` can now also detect out-of-bounds + accesses for a limited set of types (non-trivially destructible types) when the ABI configuration is disabled. + Deprecations and Removals ------------------------- diff --git a/libcxx/docs/Status/Cxx17Issues.csv b/libcxx/docs/Status/Cxx17Issues.csv index af3dee9ca50c9..e6a232980cf7c 100644 --- a/libcxx/docs/Status/Cxx17Issues.csv +++ b/libcxx/docs/Status/Cxx17Issues.csv @@ -141,7 +141,7 @@ "`LWG2441 `__","Exact-width atomic typedefs should be provided","2016-06 (Oulu)","|Complete|","","" "`LWG2451 `__","[fund.ts.v2] optional should 'forward' T's implicit conversions","2016-06 (Oulu)","|Nothing To Do|","","" "`LWG2509 `__","[fund.ts.v2] any_cast doesn't work with rvalue reference targets and cannot move with a value target","2016-06 (Oulu)","|Complete|","","" -"`LWG2516 `__","[fund.ts.v2] Public ""exposition only"" members in observer_ptr","2016-06 (Oulu)","|Complete|","18.0","" +"`LWG2516 `__","[fund.ts.v2] Public ""exposition only"" members in observer_ptr","2016-06 (Oulu)","|Complete|","18","" "`LWG2542 `__","Missing const requirements for associative containers","2016-06 (Oulu)","","","" "`LWG2549 `__","Tuple EXPLICIT constructor templates that take tuple parameters end up taking references to temporaries and will create dangling references","2016-06 (Oulu)","|Complete|","","" "`LWG2550 `__","Wording of unordered container's clear() method complexity","2016-06 (Oulu)","|Complete|","","" @@ -174,7 +174,7 @@ "`LWG2720 `__","permissions function incorrectly specified for symlinks","2016-06 (Oulu)","|Complete|","","" "`LWG2721 `__","remove_all has incorrect post conditions","2016-06 (Oulu)","|Complete|","","" "`LWG2723 `__","Do directory_iterator and recursive_directory_iterator become the end iterator upon error?","2016-06 (Oulu)","|Complete|","","" -"`LWG2724 `__","The protected virtual member functions of memory_resource should be private","2016-06 (Oulu)","|Complete|","16.0","" +"`LWG2724 `__","The protected virtual member functions of memory_resource should be private","2016-06 (Oulu)","|Complete|","16","" "`LWG2725 `__","filesystem::exists(const path&, error_code&) error reporting","2016-06 (Oulu)","|Complete|","","" "`LWG2726 `__","``[recursive_]directory_iterator::increment(error_code&)`` is underspecified","2016-06 (Oulu)","|Complete|","","" "`LWG2727 `__","Parallel algorithms with constexpr specifier","2016-06 (Oulu)","","","" @@ -206,8 +206,8 @@ "`LWG2556 `__","Wide contract for future::share()","2016-11 (Issaquah)","|Complete|","","" "`LWG2562 `__","Consistent total ordering of pointers by comparison functors","2016-11 (Issaquah)","","","" "`LWG2567 `__","Specification of logical operator traits uses BaseCharacteristic, which is defined only for UnaryTypeTraits and BinaryTypeTraits","2016-11 (Issaquah)","|Complete|","","" -"`LWG2568 `__","[fund.ts.v2] Specification of logical operator traits uses BaseCharacteristic, which is defined only for UnaryTypeTraits and BinaryTypeTraits","2016-11 (Issaquah)","|Complete|","15.0","" -"`LWG2569 `__","conjunction and disjunction requirements are too strict","2016-11 (Issaquah)","|Complete|","15.0","" +"`LWG2568 `__","[fund.ts.v2] Specification of logical operator traits uses BaseCharacteristic, which is defined only for UnaryTypeTraits and BinaryTypeTraits","2016-11 (Issaquah)","|Complete|","15","" +"`LWG2569 `__","conjunction and disjunction requirements are too strict","2016-11 (Issaquah)","|Complete|","15","" "`LWG2570 `__","[fund.ts.v2] conjunction and disjunction requirements are too strict","2016-11 (Issaquah)","","","" "`LWG2578 `__","Iterator requirements should reference iterator traits","2016-11 (Issaquah)","|Complete|","","" "`LWG2584 `__"," ECMAScript IdentityEscape is ambiguous","2016-11 (Issaquah)","","","" @@ -295,9 +295,9 @@ "`LWG2868 `__","Missing specification of bad_any_cast::what()","2017-02 (Kona)","|Complete|","","" "`LWG2872 `__","Add definition for direct-non-list-initialization","2017-02 (Kona)","|Complete|","","" "`LWG2873 `__","Add noexcept to several shared_ptr related functions","2017-02 (Kona)","|Complete|","","" -"`LWG2874 `__","Constructor ``shared_ptr::shared_ptr(Y*)``\ should be constrained","2017-02 (Kona)","|Complete|","13.0","" +"`LWG2874 `__","Constructor ``shared_ptr::shared_ptr(Y*)``\ should be constrained","2017-02 (Kona)","|Complete|","13","" "`LWG2875 `__","shared_ptr::shared_ptr(Y\*, D, [|hellip|\ ]) constructors should be constrained","2017-02 (Kona)","|Complete|","","" -"`LWG2876 `__","``shared_ptr::shared_ptr(const weak_ptr&)``\ constructor should be constrained","2017-02 (Kona)","|Complete|","14.0","" +"`LWG2876 `__","``shared_ptr::shared_ptr(const weak_ptr&)``\ constructor should be constrained","2017-02 (Kona)","|Complete|","14","" "`LWG2878 `__","Missing DefaultConstructible requirement for istream_iterator default constructor","2017-02 (Kona)","|Complete|","","" "`LWG2890 `__","The definition of 'object state' applies only to class types","2017-02 (Kona)","|Complete|","","" "`LWG2900 `__","The copy and move constructors of optional are not constexpr","2017-02 (Kona)","|Complete|","","" @@ -306,7 +306,7 @@ "`LWG2905 `__","is_constructible_v, P, D const &> should be false when D is not copy constructible","2017-02 (Kona)","|Complete|","","" "`LWG2908 `__","The less-than operator for shared pointers could do more","2017-02 (Kona)","|Complete|","","" "`LWG2911 `__","An is_aggregate type trait is needed","2017-02 (Kona)","|Complete|","","" -"`LWG2921 `__","packaged_task and type-erased allocators","2017-02 (Kona)","|Complete|","20.0","Originally implemented in LLVM 6.0 but reverted later. Old documentation incorrectly said it was implemented." +"`LWG2921 `__","packaged_task and type-erased allocators","2017-02 (Kona)","|Complete|","20","Originally implemented in LLVM 6 but reverted later. Old documentation incorrectly said it was implemented." "`LWG2934 `__","optional doesn't compare with T","2017-02 (Kona)","|Complete|","","" "","","","","","" "`LWG2901 `__","Variants cannot properly support allocators","2017-07 (Toronto)","|Complete|","","" diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv index 7714f41ca19e0..aa59cabf24f78 100644 --- a/libcxx/docs/Status/Cxx17Papers.csv +++ b/libcxx/docs/Status/Cxx17Papers.csv @@ -2,16 +2,16 @@ "`N3911 `__","TransformationTrait Alias ``void_t``\ .","2014-11 (Urbana)","|Complete|","3.6","" "`N4089 `__","Safe conversions in ``unique_ptr``\ .","2014-11 (Urbana)","|In Progress|","3.9","" "`N4169 `__","A proposal to add invoke function template","2014-11 (Urbana)","|Complete|","3.7","" -"`N4190 `__","Removing auto_ptr, random_shuffle(), And Old Stuff.","2014-11 (Urbana)","|Complete|","15.0","" +"`N4190 `__","Removing auto_ptr, random_shuffle(), And Old Stuff.","2014-11 (Urbana)","|Complete|","15","" "`N4258 `__","Cleaning-up noexcept in the Library.","2014-11 (Urbana)","|In Progress|","3.7","" -"`N4259 `__","Wording for std::uncaught_exceptions","2014-11 (Urbana)","|Complete|","3.7","``std::uncaught_exception`` is deprecated since LLVM 20.0" +"`N4259 `__","Wording for std::uncaught_exceptions","2014-11 (Urbana)","|Complete|","3.7","``std::uncaught_exception`` is deprecated since LLVM 20" "`N4277 `__","TriviallyCopyable ``reference_wrapper``\ .","2014-11 (Urbana)","|Complete|","3.2","" "`N4279 `__","Improved insertion interface for unique-key maps.","2014-11 (Urbana)","|Complete|","3.7","" "`N4280 `__","Non-member size() and more","2014-11 (Urbana)","|Complete|","3.6","" "`N4284 `__","Contiguous Iterators.","2014-11 (Urbana)","|Complete|","3.6","" -"`N4285 `__","Cleanup for exception-specification and throw-expression.","2014-11 (Urbana)","|Complete|","4.0","" +"`N4285 `__","Cleanup for exception-specification and throw-expression.","2014-11 (Urbana)","|Complete|","4","" "","","","","","" -"`N4387 `__","improving pair and tuple","2015-05 (Lenexa)","|Complete|","4.0","" +"`N4387 `__","improving pair and tuple","2015-05 (Lenexa)","|Complete|","4","" "`N4389 `__","bool_constant","2015-05 (Lenexa)","|Complete|","3.7","" "`N4508 `__","shared_mutex for C++17","2015-05 (Lenexa)","|Complete|","3.7","" "`N4366 `__","LWG 2228 missing SFINAE rule","2015-05 (Lenexa)","|Complete|","3.1","" @@ -27,87 +27,87 @@ "","","","","","" "`P0024R2 `__","The Parallelism TS Should be Standardized","2016-02 (Jacksonville)","|Partial|","","" "`P0226R1 `__","Mathematical Special Functions for C++17","2016-02 (Jacksonville)","|In Progress|","","Progress is tracked `here `__" -"`P0220R1 `__","Adopt Library Fundamentals V1 TS Components for C++17","2016-02 (Jacksonville)","|Complete|","16.0","" -"`P0218R1 `__","Adopt the File System TS for C++17","2016-02 (Jacksonville)","|Complete|","7.0","" +"`P0220R1 `__","Adopt Library Fundamentals V1 TS Components for C++17","2016-02 (Jacksonville)","|Complete|","16","" +"`P0218R1 `__","Adopt the File System TS for C++17","2016-02 (Jacksonville)","|Complete|","7","" "`P0033R1 `__","Re-enabling shared_from_this","2016-02 (Jacksonville)","|Complete|","3.9","" "`P0005R4 `__","Adopt not_fn from Library Fundamentals 2 for C++17","2016-02 (Jacksonville)","|Complete|","3.9","" "`P0152R1 `__","constexpr ``atomic::is_always_lock_free``\ ","2016-02 (Jacksonville)","|Complete|","3.9","" "`P0185R1 `__","Adding [nothrow-]swappable traits","2016-02 (Jacksonville)","|Complete|","3.9","" "`P0253R1 `__","Fixing a design mistake in the searchers interface","2016-02 (Jacksonville)","|Complete|","3.9","" "`P0025R0 `__","An algorithm to ""clamp"" a value between a pair of boundary values","2016-02 (Jacksonville)","|Complete|","3.9","" -"`P0154R1 `__","constexpr std::hardware_{constructive,destructive}_interference_size","2016-02 (Jacksonville)","|Complete|","19.0","The required macros are only implemented as of LLVM 19." +"`P0154R1 `__","constexpr std::hardware_{constructive,destructive}_interference_size","2016-02 (Jacksonville)","|Complete|","19","The required macros are only implemented as of LLVM 19." "`P0030R1 `__","Proposal to Introduce a 3-Argument Overload to std::hypot","2016-02 (Jacksonville)","|Complete|","3.9","" -"`P0031R0 `__","A Proposal to Add Constexpr Modifiers to reverse_iterator, move_iterator, array and Range Access","2016-02 (Jacksonville)","|Complete|","4.0","" +"`P0031R0 `__","A Proposal to Add Constexpr Modifiers to reverse_iterator, move_iterator, array and Range Access","2016-02 (Jacksonville)","|Complete|","4","" "`P0272R1 `__","Give ``std::string``\ a non-const ``.data()``\ member function","2016-02 (Jacksonville)","|Complete|","3.9","" "`P0077R2 `__","``is_callable``\ , the missing INVOKE related trait","2016-02 (Jacksonville)","|Complete|","3.9","" "","","","","","" -"`P0032R3 `__","Homogeneous interface for variant, any and optional","2016-06 (Oulu)","|Complete|","4.0","" -"`P0040R3 `__","Extending memory management tools","2016-06 (Oulu)","|Complete|","4.0","" -"`P0063R3 `__","C++17 should refer to C11 instead of C99","2016-06 (Oulu)","|Complete|","7.0","" +"`P0032R3 `__","Homogeneous interface for variant, any and optional","2016-06 (Oulu)","|Complete|","4","" +"`P0040R3 `__","Extending memory management tools","2016-06 (Oulu)","|Complete|","4","" +"`P0063R3 `__","C++17 should refer to C11 instead of C99","2016-06 (Oulu)","|Complete|","7","" "`P0067R3 `__","Elementary string conversions","2016-06 (Oulu)","|Nothing To Do|","n/a","Resolved by `P0067R5 `__" -"`P0083R3 `__","Splicing Maps and Sets","2016-06 (Oulu)","|Complete|","8.0","" -"`P0084R2 `__","Emplace Return Type","2016-06 (Oulu)","|Complete|","4.0","" -"`P0088R3 `__","Variant: a type-safe union for C++17","2016-06 (Oulu)","|Complete|","4.0","" -"`P0137R1 `__","Core Issue 1776: Replacement of class objects containing reference members","2016-06 (Oulu)","|Complete|","6.0","" +"`P0083R3 `__","Splicing Maps and Sets","2016-06 (Oulu)","|Complete|","8","" +"`P0084R2 `__","Emplace Return Type","2016-06 (Oulu)","|Complete|","4","" +"`P0088R3 `__","Variant: a type-safe union for C++17","2016-06 (Oulu)","|Complete|","4","" +"`P0137R1 `__","Core Issue 1776: Replacement of class objects containing reference members","2016-06 (Oulu)","|Complete|","6","" "`P0163R0 `__","shared_ptr::weak_type","2016-06 (Oulu)","|Complete|","3.9","" -"`P0174R2 `__","Deprecating Vestigial Library Parts in C++17","2016-06 (Oulu)","|Complete|","15.0","" +"`P0174R2 `__","Deprecating Vestigial Library Parts in C++17","2016-06 (Oulu)","|Complete|","15","" "`P0175R1 `__","Synopses for the C library","2016-06 (Oulu)","","","" "`P0180R2 `__","Reserve a New Library Namespace for Future Standardization","2016-06 (Oulu)","|Nothing To Do|","n/a","" "`P0181R1 `__","Ordered by Default","2016-06 (Oulu)","|Nothing To Do|","n/a","Pulled at the 2017-01 meeting in Kona" "`P0209R2 `__","make_from_tuple: apply for construction","2016-06 (Oulu)","|Complete|","3.9","" -"`P0219R1 `__","Relative Paths for Filesystem","2016-06 (Oulu)","|Complete|","7.0","" -"`P0254R2 `__","Integrating std::string_view and std::string","2016-06 (Oulu)","|Complete|","4.0","" -"`P0258R2 `__","has_unique_object_representations","2016-06 (Oulu)","|Complete|","6.0","" -"`P0295R0 `__","Adopt Selected Library Fundamentals V2 Components for C++17","2016-06 (Oulu)","|Complete|","4.0","" -"`P0302R1 `__","Removing Allocator Support in std::function","2016-06 (Oulu)","|Complete|","4.0","" -"`P0307R2 `__","Making Optional Greater Equal Again","2016-06 (Oulu)","|Complete|","4.0","" -"`P0336R1 `__","Better Names for Parallel Execution Policies in C++17","2016-06 (Oulu)","|Complete|","17.0","" +"`P0219R1 `__","Relative Paths for Filesystem","2016-06 (Oulu)","|Complete|","7","" +"`P0254R2 `__","Integrating std::string_view and std::string","2016-06 (Oulu)","|Complete|","4","" +"`P0258R2 `__","has_unique_object_representations","2016-06 (Oulu)","|Complete|","6","" +"`P0295R0 `__","Adopt Selected Library Fundamentals V2 Components for C++17","2016-06 (Oulu)","|Complete|","4","" +"`P0302R1 `__","Removing Allocator Support in std::function","2016-06 (Oulu)","|Complete|","4","" +"`P0307R2 `__","Making Optional Greater Equal Again","2016-06 (Oulu)","|Complete|","4","" +"`P0336R1 `__","Better Names for Parallel Execution Policies in C++17","2016-06 (Oulu)","|Complete|","17","" "`P0337R0 `__","Delete ``operator=``\ for polymorphic_allocator","2016-06 (Oulu)","|Complete|","3.9","" "`P0346R1 `__","A Nomenclature Tweak","2016-06 (Oulu)","|Complete|","3.9","" "`P0358R1 `__","Fixes for not_fn","2016-06 (Oulu)","|Complete|","3.9","" "`P0371R1 `__","Temporarily discourage memory_order_consume","2016-06 (Oulu)","|Nothing To Do|","n/a","" -"`P0392R0 `__","Adapting string_view by filesystem paths","2016-06 (Oulu)","|Complete|","4.0","" -"`P0393R3 `__","Making Variant Greater Equal","2016-06 (Oulu)","|Complete|","4.0","" -"`P0394R4 `__","Hotel Parallelifornia: terminate() for Parallel Algorithms Exception Handling","2016-06 (Oulu)","|Complete|","17.0","" +"`P0392R0 `__","Adapting string_view by filesystem paths","2016-06 (Oulu)","|Complete|","4","" +"`P0393R3 `__","Making Variant Greater Equal","2016-06 (Oulu)","|Complete|","4","" +"`P0394R4 `__","Hotel Parallelifornia: terminate() for Parallel Algorithms Exception Handling","2016-06 (Oulu)","|Complete|","17","" "","","","","","" -"`P0003R5 `__","Removing Deprecated Exception Specifications from C++17","2016-11 (Issaquah)","|Complete|","5.0","" -"`P0067R5 `__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","``std::(to|from)_chars`` for integrals has been available since version 7.0. ``std::to_chars`` for ``float`` and ``double`` since version 14.0 ``std::to_chars`` for ``long double`` uses the implementation for ``double``. ``std::from_chars`` for ``float`` and ``double`` since version 20.0." -"`P0403R1 `__","Literal suffixes for ``basic_string_view``\ ","2016-11 (Issaquah)","|Complete|","4.0","" -"`P0414R2 `__","Merging shared_ptr changes from Library Fundamentals to C++17","2016-11 (Issaquah)","|Complete|","11.0","" +"`P0003R5 `__","Removing Deprecated Exception Specifications from C++17","2016-11 (Issaquah)","|Complete|","5","" +"`P0067R5 `__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","``std::(to|from)_chars`` for integrals has been available since version 7. ``std::to_chars`` for ``float`` and ``double`` since version 14 ``std::to_chars`` for ``long double`` uses the implementation for ``double``. ``std::from_chars`` for ``float`` and ``double`` since version 20." +"`P0403R1 `__","Literal suffixes for ``basic_string_view``\ ","2016-11 (Issaquah)","|Complete|","4","" +"`P0414R2 `__","Merging shared_ptr changes from Library Fundamentals to C++17","2016-11 (Issaquah)","|Complete|","11","" "`P0418R2 `__","Fail or succeed: there is no atomic lattice","2016-11 (Issaquah)","","","" -"`P0426R1 `__","Constexpr for ``std::char_traits``\ ","2016-11 (Issaquah)","|Complete|","4.0","" -"`P0435R1 `__","Resolving LWG Issues re ``common_type``\ ","2016-11 (Issaquah)","|Complete|","4.0","" +"`P0426R1 `__","Constexpr for ``std::char_traits``\ ","2016-11 (Issaquah)","|Complete|","4","" +"`P0435R1 `__","Resolving LWG Issues re ``common_type``\ ","2016-11 (Issaquah)","|Complete|","4","" "`P0502R0 `__","Throwing out of a parallel algorithm terminates - but how?","2016-11 (Issaquah)","","","" -"`P0503R0 `__","Correcting library usage of ""literal type""","2016-11 (Issaquah)","|Complete|","4.0","" -"`P0504R0 `__","Revisiting in-place tag types for any/optional/variant","2016-11 (Issaquah)","|Complete|","4.0","" -"`P0505R0 `__","Wording for GB 50 - constexpr for chrono","2016-11 (Issaquah)","|Complete|","4.0","" -"`P0508R0 `__","Wording for GB 58 - structured bindings for node_handles","2016-11 (Issaquah)","|Complete|","7.0","" +"`P0503R0 `__","Correcting library usage of ""literal type""","2016-11 (Issaquah)","|Complete|","4","" +"`P0504R0 `__","Revisiting in-place tag types for any/optional/variant","2016-11 (Issaquah)","|Complete|","4","" +"`P0505R0 `__","Wording for GB 50 - constexpr for chrono","2016-11 (Issaquah)","|Complete|","4","" +"`P0508R0 `__","Wording for GB 58 - structured bindings for node_handles","2016-11 (Issaquah)","|Complete|","7","" "`P0509R1 `__","Updating ""Restrictions on exception handling""","2016-11 (Issaquah)","|Nothing To Do|","n/a","" -"`P0510R0 `__","Disallowing references, incomplete types, arrays, and empty variants","2016-11 (Issaquah)","|Complete|","4.0","" -"`P0513R0 `__","Poisoning the Hash","2016-11 (Issaquah)","|Complete|","5.0","" -"`P0516R0 `__","Clarify That shared_future's Copy Operations have Wide Contracts","2016-11 (Issaquah)","|Complete|","4.0","" -"`P0517R0 `__","Make future_error Constructible","2016-11 (Issaquah)","|Complete|","4.0","" -"`P0521R0 `__","Proposed Resolution for CA 14 (shared_ptr use_count/unique)","2016-11 (Issaquah)","|Complete|","18.0","" +"`P0510R0 `__","Disallowing references, incomplete types, arrays, and empty variants","2016-11 (Issaquah)","|Complete|","4","" +"`P0513R0 `__","Poisoning the Hash","2016-11 (Issaquah)","|Complete|","5","" +"`P0516R0 `__","Clarify That shared_future's Copy Operations have Wide Contracts","2016-11 (Issaquah)","|Complete|","4","" +"`P0517R0 `__","Make future_error Constructible","2016-11 (Issaquah)","|Complete|","4","" +"`P0521R0 `__","Proposed Resolution for CA 14 (shared_ptr use_count/unique)","2016-11 (Issaquah)","|Complete|","18","" "","","","","","" -"`P0156R2 `__","Variadic Lock guard(rev 5)","2017-02 (Kona)","|Complete|","5.0","" +"`P0156R2 `__","Variadic Lock guard(rev 5)","2017-02 (Kona)","|Complete|","5","" "`P0270R3 `__","Removing C dependencies from signal handler wording","2017-02 (Kona)","","","" -"`P0298R3 `__","A byte type definition","2017-02 (Kona)","|Complete|","5.0","" -"`P0317R1 `__","Directory Entry Caching for Filesystem","2017-02 (Kona)","|Complete|","7.0","" -"`P0430R2 `__","File system library on non-POSIX-like operating systems","2017-02 (Kona)","|Complete|","7.0","" -"`P0433R2 `__","Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library","2017-02 (Kona)","|Complete|","14.0","" +"`P0298R3 `__","A byte type definition","2017-02 (Kona)","|Complete|","5","" +"`P0317R1 `__","Directory Entry Caching for Filesystem","2017-02 (Kona)","|Complete|","7","" +"`P0430R2 `__","File system library on non-POSIX-like operating systems","2017-02 (Kona)","|Complete|","7","" +"`P0433R2 `__","Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library","2017-02 (Kona)","|Complete|","14","" "`P0452R1 `__","Unifying Parallel Algorithms","2017-02 (Kona)","|Partial|","","The changes to ``std::transform_inclusive_scan`` and ``std::transform_exclusive_scan`` have not yet been implemented." "`P0467R2 `__","Iterator Concerns for Parallel Algorithms","2017-02 (Kona)","|Partial|","","" -"`P0492R2 `__","Proposed Resolution of C++17 National Body Comments for Filesystems","2017-02 (Kona)","|Complete|","7.0","" +"`P0492R2 `__","Proposed Resolution of C++17 National Body Comments for Filesystems","2017-02 (Kona)","|Complete|","7","" "`P0518R1 `__","Allowing copies as arguments to function objects given to parallel algorithms in response to CH11","2017-02 (Kona)","|Nothing To Do|","","" "`P0523R1 `__","Wording for CH 10: Complexity of parallel algorithms","2017-02 (Kona)","|Nothing To Do|","","" -"`P0548R1 `__","common_type and duration","2017-02 (Kona)","|Complete|","5.0","" +"`P0548R1 `__","common_type and duration","2017-02 (Kona)","|Complete|","5","" "`P0558R1 `__","Resolving atomic named base class inconsistencies","2017-02 (Kona)","|Complete|","","" "`P0574R1 `__","Algorithm Complexity Constraints and Parallel Overloads","2017-02 (Kona)","|Nothing To Do|","","" -"`P0599R1 `__","noexcept for hash functions","2017-02 (Kona)","|Complete|","5.0","" +"`P0599R1 `__","noexcept for hash functions","2017-02 (Kona)","|Complete|","5","" "`P0604R0 `__","Resolving GB 55, US 84, US 85, US 86","2017-02 (Kona)","|Complete|","","" -"`P0607R0 `__","Inline Variables for the Standard Library","2017-02 (Kona)","|In Progress|","6.0","The parts of P0607 that are not done are the ```` bits" -"`P0618R0 `__","Deprecating ","2017-02 (Kona)","|Complete|","15.0","" +"`P0607R0 `__","Inline Variables for the Standard Library","2017-02 (Kona)","|In Progress|","6","The parts of P0607 that are not done are the ```` bits" +"`P0618R0 `__","Deprecating ","2017-02 (Kona)","|Complete|","15","" "`P0623R0 `__","Final C++17 Parallel Algorithms Fixes","2017-02 (Kona)","|Nothing To Do|","","" "","","","","","" "`P0682R1 `__","Repairing elementary string conversions","2017-07 (Toronto)","","","" -"`P0739R0 `__","Some improvements to class template argument deduction integration into the standard library","2017-07 (Toronto)","|Complete|","5.0","" +"`P0739R0 `__","Some improvements to class template argument deduction integration into the standard library","2017-07 (Toronto)","|Complete|","5","" diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv index b0fa5346e873d..3462557e8d668 100644 --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -9,7 +9,7 @@ "`LWG2940 `__","``result_of``\ specification also needs a little cleanup","2017-07 (Toronto)","|Nothing To Do|","","" "`LWG2942 `__","LWG 2873's resolution missed ``weak_ptr::owner_before``\ ","2017-07 (Toronto)","|Complete|","","" "`LWG2954 `__","Specialization of the convenience variable templates should be prohibited","2017-07 (Toronto)","|Complete|","","" -"`LWG2961 `__","Bad postcondition for ``set_default_resource``\ ","2017-07 (Toronto)","|Complete|","16.0","" +"`LWG2961 `__","Bad postcondition for ``set_default_resource``\ ","2017-07 (Toronto)","|Complete|","16","" "`LWG2966 `__","Incomplete resolution of US 74","2017-07 (Toronto)","|Nothing To Do|","","" "`LWG2974 `__","Diagnose out of bounds ``tuple_element/variant_alternative``\ ","2017-07 (Toronto)","|Complete|","","" "","","","","","" @@ -27,17 +27,17 @@ "`LWG2964 `__","Apparently redundant requirement for dynamic_pointer_cast","2017-11 (Albuquerque)","","","" "`LWG2965 `__","Non-existing path::native_string() in filesystem_error::what() specification","2017-11 (Albuquerque)","|Nothing To Do|","","" "`LWG2972 `__","What is ``is_trivially_destructible_v``\ ?","2017-11 (Albuquerque)","|Complete|","","" -"`LWG2976 `__","Dangling uses_allocator specialization for packaged_task","2017-11 (Albuquerque)","|Complete|","20.0","Originally implemented in LLVM 6.0 but reverted later. Old documentation incorrectly said it was implemented." +"`LWG2976 `__","Dangling uses_allocator specialization for packaged_task","2017-11 (Albuquerque)","|Complete|","20","Originally implemented in LLVM 6 but reverted later. Old documentation incorrectly said it was implemented." "`LWG2977 `__","unordered_meow::merge() has incorrect Throws: clause","2017-11 (Albuquerque)","|Nothing To Do|","","" -"`LWG2978 `__","Hash support for pmr::string and friends","2017-11 (Albuquerque)","|Complete|","16.0","" +"`LWG2978 `__","Hash support for pmr::string and friends","2017-11 (Albuquerque)","|Complete|","16","" "`LWG2979 `__","aligned_union should require complete object types","2017-11 (Albuquerque)","|Complete|","","" "`LWG2980 `__","Cannot compare_exchange empty pointers","2017-11 (Albuquerque)","","","" "`LWG2981 `__","Remove redundant deduction guides from standard library","2017-11 (Albuquerque)","|Nothing To Do|","","" "`LWG2982 `__","Making size_type consistent in associative container deduction guides","2017-11 (Albuquerque)","","","" -"`LWG2988 `__","Clause 32 cleanup missed one typename","2017-11 (Albuquerque)","|Complete|","13.0","" -"`LWG2993 `__","reference_wrapper conversion from T&&","2017-11 (Albuquerque)","|Complete|","13.0","" +"`LWG2988 `__","Clause 32 cleanup missed one typename","2017-11 (Albuquerque)","|Complete|","13","" +"`LWG2993 `__","reference_wrapper conversion from T&&","2017-11 (Albuquerque)","|Complete|","13","" "`LWG2998 `__","Requirements on function objects passed to {``forward_``,}list-specific algorithms","2017-11 (Albuquerque)","|Nothing To Do|","","" -"`LWG3001 `__","weak_ptr::element_type needs remove_extent_t","2017-11 (Albuquerque)","|Complete|","14.0","" +"`LWG3001 `__","weak_ptr::element_type needs remove_extent_t","2017-11 (Albuquerque)","|Complete|","14","" "`LWG3024 `__","variant's copies must be deleted instead of disabled via SFINAE","2017-11 (Albuquerque)","|Complete|","","" "","","","","","" "`LWG2164 `__","What are the semantics of ``vector.emplace(vector.begin(), vector.back())``\ ?","2018-03 (Jacksonville)","|Complete|","","" @@ -50,7 +50,7 @@ "`LWG2969 `__","``polymorphic_allocator::construct()``\ shouldn't pass ``resource()``\ ","2018-03 (Jacksonville)","|Complete|","","" "`LWG2975 `__","Missing case for ``pair``\ construction in scoped and polymorphic allocators","2018-03 (Jacksonville)","","","" "`LWG2989 `__","``path``\ 's stream insertion operator lets you insert everything under the sun","2018-03 (Jacksonville)","|Complete|","","" -"`LWG3000 `__","``monotonic_memory_resource::do_is_equal``\ uses ``dynamic_cast``\ unnecessarily","2018-03 (Jacksonville)","|Complete|","16.0","" +"`LWG3000 `__","``monotonic_memory_resource::do_is_equal``\ uses ``dynamic_cast``\ unnecessarily","2018-03 (Jacksonville)","|Complete|","16","" "`LWG3002 `__","[networking.ts] ``basic_socket_acceptor::is_open()``\ isn't ``noexcept``\ ","2018-03 (Jacksonville)","","","" "`LWG3004 `__","|sect|\ [string.capacity] and |sect|\ [vector.capacity] should specify time complexity for ``capacity()``\ ","2018-03 (Jacksonville)","|Nothing To Do|","","" "`LWG3005 `__","Destruction order of arrays by ``make_shared/allocate_shared``\ only recommended?","2018-03 (Jacksonville)","","","" @@ -70,15 +70,15 @@ "`LWG3041 `__","Unnecessary ``decay``\ in ``reference_wrapper``\ ","2018-03 (Jacksonville)","|Complete|","","" "`LWG3042 `__","``is_literal_type_v``\ should be inline","2018-03 (Jacksonville)","|Complete|","","" "`LWG3043 `__","Bogus postcondition for ``filesystem_error``\ constructor","2018-03 (Jacksonville)","|Complete|","","" -"`LWG3045 `__","``atomic``\ doesn't have ``value_type``\ or ``difference_type``\ ","2018-03 (Jacksonville)","|Complete|","18.0","" -"`LWG3048 `__","``transform_reduce(exec, first1, last1, first2, init)``\ discards execution policy","2018-03 (Jacksonville)","|Complete|","17.0","" +"`LWG3045 `__","``atomic``\ doesn't have ``value_type``\ or ``difference_type``\ ","2018-03 (Jacksonville)","|Complete|","18","" +"`LWG3048 `__","``transform_reduce(exec, first1, last1, first2, init)``\ discards execution policy","2018-03 (Jacksonville)","|Complete|","17","" "`LWG3051 `__","Floating point classifications were inadvertently changed in P0175","2018-03 (Jacksonville)","|Nothing To Do|","","" "`LWG3075 `__","``basic_string``\ needs deduction guides from ``basic_string_view``\ ","2018-03 (Jacksonville)","|Complete|","","" "","","","","","" "`LWG2139 `__","What is a user-defined type?","2018-06 (Rapperswil)","","","" -"`LWG2970 `__","Return type of std::visit misspecified","2018-06 (Rapperswil)","|Complete|","11.0","" +"`LWG2970 `__","Return type of std::visit misspecified","2018-06 (Rapperswil)","|Complete|","11","" "`LWG3058 `__","Parallel adjacent_difference shouldn't require creating temporaries","2018-06 (Rapperswil)","","","" -"`LWG3062 `__","Unnecessary decay_t in is_execution_policy_v should be remove_cvref_t","2018-06 (Rapperswil)","|Complete|","17.0","" +"`LWG3062 `__","Unnecessary decay_t in is_execution_policy_v should be remove_cvref_t","2018-06 (Rapperswil)","|Complete|","17","" "`LWG3067 `__","recursive_directory_iterator::pop must invalidate","2018-06 (Rapperswil)","|Nothing To Do|","","" "`LWG3071 `__","[networking.ts] read_until still refers to ""input sequence""","2018-06 (Rapperswil)","|Nothing To Do|","","" "`LWG3074 `__","Non-member functions for valarray should only deduce from the valarray","2018-06 (Rapperswil)","","","" @@ -101,23 +101,23 @@ "`LWG2936 `__","Path comparison is defined in terms of the generic format","2018-11 (San Diego)","|Complete|","","" "`LWG2943 `__","Problematic specification of the wide version of ``basic_filebuf::open``\ ","2018-11 (San Diego)","|Nothing To Do|","","" "`LWG2960 `__","[fund.ts.v3] ``nonesuch``\ is insufficiently useless","2018-11 (San Diego)","|Complete|","","" -"`LWG2995 `__","``basic_stringbuf``\ default constructor forbids it from using SSO capacity","2018-11 (San Diego)","|Complete|","20.0","" -"`LWG2996 `__","Missing rvalue overloads for ``shared_ptr``\ operations","2018-11 (San Diego)","|Complete|","17.0","" -"`LWG3008 `__","``make_shared``\ (sub)object destruction semantics are not specified","2018-11 (San Diego)","|Complete|","16.0","" +"`LWG2995 `__","``basic_stringbuf``\ default constructor forbids it from using SSO capacity","2018-11 (San Diego)","|Complete|","20","" +"`LWG2996 `__","Missing rvalue overloads for ``shared_ptr``\ operations","2018-11 (San Diego)","|Complete|","17","" +"`LWG3008 `__","``make_shared``\ (sub)object destruction semantics are not specified","2018-11 (San Diego)","|Complete|","16","" "`LWG3022 `__","``is_convertible``\ may lead to ODR","2018-11 (San Diego)","|Nothing To Do|","","Resolved by `P1285R0 `__" "`LWG3025 `__","Map-like container deduction guides should use ``pair``\ , not ``pair``\ ","2018-11 (San Diego)","|Complete|","","" "`LWG3031 `__","Algorithms and predicates with non-const reference arguments","2018-11 (San Diego)","","","" -"`LWG3037 `__","``polymorphic_allocator``\ and incomplete types","2018-11 (San Diego)","|Complete|","16.0","" -"`LWG3038 `__","``polymorphic_allocator::allocate``\ should not allow integer overflow to create vulnerabilities","2018-11 (San Diego)","|Complete|","14.0","" +"`LWG3037 `__","``polymorphic_allocator``\ and incomplete types","2018-11 (San Diego)","|Complete|","16","" +"`LWG3038 `__","``polymorphic_allocator::allocate``\ should not allow integer overflow to create vulnerabilities","2018-11 (San Diego)","|Complete|","14","" "`LWG3054 `__","``uninitialized_copy``\ appears to not be able to meet its exception-safety guarantee","2018-11 (San Diego)","|Nothing To Do|","","" "`LWG3065 `__","LWG 2989 missed that all ``path``\ 's other operators should be hidden friends as well","2018-11 (San Diego)","|Complete|","","" "`LWG3096 `__","``path::lexically_relative``\ is confused by trailing slashes","2018-11 (San Diego)","|Complete|","","" "`LWG3116 `__","``OUTERMOST_ALLOC_TRAITS``\ needs ``remove_reference_t``\ ","2018-11 (San Diego)","","","" "`LWG3122 `__","``__cpp_lib_chrono_udls``\ was accidentally dropped","2018-11 (San Diego)","|Complete|","","" -"`LWG3127 `__","``basic_osyncstream::rdbuf``\ needs a ``const_cast``\ ","2018-11 (San Diego)","|Complete|","18.0","" +"`LWG3127 `__","``basic_osyncstream::rdbuf``\ needs a ``const_cast``\ ","2018-11 (San Diego)","|Complete|","18","" "`LWG3128 `__","``strstream::rdbuf``\ needs a ``const_cast``\ ","2018-11 (San Diego)","|Nothing To Do|","","" "`LWG3129 `__","``regex_token_iterator``\ constructor uses wrong pointer arithmetic","2018-11 (San Diego)","","","" -"`LWG3130 `__","|sect|\ [input.output] needs many ``addressof``\ ","2018-11 (San Diego)","|Complete|","20.0","" +"`LWG3130 `__","|sect|\ [input.output] needs many ``addressof``\ ","2018-11 (San Diego)","|Complete|","20","" "`LWG3131 `__","``addressof``\ all the things","2018-11 (San Diego)","","","" "`LWG3132 `__","Library needs to ban macros named ``expects``\ or ``ensures``\ ","2018-11 (San Diego)","|Nothing To Do|","","" "`LWG3134 `__","[fund.ts.v3] LFTSv3 contains extraneous [meta] variable templates that should have been deleted by P09961","2018-11 (San Diego)","|Nothing To Do|","","Resolved by `P1210R0 `__" @@ -126,7 +126,7 @@ "`LWG3145 `__","``file_clock``\ breaks ABI for C++17 implementations","2018-11 (San Diego)","|Complete|","","" "`LWG3147 `__","Definitions of ""likely"" and ""unlikely"" are likely to cause problems","2018-11 (San Diego)","|Nothing To Do|","","" "`LWG3148 `__","````\ should be freestanding","2018-11 (San Diego)","","","" -"`LWG3153 `__","``Common``\ and ``common_type``\ have too little in common","2018-11 (San Diego)","|Complete|","13.0","" +"`LWG3153 `__","``Common``\ and ``common_type``\ have too little in common","2018-11 (San Diego)","|Complete|","13","" "`LWG3154 `__","``Common``\ and ``CommonReference``\ have a common defect","2018-11 (San Diego)","|Nothing To Do|","","" "","","","","","" "`LWG3012 `__","``atomic``\ is unimplementable for non-``is_trivially_copy_constructible T``\ ","2019-02 (Kona)","","","" @@ -138,165 +138,165 @@ "`LWG3119 `__","Program-definedness of closure types","2019-02 (Kona)","|Nothing To Do|","","" "`LWG3133 `__","Modernizing numeric type requirements","2019-02 (Kona)","","","" "`LWG3144 `__","``span``\ does not have a ``const_pointer``\ typedef","2019-02 (Kona)","|Complete|","","" -"`LWG3173 `__","Enable CTAD for ``ref-view``\ ","2019-02 (Kona)","|Complete|","15.0","" +"`LWG3173 `__","Enable CTAD for ``ref-view``\ ","2019-02 (Kona)","|Complete|","15","" "`LWG3179 `__","``subrange``\ should always model ``Range``\ ","2019-02 (Kona)","|Nothing To Do|","","" -"`LWG3180 `__","Inconsistently named return type for ``ranges::minmax_element``\ ","2019-02 (Kona)","|Complete|","15.0","" -"`LWG3182 `__","Specification of ``Same``\ could be clearer","2019-02 (Kona)","|Complete|","15.0","" +"`LWG3180 `__","Inconsistently named return type for ``ranges::minmax_element``\ ","2019-02 (Kona)","|Complete|","15","" +"`LWG3182 `__","Specification of ``Same``\ could be clearer","2019-02 (Kona)","|Complete|","15","" "","","","","","" "`LWG2899 `__","``is_(nothrow_)move_constructible``\ and ``tuple``\ , ``optional``\ and ``unique_ptr``\ ","2019-07 (Cologne)","","","" -"`LWG3055 `__","``path::operator+=(*single-character*)``\ misspecified","2019-07 (Cologne)","|Complete|","7.0","" -"`LWG3158 `__","``tuple(allocator_arg_t, const Alloc&)``\ should be conditionally explicit","2019-07 (Cologne)","|Complete|","10.0","" -"`LWG3169 `__","``ranges``\ permutation generators discard useful information","2019-07 (Cologne)","|Complete|","15.0","" +"`LWG3055 `__","``path::operator+=(*single-character*)``\ misspecified","2019-07 (Cologne)","|Complete|","7","" +"`LWG3158 `__","``tuple(allocator_arg_t, const Alloc&)``\ should be conditionally explicit","2019-07 (Cologne)","|Complete|","10","" +"`LWG3169 `__","``ranges``\ permutation generators discard useful information","2019-07 (Cologne)","|Complete|","15","" "`LWG3183 `__","Normative permission to specialize Ranges variable templates","2019-07 (Cologne)","|Nothing To Do|","","" -"`LWG3184 `__","Inconsistencies in ``bind_front``\ wording","2019-07 (Cologne)","|Complete|","13.0","" -"`LWG3185 `__","Uses-allocator construction functions missing ``constexpr``\ and ``noexcept``\ ","2019-07 (Cologne)","|Complete|","16.0","" -"`LWG3186 `__","``ranges``\ removal, partition, and ``partial_sort_copy``\ algorithms discard useful information","2019-07 (Cologne)","|Complete|","15.0","" +"`LWG3184 `__","Inconsistencies in ``bind_front``\ wording","2019-07 (Cologne)","|Complete|","13","" +"`LWG3185 `__","Uses-allocator construction functions missing ``constexpr``\ and ``noexcept``\ ","2019-07 (Cologne)","|Complete|","16","" +"`LWG3186 `__","``ranges``\ removal, partition, and ``partial_sort_copy``\ algorithms discard useful information","2019-07 (Cologne)","|Complete|","15","" "`LWG3187 `__","`P0591R4 `__ reverted DR 2586 fixes to ``scoped_allocator_adaptor::construct()``\ ","2019-07 (Cologne)","","","" -"`LWG3191 `__","``std::ranges::shuffle``\ synopsis does not match algorithm definition","2019-07 (Cologne)","|Complete|","15.0","" +"`LWG3191 `__","``std::ranges::shuffle``\ synopsis does not match algorithm definition","2019-07 (Cologne)","|Complete|","15","" "`LWG3196 `__","``std::optional``\ is ill-formed is ``T``\ is an array","2019-07 (Cologne)","|Complete|","","" "`LWG3198 `__","Bad constraint on ``std::span::span()``\ ","2019-07 (Cologne)","|Complete|","","" -"`LWG3199 `__","``istream >> bitset<0>``\ fails","2019-07 (Cologne)","|Complete|","10.0","" +"`LWG3199 `__","``istream >> bitset<0>``\ fails","2019-07 (Cologne)","|Complete|","10","" "`LWG3202 `__","P0318R1 was supposed to be revised","2019-07 (Cologne)","|Complete|","","" "`LWG3206 `__","``year_month_day``\ conversion to ``sys_days``\ uses not-existing member function","2019-07 (Cologne)","|Complete|","","" "`LWG3208 `__","``Boolean``\ 's expression requirements are ordered inconsistently","2019-07 (Cologne)","|Nothing To Do|","","" "`LWG3209 `__","Expression in ``year::ok()``\ returns clause is ill-formed","2019-07 (Cologne)","|Complete|","","" "","","","","","" "`LWG3231 `__","``year_month_day_last::day``\ specification does not cover ``!ok()``\ values","2019-11 (Belfast)","|Nothing To Do|","","" -"`LWG3225 `__","``zoned_time``\ converting constructor shall not be ``noexcept``\ ","2019-11 (Belfast)","|Complete|","19.0","" -"`LWG3190 `__","``std::allocator::allocate``\ sometimes returns too little storage","2019-11 (Belfast)","|Complete|","14.0","" +"`LWG3225 `__","``zoned_time``\ converting constructor shall not be ``noexcept``\ ","2019-11 (Belfast)","|Complete|","19","" +"`LWG3190 `__","``std::allocator::allocate``\ sometimes returns too little storage","2019-11 (Belfast)","|Complete|","14","" "`LWG3218 `__","Modifier for ``%d``\ parse flag does not match POSIX and ``format``\ specification","2019-11 (Belfast)","","","" -"`LWG3224 `__","``zoned_time``\ constructor from ``TimeZonePtr``\ does not specify initialization of ``tp_``\ ","2019-11 (Belfast)","|Complete|","19.0","" -"`LWG3230 `__","Format specifier ``%y/%Y``\ is missing locale alternative versions","2019-11 (Belfast)","|Complete|","16.0","" -"`LWG3232 `__","Inconsistency in ``zoned_time``\ deduction guides","2019-11 (Belfast)","|Complete|","19.0","" +"`LWG3224 `__","``zoned_time``\ constructor from ``TimeZonePtr``\ does not specify initialization of ``tp_``\ ","2019-11 (Belfast)","|Complete|","19","" +"`LWG3230 `__","Format specifier ``%y/%Y``\ is missing locale alternative versions","2019-11 (Belfast)","|Complete|","16","" +"`LWG3232 `__","Inconsistency in ``zoned_time``\ deduction guides","2019-11 (Belfast)","|Complete|","19","" "`LWG3222 `__","P0574R1 introduced preconditions on non-existent parameters","2019-11 (Belfast)","","","" -"`LWG3221 `__","Result of ``year_month``\ arithmetic with ``months``\ is ambiguous","2019-11 (Belfast)","|Complete|","8.0","" +"`LWG3221 `__","Result of ``year_month``\ arithmetic with ``months``\ is ambiguous","2019-11 (Belfast)","|Complete|","8","" "`LWG3235 `__","``parse``\ manipulator without abbreviation is not callable","2019-11 (Belfast)","","","" "`LWG3246 `__","LWG3246: What are the constraints on the template parameter of `basic_format_arg`?","2019-11 (Belfast)","|Nothing To Do|","","" -"`LWG3253 `__","``basic_syncbuf::basic_syncbuf()``\ should not be explicit","2019-11 (Belfast)","|Complete|","20.0","" +"`LWG3253 `__","``basic_syncbuf::basic_syncbuf()``\ should not be explicit","2019-11 (Belfast)","|Complete|","20","" "`LWG3245 `__","Unnecessary restriction on ``'%p'``\ parse specifier","2019-11 (Belfast)","","","" "`LWG3244 `__","Constraints for ``Source``\ in |sect|\ [fs.path.req] insufficiently constrainty","2019-11 (Belfast)","","","" -"`LWG3241 `__","``chrono-spec``\ grammar ambiguity in |sect|\ [time.format]","2019-11 (Belfast)","|Complete|","16.0","" -"`LWG3257 `__","Missing feature testing macro update from P0858","2019-11 (Belfast)","|Complete|","12.0","" -"`LWG3256 `__","Feature testing macro for ``constexpr``\ algorithms","2019-11 (Belfast)","|Complete|","13.0","" -"`LWG3273 `__","Specify ``weekday_indexed``\ to range of ``[0, 7]``\ ","2019-11 (Belfast)","|Complete|","16.0","" +"`LWG3241 `__","``chrono-spec``\ grammar ambiguity in |sect|\ [time.format]","2019-11 (Belfast)","|Complete|","16","" +"`LWG3257 `__","Missing feature testing macro update from P0858","2019-11 (Belfast)","|Complete|","12","" +"`LWG3256 `__","Feature testing macro for ``constexpr``\ algorithms","2019-11 (Belfast)","|Complete|","13","" +"`LWG3273 `__","Specify ``weekday_indexed``\ to range of ``[0, 7]``\ ","2019-11 (Belfast)","|Complete|","16","" "`LWG3070 `__","``path::lexically_relative``\ causes surprising results if a filename can also be a *root-name*","2019-11 (Belfast)","","","" -"`LWG3266 `__","``to_chars(bool)``\ should be deleted","2019-11 (Belfast)","|Complete|","14.0","" +"`LWG3266 `__","``to_chars(bool)``\ should be deleted","2019-11 (Belfast)","|Complete|","14","" "`LWG3272 `__","``%I%p``\ should parse/format ``duration``\ since midnight","2019-11 (Belfast)","","","" "`LWG3259 `__","The definition of *constexpr iterators* should be adjusted","2019-11 (Belfast)","|Nothing To Do|","","" -"`LWG3103 `__","Errors in taking subview of ``span``\ should be ill-formed where possible","2019-11 (Belfast)","|Complete|","11.0","" -"`LWG3274 `__","Missing feature test macro for ````\ ","2019-11 (Belfast)","|Complete|","11.0","" -"`LWG3276 `__","Class ``split_view::outer_iterator::value_type``\ should inherit from ``view_interface``\ ","2019-11 (Belfast)","|Complete|","15.0","" +"`LWG3103 `__","Errors in taking subview of ``span``\ should be ill-formed where possible","2019-11 (Belfast)","|Complete|","11","" +"`LWG3274 `__","Missing feature test macro for ````\ ","2019-11 (Belfast)","|Complete|","11","" +"`LWG3276 `__","Class ``split_view::outer_iterator::value_type``\ should inherit from ``view_interface``\ ","2019-11 (Belfast)","|Complete|","15","" "`LWG3277 `__","Pre-increment on prvalues is not a requirement of ``weakly_incrementable``\ ","2019-11 (Belfast)","|Nothing To Do|","","" -"`LWG3149 `__","``DefaultConstructible``\ should require default initialization","2019-11 (Belfast)","|Complete|","13.0","" +"`LWG3149 `__","``DefaultConstructible``\ should require default initialization","2019-11 (Belfast)","|Complete|","13","" "","","","","","" -"`LWG1203 `__","More useful rvalue stream insertion","2020-02 (Prague)","|Complete|","12.0","" +"`LWG1203 `__","More useful rvalue stream insertion","2020-02 (Prague)","|Complete|","12","" "`LWG2859 `__","Definition of *reachable* in [ptr.launder] misses pointer arithmetic from pointer-interconvertible object","2020-02 (Prague)","","","" "`LWG3018 `__","``shared_ptr``\ of function type","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3050 `__","Conversion specification problem in ``chrono::duration``\ constructor","2020-02 (Prague)","|Complete|","19.0","" +"`LWG3050 `__","Conversion specification problem in ``chrono::duration``\ constructor","2020-02 (Prague)","|Complete|","19","" "`LWG3141 `__","``CopyConstructible``\ doesn't preserve source values","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3150 `__","``UniformRandomBitGenerator``\ should validate ``min``\ and ``max``\ ","2020-02 (Prague)","|Complete|","13.0","" -"`LWG3175 `__","The ``CommonReference``\ requirement of concept ``SwappableWith``\ is not satisfied in the example","2020-02 (Prague)","|Complete|","13.0","" -"`LWG3194 `__","``ConvertibleTo``\ prose does not match code","2020-02 (Prague)","|Complete|","13.0","" +"`LWG3150 `__","``UniformRandomBitGenerator``\ should validate ``min``\ and ``max``\ ","2020-02 (Prague)","|Complete|","13","" +"`LWG3175 `__","The ``CommonReference``\ requirement of concept ``SwappableWith``\ is not satisfied in the example","2020-02 (Prague)","|Complete|","13","" +"`LWG3194 `__","``ConvertibleTo``\ prose does not match code","2020-02 (Prague)","|Complete|","13","" "`LWG3200 `__","``midpoint``\ should not constrain ``T``\ is complete","2020-02 (Prague)","|Nothing To Do|","","" "`LWG3201 `__","``lerp``\ should be marked as ``noexcept``\ ","2020-02 (Prague)","|Complete|","","" -"`LWG3226 `__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time``\ ","2020-02 (Prague)","|Complete|","19.0","" -"`LWG3233 `__","Broken requirements for ``shared_ptr``\ converting constructors","2020-02 (Prague)","|Complete|","19.0","" -"`LWG3237 `__","LWG 3038 and 3190 have inconsistent PRs","2020-02 (Prague)","|Complete|","16.0","" +"`LWG3226 `__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time``\ ","2020-02 (Prague)","|Complete|","19","" +"`LWG3233 `__","Broken requirements for ``shared_ptr``\ converting constructors","2020-02 (Prague)","|Complete|","19","" +"`LWG3237 `__","LWG 3038 and 3190 have inconsistent PRs","2020-02 (Prague)","|Complete|","16","" "`LWG3238 `__","Insufficiently-defined behavior of ``std::function``\ deduction guides","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3242 `__","``std::format``\ : missing rules for ``arg-id``\ in ``width``\ and ``precision``\ ","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3243 `__","``std::format``\ and negative zeroes","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3247 `__","``ranges::iter_move``\ should perform ADL-only lookup of ``iter_move``\ ","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3248 `__","``std::format``\ ``#b``\ , ``#B``\ , ``#o``\ , ``#x``\ , and ``#X``\ presentation types misformat negative numbers","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3250 `__","``std::format``\ : ``#``\ (alternate form) for NaN and inf","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3251 `__","Are ``std::format``\ alignment specifiers applied to string arguments?","2020-02 (Prague)","|Complete|","14.0","" +"`LWG3242 `__","``std::format``\ : missing rules for ``arg-id``\ in ``width``\ and ``precision``\ ","2020-02 (Prague)","|Complete|","14","" +"`LWG3243 `__","``std::format``\ and negative zeroes","2020-02 (Prague)","|Complete|","14","" +"`LWG3247 `__","``ranges::iter_move``\ should perform ADL-only lookup of ``iter_move``\ ","2020-02 (Prague)","|Complete|","15","" +"`LWG3248 `__","``std::format``\ ``#b``\ , ``#B``\ , ``#o``\ , ``#x``\ , and ``#X``\ presentation types misformat negative numbers","2020-02 (Prague)","|Complete|","14","" +"`LWG3250 `__","``std::format``\ : ``#``\ (alternate form) for NaN and inf","2020-02 (Prague)","|Complete|","14","" +"`LWG3251 `__","Are ``std::format``\ alignment specifiers applied to string arguments?","2020-02 (Prague)","|Complete|","14","" "`LWG3252 `__","Parse locale's aware modifiers for commands are not consistent with POSIX spec","2020-02 (Prague)","","","" -"`LWG3254 `__","Strike ``stop_token``\ 's ``operator!=``\ ","2020-02 (Prague)","|Complete|","17.0","" +"`LWG3254 `__","Strike ``stop_token``\ 's ``operator!=``\ ","2020-02 (Prague)","|Complete|","17","" "`LWG3255 `__","``span``\ 's ``array``\ constructor is too strict","2020-02 (Prague)","|Complete|","","" "`LWG3260 `__","``year_month*``\ arithmetic rejects durations convertible to years","2020-02 (Prague)","","","" -"`LWG3262 `__","Formatting of negative durations is not specified","2020-02 (Prague)","|Complete|","16.0","" -"`LWG3264 `__","``sized_range``\ and ``ranges::size``\ redundantly use ``disable_sized_range``\ ","2020-02 (Prague)","|Complete|","15.0","" +"`LWG3262 `__","Formatting of negative durations is not specified","2020-02 (Prague)","|Complete|","16","" +"`LWG3264 `__","``sized_range``\ and ``ranges::size``\ redundantly use ``disable_sized_range``\ ","2020-02 (Prague)","|Complete|","15","" "`LWG3269 `__","Parse manipulators do not specify the result of the extraction from stream","2020-02 (Prague)","","","" "`LWG3270 `__","Parsing and formatting ``%j``\ with ``duration``\ s","2020-02 (Prague)","|Partial|","","" -"`LWG3280 `__","View converting constructors can cause constraint recursion and are unneeded","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3281 `__","Conversion from ``*pair-like*``\ types to ``subrange``\ is a silent semantic promotion","2020-02 (Prague)","|Complete|","13.0","" -"`LWG3282 `__","``subrange``\ converting constructor should disallow derived to base conversions","2020-02 (Prague)","|Complete|","15.0","" +"`LWG3280 `__","View converting constructors can cause constraint recursion and are unneeded","2020-02 (Prague)","|Complete|","15","" +"`LWG3281 `__","Conversion from ``*pair-like*``\ types to ``subrange``\ is a silent semantic promotion","2020-02 (Prague)","|Complete|","13","" +"`LWG3282 `__","``subrange``\ converting constructor should disallow derived to base conversions","2020-02 (Prague)","|Complete|","15","" "`LWG3284 `__","``random_access_iterator``\ semantic constraints accidentally promote difference type using unary negate","2020-02 (Prague)","|Nothing To Do|","","" "`LWG3285 `__","The type of a customization point object shall satisfy ``semiregular``\ ","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3286 `__","``ranges::size``\ is not required to be valid after a call to ``ranges::begin``\ on an input range","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3291 `__","``iota_view::iterator``\ has the wrong ``iterator_category``\ ","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3292 `__","``iota_view``\ is under-constrained","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3294 `__","``zoned_time``\ deduction guides misinterprets ``string``\ /``char*``\ ","2020-02 (Prague)","|Complete|","19.0","" +"`LWG3286 `__","``ranges::size``\ is not required to be valid after a call to ``ranges::begin``\ on an input range","2020-02 (Prague)","|Complete|","15","" +"`LWG3291 `__","``iota_view::iterator``\ has the wrong ``iterator_category``\ ","2020-02 (Prague)","|Complete|","15","" +"`LWG3292 `__","``iota_view``\ is under-constrained","2020-02 (Prague)","|Complete|","15","" +"`LWG3294 `__","``zoned_time``\ deduction guides misinterprets ``string``\ /``char*``\ ","2020-02 (Prague)","|Complete|","19","" "`LWG3296 `__","Inconsistent default argument for ``basic_regex<>::assign``\ ","2020-02 (Prague)","|Complete|","","" -"`LWG3299 `__","Pointers don't need customized iterator behavior","2020-02 (Prague)","|Complete|","15.0","" +"`LWG3299 `__","Pointers don't need customized iterator behavior","2020-02 (Prague)","|Complete|","15","" "`LWG3300 `__","Non-array ``ssize``\ overload is underconstrained","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3301 `__","``transform_view::iterator``\ has incorrect ``iterator_category``\ ","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3302 `__","Range adaptor objects ``keys``\ and ``values``\ are unspecified","2020-02 (Prague)","|Complete|","16.0","" +"`LWG3301 `__","``transform_view::iterator``\ has incorrect ``iterator_category``\ ","2020-02 (Prague)","|Complete|","15","" +"`LWG3302 `__","Range adaptor objects ``keys``\ and ``values``\ are unspecified","2020-02 (Prague)","|Complete|","16","" "`LWG3303 `__","Bad ""``constexpr``\ "" marker for ``destroy/destroy_n``\ ","2020-02 (Prague)","","","" -"`LWG3304 `__","Allocate functions of ``std::polymorphic_allocator``\ should require ``[[nodiscard]]``\ ","2020-02 (Prague)","|Complete|","16.0","" -"`LWG3307 `__","``std::allocator().allocate(n)``\ ","2020-02 (Prague)","|Complete|","20.0","" -"`LWG3310 `__","Replace ``SIZE_MAX``\ with ``numeric_limits::max()``\ ","2020-02 (Prague)","|Complete|","16.0","" -"`LWG3313 `__","``join_view::iterator::operator--``\ is incorrectly constrained","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3314 `__","Is stream insertion behavior locale dependent when ``Period::type``\ is ``micro``\ ?","2020-02 (Prague)","|Complete|","16.0","" +"`LWG3304 `__","Allocate functions of ``std::polymorphic_allocator``\ should require ``[[nodiscard]]``\ ","2020-02 (Prague)","|Complete|","16","" +"`LWG3307 `__","``std::allocator().allocate(n)``\ ","2020-02 (Prague)","|Complete|","20","" +"`LWG3310 `__","Replace ``SIZE_MAX``\ with ``numeric_limits::max()``\ ","2020-02 (Prague)","|Complete|","16","" +"`LWG3313 `__","``join_view::iterator::operator--``\ is incorrectly constrained","2020-02 (Prague)","|Complete|","14","" +"`LWG3314 `__","Is stream insertion behavior locale dependent when ``Period::type``\ is ``micro``\ ?","2020-02 (Prague)","|Complete|","16","" "`LWG3315 `__","LWG3315: Correct Allocator Default Behavior","2020-02 (Prague)","|Complete|","","" "`LWG3316 `__","Correctly define epoch for ``utc_clock``\ / ``utc_timepoint``\ ","2020-02 (Prague)","","","" -"`LWG3317 `__","Incorrect ``operator<<``\ for floating-point durations","2020-02 (Prague)","|Complete|","16.0","" +"`LWG3317 `__","Incorrect ``operator<<``\ for floating-point durations","2020-02 (Prague)","|Complete|","16","" "`LWG3318 `__","Clarify whether clocks can represent time before their epoch","2020-02 (Prague)","","","" "`LWG3319 `__","Properly reference specification of IANA time zone database","2020-02 (Prague)","|Nothing To Do|","","" "`LWG3320 `__","``span::cbegin/cend``\ methods produce different results than ``std::[ranges::]cbegin/cend``\ ","2020-02 (Prague)","|Complete|","","" -"`LWG3321 `__","``uninitialized_construct_using_allocator``\ should use ``construct_at``\ ","2020-02 (Prague)","|Complete|","16.0","" -"`LWG3323 `__","``*has-tuple-element*``\ helper concept needs ``convertible_to``\ ","2020-02 (Prague)","|Complete|","16.0","" -"`LWG3324 `__","Special-case ``std::strong/weak/partial_order``\ for pointers","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3325 `__","Constrain return type of transformation function for ``transform_view``\ ","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3326 `__","``enable_view``\ has false positives","2020-02 (Prague)","|Complete|","15.0","" +"`LWG3321 `__","``uninitialized_construct_using_allocator``\ should use ``construct_at``\ ","2020-02 (Prague)","|Complete|","16","" +"`LWG3323 `__","``*has-tuple-element*``\ helper concept needs ``convertible_to``\ ","2020-02 (Prague)","|Complete|","16","" +"`LWG3324 `__","Special-case ``std::strong/weak/partial_order``\ for pointers","2020-02 (Prague)","|Complete|","14","" +"`LWG3325 `__","Constrain return type of transformation function for ``transform_view``\ ","2020-02 (Prague)","|Complete|","15","" +"`LWG3326 `__","``enable_view``\ has false positives","2020-02 (Prague)","|Complete|","15","" "`LWG3327 `__","Format alignment specifiers vs. text direction","2020-02 (Prague)","|Nothing To Do|","","" "`LWG3328 `__","Clarify that ``std::string``\ is not good for UTF-8","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3329 `__","``totally_ordered_with``\ both directly and indirectly requires ``common_reference_with``\ ","2020-02 (Prague)","|Complete|","13.0","" -"`LWG3330 `__","Include ````\ from most library headers","2020-02 (Prague)","|Complete|","13.0","" -"`LWG3331 `__","Define ``totally_ordered/_with``\ in terms of ``partially-ordered-with``\ ","2020-02 (Prague)","|Complete|","13.0","" -"`LWG3332 `__","Issue in |sect|\ [time.format]","2020-02 (Prague)","|Complete|","16.0","" -"`LWG3334 `__","``basic_osyncstream``\ move assignment and destruction calls ``basic_syncbuf::emit()``\ twice","2020-02 (Prague)","|Complete|","18.0","" -"`LWG3335 `__","Resolve C++20 NB comments US 273 and GB 274","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3338 `__","Rename ``default_constructible``\ to ``default_initializable``\ ","2020-02 (Prague)","|Complete|","13.0","" -"`LWG3340 `__","Formatting functions should throw on argument/format string mismatch in |sect|\ [format.functions]","2020-02 (Prague)","|Complete|","14.0","" +"`LWG3329 `__","``totally_ordered_with``\ both directly and indirectly requires ``common_reference_with``\ ","2020-02 (Prague)","|Complete|","13","" +"`LWG3330 `__","Include ````\ from most library headers","2020-02 (Prague)","|Complete|","13","" +"`LWG3331 `__","Define ``totally_ordered/_with``\ in terms of ``partially-ordered-with``\ ","2020-02 (Prague)","|Complete|","13","" +"`LWG3332 `__","Issue in |sect|\ [time.format]","2020-02 (Prague)","|Complete|","16","" +"`LWG3334 `__","``basic_osyncstream``\ move assignment and destruction calls ``basic_syncbuf::emit()``\ twice","2020-02 (Prague)","|Complete|","18","" +"`LWG3335 `__","Resolve C++20 NB comments US 273 and GB 274","2020-02 (Prague)","|Complete|","15","" +"`LWG3338 `__","Rename ``default_constructible``\ to ``default_initializable``\ ","2020-02 (Prague)","|Complete|","13","" +"`LWG3340 `__","Formatting functions should throw on argument/format string mismatch in |sect|\ [format.functions]","2020-02 (Prague)","|Complete|","14","" "`LWG3346 `__","``pair``\ and ``tuple``\ copy and move constructor have backwards specification","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3347 `__","``std::pair``\ now requires ``T``\ and ``U``\ to be less-than-comparable","2020-02 (Prague)","|Complete|","17.0","" -"`LWG3348 `__","``__cpp_lib_unwrap_ref``\ in wrong header","2020-02 (Prague)","|Complete|","12.0","" -"`LWG3349 `__","Missing ``__cpp_lib_constexpr_complex``\ for P0415R1","2020-02 (Prague)","|Complete|","16.0","" -"`LWG3350 `__","Simplify return type of ``lexicographical_compare_three_way``\ ","2020-02 (Prague)","|Complete|","17.0","" -"`LWG3351 `__","``ranges::enable_safe_range``\ should not be constrained","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3352 `__","``strong_equality``\ isn't a thing","2020-02 (Prague)","|Complete|","19.0","" +"`LWG3347 `__","``std::pair``\ now requires ``T``\ and ``U``\ to be less-than-comparable","2020-02 (Prague)","|Complete|","17","" +"`LWG3348 `__","``__cpp_lib_unwrap_ref``\ in wrong header","2020-02 (Prague)","|Complete|","12","" +"`LWG3349 `__","Missing ``__cpp_lib_constexpr_complex``\ for P0415R1","2020-02 (Prague)","|Complete|","16","" +"`LWG3350 `__","Simplify return type of ``lexicographical_compare_three_way``\ ","2020-02 (Prague)","|Complete|","17","" +"`LWG3351 `__","``ranges::enable_safe_range``\ should not be constrained","2020-02 (Prague)","|Complete|","15","" +"`LWG3352 `__","``strong_equality``\ isn't a thing","2020-02 (Prague)","|Complete|","19","" "`LWG3354 `__","``has_strong_structural_equality``\ has a meaningless definition","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3355 `__","The memory algorithms should support move-only input iterators introduced by P1207","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3356 `__","``__cpp_lib_nothrow_convertible``\ should be ``__cpp_lib_is_nothrow_convertible``\ ","2020-02 (Prague)","|Complete|","12.0","" -"`LWG3358 `__","|sect|\ [span.cons] is mistaken that ``to_address``\ can throw","2020-02 (Prague)","|Complete|","17.0","" +"`LWG3355 `__","The memory algorithms should support move-only input iterators introduced by P1207","2020-02 (Prague)","|Complete|","15","" +"`LWG3356 `__","``__cpp_lib_nothrow_convertible``\ should be ``__cpp_lib_is_nothrow_convertible``\ ","2020-02 (Prague)","|Complete|","12","" +"`LWG3358 `__","|sect|\ [span.cons] is mistaken that ``to_address``\ can throw","2020-02 (Prague)","|Complete|","17","" "`LWG3359 `__","````\ leap second support should allow for negative leap seconds","2020-02 (Prague)","|In Progress|","","" "`LWG3360 `__","``three_way_comparable_with``\ is inconsistent with similar concepts","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3362 `__","Strike ``stop_source``\ 's ``operator!=``\ ","2020-02 (Prague)","|Complete|","17.0","" +"`LWG3362 `__","Strike ``stop_source``\ 's ``operator!=``\ ","2020-02 (Prague)","|Complete|","17","" "`LWG3363 `__","``drop_while_view``\ should opt-out of ``sized_range``\ ","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3364 `__","Initialize data members of ranges and their iterators","2020-02 (Prague)","|Complete|","16.0","" +"`LWG3364 `__","Initialize data members of ranges and their iterators","2020-02 (Prague)","|Complete|","16","" "`LWG3367 `__","Integer-class conversions should not throw","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3369 `__","``span``\ 's deduction-guide for built-in arrays doesn't work","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3371 `__","``visit_format_arg``\ and ``make_format_args``\ are not hidden friends","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3372 `__","``vformat_to``\ should not try to deduce ``Out``\ twice","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3373 `__","``{to,from}_chars_result``\ and ``format_to_n_result``\ need the ""we really mean what we say"" wording","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3374 `__","P0653 + P1006 should have made the other ``std::to_address``\ overload ``constexpr``\ ","2020-02 (Prague)","|Complete|","12.0","" -"`LWG3375 `__","``decay``\ in ``viewable_range``\ should be ``remove_cvref``\ ","2020-02 (Prague)","|Complete|","15.0","" +"`LWG3369 `__","``span``\ 's deduction-guide for built-in arrays doesn't work","2020-02 (Prague)","|Complete|","14","" +"`LWG3371 `__","``visit_format_arg``\ and ``make_format_args``\ are not hidden friends","2020-02 (Prague)","|Complete|","14","" +"`LWG3372 `__","``vformat_to``\ should not try to deduce ``Out``\ twice","2020-02 (Prague)","|Complete|","14","" +"`LWG3373 `__","``{to,from}_chars_result``\ and ``format_to_n_result``\ need the ""we really mean what we say"" wording","2020-02 (Prague)","|Complete|","14","" +"`LWG3374 `__","P0653 + P1006 should have made the other ``std::to_address``\ overload ``constexpr``\ ","2020-02 (Prague)","|Complete|","12","" +"`LWG3375 `__","``decay``\ in ``viewable_range``\ should be ``remove_cvref``\ ","2020-02 (Prague)","|Complete|","15","" "`LWG3377 `__","``elements_view::iterator``\ befriends a specialization of itself","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3379 `__","""``safe``\ "" in several library names is misleading","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3380 `__","``common_type``\ and comparison categories","2020-02 (Prague)","|Complete|","15.0","" +"`LWG3379 `__","""``safe``\ "" in several library names is misleading","2020-02 (Prague)","|Complete|","15","" +"`LWG3380 `__","``common_type``\ and comparison categories","2020-02 (Prague)","|Complete|","15","" "`LWG3381 `__","``begin``\ and ``data``\ must agree for ``contiguous_range``\ ","2020-02 (Prague)","|Nothing To Do|","","" "`LWG3382 `__","NTTP for ``pair``\ and ``array``\ ","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3383 `__","|sect|\ [time.zone.leap.nonmembers] ``sys_seconds``\ should be replaced with ``seconds``\ ","2020-02 (Prague)","|Complete|","19.0","" -"`LWG3384 `__","``transform_view::*sentinel*``\ has an incorrect ``operator-``\ ","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3385 `__","``common_iterator``\ is not sufficiently constrained for non-copyable iterators","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3387 `__","|sect|\ [range.reverse.view] ``reverse_view``\ unintentionally requires ``range``\ ","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3388 `__","``view``\ iterator types have ill-formed ``<=>``\ operators","2020-02 (Prague)","|Complete|","16.0","" -"`LWG3389 `__","A move-only iterator still does not have a ``counted_iterator``\ ","2020-02 (Prague)","|Complete|","15.0","" -"`LWG3390 `__","``make_move_iterator()``\ cannot be used to construct a ``move_iterator``\ for a move-only iterator","2020-02 (Prague)","|Complete|","14.0","" -"`LWG3393 `__","Missing/incorrect feature test macro for coroutines","2020-02 (Prague)","|Complete|","14.0","" +"`LWG3383 `__","|sect|\ [time.zone.leap.nonmembers] ``sys_seconds``\ should be replaced with ``seconds``\ ","2020-02 (Prague)","|Complete|","19","" +"`LWG3384 `__","``transform_view::*sentinel*``\ has an incorrect ``operator-``\ ","2020-02 (Prague)","|Complete|","15","" +"`LWG3385 `__","``common_iterator``\ is not sufficiently constrained for non-copyable iterators","2020-02 (Prague)","|Complete|","15","" +"`LWG3387 `__","|sect|\ [range.reverse.view] ``reverse_view``\ unintentionally requires ``range``\ ","2020-02 (Prague)","|Complete|","15","" +"`LWG3388 `__","``view``\ iterator types have ill-formed ``<=>``\ operators","2020-02 (Prague)","|Complete|","16","" +"`LWG3389 `__","A move-only iterator still does not have a ``counted_iterator``\ ","2020-02 (Prague)","|Complete|","15","" +"`LWG3390 `__","``make_move_iterator()``\ cannot be used to construct a ``move_iterator``\ for a move-only iterator","2020-02 (Prague)","|Complete|","14","" +"`LWG3393 `__","Missing/incorrect feature test macro for coroutines","2020-02 (Prague)","|Complete|","14","" "`LWG3395 `__","LWG3395: Definition for three-way comparison needs to be updated (US 152)","2020-02 (Prague)","|Nothing To Do|","","" -"`LWG3396 `__","Clarify point of reference for ``source_location::current()``\ (DE 169)","2020-02 (Prague)","|Nothing To Do|","16.0","" -"`LWG3397 `__","``ranges::basic_istream_view::iterator``\ should not provide ``iterator_category``\ ","2020-02 (Prague)","|Complete|","16.0","" -"`LWG3398 `__","``tuple_element_t``\ is also wrong for ``const subrange``\ ","2020-02 (Prague)","|Complete|","14.0","" +"`LWG3396 `__","Clarify point of reference for ``source_location::current()``\ (DE 169)","2020-02 (Prague)","|Nothing To Do|","16","" +"`LWG3397 `__","``ranges::basic_istream_view::iterator``\ should not provide ``iterator_category``\ ","2020-02 (Prague)","|Complete|","16","" +"`LWG3398 `__","``tuple_element_t``\ is also wrong for ``const subrange``\ ","2020-02 (Prague)","|Complete|","14","" "","","","","","" -"`LWG3446 `__","``indirectly_readable_traits``\ ambiguity for types with both ``value_type``\ and ``element_type``\ ","2020-11 (Virtual)","|Complete|","13.0","" +"`LWG3446 `__","``indirectly_readable_traits``\ ambiguity for types with both ``value_type``\ and ``element_type``\ ","2020-11 (Virtual)","|Complete|","13","" diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv index 5cd77be4d58de..66cb1012eceb9 100644 --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -1,148 +1,148 @@ "Paper #","Paper Name","Meeting","Status","First released version","Notes" -"`P0463R1 `__","Endian just Endian","2017-07 (Toronto)","|Complete|","7.0","" -"`P0674R1 `__","Extending make_shared to Support Arrays","2017-07 (Toronto)","|Complete|","15.0","" +"`P0463R1 `__","Endian just Endian","2017-07 (Toronto)","|Complete|","7","" +"`P0674R1 `__","Extending make_shared to Support Arrays","2017-07 (Toronto)","|Complete|","15","" "","","","","","" -"`P0020R6 `__","Floating Point Atomic","2017-11 (Albuquerque)","|Complete|","18.0","" -"`P0053R7 `__","C++ Synchronized Buffered Ostream","2017-11 (Albuquerque)","|Complete|","18.0","" -"`P0202R3 `__","Add constexpr modifiers to functions in and Headers","2017-11 (Albuquerque)","|Complete|","12.0","" -"`P0415R1 `__","Constexpr for ``std::complex``\ ","2017-11 (Albuquerque)","|Complete|","16.0","" +"`P0020R6 `__","Floating Point Atomic","2017-11 (Albuquerque)","|Complete|","18","" +"`P0053R7 `__","C++ Synchronized Buffered Ostream","2017-11 (Albuquerque)","|Complete|","18","" +"`P0202R3 `__","Add constexpr modifiers to functions in and Headers","2017-11 (Albuquerque)","|Complete|","12","" +"`P0415R1 `__","Constexpr for ``std::complex``\ ","2017-11 (Albuquerque)","|Complete|","16","" "`P0439R0 `__","Make ``std::memory_order``\ a scoped enumeration","2017-11 (Albuquerque)","|Complete|","","" -"`P0457R2 `__","String Prefix and Suffix Checking","2017-11 (Albuquerque)","|Complete|","6.0","" -"`P0550R2 `__","Transformation Trait ``remove_cvref``\ ","2017-11 (Albuquerque)","|Complete|","6.0","" -"`P0600R1 `__","nodiscard in the Library","2017-11 (Albuquerque)","|Complete|","16.0","" -"`P0616R0 `__","de-pessimize legacy algorithms with std::move","2017-11 (Albuquerque)","|Complete|","12.0","" -"`P0653R2 `__","Utility to convert a pointer to a raw pointer","2017-11 (Albuquerque)","|Complete|","6.0","" +"`P0457R2 `__","String Prefix and Suffix Checking","2017-11 (Albuquerque)","|Complete|","6","" +"`P0550R2 `__","Transformation Trait ``remove_cvref``\ ","2017-11 (Albuquerque)","|Complete|","6","" +"`P0600R1 `__","nodiscard in the Library","2017-11 (Albuquerque)","|Complete|","16","" +"`P0616R0 `__","de-pessimize legacy algorithms with std::move","2017-11 (Albuquerque)","|Complete|","12","" +"`P0653R2 `__","Utility to convert a pointer to a raw pointer","2017-11 (Albuquerque)","|Complete|","6","" "`P0718R2 `__","Atomic shared_ptr","2017-11 (Albuquerque)","","","" -"`P0767R1 `__","Deprecate POD","2017-11 (Albuquerque)","|Complete|","7.0","" +"`P0767R1 `__","Deprecate POD","2017-11 (Albuquerque)","|Complete|","7","" "`P0768R1 `__","Library Support for the Spaceship (Comparison) Operator","2017-11 (Albuquerque)","|Complete|","","" -"`P0777R1 `__","Treating Unnecessary ``decay``\ ","2017-11 (Albuquerque)","|Complete|","7.0","" +"`P0777R1 `__","Treating Unnecessary ``decay``\ ","2017-11 (Albuquerque)","|Complete|","7","" "","","","","","" -"`P0122R7 `__","","2018-03 (Jacksonville)","|Complete|","7.0","" +"`P0122R7 `__","","2018-03 (Jacksonville)","|Complete|","7","" "`P0355R7 `__","Extending chrono to Calendars and Time Zones","2018-03 (Jacksonville)","|Partial|","","See the `Github issue `__ for detailed status" -"`P0551R3 `__","Thou Shalt Not Specialize ``std``\ Function Templates!","2018-03 (Jacksonville)","|Complete|","11.0","" +"`P0551R3 `__","Thou Shalt Not Specialize ``std``\ Function Templates!","2018-03 (Jacksonville)","|Complete|","11","" "`P0753R2 `__","Manipulators for C++ Synchronized Buffered Ostream","2018-03 (Jacksonville)","","","" -"`P0754R2 `__","","2018-03 (Jacksonville)","|Complete|","7.0","" +"`P0754R2 `__","","2018-03 (Jacksonville)","|Complete|","7","" "`P0809R0 `__","Comparing Unordered Containers","2018-03 (Jacksonville)","|Nothing To Do|","","" -"`P0858R0 `__","Constexpr iterator requirements","2018-03 (Jacksonville)","|Complete|","12.0","" -"`P0905R1 `__","Symmetry for spaceship","2018-03 (Jacksonville)","|Complete|","7.0","" -"`P0966R1 `__","``string::reserve``\ Should Not Shrink","2018-03 (Jacksonville)","|Complete|","12.0","It was previously erroneously marked as complete in version 8.0. See `bug 45368 `__" +"`P0858R0 `__","Constexpr iterator requirements","2018-03 (Jacksonville)","|Complete|","12","" +"`P0905R1 `__","Symmetry for spaceship","2018-03 (Jacksonville)","|Complete|","7","" +"`P0966R1 `__","``string::reserve``\ Should Not Shrink","2018-03 (Jacksonville)","|Complete|","12","It was previously erroneously marked as complete in version 8. See `bug 45368 `__" "","","","","","" -"`P0019R8 `__","Atomic Ref","2018-06 (Rapperswil)","|Complete|","19.0","" -"`P0458R2 `__","Checking for Existence of an Element in Associative Containers","2018-06 (Rapperswil)","|Complete|","13.0","" +"`P0019R8 `__","Atomic Ref","2018-06 (Rapperswil)","|Complete|","19","" +"`P0458R2 `__","Checking for Existence of an Element in Associative Containers","2018-06 (Rapperswil)","|Complete|","13","" "`P0475R1 `__","LWG 2511: guaranteed copy elision for piecewise construction","2018-06 (Rapperswil)","|Complete|","","" -"`P0476R2 `__","Bit-casting object representations","2018-06 (Rapperswil)","|Complete|","14.0","" +"`P0476R2 `__","Bit-casting object representations","2018-06 (Rapperswil)","|Complete|","14","" "`P0528R3 `__","The Curious Case of Padding Bits, Featuring Atomic Compare-and-Exchange","2018-06 (Rapperswil)","","","" "`P0542R5 `__","Support for contract based programming in C++","2018-06 (Rapperswil)","|Nothing To Do|","n/a","Pulled at the 2019-07 meeting in Cologne" -"`P0556R3 `__","Integral power-of-2 operations","2018-06 (Rapperswil)","|Complete|","9.0","" -"`P0619R4 `__","Reviewing Deprecated Facilities of C++17 for C++20","2018-06 (Rapperswil)","|Complete|","20.0","Removed headers are still provided as an extension, but with deprecation warnings" -"`P0646R1 `__","Improving the Return Value of Erase-Like Algorithms","2018-06 (Rapperswil)","|Complete|","10.0","" -"`P0722R3 `__","Efficient sized delete for variable sized classes","2018-06 (Rapperswil)","|Complete|","9.0","" +"`P0556R3 `__","Integral power-of-2 operations","2018-06 (Rapperswil)","|Complete|","9","" +"`P0619R4 `__","Reviewing Deprecated Facilities of C++17 for C++20","2018-06 (Rapperswil)","|Complete|","20","Removed headers are still provided as an extension, but with deprecation warnings" +"`P0646R1 `__","Improving the Return Value of Erase-Like Algorithms","2018-06 (Rapperswil)","|Complete|","10","" +"`P0722R3 `__","Efficient sized delete for variable sized classes","2018-06 (Rapperswil)","|Complete|","9","" "`P0758R1 `__","Implicit conversion traits and utility functions","2018-06 (Rapperswil)","|Complete|","","" -"`P0759R1 `__","fpos Requirements","2018-06 (Rapperswil)","|Complete|","11.0","" -"`P0769R2 `__","Add shift to ","2018-06 (Rapperswil)","|Complete|","12.0","" +"`P0759R1 `__","fpos Requirements","2018-06 (Rapperswil)","|Complete|","11","" +"`P0769R2 `__","Add shift to ","2018-06 (Rapperswil)","|Complete|","12","" "`P0788R3 `__","Standard Library Specification in a Concepts and Contracts World","2018-06 (Rapperswil)","|Nothing To Do|","n/a","Pulled at the 2019-07 meeting in Cologne" -"`P0879R0 `__","Constexpr for swap and swap related functions Also resolves LWG issue 2800.","2018-06 (Rapperswil)","|Complete|","13.0","" -"`P0887R1 `__","The identity metafunction","2018-06 (Rapperswil)","|Complete|","8.0","" +"`P0879R0 `__","Constexpr for swap and swap related functions Also resolves LWG issue 2800.","2018-06 (Rapperswil)","|Complete|","13","" +"`P0887R1 `__","The identity metafunction","2018-06 (Rapperswil)","|Complete|","8","" "`P0892R2 `__","explicit(bool)","2018-06 (Rapperswil)","","","" -"`P0898R3 `__","Standard Library Concepts","2018-06 (Rapperswil)","|Complete|","13.0","" -"`P0935R0 `__","Eradicating unnecessarily explicit default constructors from the standard library","2018-06 (Rapperswil)","|Complete|","12.0","" +"`P0898R3 `__","Standard Library Concepts","2018-06 (Rapperswil)","|Complete|","13","" +"`P0935R0 `__","Eradicating unnecessarily explicit default constructors from the standard library","2018-06 (Rapperswil)","|Complete|","12","" "`P0941R2 `__","Integrating feature-test macros into the C++ WD","2018-06 (Rapperswil)","|In Progress|","","" -"`P1023R0 `__","constexpr comparison operators for std::array","2018-06 (Rapperswil)","|Complete|","8.0","" +"`P1023R0 `__","constexpr comparison operators for std::array","2018-06 (Rapperswil)","|Complete|","8","" "`P1025R1 `__","Update The Reference To The Unicode Standard","2018-06 (Rapperswil)","","","" "`P1120R0 `__","Consistency improvements for <=> and other comparison operators","2018-06 (Rapperswil)","","","" "","","","","","" -"`P0318R1 `__","unwrap_ref_decay and unwrap_reference","2018-11 (San Diego)","|Complete|","8.0","" -"`P0356R5 `__","Simplified partial function application","2018-11 (San Diego)","|Complete|","13.0","" -"`P0357R3 `__","reference_wrapper for incomplete types","2018-11 (San Diego)","|Complete|","8.0","" -"`P0482R6 `__","char8_t: A type for UTF-8 characters and strings","2018-11 (San Diego)","|Complete|","16.0","" -"`P0487R1 `__","Fixing ``operator>>(basic_istream&, CharT*)``\ (LWG 2499)","2018-11 (San Diego)","|Complete|","8.0","" +"`P0318R1 `__","unwrap_ref_decay and unwrap_reference","2018-11 (San Diego)","|Complete|","8","" +"`P0356R5 `__","Simplified partial function application","2018-11 (San Diego)","|Complete|","13","" +"`P0357R3 `__","reference_wrapper for incomplete types","2018-11 (San Diego)","|Complete|","8","" +"`P0482R6 `__","char8_t: A type for UTF-8 characters and strings","2018-11 (San Diego)","|Complete|","16","" +"`P0487R1 `__","Fixing ``operator>>(basic_istream&, CharT*)``\ (LWG 2499)","2018-11 (San Diego)","|Complete|","8","" "`P0591R4 `__","Utility functions to implement uses-allocator construction","2018-11 (San Diego)","|Partial|","","The changes in [mem.poly.allocator.mem] are missing" -"`P0595R2 `__","std::is_constant_evaluated()","2018-11 (San Diego)","|Complete|","9.0","" -"`P0602R4 `__","variant and optional should propagate copy/move triviality","2018-11 (San Diego)","|Complete|","8.0","" -"`P0608R3 `__","A sane variant converting constructor","2018-11 (San Diego)","|Complete|","9.0","" -"`P0655R1 `__","visit: Explicit Return Type for visit","2018-11 (San Diego)","|Complete|","12.0","" -"`P0771R1 `__","std::function move constructor should be noexcept","2018-11 (San Diego)","|Complete|","6.0","" -"`P0896R4 `__","The One Ranges Proposal","2018-11 (San Diego)","|Complete|","15.0","" +"`P0595R2 `__","std::is_constant_evaluated()","2018-11 (San Diego)","|Complete|","9","" +"`P0602R4 `__","variant and optional should propagate copy/move triviality","2018-11 (San Diego)","|Complete|","8","" +"`P0608R3 `__","A sane variant converting constructor","2018-11 (San Diego)","|Complete|","9","" +"`P0655R1 `__","visit: Explicit Return Type for visit","2018-11 (San Diego)","|Complete|","12","" +"`P0771R1 `__","std::function move constructor should be noexcept","2018-11 (San Diego)","|Complete|","6","" +"`P0896R4 `__","The One Ranges Proposal","2018-11 (San Diego)","|Complete|","15","" "`P0899R1 `__","P0899R1 - LWG 3016 is not a defect","2018-11 (San Diego)","|Nothing To Do|","","" -"`P0919R3 `__","Heterogeneous lookup for unordered containers","2018-11 (San Diego)","|Complete|","12.0","" -"`P0972R0 `__"," ``zero()``\ , ``min()``\ , and ``max()``\ should be noexcept","2018-11 (San Diego)","|Complete|","8.0","" -"`P1006R1 `__","Constexpr in std::pointer_traits","2018-11 (San Diego)","|Complete|","8.0","" -"`P1007R3 `__","``std::assume_aligned``\ ","2018-11 (San Diego)","|Complete|","15.0","" -"`P1020R1 `__","Smart pointer creation with default initialization","2018-11 (San Diego)","|Complete|","16.0","" -"`P1032R1 `__","Misc constexpr bits","2018-11 (San Diego)","|Complete|","13.0","" -"`P1085R2 `__","Should Span be Regular?","2018-11 (San Diego)","|Complete|","8.0","" +"`P0919R3 `__","Heterogeneous lookup for unordered containers","2018-11 (San Diego)","|Complete|","12","" +"`P0972R0 `__"," ``zero()``\ , ``min()``\ , and ``max()``\ should be noexcept","2018-11 (San Diego)","|Complete|","8","" +"`P1006R1 `__","Constexpr in std::pointer_traits","2018-11 (San Diego)","|Complete|","8","" +"`P1007R3 `__","``std::assume_aligned``\ ","2018-11 (San Diego)","|Complete|","15","" +"`P1020R1 `__","Smart pointer creation with default initialization","2018-11 (San Diego)","|Complete|","16","The feature-test macro was not set until LLVM 20." +"`P1032R1 `__","Misc constexpr bits","2018-11 (San Diego)","|Complete|","13","" +"`P1085R2 `__","Should Span be Regular?","2018-11 (San Diego)","|Complete|","8","" "`P1123R0 `__","Editorial Guidance for merging P0019r8 and P0528r3","2018-11 (San Diego)","","","" "`P1148R0 `__","Cleaning up Clause 20","2018-11 (San Diego)","","","" -"`P1165R1 `__","Make stateful allocator propagation more consistent for ``operator+(basic_string)``\ ","2018-11 (San Diego)","|Complete|","15.0","" -"`P1209R0 `__","Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20","2018-11 (San Diego)","|Complete|","8.0","" +"`P1165R1 `__","Make stateful allocator propagation more consistent for ``operator+(basic_string)``\ ","2018-11 (San Diego)","|Complete|","15","" +"`P1209R0 `__","Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20","2018-11 (San Diego)","|Complete|","8","" "`P1210R0 `__","P1210R0: Completing the Rebase of Library Fundamentals, Version 3, Working Draft","2018-11 (San Diego)","|Nothing To Do|","","" "`P1236R1 `__","Alternative Wording for P0907R4 Signed Integers are Two's Complement","2018-11 (San Diego)","","","" -"`P1248R1 `__","Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)","2018-11 (San Diego)","|Complete|","13.0","" +"`P1248R1 `__","Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)","2018-11 (San Diego)","|Complete|","13","" "`P1285R0 `__","Improving Completeness Requirements for Type Traits","2018-11 (San Diego)","","","" "`P1353R0 `__","Missing feature test macros","2018-11 (San Diego)","|In Progress|","","" "","","","","","" -"`P0339R6 `__","polymorphic_allocator<> as a vocabulary type","2019-02 (Kona)","|Complete|","16.0","" -"`P0340R3 `__","Making std::underlying_type SFINAE-friendly","2019-02 (Kona)","|Complete|","9.0","" +"`P0339R6 `__","polymorphic_allocator<> as a vocabulary type","2019-02 (Kona)","|Complete|","16","" +"`P0340R3 `__","Making std::underlying_type SFINAE-friendly","2019-02 (Kona)","|Complete|","9","" "`P0738R2 `__","I Stream, You Stream, We All Stream for istream_iterator","2019-02 (Kona)","","","" -"`P0811R3 `__","Well-behaved interpolation for numbers and pointers","2019-02 (Kona)","|Complete|","9.0","" +"`P0811R3 `__","Well-behaved interpolation for numbers and pointers","2019-02 (Kona)","|Complete|","9","" "`P0920R2 `__","Precalculated hash values in lookup","2019-02 (Kona)","|Nothing To Do|","","Reverted by `P1661 `__" -"`P1001R2 `__","Target Vectorization Policies from Parallelism V2 TS to C++20","2019-02 (Kona)","|Complete|","17.0","" -"`P1024R3 `__","Usability Enhancements for std::span","2019-02 (Kona)","|Complete|","9.0","" -"`P1164R1 `__","Make create_directory() Intuitive","2019-02 (Kona)","|Complete|","12.0","" -"`P1227R2 `__","Signed ssize() functions, unsigned size() functions","2019-02 (Kona)","|Complete|","9.0","" -"`P1252R2 `__","Ranges Design Cleanup","2019-02 (Kona)","|Complete|","15.0","" +"`P1001R2 `__","Target Vectorization Policies from Parallelism V2 TS to C++20","2019-02 (Kona)","|Complete|","17","" +"`P1024R3 `__","Usability Enhancements for std::span","2019-02 (Kona)","|Complete|","9","" +"`P1164R1 `__","Make create_directory() Intuitive","2019-02 (Kona)","|Complete|","12","" +"`P1227R2 `__","Signed ssize() functions, unsigned size() functions","2019-02 (Kona)","|Complete|","9","" +"`P1252R2 `__","Ranges Design Cleanup","2019-02 (Kona)","|Complete|","15","" "`P1286R2 `__","Contra CWG DR1778","2019-02 (Kona)","","","" -"`P1357R1 `__","Traits for [Un]bounded Arrays","2019-02 (Kona)","|Complete|","9.0","" -"`P1458R1 `__","Mandating the Standard Library: Clause 16 - Language support library","2019-02 (Kona)","|Complete|","9.0","" -"`P1459R1 `__","Mandating the Standard Library: Clause 18 - Diagnostics library","2019-02 (Kona)","|Complete|","9.0","" -"`P1462R1 `__","Mandating the Standard Library: Clause 20 - Strings library","2019-02 (Kona)","|Complete|","9.0","" +"`P1357R1 `__","Traits for [Un]bounded Arrays","2019-02 (Kona)","|Complete|","9","" +"`P1458R1 `__","Mandating the Standard Library: Clause 16 - Language support library","2019-02 (Kona)","|Complete|","9","" +"`P1459R1 `__","Mandating the Standard Library: Clause 18 - Diagnostics library","2019-02 (Kona)","|Complete|","9","" +"`P1462R1 `__","Mandating the Standard Library: Clause 20 - Strings library","2019-02 (Kona)","|Complete|","9","" "`P1463R1 `__","Mandating the Standard Library: Clause 21 - Containers library","2019-02 (Kona)","","","" -"`P1464R1 `__","Mandating the Standard Library: Clause 22 - Iterators library","2019-02 (Kona)","|Complete|","9.0","" +"`P1464R1 `__","Mandating the Standard Library: Clause 22 - Iterators library","2019-02 (Kona)","|Complete|","9","" "","","","","","" -"`P0325R4 `__","to_array from LFTS with updates","2019-07 (Cologne)","|Complete|","10.0","" -"`P0408R7 `__","Efficient Access to basic_stringbuf's Buffer","2019-07 (Cologne)","|Complete|","17.0","" +"`P0325R4 `__","to_array from LFTS with updates","2019-07 (Cologne)","|Complete|","10","" +"`P0408R7 `__","Efficient Access to basic_stringbuf's Buffer","2019-07 (Cologne)","|Complete|","17","" "`P0466R5 `__","Layout-compatibility and Pointer-interconvertibility Traits","2019-07 (Cologne)","","","" -"`P0553R4 `__","Bit operations","2019-07 (Cologne)","|Complete|","9.0","" -"`P0631R8 `__","Math Constants","2019-07 (Cologne)","|Complete|","11.0","" -"`P0645R10 `__","Text Formatting","2019-07 (Cologne)","|Complete|","14.0","The implementation was complete since LLVM 14, but the feature-test macro was not set until LLVM 19" -"`P0660R10 `__","Stop Token and Joining Thread, Rev 10.","2019-07 (Cologne)","|Complete|","20.0","The feature was implemented since LLVM 18 but was guarded behind ``-fexperimental-library``." -"`P0784R7 `__","More constexpr containers","2019-07 (Cologne)","|Complete|","12.0","" -"`P0980R1 `__","Making std::string constexpr","2019-07 (Cologne)","|Complete|","15.0","" -"`P1004R2 `__","Making std::vector constexpr","2019-07 (Cologne)","|Complete|","15.0","" -"`P1035R7 `__","Input Range Adaptors","2019-07 (Cologne)","|Complete|","16.0","" -"`P1065R2 `__","Constexpr INVOKE","2019-07 (Cologne)","|Complete|","12.0","" -"`P1135R6 `__","The C++20 Synchronization Library","2019-07 (Cologne)","|Complete|","11.0","" -"`P1207R4 `__","Movability of Single-pass Iterators","2019-07 (Cologne)","|Complete|","15.0","" -"`P1208R6 `__","Adopt source_location for C++20","2019-07 (Cologne)","|Complete|","16.0","" -"`P1355R2 `__","Exposing a narrow contract for ceil2","2019-07 (Cologne)","|Complete|","9.0","" +"`P0553R4 `__","Bit operations","2019-07 (Cologne)","|Complete|","9","" +"`P0631R8 `__","Math Constants","2019-07 (Cologne)","|Complete|","11","" +"`P0645R10 `__","Text Formatting","2019-07 (Cologne)","|Complete|","14","The implementation was complete since LLVM 14, but the feature-test macro was not set until LLVM 19" +"`P0660R10 `__","Stop Token and Joining Thread, Rev 10.","2019-07 (Cologne)","|Complete|","20","The feature was implemented since LLVM 18 but was guarded behind ``-fexperimental-library``." +"`P0784R7 `__","More constexpr containers","2019-07 (Cologne)","|Complete|","12","" +"`P0980R1 `__","Making std::string constexpr","2019-07 (Cologne)","|Complete|","15","" +"`P1004R2 `__","Making std::vector constexpr","2019-07 (Cologne)","|Complete|","15","" +"`P1035R7 `__","Input Range Adaptors","2019-07 (Cologne)","|Complete|","16","" +"`P1065R2 `__","Constexpr INVOKE","2019-07 (Cologne)","|Complete|","12","" +"`P1135R6 `__","The C++20 Synchronization Library","2019-07 (Cologne)","|Complete|","11","" +"`P1207R4 `__","Movability of Single-pass Iterators","2019-07 (Cologne)","|Complete|","15","" +"`P1208R6 `__","Adopt source_location for C++20","2019-07 (Cologne)","|Complete|","16","" +"`P1355R2 `__","Exposing a narrow contract for ceil2","2019-07 (Cologne)","|Complete|","9","" "`P1361R2 `__","Integration of chrono with text formatting","2019-07 (Cologne)","|Partial|","","" -"`P1423R3 `__","char8_t backward compatibility remediation","2019-07 (Cologne)","|Complete|","15.0","" +"`P1423R3 `__","char8_t backward compatibility remediation","2019-07 (Cologne)","|Complete|","15","" "`P1424R1 `__","'constexpr' feature macro concerns","2019-07 (Cologne)","|Nothing To Do|","","Superseded by `P1902 `__" "`P1466R3 `__","Miscellaneous minor fixes for chrono","2019-07 (Cologne)","|Partial|","","" -"`P1474R1 `__","Helpful pointers for ContiguousIterator","2019-07 (Cologne)","|Complete|","15.0","" +"`P1474R1 `__","Helpful pointers for ContiguousIterator","2019-07 (Cologne)","|Complete|","15","" "`P1502R1 `__","Standard library header units for C++20","2019-07 (Cologne)","","","" -"`P1522R1 `__","Iterator Difference Type and Integer Overflow","2019-07 (Cologne)","|Complete|","15.0","" -"`P1523R1 `__","Views and Size Types","2019-07 (Cologne)","|Complete|","15.0","" -"`P1612R1 `__","Relocate Endian's Specification","2019-07 (Cologne)","|Complete|","10.0","" -"`P1614R2 `__","The Mothership has Landed","2019-07 (Cologne)","|Complete|","19.0","``std::strong_order(long double, long double)`` is partly implemented." -"`P1638R1 `__","basic_istream_view::iterator should not be copyable","2019-07 (Cologne)","|Complete|","16.0","" -"`P1643R1 `__","Add wait/notify to atomic_ref","2019-07 (Cologne)","|Complete|","19.0","" +"`P1522R1 `__","Iterator Difference Type and Integer Overflow","2019-07 (Cologne)","|Complete|","15","" +"`P1523R1 `__","Views and Size Types","2019-07 (Cologne)","|Complete|","15","" +"`P1612R1 `__","Relocate Endian's Specification","2019-07 (Cologne)","|Complete|","10","" +"`P1614R2 `__","The Mothership has Landed","2019-07 (Cologne)","|Complete|","19","``std::strong_order(long double, long double)`` is partly implemented." +"`P1638R1 `__","basic_istream_view::iterator should not be copyable","2019-07 (Cologne)","|Complete|","16","" +"`P1643R1 `__","Add wait/notify to atomic_ref","2019-07 (Cologne)","|Complete|","19","" "`P1644R0 `__","Add wait/notify to atomic","2019-07 (Cologne)","","","" -"`P1650R0 `__","Output std::chrono::days with 'd' suffix","2019-07 (Cologne)","|Complete|","16.0","" -"`P1651R0 `__","bind_front should not unwrap reference_wrapper","2019-07 (Cologne)","|Complete|","13.0","" -"`P1652R1 `__","Printf corner cases in std::format","2019-07 (Cologne)","|Complete|","14.0","" +"`P1650R0 `__","Output std::chrono::days with 'd' suffix","2019-07 (Cologne)","|Complete|","16","" +"`P1651R0 `__","bind_front should not unwrap reference_wrapper","2019-07 (Cologne)","|Complete|","13","" +"`P1652R1 `__","Printf corner cases in std::format","2019-07 (Cologne)","|Complete|","14","" "`P1661R1 `__","Remove dedicated precalculated hash lookup interface","2019-07 (Cologne)","|Nothing To Do|","","" -"`P1754R1 `__","Rename concepts to standard_case for C++20, while we still can","2019-07 (Cologne)","|Complete|","15.0","" +"`P1754R1 `__","Rename concepts to standard_case for C++20, while we still can","2019-07 (Cologne)","|Complete|","15","" "","","","","","" -"`P0883R2 `__","Fixing Atomic Initialization","2019-11 (Belfast)","|Complete|","14.0","shared_ptr and floating-point changes weren't applied as they themselves aren't implemented yet. Also, ``ATOMIC_FLAG_INIT`` was marked deprecated in version 14.0, but was undeprecated with the implementation of LWG3659 in version 15.0." -"`P1391R4 `__","Range constructor for std::string_view","2019-11 (Belfast)","|Complete|","14.0","" -"`P1394R4 `__","Range constructor for std::span","2019-11 (Belfast)","|Complete|","14.0","" -"`P1456R1 `__","Move-only views","2019-11 (Belfast)","|Complete|","15.0","" +"`P0883R2 `__","Fixing Atomic Initialization","2019-11 (Belfast)","|Complete|","14","shared_ptr and floating-point changes weren't applied as they themselves aren't implemented yet. Also, ``ATOMIC_FLAG_INIT`` was marked deprecated in version 14, but was undeprecated with the implementation of LWG3659 in version 15." +"`P1391R4 `__","Range constructor for std::string_view","2019-11 (Belfast)","|Complete|","14","" +"`P1394R4 `__","Range constructor for std::span","2019-11 (Belfast)","|Complete|","14","" +"`P1456R1 `__","Move-only views","2019-11 (Belfast)","|Complete|","15","" "`P1622R3 `__","Mandating the Standard Library: Clause 32 - Thread support library","2019-11 (Belfast)","","","" -"`P1645R1 `__","constexpr for numeric algorithms","2019-11 (Belfast)","|Complete|","12.0","" +"`P1645R1 `__","constexpr for numeric algorithms","2019-11 (Belfast)","|Complete|","12","" "`P1686R2 `__","Mandating the Standard Library: Clause 27 - Time library","2019-11 (Belfast)","","","" -"`P1690R1 `__","Refinement Proposal for P0919 Heterogeneous lookup for unordered containers","2019-11 (Belfast)","|Complete|","12.0","" -"`P1716R3 `__","ranges compare algorithm are over-constrained","2019-11 (Belfast)","|Complete|","15.0","" +"`P1690R1 `__","Refinement Proposal for P0919 Heterogeneous lookup for unordered containers","2019-11 (Belfast)","|Complete|","12","" +"`P1716R3 `__","ranges compare algorithm are over-constrained","2019-11 (Belfast)","|Complete|","15","" "`P1718R2 `__","Mandating the Standard Library: Clause 25 - Algorithms library","2019-11 (Belfast)","","","" "`P1719R2 `__","Mandating the Standard Library: Clause 26 - Numerics library","2019-11 (Belfast)","","","" "`P1720R2 `__","Mandating the Standard Library: Clause 28 - Localization library","2019-11 (Belfast)","","","" @@ -150,57 +150,57 @@ "`P1722R2 `__","Mandating the Standard Library: Clause 30 - Regular Expression library","2019-11 (Belfast)","","","" "`P1723R2 `__","Mandating the Standard Library: Clause 31 - Atomics library","2019-11 (Belfast)","","","" "`P1855R0 `__","Make ````\ freestanding","2019-11 (Belfast)","","","" -"`P1862R1 `__","Ranges adaptors for non-copyable iterators","2019-11 (Belfast)","|Complete|","16.0","" -"`P1865R1 `__","Add max() to latch and barrier","2019-11 (Belfast)","|Complete|","11.0","" -"`P1869R1 `__","Rename 'condition_variable_any' interruptible wait methods","2019-11 (Belfast)","|Complete|","18.0","" -"`P1870R1 `__","forwarding-range is too subtle","2019-11 (Belfast)","|Complete|","15.0","" -"`P1871R1 `__","Concept traits should be named after concepts","2019-11 (Belfast)","|Complete|","14.0","" -"`P1872R0 `__","span should have size_type, not index_type","2019-11 (Belfast)","|Complete|","10.0","" -"`P1878R1 `__","Constraining Readable Types","2019-11 (Belfast)","|Complete|","15.0","" -"`P1892R1 `__","Extended locale-specific presentation specifiers for std::format","2019-11 (Belfast)","|Complete|","14.0","" +"`P1862R1 `__","Ranges adaptors for non-copyable iterators","2019-11 (Belfast)","|Complete|","16","" +"`P1865R1 `__","Add max() to latch and barrier","2019-11 (Belfast)","|Complete|","11","" +"`P1869R1 `__","Rename 'condition_variable_any' interruptible wait methods","2019-11 (Belfast)","|Complete|","18","" +"`P1870R1 `__","forwarding-range is too subtle","2019-11 (Belfast)","|Complete|","15","" +"`P1871R1 `__","Concept traits should be named after concepts","2019-11 (Belfast)","|Complete|","14","" +"`P1872R0 `__","span should have size_type, not index_type","2019-11 (Belfast)","|Complete|","10","" +"`P1878R1 `__","Constraining Readable Types","2019-11 (Belfast)","|Complete|","15","" +"`P1892R1 `__","Extended locale-specific presentation specifiers for std::format","2019-11 (Belfast)","|Complete|","14","" "`P1902R1 `__","Missing feature-test macros 2018-2019","2019-11 (Belfast)","","","" "`P1959R0 `__","Remove std::weak_equality and std::strong_equality","2019-11 (Belfast)","|Nothing To Do|","","" "`P1960R0 `__","NB Comment Changes Reviewed by SG1","2019-11 (Belfast)","","","" "`P1961R0 `__","Harmonizing the definitions of total order for pointers","2019-11 (Belfast)","","","" "`P1965R0 `__","Blanket Wording for Specifying ""Hidden Friends""","2019-11 (Belfast)","","","" "","","","","","" -"`P0586R2 `__","Safe integral comparisons","2020-02 (Prague)","|Complete|","13.0","" +"`P0586R2 `__","Safe integral comparisons","2020-02 (Prague)","|Complete|","13","" "`P0593R6 `__","Implicit creation of objects for low-level object manipulation","2020-02 (Prague)","","","" -"`P1115R3 `__","Improving the Return Value of Erase-Like Algorithms II: Free erase/erase if","2020-02 (Prague)","|Complete|","11.0","" -"`P1243R4 `__","Rangify New Algorithms","2020-02 (Prague)","|Complete|","15.0","" +"`P1115R3 `__","Improving the Return Value of Erase-Like Algorithms II: Free erase/erase if","2020-02 (Prague)","|Complete|","11","" +"`P1243R4 `__","Rangify New Algorithms","2020-02 (Prague)","|Complete|","15","" "`P1460R1 `__","Mandating the Standard Library: Clause 20 - Utilities library","2020-02 (Prague)","","","" -"`P1739R4 `__","Avoid template bloat for safe_ranges in combination with ""subrange-y"" view adaptors","2020-02 (Prague)","|Complete|","15.0","" +"`P1739R4 `__","Avoid template bloat for safe_ranges in combination with ""subrange-y"" view adaptors","2020-02 (Prague)","|Complete|","15","" "`P1831R1 `__","Deprecating volatile: library","2020-02 (Prague)","","","" -"`P1868R2 `__","width: clarifying units of width and precision in std::format","2020-02 (Prague)","|Complete|","14.0","" -"`P1956R1 `__","On the names of low-level bit manipulation functions","2020-02 (Prague)","|Complete|","12.0","" -"`P1957R2 `__","Converting from ``T*``\ to bool should be considered narrowing (re: US 212)","2020-02 (Prague)","|Complete|","18.0","" +"`P1868R2 `__","width: clarifying units of width and precision in std::format","2020-02 (Prague)","|Complete|","14","" +"`P1956R1 `__","On the names of low-level bit manipulation functions","2020-02 (Prague)","|Complete|","12","" +"`P1957R2 `__","Converting from ``T*``\ to bool should be considered narrowing (re: US 212)","2020-02 (Prague)","|Complete|","18","" "`P1963R0 `__","Fixing US 313","2020-02 (Prague)","","","" -"`P1964R2 `__","Wording for boolean-testable","2020-02 (Prague)","|Complete|","13.0","" -"`P1970R2 `__","Consistency for size() functions: Add ranges::ssize","2020-02 (Prague)","|Complete|","15.0","" -"`P1973R1 `__","Rename ""_default_init"" Functions, Rev1","2020-02 (Prague)","|Complete|","16.0","" -"`P1976R2 `__","Fixed-size span construction from dynamic range","2020-02 (Prague)","|Complete|","11.0","" -"`P1981R0 `__","Rename leap to leap_second","2020-02 (Prague)","|Complete|","19.0","" -"`P1982R0 `__","Rename link to time_zone_link","2020-02 (Prague)","|Complete|","19.0","" -"`P1983R0 `__","Wording for GB301, US296, US292, US291, and US283","2020-02 (Prague)","|Complete|","15.0","" -"`P1994R1 `__","elements_view needs its own sentinel","2020-02 (Prague)","|Complete|","16.0","" -"`P2002R1 `__","Defaulted comparison specification cleanups","2020-02 (Prague)","|Complete|","7.0","" +"`P1964R2 `__","Wording for boolean-testable","2020-02 (Prague)","|Complete|","13","" +"`P1970R2 `__","Consistency for size() functions: Add ranges::ssize","2020-02 (Prague)","|Complete|","15","" +"`P1973R1 `__","Rename ""_default_init"" Functions, Rev1","2020-02 (Prague)","|Complete|","16","The feature-test macro was not set until LLVM 20." +"`P1976R2 `__","Fixed-size span construction from dynamic range","2020-02 (Prague)","|Complete|","11","" +"`P1981R0 `__","Rename leap to leap_second","2020-02 (Prague)","|Complete|","19","" +"`P1982R0 `__","Rename link to time_zone_link","2020-02 (Prague)","|Complete|","19","" +"`P1983R0 `__","Wording for GB301, US296, US292, US291, and US283","2020-02 (Prague)","|Complete|","15","" +"`P1994R1 `__","elements_view needs its own sentinel","2020-02 (Prague)","|Complete|","16","" +"`P2002R1 `__","Defaulted comparison specification cleanups","2020-02 (Prague)","|Complete|","7","" "`P2045R1 `__","Missing Mandates for the standard library","2020-02 (Prague)","","","" "`P2085R0 `__","Consistent defaulted comparisons","2020-02 (Prague)","","","" -"`P2091R0 `__","Issues with range access CPOs","2020-02 (Prague)","|Complete|","15.0","" +"`P2091R0 `__","Issues with range access CPOs","2020-02 (Prague)","|Complete|","15","" "`P2101R0 `__","P2101R0: 'Models' subsumes 'satisfies' (Wording for US298 and US300)","2020-02 (Prague)","|Nothing To Do|","","" -"`P2102R0 `__","Make 'implicit expression variations' more explicit (Wording for US185)","2020-02 (Prague)","|Complete|","15.0","" -"`P2106R0 `__","Alternative wording for GB315 and GB316","2020-02 (Prague)","|Complete|","15.0","" -"`P2116R0 `__","Remove tuple-like protocol support from fixed-extent span","2020-02 (Prague)","|Complete|","11.0","" +"`P2102R0 `__","Make 'implicit expression variations' more explicit (Wording for US185)","2020-02 (Prague)","|Complete|","15","" +"`P2106R0 `__","Alternative wording for GB315 and GB316","2020-02 (Prague)","|Complete|","15","" +"`P2116R0 `__","Remove tuple-like protocol support from fixed-extent span","2020-02 (Prague)","|Complete|","11","" "","","","","","" -"`P2231R1 `__","Missing constexpr in std::optional and std::variant","2021-06 (Virtual)","|Complete|","19.0","Changes of feature-test macros are completed in LLVM 20." -"`P2325R3 `__","Views should not be required to be default constructible","2021-06 (Virtual)","|Complete|","16.0","" -"`P2210R2 `__","Superior String Splitting","2021-06 (Virtual)","|Complete|","16.0","" -"`P2216R3 `__","std::format improvements","2021-06 (Virtual)","|Complete|","15.0","" -"`P2281R1 `__","Clarifying range adaptor objects","2021-06 (Virtual)","|Complete|","14.0","" -"`P2328R1 `__","join_view should join all views of ranges","2021-06 (Virtual)","|Complete|","15.0","" -"`P2367R0 `__","Remove misuses of list-initialization from Clause 24","2021-06 (Virtual)","|Complete|","15.0","" +"`P2231R1 `__","Missing constexpr in std::optional and std::variant","2021-06 (Virtual)","|Complete|","19","Changes of feature-test macros are completed in LLVM 20." +"`P2325R3 `__","Views should not be required to be default constructible","2021-06 (Virtual)","|Complete|","16","" +"`P2210R2 `__","Superior String Splitting","2021-06 (Virtual)","|Complete|","16","" +"`P2216R3 `__","std::format improvements","2021-06 (Virtual)","|Complete|","15","" +"`P2281R1 `__","Clarifying range adaptor objects","2021-06 (Virtual)","|Complete|","14","" +"`P2328R1 `__","join_view should join all views of ranges","2021-06 (Virtual)","|Complete|","15","" +"`P2367R0 `__","Remove misuses of list-initialization from Clause 24","2021-06 (Virtual)","|Complete|","15","" "","","","","","" "`P2372R3 `__","Fixing locale handling in chrono formatters","2021-10 (Virtual)","|In Progress|","","" -"`P2415R2 `__","What is a ``view``","2021-10 (Virtual)","|Complete|","14.0","" -"`P2418R2 `__","Add support for ``std::generator``-like types to ``std::format``","2021-10 (Virtual)","|Complete|","15.0","" -"`P2432R1 `__","Fix ``istream_view``","2021-10 (Virtual)","|Complete|","16.0","" +"`P2415R2 `__","What is a ``view``","2021-10 (Virtual)","|Complete|","14","" +"`P2418R2 `__","Add support for ``std::generator``-like types to ``std::format``","2021-10 (Virtual)","|Complete|","15","" +"`P2432R1 `__","Fix ``istream_view``","2021-10 (Virtual)","|Complete|","16","" diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index cfa721230e5fb..1215f21985eb9 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -1,141 +1,141 @@ "Issue #","Issue Name","Meeting","Status","First released version","Notes" "`LWG2839 `__","Self-move-assignment of library types, again","2020-11 (Virtual)","|Nothing To Do|","","" -"`LWG3117 `__","Missing ``packaged_task`` deduction guides","2020-11 (Virtual)","|Complete|","16.0","" +"`LWG3117 `__","Missing ``packaged_task`` deduction guides","2020-11 (Virtual)","|Complete|","16","" "`LWG3143 `__","``monotonic_buffer_resource`` growth policy is unclear","2020-11 (Virtual)","","","" "`LWG3195 `__","What is the stored pointer value of an empty ``weak_ptr``?","2020-11 (Virtual)","|Nothing To Do|","","" -"`LWG3211 `__","``std::tuple<>`` should be trivially constructible","2020-11 (Virtual)","|Complete|","9.0","" +"`LWG3211 `__","``std::tuple<>`` should be trivially constructible","2020-11 (Virtual)","|Complete|","9","" "`LWG3236 `__","Random access iterator requirements lack limiting relational operators domain to comparing those from the same range","2020-11 (Virtual)","|Nothing To Do|","","" "`LWG3265 `__","``move_iterator``'s conversions are more broken after P1207","2020-11 (Virtual)","|Nothing To Do|","","Resolved by `LWG3435 `__" -"`LWG3435 `__","``three_way_comparable_with, reverse_iterator>``","2020-11 (Virtual)","|Complete|","13.0","" -"`LWG3432 `__","Missing requirement for ``comparison_category``","2020-11 (Virtual)","|Complete|","16.0","" -"`LWG3447 `__","Deduction guides for ``take_view`` and ``drop_view`` have different constraints","2020-11 (Virtual)","|Complete|","14.0","" -"`LWG3450 `__","The const overloads of ``take_while_view::begin/end`` are underconstrained","2020-11 (Virtual)","|Complete|","16.0","" -"`LWG3464 `__","``istream::gcount()`` can overflow","2020-11 (Virtual)","|Complete|","18.0","" -"`LWG2731 `__","Existence of ``lock_guard::mutex_type`` typedef unclear","2020-11 (Virtual)","|Complete|","5.0","" +"`LWG3435 `__","``three_way_comparable_with, reverse_iterator>``","2020-11 (Virtual)","|Complete|","13","" +"`LWG3432 `__","Missing requirement for ``comparison_category``","2020-11 (Virtual)","|Complete|","16","" +"`LWG3447 `__","Deduction guides for ``take_view`` and ``drop_view`` have different constraints","2020-11 (Virtual)","|Complete|","14","" +"`LWG3450 `__","The const overloads of ``take_while_view::begin/end`` are underconstrained","2020-11 (Virtual)","|Complete|","16","" +"`LWG3464 `__","``istream::gcount()`` can overflow","2020-11 (Virtual)","|Complete|","18","" +"`LWG2731 `__","Existence of ``lock_guard::mutex_type`` typedef unclear","2020-11 (Virtual)","|Complete|","5","" "`LWG2743 `__","P0083R3 ``node_handle`` private members missing ""exposition only"" comment","2020-11 (Virtual)","|Nothing To Do|","","" "`LWG2820 `__","Clarify ```` macros","2020-11 (Virtual)","|Nothing To Do|","","" "`LWG3120 `__","Unclear behavior of ``monotonic_buffer_resource::release()``","2020-11 (Virtual)","","","" -"`LWG3170 `__","``is_always_equal`` added to ``std::allocator`` makes the standard library treat derived types as always equal","2020-11 (Virtual)","|Complete|","18.0","" +"`LWG3170 `__","``is_always_equal`` added to ``std::allocator`` makes the standard library treat derived types as always equal","2020-11 (Virtual)","|Complete|","18","" "`LWG3036 `__","``polymorphic_allocator::destroy`` is extraneous","2020-11 (Virtual)","|Nothing To Do|","","Reverted by P2875R4" -"`LWG3171 `__","LWG2989 breaks ``directory_entry`` stream insertion","2020-11 (Virtual)","|Complete|","14.0","" -"`LWG3306 `__","``ranges::advance`` violates its preconditions","2020-11 (Virtual)","|Complete|","14.0","" +"`LWG3171 `__","LWG2989 breaks ``directory_entry`` stream insertion","2020-11 (Virtual)","|Complete|","14","" +"`LWG3306 `__","``ranges::advance`` violates its preconditions","2020-11 (Virtual)","|Complete|","14","" "`LWG3403 `__","Domain of ``ranges::ssize(E)`` doesn't ``match ranges::size(E)``","2020-11 (Virtual)","","","" -"`LWG3404 `__","Finish removing subrange's conversions from pair-like","2020-11 (Virtual)","|Complete|","13.0","" -"`LWG3405 `__","``common_view``'s converting constructor is bad, too","2020-11 (Virtual)","|Complete|","14.0","" -"`LWG3406 `__","``elements_view::begin()`` and ``elements_view::end()`` have incompatible constraints","2020-11 (Virtual)","|Complete|","16.0","" +"`LWG3404 `__","Finish removing subrange's conversions from pair-like","2020-11 (Virtual)","|Complete|","13","" +"`LWG3405 `__","``common_view``'s converting constructor is bad, too","2020-11 (Virtual)","|Complete|","14","" +"`LWG3406 `__","``elements_view::begin()`` and ``elements_view::end()`` have incompatible constraints","2020-11 (Virtual)","|Complete|","16","" "`LWG3419 `__","[algorithms.requirements]/15 doesn't reserve as many rights as it intends to","2020-11 (Virtual)","|Nothing To Do|","","" -"`LWG3420 `__","cpp17-iterator should check that the type looks like an iterator first","2020-11 (Virtual)","|Complete|","14.0","" +"`LWG3420 `__","cpp17-iterator should check that the type looks like an iterator first","2020-11 (Virtual)","|Complete|","14","" "`LWG3421 `__","Imperfect ADL emulation for boolean-testable","2020-11 (Virtual)","|Nothing To Do|","","" "`LWG3425 `__","``condition_variable_any`` fails to constrain its Lock parameters","2020-11 (Virtual)","|Nothing To Do|","","" -"`LWG3426 `__","``operator<=>(const unique_ptr&, nullptr_t)`` can't get no satisfaction","2020-11 (Virtual)","|Complete|","16.0","" -"`LWG3427 `__","``operator<=>(const shared_ptr&, nullptr_t)`` definition ill-formed","2020-11 (Virtual)","|Complete|","16.0","" -"`LWG3428 `__","``single_view``'s in place constructor should be explicit","2020-11 (Virtual)","|Complete|","14.0","" +"`LWG3426 `__","``operator<=>(const unique_ptr&, nullptr_t)`` can't get no satisfaction","2020-11 (Virtual)","|Complete|","16","" +"`LWG3427 `__","``operator<=>(const shared_ptr&, nullptr_t)`` definition ill-formed","2020-11 (Virtual)","|Complete|","16","" +"`LWG3428 `__","``single_view``'s in place constructor should be explicit","2020-11 (Virtual)","|Complete|","14","" "`LWG3434 `__","``ios_base`` never reclaims memory for iarray and parray","2020-11 (Virtual)","|Nothing To Do|","","" -"`LWG3437 `__","``__cpp_lib_polymorphic_allocator`` is in the wrong header","2020-11 (Virtual)","|Complete|","14.0","" -"`LWG3446 `__","``indirectly_readable_traits`` ambiguity for types with both ``value_type`` and ``element_type``","2020-11 (Virtual)","|Complete|","14.0","" +"`LWG3437 `__","``__cpp_lib_polymorphic_allocator`` is in the wrong header","2020-11 (Virtual)","|Complete|","14","" +"`LWG3446 `__","``indirectly_readable_traits`` ambiguity for types with both ``value_type`` and ``element_type``","2020-11 (Virtual)","|Complete|","14","" "`LWG3448 `__","``transform_view``'s ``sentinel`` not comparable with ``iterator``","2020-11 (Virtual)","","","" -"`LWG3449 `__","``take_view`` and ``take_while_view``'s ``sentinel`` not comparable with their ``const iterator``","2020-11 (Virtual)","|Complete|","16.0","" +"`LWG3449 `__","``take_view`` and ``take_while_view``'s ``sentinel`` not comparable with their ``const iterator``","2020-11 (Virtual)","|Complete|","16","" "`LWG3453 `__","Generic code cannot call ``ranges::advance(i, s)``","2020-11 (Virtual)","|Nothing To Do|","","" "`LWG3455 `__","Incorrect Postconditions on ``unique_ptr`` move assignment","2020-11 (Virtual)","|Nothing To Do|","","" -"`LWG3460 `__","Unimplementable ``noop_coroutine_handle`` guarantees","2020-11 (Virtual)","|Complete|","14.0","" +"`LWG3460 `__","Unimplementable ``noop_coroutine_handle`` guarantees","2020-11 (Virtual)","|Complete|","14","" "`LWG3461 `__","``convertible_to``'s description mishandles cv-qualified ``void``","2020-11 (Virtual)","|Nothing To Do|","","" -"`LWG3465 `__","``compare_partial_order_fallback`` requires ``F < E``","2020-11 (Virtual)","|Complete|","14.0","" +"`LWG3465 `__","``compare_partial_order_fallback`` requires ``F < E``","2020-11 (Virtual)","|Complete|","14","" "`LWG3466 `__","Specify the requirements for ``promise``/``future``/``shared_future`` consistently","2020-11 (Virtual)","|Nothing To Do|","","" -"`LWG3467 `__","``bool`` can't be an integer-like type","2020-11 (Virtual)","|Complete|","14.0","" -"`LWG3472 `__","``counted_iterator`` is missing preconditions","2020-11 (Virtual)","|Complete|","14.0","" -"`LWG3473 `__","Normative encouragement in non-normative note","2020-11 (Virtual)","|Complete|","15.0","" -"`LWG3474 `__","Nesting ``join_views`` is broken because of CTAD","2020-11 (Virtual)","|Complete|","15.0","" +"`LWG3467 `__","``bool`` can't be an integer-like type","2020-11 (Virtual)","|Complete|","14","" +"`LWG3472 `__","``counted_iterator`` is missing preconditions","2020-11 (Virtual)","|Complete|","14","" +"`LWG3473 `__","Normative encouragement in non-normative note","2020-11 (Virtual)","|Complete|","15","" +"`LWG3474 `__","Nesting ``join_views`` is broken because of CTAD","2020-11 (Virtual)","|Complete|","15","" "`LWG3476 `__","``thread`` and ``jthread`` constructors require that the parameters be move-constructible but never move construct the parameters","2020-11 (Virtual)","","","" -"`LWG3477 `__","Simplify constraints for ``semiregular-box``","2020-11 (Virtual)","|Complete|","13.0","" -"`LWG3482 `__","``drop_view``'s const begin should additionally require ``sized_range``","2020-11 (Virtual)","|Complete|","14.0","" -"`LWG3483 `__","``transform_view::iterator``'s difference is overconstrained","2020-11 (Virtual)","|Complete|","14.0","" +"`LWG3477 `__","Simplify constraints for ``semiregular-box``","2020-11 (Virtual)","|Complete|","13","" +"`LWG3482 `__","``drop_view``'s const begin should additionally require ``sized_range``","2020-11 (Virtual)","|Complete|","14","" +"`LWG3483 `__","``transform_view::iterator``'s difference is overconstrained","2020-11 (Virtual)","|Complete|","14","" "","","","","","" "`LWG3391 `__","Problems with ``counted_iterator``/``move_iterator::base() const &``","2021-02 (Virtual)","","","" -"`LWG3433 `__","``subrange::advance(n)`` has UB when ``n < 0``","2021-02 (Virtual)","|Complete|","14.0","" +"`LWG3433 `__","``subrange::advance(n)`` has UB when ``n < 0``","2021-02 (Virtual)","|Complete|","14","" "`LWG3490 `__","``ranges::drop_while_view::begin()`` is missing a precondition","2021-02 (Virtual)","|Nothing To Do|","","" -"`LWG3492 `__","Minimal improvements to ``elements_view::iterator``","2021-02 (Virtual)","|Complete|","16.0","" +"`LWG3492 `__","Minimal improvements to ``elements_view::iterator``","2021-02 (Virtual)","|Complete|","16","" "`LWG3494 `__","Allow ranges to be conditionally borrowed","2021-02 (Virtual)","|Nothing To Do|","","Superseded by `P2017R1 `__" "`LWG3495 `__","``constexpr launder`` makes pointers to inactive members of unions usable","2021-02 (Virtual)","|Nothing To Do|","","" -"`LWG3500 `__","``join_view::iterator::operator->()`` is bogus","2021-02 (Virtual)","|Complete|","14.0","" -"`LWG3502 `__","``elements_view`` should not be allowed to return dangling reference","2021-02 (Virtual)","|Complete|","16.0","" +"`LWG3500 `__","``join_view::iterator::operator->()`` is bogus","2021-02 (Virtual)","|Complete|","14","" +"`LWG3502 `__","``elements_view`` should not be allowed to return dangling reference","2021-02 (Virtual)","|Complete|","16","" "`LWG3505 `__","``split_view::outer-iterator::operator++`` misspecified","2021-02 (Virtual)","","","" "","","","","","" "`LWG2774 `__","``std::function`` construction vs assignment","2021-06 (Virtual)","","","" "`LWG2818 `__","``::std::`` everywhere rule needs tweaking","2021-06 (Virtual)","|Nothing To Do|","","" "`LWG2997 `__","LWG 491 and the specification of ``{forward_,}list::unique``","2021-06 (Virtual)","","","" -"`LWG3410 `__","``lexicographical_compare_three_way`` is overspecified","2021-06 (Virtual)","|Complete|","17.0","" -"`LWG3430 `__","``std::fstream`` & co. should be constructible from string_view","2021-06 (Virtual)","|Complete|","19.0","" +"`LWG3410 `__","``lexicographical_compare_three_way`` is overspecified","2021-06 (Virtual)","|Complete|","17","" +"`LWG3430 `__","``std::fstream`` & co. should be constructible from string_view","2021-06 (Virtual)","|Complete|","19","" "`LWG3462 `__","§[formatter.requirements]: Formatter requirements forbid use of ``fc.arg()``","2021-06 (Virtual)","|Nothing To Do|","","" "`LWG3481 `__","``viewable_range`` mishandles lvalue move-only views","2021-06 (Virtual)","|Nothing To Do|","","Superseded by `P2415R2 `__" -"`LWG3506 `__","Missing allocator-extended constructors for ``priority_queue``","2021-06 (Virtual)","|Complete|","14.0","" -"`LWG3517 `__","``join_view::iterator``'s ``iter_swap`` is underconstrained","2021-06 (Virtual)","|Complete|","14.0","" +"`LWG3506 `__","Missing allocator-extended constructors for ``priority_queue``","2021-06 (Virtual)","|Complete|","14","" +"`LWG3517 `__","``join_view::iterator``'s ``iter_swap`` is underconstrained","2021-06 (Virtual)","|Complete|","14","" "`LWG3518 `__","Exception requirements on char trait operations unclear","2021-06 (Virtual)","|Nothing To Do|","","" "`LWG3519 `__","Incomplete synopses for ```` classes","2021-06 (Virtual)","","","" -"`LWG3520 `__","``iter_move`` and ``iter_swap`` are inconsistent for ``transform_view::iterator``","2021-06 (Virtual)","|Complete|","14.0","" +"`LWG3520 `__","``iter_move`` and ``iter_swap`` are inconsistent for ``transform_view::iterator``","2021-06 (Virtual)","|Complete|","14","" "`LWG3521 `__","Overly strict requirements on ``qsort`` and ``bsearch``","2021-06 (Virtual)","|Nothing To Do|","","" -"`LWG3522 `__","Missing requirement on ``InputIterator`` template parameter for ``priority_queue`` constructors","2021-06 (Virtual)","|Complete|","14.0","" -"`LWG3523 `__","``iota_view::sentinel`` is not always ``iota_view``'s sentinel","2021-06 (Virtual)","|Complete|","17.0","" +"`LWG3522 `__","Missing requirement on ``InputIterator`` template parameter for ``priority_queue`` constructors","2021-06 (Virtual)","|Complete|","14","" +"`LWG3523 `__","``iota_view::sentinel`` is not always ``iota_view``'s sentinel","2021-06 (Virtual)","|Complete|","17","" "`LWG3526 `__","Return types of ``uses_allocator_construction_args`` unspecified","2021-06 (Virtual)","","","" "`LWG3527 `__","``uses_allocator_construction_args`` handles rvalue pairs of rvalue references incorrectly","2021-06 (Virtual)","","","" -"`LWG3528 `__","``make_from_tuple`` can perform (the equivalent of) a C-style cast","2021-06 (Virtual)","|Complete|","19.0","" -"`LWG3529 `__","``priority_queue(first, last)`` should construct ``c`` with ``(first, last)``","2021-06 (Virtual)","|Complete|","14.0","" +"`LWG3528 `__","``make_from_tuple`` can perform (the equivalent of) a C-style cast","2021-06 (Virtual)","|Complete|","19","" +"`LWG3529 `__","``priority_queue(first, last)`` should construct ``c`` with ``(first, last)``","2021-06 (Virtual)","|Complete|","14","" "`LWG3530 `__","``BUILTIN-PTR-MEOW`` should not opt the type out of syntactic checks","2021-06 (Virtual)","","","" "`LWG3532 `__","``split_view::inner-iterator::operator++(int)`` should depend on ``Base``","2021-06 (Virtual)","","","" -"`LWG3533 `__","Make ``base() const &`` consistent across iterator wrappers that supports ``input_iterators``","2021-06 (Virtual)","|Complete|","14.0","" +"`LWG3533 `__","Make ``base() const &`` consistent across iterator wrappers that supports ``input_iterators``","2021-06 (Virtual)","|Complete|","14","" "`LWG3536 `__","Should ``chrono::from_stream()`` assign zero to duration for failure?","2021-06 (Virtual)","","","" -"`LWG3539 `__","``format_to`` must not copy models of ``output_iterator``","2021-06 (Virtual)","|Complete|","14.0","" -"`LWG3540 `__","§[format.arg] There should be no const in ``basic_format_arg(const T* p)``","2021-06 (Virtual)","|Complete|","14.0","" -"`LWG3541 `__","``indirectly_readable_traits`` should be SFINAE-friendly for all types","2021-06 (Virtual)","|Complete|","14.0","" -"`LWG3542 `__","``basic_format_arg`` mishandles ``basic_string_view`` with custom traits","2021-06 (Virtual)","|Complete|","14.0","" +"`LWG3539 `__","``format_to`` must not copy models of ``output_iterator``","2021-06 (Virtual)","|Complete|","14","" +"`LWG3540 `__","§[format.arg] There should be no const in ``basic_format_arg(const T* p)``","2021-06 (Virtual)","|Complete|","14","" +"`LWG3541 `__","``indirectly_readable_traits`` should be SFINAE-friendly for all types","2021-06 (Virtual)","|Complete|","14","" +"`LWG3542 `__","``basic_format_arg`` mishandles ``basic_string_view`` with custom traits","2021-06 (Virtual)","|Complete|","14","" "`LWG3543 `__","Definition of when ``counted_iterators`` refer to the same sequence isn't quite right","2021-06 (Virtual)","|Nothing To Do|","","" -"`LWG3544 `__","``format-arg-store::args`` is unintentionally not exposition-only","2021-06 (Virtual)","|Complete|","14.0","" +"`LWG3544 `__","``format-arg-store::args`` is unintentionally not exposition-only","2021-06 (Virtual)","|Complete|","14","" "`LWG3546 `__","``common_iterator``'s postfix-proxy is not quite right","2021-06 (Virtual)","","","" -"`LWG3548 `__","``shared_ptr`` construction from ``unique_ptr`` should move (not copy) the deleter","2021-06 (Virtual)","|Complete|","15.0","" -"`LWG3549 `__","``view_interface`` is overspecified to derive from ``view_base``","2021-06 (Virtual)","|Complete|","14.0","" +"`LWG3548 `__","``shared_ptr`` construction from ``unique_ptr`` should move (not copy) the deleter","2021-06 (Virtual)","|Complete|","15","" +"`LWG3549 `__","``view_interface`` is overspecified to derive from ``view_base``","2021-06 (Virtual)","|Complete|","14","" "`LWG3551 `__","``borrowed_{iterator,subrange}_t`` are overspecified","2021-06 (Virtual)","|Nothing To Do|","","" "`LWG3552 `__","Parallel specialized memory algorithms should require forward iterators","2021-06 (Virtual)","","","" "`LWG3553 `__","Useless constraint in ``split_view::outer-iterator::value_type::begin()``","2021-06 (Virtual)","","","" "`LWG3555 `__","``{transform,elements}_view::iterator::iterator_concept`` should consider const-qualification of the underlying range","2021-06 (Virtual)","","","" "","","","","","" "`LWG2191 `__","Incorrect specification of ``match_results(match_results&&)``","2021-10 (Virtual)","|Nothing To Do|","","" -"`LWG2381 `__","Inconsistency in parsing floating point numbers","2021-10 (Virtual)","|Complete|","19.0","" -"`LWG2762 `__","``unique_ptr operator*()`` should be ``noexcept``","2021-10 (Virtual)","|Complete|","19.0","" +"`LWG2381 `__","Inconsistency in parsing floating point numbers","2021-10 (Virtual)","|Complete|","19","" +"`LWG2762 `__","``unique_ptr operator*()`` should be ``noexcept``","2021-10 (Virtual)","|Complete|","19","" "`LWG3121 `__","``tuple`` constructor constraints for ``UTypes&&...`` overloads","2021-10 (Virtual)","","","" "`LWG3123 `__","``duration`` constructor from representation shouldn't be effectively non-throwing","2021-10 (Virtual)","","","" -"`LWG3146 `__","Excessive unwrapping in ``std::ref/cref``","2021-10 (Virtual)","|Complete|","14.0","" +"`LWG3146 `__","Excessive unwrapping in ``std::ref/cref``","2021-10 (Virtual)","|Complete|","14","" "`LWG3152 `__","``common_type`` and ``common_reference`` have flaws in common","2021-10 (Virtual)","","","" -"`LWG3293 `__","``move_iterator operator+()`` has incorrect constraints","2021-10 (Virtual)","|Complete|","15.0","" +"`LWG3293 `__","``move_iterator operator+()`` has incorrect constraints","2021-10 (Virtual)","|Complete|","15","" "`LWG3361 `__","``safe_range`` case","2021-10 (Virtual)","|Nothing To Do|","","" -"`LWG3392 `__","``ranges::distance()`` cannot be used on a move-only iterator with a sized sentinel","2021-10 (Virtual)","|Complete|","14.0","" -"`LWG3407 `__","Some problems with the wording changes of P1739R4","2021-10 (Virtual)","|Complete|","15.0","" -"`LWG3422 `__","Issues of ``seed_seq``'s constructors","2021-10 (Virtual)","|Complete|","14.0","" -"`LWG3470 `__","``convertible-to-non-slicing`` seems to reject valid case","2021-10 (Virtual)","|Complete|","14.0","" -"`LWG3480 `__","``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","2021-10 (Virtual)","|Complete|","14.0","" +"`LWG3392 `__","``ranges::distance()`` cannot be used on a move-only iterator with a sized sentinel","2021-10 (Virtual)","|Complete|","14","" +"`LWG3407 `__","Some problems with the wording changes of P1739R4","2021-10 (Virtual)","|Complete|","15","" +"`LWG3422 `__","Issues of ``seed_seq``'s constructors","2021-10 (Virtual)","|Complete|","14","" +"`LWG3470 `__","``convertible-to-non-slicing`` seems to reject valid case","2021-10 (Virtual)","|Complete|","14","" +"`LWG3480 `__","``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","2021-10 (Virtual)","|Complete|","14","" "`LWG3498 `__","Inconsistent ``noexcept``-specifiers for ``basic_syncbuf``","2021-10 (Virtual)","","","" -"`LWG3535 `__","``join_view::iterator::iterator_category`` and ``::iterator_concept`` lie","2021-10 (Virtual)","|Complete|","15.0","" +"`LWG3535 `__","``join_view::iterator::iterator_category`` and ``::iterator_concept`` lie","2021-10 (Virtual)","|Complete|","15","" "`LWG3554 `__","``chrono::parse`` needs ``const charT*`` and ``basic_string_view`` overloads","2021-10 (Virtual)","","","" -"`LWG3557 `__","The ``static_cast`` expression in ``convertible_to`` has the wrong operand","2021-10 (Virtual)","|Complete|","14.0","" +"`LWG3557 `__","The ``static_cast`` expression in ``convertible_to`` has the wrong operand","2021-10 (Virtual)","|Complete|","14","" "`LWG3559 `__","Semantic requirements of ``sized_range`` is circular","2021-10 (Virtual)","|Nothing To Do|","","" "`LWG3560 `__","``ranges::equal`` and ``ranges::is_permutation`` should short-circuit for ``sized_ranges``","2021-10 (Virtual)","","","" "`LWG3561 `__","Issue with internal counter in ``discard_block_engine``","2021-10 (Virtual)","","","" "`LWG3563 `__","``keys_view`` example is broken","2021-10 (Virtual)","","","" -"`LWG3566 `__","Constraint recursion for ``operator<=>(optional, U)``","2021-10 (Virtual)","|Complete|","17.0","" -"`LWG3567 `__","Formatting move-only iterators take two","2021-10 (Virtual)","|Complete|","16.0","" -"`LWG3568 `__","``basic_istream_view`` needs to initialize ``value_``","2021-10 (Virtual)","|Complete|","16.0","" -"`LWG3570 `__","``basic_osyncstream::emit`` should be an unformatted output function","2021-10 (Virtual)","|Complete|","18.0","" +"`LWG3566 `__","Constraint recursion for ``operator<=>(optional, U)``","2021-10 (Virtual)","|Complete|","17","" +"`LWG3567 `__","Formatting move-only iterators take two","2021-10 (Virtual)","|Complete|","16","" +"`LWG3568 `__","``basic_istream_view`` needs to initialize ``value_``","2021-10 (Virtual)","|Complete|","16","" +"`LWG3570 `__","``basic_osyncstream::emit`` should be an unformatted output function","2021-10 (Virtual)","|Complete|","18","" "`LWG3571 `__","``flush_emit`` should set ``badbit`` if the ``emit`` call fails","2021-10 (Virtual)","","","" -"`LWG3572 `__","``copyable-box`` should be fully ``constexpr``","2021-10 (Virtual)","|Complete|","14.0","" -"`LWG3573 `__","Missing Throws element for ``basic_string_view(It begin, End end)``","2021-10 (Virtual)","|Complete|","14.0","" -"`LWG3574 `__","``common_iterator`` should be completely ``constexpr``-able","2021-10 (Virtual)","|Complete|","14.0","" -"`LWG3580 `__","``iota_view``'s ``iterator``'s binary ``operator+`` should be improved","2021-10 (Virtual)","|Complete|","14.0","" -"`LWG3581 `__","The range constructor makes ``basic_string_view`` not trivially move constructible","2021-10 (Virtual)","|Complete|","14.0","" +"`LWG3572 `__","``copyable-box`` should be fully ``constexpr``","2021-10 (Virtual)","|Complete|","14","" +"`LWG3573 `__","Missing Throws element for ``basic_string_view(It begin, End end)``","2021-10 (Virtual)","|Complete|","14","" +"`LWG3574 `__","``common_iterator`` should be completely ``constexpr``-able","2021-10 (Virtual)","|Complete|","14","" +"`LWG3580 `__","``iota_view``'s ``iterator``'s binary ``operator+`` should be improved","2021-10 (Virtual)","|Complete|","14","" +"`LWG3581 `__","The range constructor makes ``basic_string_view`` not trivially move constructible","2021-10 (Virtual)","|Complete|","14","" "`LWG3585 `__","``variant`` converting assignment with immovable alternative","2021-10 (Virtual)","","","" -"`LWG3589 `__","The ``const`` lvalue reference overload of ``get`` for ``subrange`` does not constrain ``I`` to be ``copyable`` when ``N == 0``","2021-10 (Virtual)","|Complete|","14.0","" -"`LWG3590 `__","``split_view::base() const &`` is overconstrained","2021-10 (Virtual)","|Complete|","16.0","" +"`LWG3589 `__","The ``const`` lvalue reference overload of ``get`` for ``subrange`` does not constrain ``I`` to be ``copyable`` when ``N == 0``","2021-10 (Virtual)","|Complete|","14","" +"`LWG3590 `__","``split_view::base() const &`` is overconstrained","2021-10 (Virtual)","|Complete|","16","" "`LWG3591 `__","``lazy_split_view::inner-iterator::base() &&`` invalidates outer iterators","2021-10 (Virtual)","","","" "`LWG3592 `__","``lazy_split_view`` needs to check the simpleness of Pattern","2021-10 (Virtual)","","","" "`LWG3593 `__","Several iterators' ``base() const &`` and ``lazy_split_view::outer-iterator::value_type::end()`` missing ``noexcept``","2021-10 (Virtual)","","","" -"`LWG3595 `__","Exposition-only classes proxy and postfix-proxy for ``common_iterator`` should be fully ``constexpr``","2021-10 (Virtual)","|Complete|","14.0","" +"`LWG3595 `__","Exposition-only classes proxy and postfix-proxy for ``common_iterator`` should be fully ``constexpr``","2021-10 (Virtual)","|Complete|","14","" "","","","","","" "`LWG3088 `__","``forward_list::merge`` behaviour unclear when passed ``*this``","2022-02 (Virtual)","","","" "`LWG3471 `__","``polymorphic_allocator::allocate`` does not satisfy ``Cpp17Allocator`` requirements","2022-02 (Virtual)","","","" @@ -144,81 +144,81 @@ "`LWG3601 `__","common_iterator's postfix-proxy needs ``indirectly_readable`` ","2022-02 (Virtual)","","","" "`LWG3607 `__","``contiguous_iterator`` should not be allowed to have custom ``iter_move`` and ``iter_swap`` behavior","2022-02 (Virtual)","|Nothing To Do|","","" "`LWG3610 `__","``iota_view::size`` sometimes rejects integer-class types","2022-02 (Virtual)","","","" -"`LWG3612 `__","Inconsistent pointer alignment in ``std::format`` ","2022-02 (Virtual)","|Complete|","14.0","" -"`LWG3616 `__","LWG 3498 seems to miss the non-member ``swap`` for ``basic_syncbuf`` ","2022-02 (Virtual)","|Complete|","18.0","" -"`LWG3618 `__","Unnecessary ``iter_move`` for ``transform_view::iterator`` ","2022-02 (Virtual)","|Complete|","19.0","" +"`LWG3612 `__","Inconsistent pointer alignment in ``std::format`` ","2022-02 (Virtual)","|Complete|","14","" +"`LWG3616 `__","LWG 3498 seems to miss the non-member ``swap`` for ``basic_syncbuf`` ","2022-02 (Virtual)","|Complete|","18","" +"`LWG3618 `__","Unnecessary ``iter_move`` for ``transform_view::iterator`` ","2022-02 (Virtual)","|Complete|","19","" "`LWG3619 `__","Specification of ``vformat_to`` contains ill-formed ``formatted_size`` calls","2022-02 (Virtual)","|Nothing To Do|","","" -"`LWG3621 `__","Remove feature-test macro ``__cpp_lib_monadic_optional`` ","2022-02 (Virtual)","|Complete|","15.0","" +"`LWG3621 `__","Remove feature-test macro ``__cpp_lib_monadic_optional`` ","2022-02 (Virtual)","|Complete|","15","" "`LWG3632 `__","``unique_ptr`` ""Mandates: This constructor is not selected by class template argument deduction""","2022-02 (Virtual)","|Nothing To Do|","","" -"`LWG3643 `__","Missing ``constexpr`` in ``std::counted_iterator`` ","2022-02 (Virtual)","|Complete|","19.0","" -"`LWG3648 `__","``format`` should not print ``bool`` with ``'c'`` ","2022-02 (Virtual)","|Complete|","15.0","" +"`LWG3643 `__","Missing ``constexpr`` in ``std::counted_iterator`` ","2022-02 (Virtual)","|Complete|","19","" +"`LWG3648 `__","``format`` should not print ``bool`` with ``'c'`` ","2022-02 (Virtual)","|Complete|","15","" "`LWG3649 `__","[fund.ts.v2] Reinstate and bump ``__cpp_lib_experimental_memory_resource`` feature test macro","2022-02 (Virtual)","","","" "`LWG3650 `__","Are ``std::basic_string`` 's ``iterator`` and ``const_iterator`` constexpr iterators?","2022-02 (Virtual)","|Nothing To Do|","","" -"`LWG3654 `__","``basic_format_context::arg(size_t)`` should be ``noexcept`` ","2022-02 (Virtual)","|Complete|","15.0","" -"`LWG3657 `__","``std::hash`` is not enabled","2022-02 (Virtual)","|Complete|","17.0","" -"`LWG3660 `__","``iterator_traits::pointer`` should conform to §[iterator.traits]","2022-02 (Virtual)","|Complete|","14.0","" +"`LWG3654 `__","``basic_format_context::arg(size_t)`` should be ``noexcept`` ","2022-02 (Virtual)","|Complete|","15","" +"`LWG3657 `__","``std::hash`` is not enabled","2022-02 (Virtual)","|Complete|","17","" +"`LWG3660 `__","``iterator_traits::pointer`` should conform to §[iterator.traits]","2022-02 (Virtual)","|Complete|","14","" "`LWG3661 `__","``constinit atomic> a(nullptr);`` should work","2022-02 (Virtual)","","","" "","","","","","" -"`LWG3564 `__","``transform_view::iterator::value_type`` and ``iterator_category`` should use ``const F&``","2022-07 (Virtual)","|Complete|","20.0","" +"`LWG3564 `__","``transform_view::iterator::value_type`` and ``iterator_category`` should use ``const F&``","2022-07 (Virtual)","|Complete|","20","" "`LWG3617 `__","``function``/``packaged_task`` deduction guides and deducing ``this``","2022-07 (Virtual)","","","" -"`LWG3656 `__","Inconsistent bit operations returning a count","2022-07 (Virtual)","|Complete|","15.0","" -"`LWG3659 `__","Consider ``ATOMIC_FLAG_INIT`` undeprecation","2022-07 (Virtual)","|Complete|","15.0","" +"`LWG3656 `__","Inconsistent bit operations returning a count","2022-07 (Virtual)","|Complete|","15","" +"`LWG3659 `__","Consider ``ATOMIC_FLAG_INIT`` undeprecation","2022-07 (Virtual)","|Complete|","15","" "`LWG3670 `__","``Cpp17InputIterators`` don't have integer-class difference types","2022-07 (Virtual)","","","" -"`LWG3671 `__","``atomic_fetch_xor`` missing from ``stdatomic.h``","2022-07 (Virtual)","|Complete|","20.0","" -"`LWG3672 `__","``common_iterator::operator->()`` should return by value","2022-07 (Virtual)","|Complete|","19.0","" -"`LWG3683 `__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","2022-07 (Virtual)","|Complete|","20.0","" -"`LWG3687 `__","``expected`` move constructor should move","2022-07 (Virtual)","|Complete|","16.0","" -"`LWG3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","|Complete|","20.0","" -"`LWG3701 `__","Make ``formatter, charT>`` requirement explicit","2022-07 (Virtual)","|Complete|","15.0","" +"`LWG3671 `__","``atomic_fetch_xor`` missing from ``stdatomic.h``","2022-07 (Virtual)","|Complete|","20","" +"`LWG3672 `__","``common_iterator::operator->()`` should return by value","2022-07 (Virtual)","|Complete|","19","" +"`LWG3683 `__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","2022-07 (Virtual)","|Complete|","20","" +"`LWG3687 `__","``expected`` move constructor should move","2022-07 (Virtual)","|Complete|","16","" +"`LWG3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","|Complete|","20","" +"`LWG3701 `__","Make ``formatter, charT>`` requirement explicit","2022-07 (Virtual)","|Complete|","15","" "`LWG3702 `__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","","","" -"`LWG3703 `__","Missing requirements for ``expected`` requires ``is_void``","2022-07 (Virtual)","|Complete|","16.0","" +"`LWG3703 `__","Missing requirements for ``expected`` requires ``is_void``","2022-07 (Virtual)","|Complete|","16","" "`LWG3704 `__","LWG 2059 added overloads that might be ill-formed for sets","2022-07 (Virtual)","","","" -"`LWG3705 `__","Hashability shouldn't depend on basic_string's allocator","2022-07 (Virtual)","|Complete|","16.0","" +"`LWG3705 `__","Hashability shouldn't depend on basic_string's allocator","2022-07 (Virtual)","|Complete|","16","" "`LWG3707 `__","chunk_view::outer-iterator::value_type::size should return unsigned type","2022-07 (Virtual)","","","" -"`LWG3708 `__","``take_while_view::sentinel``'s conversion constructor should move","2022-07 (Virtual)","|Complete|","16.0","" +"`LWG3708 `__","``take_while_view::sentinel``'s conversion constructor should move","2022-07 (Virtual)","|Complete|","16","" "`LWG3709 `__","LWG-3703 was underly ambitious","2022-07 (Virtual)","","","" "`LWG3710 `__","The ``end`` of ``chunk_view`` for input ranges can be ``const``","2022-07 (Virtual)","","","" "`LWG3711 `__","Missing preconditions for slide_view constructor","2022-07 (Virtual)","","","" "`LWG3712 `__","``chunk_view`` and ``slide_view`` should not be ``default_initializable``","2022-07 (Virtual)","","","" "`LWG3713 `__","Sorted with respect to comparator (only)","2022-07 (Virtual)","|Nothing To Do|","","" -"`LWG3715 `__","``view_interface::empty`` is overconstrained","2022-07 (Virtual)","|Complete|","19.0","" -"`LWG3719 `__","Directory iterators should be usable with default sentinel","2022-07 (Virtual)","|Complete|","17.0","" -"`LWG3721 `__","Allow an ``arg-id`` with a value of zero for ``width`` in ``std-format-spec``","2022-07 (Virtual)","|Complete|","16.0","" -"`LWG3724 `__","``decay-copy`` should be constrained","2022-07 (Virtual)","|Complete|","14.0","" +"`LWG3715 `__","``view_interface::empty`` is overconstrained","2022-07 (Virtual)","|Complete|","19","" +"`LWG3719 `__","Directory iterators should be usable with default sentinel","2022-07 (Virtual)","|Complete|","17","" +"`LWG3721 `__","Allow an ``arg-id`` with a value of zero for ``width`` in ``std-format-spec``","2022-07 (Virtual)","|Complete|","16","" +"`LWG3724 `__","``decay-copy`` should be constrained","2022-07 (Virtual)","|Complete|","14","" "","","","","","" "`LWG3028 `__","Container requirements tables should distinguish ``const`` and non-``const`` variables","2022-11 (Kona)","","","" "`LWG3118 `__","``fpos`` equality comparison unspecified","2022-11 (Kona)","","","" "`LWG3177 `__","Limit permission to specialize variable templates to program-defined types","2022-11 (Kona)","|Nothing To Do|","","" "`LWG3515 `__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized","2022-11 (Kona)","","","" -"`LWG3545 `__","``std::pointer_traits`` should be SFINAE-friendly","2022-11 (Kona)","|Complete|","18.0","" +"`LWG3545 `__","``std::pointer_traits`` should be SFINAE-friendly","2022-11 (Kona)","|Complete|","18","" "`LWG3569 `__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators","2022-11 (Kona)","","","" -"`LWG3594 `__","``inout_ptr`` — inconsistent ``release()`` in destructor","2022-11 (Kona)","|Complete|","19.0","" +"`LWG3594 `__","``inout_ptr`` — inconsistent ``release()`` in destructor","2022-11 (Kona)","|Complete|","19","" "`LWG3597 `__","Unsigned integer types don't model advanceable","2022-11 (Kona)","","","" "`LWG3600 `__","Making ``istream_iterator`` copy constructor trivial is an ABI break","2022-11 (Kona)","","","" -"`LWG3629 `__","``make_error_code`` and ``make_error_condition`` are customization points","2022-11 (Kona)","|Complete|","16.0","" -"`LWG3636 `__","``formatter::format`` should be ``const``-qualified","2022-11 (Kona)","|Complete|","16.0","" -"`LWG3646 `__","``std::ranges::view_interface::size`` returns a signed type","2022-11 (Kona)","|Complete|","16.0","" -"`LWG3677 `__","Is a cv-qualified ``pair`` specially handled in uses-allocator construction?","2022-11 (Kona)","|Complete|","18.0","" +"`LWG3629 `__","``make_error_code`` and ``make_error_condition`` are customization points","2022-11 (Kona)","|Complete|","16","" +"`LWG3636 `__","``formatter::format`` should be ``const``-qualified","2022-11 (Kona)","|Complete|","16","" +"`LWG3646 `__","``std::ranges::view_interface::size`` returns a signed type","2022-11 (Kona)","|Complete|","16","" +"`LWG3677 `__","Is a cv-qualified ``pair`` specially handled in uses-allocator construction?","2022-11 (Kona)","|Complete|","18","" "`LWG3717 `__","``common_view::end`` should improve ``random_access_range`` case","2022-11 (Kona)","","","" "`LWG3732 `__","``prepend_range`` and ``append_range`` can't be amortized constant time","2022-11 (Kona)","|Nothing To Do|","","" -"`LWG3736 `__","``move_iterator`` missing ``disable_sized_sentinel_for`` specialization","2022-11 (Kona)","|Complete|","19.0","" +"`LWG3736 `__","``move_iterator`` missing ``disable_sized_sentinel_for`` specialization","2022-11 (Kona)","|Complete|","19","" "`LWG3737 `__","``take_view::sentinel`` should provide ``operator-``","2022-11 (Kona)","","","" -"`LWG3738 `__","Missing preconditions for ``take_view`` constructor","2022-11 (Kona)","|Complete|","16.0","" +"`LWG3738 `__","Missing preconditions for ``take_view`` constructor","2022-11 (Kona)","|Complete|","16","" "`LWG3743 `__","``ranges::to``'s reserve may be ill-formed","2022-11 (Kona)","","","" -"`LWG3745 `__","``std::atomic_wait`` and its friends lack ``noexcept``","2022-11 (Kona)","|Complete|","16.0","" -"`LWG3746 `__","``optional``'s spaceship with ``U`` with a type derived from optional causes infinite constraint meta-recursion","2022-11 (Kona)","|Complete|","17.0","" +"`LWG3745 `__","``std::atomic_wait`` and its friends lack ``noexcept``","2022-11 (Kona)","|Complete|","16","" +"`LWG3746 `__","``optional``'s spaceship with ``U`` with a type derived from optional causes infinite constraint meta-recursion","2022-11 (Kona)","|Complete|","17","" "`LWG3747 `__","``ranges::uninitialized_copy_n``, ``ranges::uninitialized_move_n``, and ``ranges::destroy_n`` should use ``std::move``","2022-11 (Kona)","","","" "`LWG3750 `__","Too many papers bump ``__cpp_lib_format``","2022-11 (Kona)","|Partial|","","Only ``__cpp_lib_format_ranges`` is fully implemented" "`LWG3751 `__","Missing feature macro for ``flat_set``","2022-11 (Kona)","","","" "`LWG3753 `__","Clarify entity vs. freestanding entity","2022-11 (Kona)","","","" "`LWG3754 `__","Class template expected synopsis contains declarations that do not match the detailed description","2022-11 (Kona)","|Nothing To Do|","","" -"`LWG3755 `__","``tuple-for-each`` can call ``user-defined`` ``operator,``","2022-11 (Kona)","|Complete|","17.0","" +"`LWG3755 `__","``tuple-for-each`` can call ``user-defined`` ``operator,``","2022-11 (Kona)","|Complete|","17","" "`LWG3757 `__","What's the effect of ``std::forward_like(x)``?","2022-11 (Kona)","","","" -"`LWG3759 `__","``ranges::rotate_copy`` should use ``std::move``","2022-11 (Kona)","|Complete|","15.0","" +"`LWG3759 `__","``ranges::rotate_copy`` should use ``std::move``","2022-11 (Kona)","|Complete|","15","" "`LWG3760 `__","``cartesian_product_view::iterator``'s ``parent_`` is never valid","2022-11 (Kona)","","","" "`LWG3761 `__","``cartesian_product_view::iterator::operator-`` should pass by reference","2022-11 (Kona)","","","" "`LWG3762 `__","``generator::iterator::operator==`` should pass by reference","2022-11 (Kona)","","","" -"`LWG3764 `__","``reference_wrapper::operator()`` should propagate noexcept","2022-11 (Kona)","|Complete|","17.0","" +"`LWG3764 `__","``reference_wrapper::operator()`` should propagate noexcept","2022-11 (Kona)","|Complete|","17","" "`LWG3765 `__","``const_sentinel`` should be constrained","2022-11 (Kona)","","","" "`LWG3766 `__","``view_interface::cbegin`` is underconstrained","2022-11 (Kona)","","","" "`LWG3770 `__","``const_sentinel_t`` is missing","2022-11 (Kona)","","","" @@ -227,11 +227,11 @@ "`LWG3775 `__","Broken dependencies in the ``Cpp17Allocator`` requirements","2022-11 (Kona)","","","" "`LWG3778 `__","``vector`` missing exception specifications","2022-11 (Kona)","|Complete|","3.7","" "`LWG3781 `__","The exposition-only alias templates ``cont-key-type`` and ``cont-mapped-type`` should be removed","2022-11 (Kona)","|Nothing To Do|","","" -"`LWG3782 `__","Should ```` declare ``::lerp``?","2022-11 (Kona)","|Complete|","17.0","" -"`LWG3784 `__","std.compat should not provide ``::byte`` and its friends","2022-11 (Kona)","|Complete|","19.0","" +"`LWG3782 `__","Should ```` declare ``::lerp``?","2022-11 (Kona)","|Complete|","17","" +"`LWG3784 `__","std.compat should not provide ``::byte`` and its friends","2022-11 (Kona)","|Complete|","19","" "`LWG3785 `__","``ranges::to`` is over-constrained on the destination type being a range","2022-11 (Kona)","","","" "`LWG3788 `__","``jthread::operator=(jthread&&)`` postconditions are unimplementable under self-assignment","2022-11 (Kona)","","","" -"`LWG3792 `__","``__cpp_lib_constexpr_algorithms`` should also be defined in ````","2022-11 (Kona)","|Complete|","16.0","" +"`LWG3792 `__","``__cpp_lib_constexpr_algorithms`` should also be defined in ````","2022-11 (Kona)","|Complete|","16","" "`LWG3795 `__","Self-move-assignment of ``std::future`` and ``std::shared_future`` have unimplementable postconditions","2022-11 (Kona)","","","" "`LWG3796 `__","``movable-box`` as member should use ``default-initialization`` instead of ``copy-initialization``","2022-11 (Kona)","","","" "`LWG3798 `__","Rvalue reference and ``iterator_category``","2022-11 (Kona)","|Partial|","","``join_with_view``, ``zip_transform_view``, and ``adjacent_transform_view`` haven't been done yet since these types aren't implemented yet" @@ -250,59 +250,59 @@ "`LWG3032 `__","``ValueSwappable`` requirement missing for ``push_heap`` and ``make_heap``","2023-02 (Issaquah)","","","" "`LWG3085 `__","``char_traits::copy`` precondition too weak","2023-02 (Issaquah)","","","" "`LWG3664 `__","`LWG 3392 `__ ``broke std::ranges::distance(a, a+3)``","2023-02 (Issaquah)","","","" -"`LWG3720 `__","Restrict the valid types of ``arg-id`` for width and precision in ``std-format-spec``","2023-02 (Issaquah)","|Complete|","17.0","" +"`LWG3720 `__","Restrict the valid types of ``arg-id`` for width and precision in ``std-format-spec``","2023-02 (Issaquah)","|Complete|","17","" "`LWG3756 `__","Is the ``std::atomic_flag`` class signal-safe?","2023-02 (Issaquah)","","","" "`LWG3769 `__","``basic_const_iterator::operator==`` causes infinite constraint recursion","2023-02 (Issaquah)","","","" "`LWG3807 `__","The feature test macro for ``ranges::find_last`` should be renamed","2023-02 (Issaquah)","","","" "`LWG3811 `__","``views::as_const`` on ``ref_view`` should return ``ref_view``","2023-02 (Issaquah)","","","" "`LWG3820 `__","``cartesian_product_view::iterator::prev`` is not quite right","2023-02 (Issaquah)","","","" -"`LWG3825 `__","Missing compile-time argument ``id`` check in ``basic_format_parse_context::next_arg_id``","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3204 `__","``sub_match::swap`` only swaps the base class","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3733 `__","``ranges::to`` misuses ``cpp17-input-iterator``","2023-02 (Issaquah)","|Complete|","17.0","" +"`LWG3825 `__","Missing compile-time argument ``id`` check in ``basic_format_parse_context::next_arg_id``","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3204 `__","``sub_match::swap`` only swaps the base class","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3733 `__","``ranges::to`` misuses ``cpp17-input-iterator``","2023-02 (Issaquah)","|Complete|","17","" "`LWG3742 `__","``deque::prepend_range`` needs to permute","2023-02 (Issaquah)","","","" "`LWG3790 `__","`P1467 `__ accidentally changed ``nexttoward``'s signature","2023-02 (Issaquah)","","","" "`LWG3819 `__","``reference_meows_from_temporary`` should not use ``is_meowible``","2023-02 (Issaquah)","","","" -"`LWG3821 `__","``uses_allocator_construction_args`` should have overload for ``pair-like``","2023-02 (Issaquah)","|Complete|","18.0","" +"`LWG3821 `__","``uses_allocator_construction_args`` should have overload for ``pair-like``","2023-02 (Issaquah)","|Complete|","18","" "`LWG3834 `__","Missing ``constexpr`` for ``std::intmax_t`` math functions in ````","2023-02 (Issaquah)","","","" -"`LWG3839 `__","``range_formatter``'s ``set_separator``, ``set_brackets``, and ``underlying`` functions should be ``noexcept``","2023-02 (Issaquah)","|Complete|","17.0","" +"`LWG3839 `__","``range_formatter``'s ``set_separator``, ``set_brackets``, and ``underlying`` functions should be ``noexcept``","2023-02 (Issaquah)","|Complete|","17","" "`LWG3841 `__","```` should not be ""all freestanding""","2023-02 (Issaquah)","","","" -"`LWG3842 `__","Unclear wording for ``precision`` in ``chrono-format-spec``","2023-02 (Issaquah)","|Complete|","16.0","" +"`LWG3842 `__","Unclear wording for ``precision`` in ``chrono-format-spec``","2023-02 (Issaquah)","|Complete|","16","" "`LWG3848 `__","``adjacent_view``, ``adjacent_transform_view`` and ``slide_view`` missing ``base`` accessor","2023-02 (Issaquah)","","","" "`LWG3849 `__","``cartesian_product_view::iterator``'s default constructor is overconstrained","2023-02 (Issaquah)","","","" "`LWG3850 `__","``views::as_const`` on ``empty_view`` should return ``empty_view``","2023-02 (Issaquah)","","","" "`LWG3851 `__","``chunk_view::inner-iterator`` missing custom ``iter_move`` and ``iter_swap``","2023-02 (Issaquah)","","","" "`LWG3853 `__","``basic_const_iterator::operator->`` is ill-formed","2023-02 (Issaquah)","","","" -"`LWG3857 `__","``basic_string_view`` should allow explicit conversion when only traits vary","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3860 `__","``range_common_reference_t`` is missing","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3866 `__","Bad Mandates for ``expected::transform_error`` overloads","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3867 `__","Should ``std::basic_osyncstream``'s move assignment operator be ``noexcept``?","2023-02 (Issaquah)","|Complete|","18.0","" +"`LWG3857 `__","``basic_string_view`` should allow explicit conversion when only traits vary","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3860 `__","``range_common_reference_t`` is missing","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3866 `__","Bad Mandates for ``expected::transform_error`` overloads","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3867 `__","Should ``std::basic_osyncstream``'s move assignment operator be ``noexcept``?","2023-02 (Issaquah)","|Complete|","18","" "`LWG3441 `__","Misleading note about calls to customization points","2023-02 (Issaquah)","","","" "`LWG3622 `__","Misspecified transitivity of equivalence in §[unord.req.general]","2023-02 (Issaquah)","","","" -"`LWG3631 `__","``basic_format_arg(T&&)`` should use ``remove_cvref_t`` throughout","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3645 `__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","2023-02 (Issaquah)","|Complete|","14.0","" -"`LWG3655 `__","The ``INVOKE`` operation and union types","2023-02 (Issaquah)","|Complete|","18.0","" -"`LWG3723 `__","``priority_queue::push_range`` needs to ``append_range``","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3734 `__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","2023-02 (Issaquah)","|Complete|","19.0","" -"`LWG3772 `__","``repeat_view``'s ``piecewise`` constructor is missing Postconditions","2023-02 (Issaquah)","|Complete|","17.0","" +"`LWG3631 `__","``basic_format_arg(T&&)`` should use ``remove_cvref_t`` throughout","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3645 `__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","2023-02 (Issaquah)","|Complete|","14","" +"`LWG3655 `__","The ``INVOKE`` operation and union types","2023-02 (Issaquah)","|Complete|","18","" +"`LWG3723 `__","``priority_queue::push_range`` needs to ``append_range``","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3734 `__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","2023-02 (Issaquah)","|Complete|","19","" +"`LWG3772 `__","``repeat_view``'s ``piecewise`` constructor is missing Postconditions","2023-02 (Issaquah)","|Complete|","17","" "`LWG3786 `__","Flat maps' deduction guide needs to default ``Allocator`` to be useful","2023-02 (Issaquah)","","","" "`LWG3803 `__","``flat_foo`` constructors taking ``KeyContainer`` lack ``KeyCompare`` parameter","2023-02 (Issaquah)","","","" -"`LWG3810 `__","CTAD for ``std::basic_format_args``","2023-02 (Issaquah)","|Complete|","17.0","" +"`LWG3810 `__","CTAD for ``std::basic_format_args``","2023-02 (Issaquah)","|Complete|","17","" "`LWG3827 `__","Deprecate ```` and ```` macros","2023-02 (Issaquah)","","","" "`LWG3828 `__","Sync ``intmax_t`` and ``uintmax_t`` with C2x","2023-02 (Issaquah)","|Nothing To Do|","","" -"`LWG3833 `__","Remove specialization ``template struct formatter``","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3836 `__","``std::expected`` conversion constructor ``expected(const expected&)`` should take precedence over ``expected(U&&)`` with operator ``bool``","2023-02 (Issaquah)","|Complete|","18.0","" -"`LWG3843 `__","``std::expected::value() &`` assumes ``E`` is copy constructible","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3847 `__","``ranges::to`` can still return views","2023-02 (Issaquah)","|Complete|","17.0","" +"`LWG3833 `__","Remove specialization ``template struct formatter``","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3836 `__","``std::expected`` conversion constructor ``expected(const expected&)`` should take precedence over ``expected(U&&)`` with operator ``bool``","2023-02 (Issaquah)","|Complete|","18","" +"`LWG3843 `__","``std::expected::value() &`` assumes ``E`` is copy constructible","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3847 `__","``ranges::to`` can still return views","2023-02 (Issaquah)","|Complete|","17","" "`LWG3862 `__","``basic_const_iterator``'s ``common_type`` specialization is underconstrained","2023-02 (Issaquah)","","","" -"`LWG3865 `__","Sorting a range of ``pairs``","2023-02 (Issaquah)","|Complete|","17.0","" -"`LWG3869 `__","Deprecate ``std::errc`` constants related to UNIX STREAMS","2023-02 (Issaquah)","|Complete|","19.0","" -"`LWG3870 `__","Remove ``voidify``","2023-02 (Issaquah)","|Complete|","20.0","" +"`LWG3865 `__","Sorting a range of ``pairs``","2023-02 (Issaquah)","|Complete|","17","" +"`LWG3869 `__","Deprecate ``std::errc`` constants related to UNIX STREAMS","2023-02 (Issaquah)","|Complete|","19","" +"`LWG3870 `__","Remove ``voidify``","2023-02 (Issaquah)","|Complete|","20","" "`LWG3871 `__","Adjust note about ``terminate``","2023-02 (Issaquah)","","","" "`LWG3872 `__","``basic_const_iterator`` should have custom ``iter_move``","2023-02 (Issaquah)","","","" -"`LWG3875 `__","``std::ranges::repeat_view::iterator`` may be ill-formed","2023-02 (Issaquah)","|Complete|","17.0","" +"`LWG3875 `__","``std::ranges::repeat_view::iterator`` may be ill-formed","2023-02 (Issaquah)","|Complete|","17","" "`LWG3876 `__","Default constructor of ``std::layout_XX::mapping`` misses precondition","2023-02 (Issaquah)","","","" -"`LWG3877 `__","Incorrect constraints on ``const``-qualified monadic overloads for ``std::expected``","2023-02 (Issaquah)","|Complete|","17.0","" +"`LWG3877 `__","Incorrect constraints on ``const``-qualified monadic overloads for ``std::expected``","2023-02 (Issaquah)","|Complete|","17","" "`LWG3878 `__","import ``std;`` should guarantee initialization of standard iostreams objects","2023-02 (Issaquah)","","","" "`LWG3879 `__","``erase_if`` for ``flat_{,multi}set`` is incorrectly specified","2023-02 (Issaquah)","","","" "`LWG3880 `__","Clarify ``operator+=`` complexity for ``{chunk,stride}_view::iterator``","2023-02 (Issaquah)","","","" -"`LWG3881 `__","Incorrect formatting of container adapters backed by ``std::string``","2023-02 (Issaquah)","|Complete|","17.0","" +"`LWG3881 `__","Incorrect formatting of container adapters backed by ``std::string``","2023-02 (Issaquah)","|Complete|","17","" diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 6f1626da73507..4a4fbe9bec222 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -1,123 +1,123 @@ "Paper #","Paper Name","Meeting","Status","First released version","Notes" "`P0881R7 `__","A Proposal to add stacktrace library","2020-11 (Virtual)","","","" -"`P0943R6 `__","Support C atomics in C++","2020-11 (Virtual)","|Complete|","15.0","" -"`P1048R1 `__","A proposal for a type trait to detect scoped enumerations","2020-11 (Virtual)","|Complete|","12.0","" -"`P1679R3 `__","string contains function","2020-11 (Virtual)","|Complete|","12.0","" +"`P0943R6 `__","Support C atomics in C++","2020-11 (Virtual)","|Complete|","15","" +"`P1048R1 `__","A proposal for a type trait to detect scoped enumerations","2020-11 (Virtual)","|Complete|","12","" +"`P1679R3 `__","string contains function","2020-11 (Virtual)","|Complete|","12","" "","","","","","" -"`P1682R3 `__","std::to_underlying for enumerations","2021-02 (Virtual)","|Complete|","13.0","" -"`P2017R1 `__","Conditionally borrowed ranges","2021-02 (Virtual)","|Complete|","16.0","" +"`P1682R3 `__","std::to_underlying for enumerations","2021-02 (Virtual)","|Complete|","13","" +"`P2017R1 `__","Conditionally borrowed ranges","2021-02 (Virtual)","|Complete|","16","" "`P2160R1 `__","Locks lock lockables","2021-02 (Virtual)","|Nothing To Do|","","" -"`P2162R2 `__","Inheriting from std::variant","2021-02 (Virtual)","|Complete|","13.0","" +"`P2162R2 `__","Inheriting from std::variant","2021-02 (Virtual)","|Complete|","13","" "`P2212R2 `__","Relax Requirements for time_point::clock","2021-02 (Virtual)","|Nothing To Do|","","" "`P2259R1 `__","Repairing input range adaptors and counted_iterator","2021-02 (Virtual)","","","" "","","","","","" -"`P0401R6 `__","Providing size feedback in the Allocator interface","2021-06 (Virtual)","|Complete|","15.0","" +"`P0401R6 `__","Providing size feedback in the Allocator interface","2021-06 (Virtual)","|Complete|","15","" "`P0448R4 `__","A strstream replacement using span as buffer","2021-06 (Virtual)","","","" -"`P1132R8 `__","out_ptr - a scalable output pointer abstraction","2021-06 (Virtual)","|Complete|","19.0","" -"`P1328R1 `__","Making std::type_info::operator== constexpr","2021-06 (Virtual)","|Complete|","17.0","" -"`P1425R4 `__","Iterators pair constructors for stack and queue","2021-06 (Virtual)","|Complete|","14.0","" -"`P1518R2 `__","Stop overconstraining allocators in container deduction guides","2021-06 (Virtual)","|Complete|","13.0","" -"`P1659R3 `__","starts_with and ends_with","2021-06 (Virtual)","|Complete|","19.0","" -"`P1951R1 `__","Default Arguments for pair Forwarding Constructor","2021-06 (Virtual)","|Complete|","14.0","" -"`P1989R2 `__","Range constructor for std::string_view","2021-06 (Virtual)","|Complete|","14.0","" -"`P2136R3 `__","invoke_r","2021-06 (Virtual)","|Complete|","17.0","" -"`P2166R1 `__","A Proposal to Prohibit std::basic_string and std::basic_string_view construction from nullptr","2021-06 (Virtual)","|Complete|","13.0","" +"`P1132R8 `__","out_ptr - a scalable output pointer abstraction","2021-06 (Virtual)","|Complete|","19","" +"`P1328R1 `__","Making std::type_info::operator== constexpr","2021-06 (Virtual)","|Complete|","17","" +"`P1425R4 `__","Iterators pair constructors for stack and queue","2021-06 (Virtual)","|Complete|","14","" +"`P1518R2 `__","Stop overconstraining allocators in container deduction guides","2021-06 (Virtual)","|Complete|","13","" +"`P1659R3 `__","starts_with and ends_with","2021-06 (Virtual)","|Complete|","19","" +"`P1951R1 `__","Default Arguments for pair Forwarding Constructor","2021-06 (Virtual)","|Complete|","14","" +"`P1989R2 `__","Range constructor for std::string_view","2021-06 (Virtual)","|Complete|","14","" +"`P2136R3 `__","invoke_r","2021-06 (Virtual)","|Complete|","17","" +"`P2166R1 `__","A Proposal to Prohibit std::basic_string and std::basic_string_view construction from nullptr","2021-06 (Virtual)","|Complete|","13","" "","","","","","" "`P0288R9 `__","``any_invocable``","2021-10 (Virtual)","","","" -"`P0798R8 `__","Monadic operations for ``std::optional``","2021-10 (Virtual)","|Complete|","14.0","" -"`P0849R8 `__","``auto(x)``: ``DECAY_COPY`` in the language","2021-10 (Virtual)","|Complete|","14.0","" -"`P1072R10 `__","``basic_string::resize_and_overwrite``","2021-10 (Virtual)","|Complete|","14.0","" -"`P1147R1 `__","Printing ``volatile`` Pointers","2021-10 (Virtual)","|Complete|","14.0","" -"`P1272R4 `__","Byteswapping for fun&&nuf","2021-10 (Virtual)","|Complete|","14.0","" +"`P0798R8 `__","Monadic operations for ``std::optional``","2021-10 (Virtual)","|Complete|","14","" +"`P0849R8 `__","``auto(x)``: ``DECAY_COPY`` in the language","2021-10 (Virtual)","|Complete|","14","" +"`P1072R10 `__","``basic_string::resize_and_overwrite``","2021-10 (Virtual)","|Complete|","14","" +"`P1147R1 `__","Printing ``volatile`` Pointers","2021-10 (Virtual)","|Complete|","14","" +"`P1272R4 `__","Byteswapping for fun&&nuf","2021-10 (Virtual)","|Complete|","14","" "`P1675R2 `__","``rethrow_exception`` must be allowed to copy","2021-10 (Virtual)","|Nothing To Do|","","" "`P2077R3 `__","Heterogeneous erasure overloads for associative containers","2021-10 (Virtual)","","","" -"`P2251R1 `__","Require ``span`` & ``basic_string_view`` to be Trivially Copyable","2021-10 (Virtual)","|Complete|","14.0","" +"`P2251R1 `__","Require ``span`` & ``basic_string_view`` to be Trivially Copyable","2021-10 (Virtual)","|Complete|","14","" "`P2301R1 `__","Add a ``pmr`` alias for ``std::stacktrace``","2021-10 (Virtual)","","","" "`P2321R2 `__","``zip``","2021-10 (Virtual)","|In Progress|","","" "`P2340R1 `__","Clarifying the status of the 'C headers'","2021-10 (Virtual)","|Nothing To Do|","","" "`P2393R1 `__","Cleaning up ``integer``-class types","2021-10 (Virtual)","","","" -"`P2401R0 `__","Add a conditional ``noexcept`` specification to ``std::exchange``","2021-10 (Virtual)","|Complete|","14.0","" +"`P2401R0 `__","Add a conditional ``noexcept`` specification to ``std::exchange``","2021-10 (Virtual)","|Complete|","14","" "","","","","","" -"`P0323R12 `__","``std::expected``","2022-02 (Virtual)","|Complete|","16.0","" +"`P0323R12 `__","``std::expected``","2022-02 (Virtual)","|Complete|","16","" "`P0533R9 `__","``constexpr`` for ```` and ````","2022-02 (Virtual)","|In Progress|","","``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented" -"`P0627R6 `__","Function to mark unreachable code","2022-02 (Virtual)","|Complete|","15.0","" -"`P1206R7 `__","``ranges::to``: A function to convert any range to a container","2022-02 (Virtual)","|Complete|","17.0","" +"`P0627R6 `__","Function to mark unreachable code","2022-02 (Virtual)","|Complete|","15","" +"`P1206R7 `__","``ranges::to``: A function to convert any range to a container","2022-02 (Virtual)","|Complete|","17","" "`P1413R3 `__","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","2022-02 (Virtual)","|Complete|","","``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations." "`P2255R2 `__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","","","" -"`P2273R3 `__","Making ``std::unique_ptr`` constexpr","2022-02 (Virtual)","|Complete|","16.0","" -"`P2387R3 `__","Pipe support for user-defined range adaptors","2022-02 (Virtual)","|Complete|","19.0","" +"`P2273R3 `__","Making ``std::unique_ptr`` constexpr","2022-02 (Virtual)","|Complete|","16","" +"`P2387R3 `__","Pipe support for user-defined range adaptors","2022-02 (Virtual)","|Complete|","19","" "`P2440R1 `__","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","2022-02 (Virtual)","","","" "`P2441R2 `__","``views::join_with``","2022-02 (Virtual)","|In Progress|","","" "`P2442R1 `__","Windowing range adaptors: ``views::chunk`` and ``views::slide``","2022-02 (Virtual)","","","" -"`P2443R1 `__","``views::chunk_by``","2022-02 (Virtual)","|Complete|","18.0","" +"`P2443R1 `__","``views::chunk_by``","2022-02 (Virtual)","|Complete|","18","" "","","","","","" -"`P0009R18 `__","mdspan: A Non-Owning Multidimensional Array Reference","2022-07 (Virtual)","|Complete|","18.0","" +"`P0009R18 `__","mdspan: A Non-Owning Multidimensional Array Reference","2022-07 (Virtual)","|Complete|","18","" "`P0429R9 `__","A Standard ``flat_map``","2022-07 (Virtual)","|In progress|","","" -"`P1169R4 `__","``static operator()``","2022-07 (Virtual)","|Complete|","16.0","" +"`P1169R4 `__","``static operator()``","2022-07 (Virtual)","|Complete|","16","" "`P1222R4 `__","A Standard ``flat_set``","2022-07 (Virtual)","","","" -"`P1223R5 `__","``ranges::find_last()``, ``ranges::find_last_if()``, and ``ranges::find_last_if_not()``","2022-07 (Virtual)","|Complete|","19.0","" +"`P1223R5 `__","``ranges::find_last()``, ``ranges::find_last_if()``, and ``ranges::find_last_if_not()``","2022-07 (Virtual)","|Complete|","19","" "`P1467R9 `__","Extended ``floating-point`` types and standard names","2022-07 (Virtual)","","","" "`P1642R11 `__","Freestanding ``[utilities]``, ``[ranges]``, and ``[iterators]``","2022-07 (Virtual)","","","" "`P1899R3 `__","``stride_view``","2022-07 (Virtual)","","","" -"`P2093R14 `__","Formatted output","2022-07 (Virtual)","|Complete|","18.0","" +"`P2093R14 `__","Formatted output","2022-07 (Virtual)","|Complete|","18","" "`P2165R4 `__","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","2022-07 (Virtual)","|Partial|","","Only the part for ``zip_view`` is implemented." "`P2278R4 `__","``cbegin`` should always return a constant iterator","2022-07 (Virtual)","","","" -"`P2286R8 `__","Formatting Ranges","2022-07 (Virtual)","|Complete|","16.0","" -"`P2291R3 `__","Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ```` Header","2022-07 (Virtual)","|Complete|","16.0","" -"`P2302R4 `__","``std::ranges::contains``","2022-07 (Virtual)","|Complete|","19.0","" +"`P2286R8 `__","Formatting Ranges","2022-07 (Virtual)","|Complete|","16","" +"`P2291R3 `__","Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ```` Header","2022-07 (Virtual)","|Complete|","16","" +"`P2302R4 `__","``std::ranges::contains``","2022-07 (Virtual)","|Complete|","19","" "`P2322R6 `__","``ranges::fold``","2022-07 (Virtual)","","","" "`P2374R4 `__","``views::cartesian_product``","2022-07 (Virtual)","","","" "`P2404R3 `__","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","2022-07 (Virtual)","","","" "`P2408R5 `__","Ranges iterators as inputs to non-Ranges algorithms","2022-07 (Virtual)","","","" -"`P2417R2 `__","A more ``constexpr`` ``bitset``","2022-07 (Virtual)","|Complete|","16.0","" +"`P2417R2 `__","A more ``constexpr`` ``bitset``","2022-07 (Virtual)","|Complete|","16","" "`P2419R2 `__","Clarify handling of encodings in localized formatting of chrono types","2022-07 (Virtual)","","","" -"`P2438R2 `__","``std::string::substr() &&``","2022-07 (Virtual)","|Complete|","16.0","" -"`P2445R1 `__","``forward_like``","2022-07 (Virtual)","|Complete|","16.0","" -"`P2446R2 `__","``views::as_rvalue``","2022-07 (Virtual)","|Complete|","16.0","" +"`P2438R2 `__","``std::string::substr() &&``","2022-07 (Virtual)","|Complete|","16","" +"`P2445R1 `__","``forward_like``","2022-07 (Virtual)","|Complete|","16","" +"`P2446R2 `__","``views::as_rvalue``","2022-07 (Virtual)","|Complete|","16","" "`P2460R2 `__","Relax requirements on ``wchar_t`` to match existing practices","2022-07 (Virtual)","|Nothing To Do|","","" -"`P2465R3 `__","Standard Library Modules ``std`` and ``std.compat``","2022-07 (Virtual)","|Complete|","19.0","" -"`P2467R1 `__","Support exclusive mode for ``fstreams``","2022-07 (Virtual)","|Complete|","18.0","" -"`P2474R2 `__","``views::repeat``","2022-07 (Virtual)","|Complete|","17.0","" -"`P2494R2 `__","Relaxing range adaptors to allow for move only types","2022-07 (Virtual)","|Complete|","17.0","" -"`P2499R0 `__","``string_view`` range constructor should be ``explicit``","2022-07 (Virtual)","|Complete|","16.0","" +"`P2465R3 `__","Standard Library Modules ``std`` and ``std.compat``","2022-07 (Virtual)","|Complete|","19","" +"`P2467R1 `__","Support exclusive mode for ``fstreams``","2022-07 (Virtual)","|Complete|","18","" +"`P2474R2 `__","``views::repeat``","2022-07 (Virtual)","|Complete|","17","" +"`P2494R2 `__","Relaxing range adaptors to allow for move only types","2022-07 (Virtual)","|Complete|","17","" +"`P2499R0 `__","``string_view`` range constructor should be ``explicit``","2022-07 (Virtual)","|Complete|","16","" "`P2502R2 `__","``std::generator``: Synchronous Coroutine Generator for Ranges","2022-07 (Virtual)","","","" -"`P2508R1 `__","Exposing ``std::basic-format-string``","2022-07 (Virtual)","|Complete|","15.0","" +"`P2508R1 `__","Exposing ``std::basic-format-string``","2022-07 (Virtual)","|Complete|","15","" "`P2513R4 `__","``char8_t`` Compatibility and Portability Fixes","2022-07 (Virtual)","","","" "`P2517R1 `__","Add a conditional ``noexcept`` specification to ``std::apply``","2022-07 (Virtual)","|Complete|","3.9","" -"`P2520R0 `__","``move_iterator`` should be a random access iterator","2022-07 (Virtual)","|Complete|","17.0","Implemented as a DR in C++20" +"`P2520R0 `__","``move_iterator`` should be a random access iterator","2022-07 (Virtual)","|Complete|","17","Implemented as a DR in C++20" "`P2540R1 `__","Empty Product for certain Views","2022-07 (Virtual)","","","" -"`P2549R1 `__","``std::unexpected`` should have ``error()`` as member accessor","2022-07 (Virtual)","|Complete|","16.0","" -"`P2585R0 `__","Improving default container formatting","2022-07 (Virtual)","|Complete|","17.0","" +"`P2549R1 `__","``std::unexpected`` should have ``error()`` as member accessor","2022-07 (Virtual)","|Complete|","16","" +"`P2585R0 `__","Improving default container formatting","2022-07 (Virtual)","|Complete|","17","" "`P2590R2 `__","Explicit lifetime management","2022-07 (Virtual)","","","" -"`P2599R2 `__","``mdspan::size_type`` should be ``index_type``","2022-07 (Virtual)","|Complete|","18.0","" -"`P2604R0 `__","mdspan: rename pointer and contiguous","2022-07 (Virtual)","|Complete|","18.0","" -"`P2613R1 `__","Add the missing ``empty`` to ``mdspan``","2022-07 (Virtual)","|Complete|","18.0","" +"`P2599R2 `__","``mdspan::size_type`` should be ``index_type``","2022-07 (Virtual)","|Complete|","18","" +"`P2604R0 `__","mdspan: rename pointer and contiguous","2022-07 (Virtual)","|Complete|","18","" +"`P2613R1 `__","Add the missing ``empty`` to ``mdspan``","2022-07 (Virtual)","|Complete|","18","" "","","","","","" "`P1202R5 `__","Asymmetric Fences","2022-11 (Kona)","","","" -"`P1264R2 `__","Revising the wording of ``stream`` input operations","2022-11 (Kona)","|Complete|","9.0","" +"`P1264R2 `__","Revising the wording of ``stream`` input operations","2022-11 (Kona)","|Complete|","9","" "`P1478R8 `__","``Byte-wise`` ``atomic`` ``memcpy``","2022-11 (Kona)","","","" -"`P2167R3 `__","Improved Proposed Wording for LWG 2114","2022-11 (Kona)","|Complete|","20.0","The `[cmp.alg] `__ part is implemented as a DR against C++20. MSVC STL does the same. Other parts are Nothing To Do." +"`P2167R3 `__","Improved Proposed Wording for LWG 2114","2022-11 (Kona)","|Complete|","20","The `[cmp.alg] `__ part is implemented as a DR against C++20. MSVC STL does the same. Other parts are Nothing To Do." "`P2396R1 `__","Concurrency TS 2 fixes ","2022-11 (Kona)","","","" -"`P2505R5 `__","Monadic Functions for ``std::expected``","2022-11 (Kona)","|Complete|","17.0","" -"`P2539R4 `__","Should the output of ``std::print`` to a terminal be synchronized with the underlying stream?","2022-11 (Kona)","|Complete|","18.0","" -"`P2602R2 `__","Poison Pills are Too Toxic","2022-11 (Kona)","|Complete|","19.0","Implemented as a DR in C++20" +"`P2505R5 `__","Monadic Functions for ``std::expected``","2022-11 (Kona)","|Complete|","17","" +"`P2539R4 `__","Should the output of ``std::print`` to a terminal be synchronized with the underlying stream?","2022-11 (Kona)","|Complete|","18","" +"`P2602R2 `__","Poison Pills are Too Toxic","2022-11 (Kona)","|Complete|","19","Implemented as a DR in C++20" "`P2708R1 `__","No Further Fundamentals TSes","2022-11 (Kona)","|Nothing To Do|","","" "","","","","","" "`P0290R4 `__","``apply()`` for ``synchronized_value``","2023-02 (Issaquah)","","","" "`P2770R0 `__","Stashing stashing ``iterators`` for proper flattening","2023-02 (Issaquah)","|Partial|","","``join_with_view`` hasn't been done yet since this type isn't implemented yet" "`P2164R9 `__","``views::enumerate``","2023-02 (Issaquah)","","","" "`P2711R1 `__","Making multi-param constructors of ``views`` ``explicit``","2023-02 (Issaquah)","|In Progress|","","``join_with_view`` hasn't been done yet since this type isn't implemented yet" -"`P2609R3 `__","Relaxing Ranges Just A Smidge","2023-02 (Issaquah)","|Complete|","20.0","Implemented as a DR in C++20. Other implementations will do the same." -"`P2713R1 `__","Escaping improvements in ``std::format``","2023-02 (Issaquah)","|Complete|","19.0","" -"`P2675R1 `__","``format``'s width estimation is too approximate and not forward compatible","2023-02 (Issaquah)","|Complete|","17.0","" -"`P2572R1 `__","``std::format`` fill character allowances","2023-02 (Issaquah)","|Complete|","17.0","" +"`P2609R3 `__","Relaxing Ranges Just A Smidge","2023-02 (Issaquah)","|Complete|","20","Implemented as a DR in C++20. Other implementations will do the same." +"`P2713R1 `__","Escaping improvements in ``std::format``","2023-02 (Issaquah)","|Complete|","19","" +"`P2675R1 `__","``format``'s width estimation is too approximate and not forward compatible","2023-02 (Issaquah)","|Complete|","17","" +"`P2572R1 `__","``std::format`` fill character allowances","2023-02 (Issaquah)","|Complete|","17","" "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``","2023-02 (Issaquah)","|Partial|","","The formatter for ``stacktrace`` is not implemented, since ``stacktrace`` is not implemented yet" "`P2679R2 `__","Fixing ``std::start_lifetime_as`` for arrays","2023-02 (Issaquah)","","","" -"`P2674R1 `__","A trait for implicit lifetime types","2023-02 (Issaquah)","|Complete|","20.0","" +"`P2674R1 `__","A trait for implicit lifetime types","2023-02 (Issaquah)","|Complete|","20","" "`P2655R3 `__","``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","2023-02 (Issaquah)","","","" -"`P2652R2 `__","Disallow User Specialization of ``allocator_traits``","2023-02 (Issaquah)","|Complete|","19.0","" +"`P2652R2 `__","Disallow User Specialization of ``allocator_traits``","2023-02 (Issaquah)","|Complete|","19","" "`P2787R1 `__","``pmr::generator`` - Promise Types are not Values","2023-02 (Issaquah)","","","" -"`P2614R2 `__","Deprecate ``numeric_limits::has_denorm``","2023-02 (Issaquah)","|Complete|","18.0","" +"`P2614R2 `__","Deprecate ``numeric_limits::has_denorm``","2023-02 (Issaquah)","|Complete|","18","" "`P2588R3 `__","``barrier``’s phase completion guarantees","2023-02 (Issaquah)","","","" "`P2763R1 `__","``layout_stride`` static extents default constructor fix","2023-02 (Issaquah)","","","" -"`P2736R2 `__","Referencing The Unicode Standard","2023-02 (Issaquah)","|Complete|","19.0","" +"`P2736R2 `__","Referencing The Unicode Standard","2023-02 (Issaquah)","|Complete|","19","" diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv index 247e8a91fa49b..a0d2ccdc34d08 100644 --- a/libcxx/docs/Status/Cxx2cIssues.csv +++ b/libcxx/docs/Status/Cxx2cIssues.csv @@ -1,71 +1,71 @@ "Issue #","Issue Name","Meeting","Status","First released version","Notes" -"`LWG2994 `__","Needless UB for ``basic_string`` and ``basic_string_view``","2023-06 (Varna)","|Complete|","5.0","" +"`LWG2994 `__","Needless UB for ``basic_string`` and ``basic_string_view``","2023-06 (Varna)","|Complete|","5","" "`LWG3884 `__","``flat_foo`` is missing allocator-extended copy/move constructors","2023-06 (Varna)","","","" "`LWG3885 `__","``op`` should be in [zombie.names]","2023-06 (Varna)","|Nothing To Do|","","" -"`LWG3887 `__","Version macro for ``allocate_at_least``","2023-06 (Varna)","|Complete|","19.0","" +"`LWG3887 `__","Version macro for ``allocate_at_least``","2023-06 (Varna)","|Complete|","19","" "`LWG3893 `__","LWG 3661 broke ``atomic> a; a = nullptr;``","2023-06 (Varna)","","","" "`LWG3894 `__","``generator::promise_type::yield_value(ranges::elements_of)`` should not be ``noexcept``","2023-06 (Varna)","","","" -"`LWG3903 `__","span destructor is redundantly noexcept","2023-06 (Varna)","|Complete|","7.0","" +"`LWG3903 `__","span destructor is redundantly noexcept","2023-06 (Varna)","|Complete|","7","" "`LWG3904 `__","``lazy_split_view::outer-iterator``'s const-converting constructor isn't setting ``trailing_empty_``","2023-06 (Varna)","","","" "`LWG3905 `__","Type of ``std::fexcept_t``","2023-06 (Varna)","|Complete|","3.4","" "`LWG3912 `__","``enumerate_view::iterator::operator-`` should be ``noexcept``","2023-06 (Varna)","","","" "`LWG3914 `__","Inconsistent template-head of ``ranges::enumerate_view``","2023-06 (Varna)","","","" "`LWG3915 `__","Redundant paragraph about expression variations","2023-06 (Varna)","","","" -"`LWG3925 `__","Concept ``formattable``'s definition is incorrect","2023-06 (Varna)","|Complete|","17.0","" +"`LWG3925 `__","Concept ``formattable``'s definition is incorrect","2023-06 (Varna)","|Complete|","17","" "`LWG3927 `__","Unclear preconditions for ``operator[]`` for sequence containers","2023-06 (Varna)","|Nothing To Do|","","" "`LWG3935 `__","``template constexpr complex& operator=(const complex&)`` has no specification","2023-06 (Varna)","|Complete|","3.4","" -"`LWG3938 `__","Cannot use ``std::expected`` monadic ops with move-only ``error_type``","2023-06 (Varna)","|Complete|","18.0","" -"`LWG3940 `__","``std::expected::value()`` also needs ``E`` to be copy constructible","2023-06 (Varna)","|Complete|","18.0","" +"`LWG3938 `__","Cannot use ``std::expected`` monadic ops with move-only ``error_type``","2023-06 (Varna)","|Complete|","18","" +"`LWG3940 `__","``std::expected::value()`` also needs ``E`` to be copy constructible","2023-06 (Varna)","|Complete|","18","" "","","","","","" "`LWG2392 `__","""character type"" is used but not defined","2023-11 (Kona)","","","" "`LWG3203 `__","``span`` element access invalidation","2023-11 (Kona)","|Nothing To Do|","","" -"`LWG3305 `__","``any_cast``","2023-11 (Kona)","|Complete|","18.0","" +"`LWG3305 `__","``any_cast``","2023-11 (Kona)","|Complete|","18","" "`LWG3431 `__","``<=>`` for containers should require ``three_way_comparable`` instead of ``<=>``","2023-11 (Kona)","","","" "`LWG3749 `__","``common_iterator`` should handle integer-class difference types","2023-11 (Kona)","","","" "`LWG3809 `__","Is ``std::subtract_with_carry_engine`` supposed to work","2023-11 (Kona)","","","" -"`LWG3892 `__","Incorrect formatting of nested ranges and tuples","2023-11 (Kona)","|Complete|","17.0","" -"`LWG3897 `__","``inout_ptr`` will not update raw pointer to 0","2023-11 (Kona)","|Complete|","19.0","" +"`LWG3892 `__","Incorrect formatting of nested ranges and tuples","2023-11 (Kona)","|Complete|","17","" +"`LWG3897 `__","``inout_ptr`` will not update raw pointer to 0","2023-11 (Kona)","|Complete|","19","" "`LWG3946 `__","The definition of ``const_iterator_t`` should be reworked","2023-11 (Kona)","","","" "`LWG3947 `__","Unexpected constraints on ``adjacent_transform_view::base()``","2023-11 (Kona)","","","" "`LWG3948 `__","``possibly-const-range and as-const-pointer`` should be ``noexcept``","2023-11 (Kona)","","","" "`LWG3949 `__","``std::atomic``'s trivial destructor dropped in C++17 spec wording","2023-11 (Kona)","","","" -"`LWG3951 `__","[expected.object.swap]: Using ``value()`` instead of ``has_value()``","2023-11 (Kona)","|Complete|","16.0","" -"`LWG3953 `__","``iter_move`` for ``common_iterator`` and ``counted_iterator`` should return ``decltype(auto)``","2023-11 (Kona)","|Complete|","20.0","" +"`LWG3951 `__","[expected.object.swap]: Using ``value()`` instead of ``has_value()``","2023-11 (Kona)","|Complete|","16","" +"`LWG3953 `__","``iter_move`` for ``common_iterator`` and ``counted_iterator`` should return ``decltype(auto)``","2023-11 (Kona)","|Complete|","20","" "`LWG3957 `__","[container.alloc.reqmts] The value category of v should be claimed","2023-11 (Kona)","","","" -"`LWG3965 `__","Incorrect example in [format.string.escaped] p3 for formatting of combining characters","2023-11 (Kona)","|Complete|","19.0","" +"`LWG3965 `__","Incorrect example in [format.string.escaped] p3 for formatting of combining characters","2023-11 (Kona)","|Complete|","19","" "`LWG3970 `__","[mdspan.syn] Missing definition of ``full_extent_t`` and ``full_extent``","2023-11 (Kona)","","","" "`LWG3973 `__","Monadic operations should be ADL-proof","2023-11 (Kona)","","","" "`LWG3974 `__","``mdspan::operator[]`` should not copy ``OtherIndexTypes``","2023-11 (Kona)","","","" "`LWG3987 `__","Including ```` doesn't provide ``std::begin``/``end``","2023-11 (Kona)","","","" "`LWG3990 `__","Program-defined specializations of ``std::tuple`` and ``std::variant`` can't be properly supported","2023-11 (Kona)","","","" -"`LWG4001 `__","``iota_view`` should provide ``empty``","2023-11 (Kona)","|Complete|","19.0","" +"`LWG4001 `__","``iota_view`` should provide ``empty``","2023-11 (Kona)","|Complete|","19","" "","","","","","" "`LWG3767 `__","``codecvt`` incorrectly added to locale","2024-03 (Tokyo)","","","" "`LWG3919 `__","``enumerate_view`` may invoke UB for sized common non-forward underlying ranges","2024-03 (Tokyo)","","","" -"`LWG3950 `__","``std::basic_string_view`` comparison operators are overspecified","2024-03 (Tokyo)","|Complete|","18.0","" +"`LWG3950 `__","``std::basic_string_view`` comparison operators are overspecified","2024-03 (Tokyo)","|Complete|","18","" "`LWG3975 `__","Specializations of ``basic_format_context`` should not be permitted","2024-03 (Tokyo)","|Nothing To Do|","","" -"`LWG3984 `__","``ranges::to``'s recursion branch may be ill-formed","2024-03 (Tokyo)","|Complete|","19.0","" +"`LWG3984 `__","``ranges::to``'s recursion branch may be ill-formed","2024-03 (Tokyo)","|Complete|","19","" "`LWG4011 `__","``""Effects: Equivalent to return""`` in ``[span.elem]``","2024-03 (Tokyo)","|Nothing To Do|","","" "`LWG4012 `__","``common_view::begin/end`` are missing the ``simple-view`` check","2024-03 (Tokyo)","","","" "`LWG4013 `__","``lazy_split_view::outer-iterator::value_type`` should not provide default constructor","2024-03 (Tokyo)","","","" -"`LWG4016 `__","container-insertable checks do not match what container-inserter does","2024-03 (Tokyo)","|Complete|","20.0","" -"`LWG4023 `__","Preconditions of ``std::basic_streambuf::setg/setp``","2024-03 (Tokyo)","|Complete|","19.0","" -"`LWG4025 `__","Move assignment operator of ``std::expected`` should not be conditionally deleted","2024-03 (Tokyo)","|Complete|","20.0","" +"`LWG4016 `__","container-insertable checks do not match what container-inserter does","2024-03 (Tokyo)","|Complete|","20","" +"`LWG4023 `__","Preconditions of ``std::basic_streambuf::setg/setp``","2024-03 (Tokyo)","|Complete|","19","" +"`LWG4025 `__","Move assignment operator of ``std::expected`` should not be conditionally deleted","2024-03 (Tokyo)","|Complete|","20","" "`LWG4030 `__","Clarify whether arithmetic expressions in ``[numeric.sat.func]`` are mathematical or C++","2024-03 (Tokyo)","|Nothing To Do|","","" -"`LWG4031 `__","``bad_expected_access`` member functions should be ``noexcept``","2024-03 (Tokyo)","|Complete|","16.0","" -"`LWG4035 `__","``single_view`` should provide ``empty``","2024-03 (Tokyo)","|Complete|","19.0","" +"`LWG4031 `__","``bad_expected_access`` member functions should be ``noexcept``","2024-03 (Tokyo)","|Complete|","16","" +"`LWG4035 `__","``single_view`` should provide ``empty``","2024-03 (Tokyo)","|Complete|","19","" "`LWG4036 `__","``__alignof_is_defined`` is only implicitly specified in C++ and not yet deprecated","2024-03 (Tokyo)","","","" "`LWG4037 `__","Static data members of ``ctype_base`` are not yet required to be usable in constant expressions","2024-03 (Tokyo)","","","" "`LWG4038 `__","``std::text_encoding::aliases_view`` should have constexpr iterators","2024-03 (Tokyo)","","","" "`LWG4043 `__","""ASCII"" is not a registered character encoding","2024-03 (Tokyo)","|Nothing To Do|","","" "`LWG4045 `__","``tuple`` can create dangling references from ``tuple-like``","2024-03 (Tokyo)","","","" -"`LWG4053 `__","Unary call to ``std::views::repeat`` does not decay the argument","2024-03 (Tokyo)","|Complete|","19.0","" -"`LWG4054 `__","Repeating a ``repeat_view`` should repeat the view","2024-03 (Tokyo)","|Complete|","19.0","" +"`LWG4053 `__","Unary call to ``std::views::repeat`` does not decay the argument","2024-03 (Tokyo)","|Complete|","19","" +"`LWG4054 `__","Repeating a ``repeat_view`` should repeat the view","2024-03 (Tokyo)","|Complete|","19","" "","","","","","" "`LWG3944 `__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","2024-06 (St. Louis)","","","" "`LWG4060 `__","``submdspan`` preconditions do not forbid creating invalid pointer","2024-06 (St. Louis)","","","" -"`LWG4061 `__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","2024-06 (St. Louis)","|Complete|","19.0","" -"`LWG4071 `__","``reference_wrapper`` comparisons are not SFINAE-friendly","2024-06 (St. Louis)","|Complete|","19.0","" +"`LWG4061 `__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","2024-06 (St. Louis)","|Complete|","19","" +"`LWG4071 `__","``reference_wrapper`` comparisons are not SFINAE-friendly","2024-06 (St. Louis)","|Complete|","19","" "`LWG4074 `__","``compatible-joinable-ranges`` is underconstrained","2024-06 (St. Louis)","","","" "`LWG4076 `__","``concat_view`` should be freestanding","2024-06 (St. Louis)","","","" "`LWG4079 `__","Missing Preconditions in ``concat_view::iterator``\`s conversion constructor","2024-06 (St. Louis)","","","" @@ -74,9 +74,9 @@ "`LWG4096 `__","``views::iota(views::iota(0))`` should be rejected","2024-06 (St. Louis)","","","" "`LWG4098 `__","``views::adjacent<0>`` should reject non-forward ranges","2024-06 (St. Louis)","","","" "`LWG4105 `__","``ranges::ends_with``\`s Returns misses difference casting","2024-06 (St. Louis)","","","" -"`LWG4106 `__","``basic_format_args`` should not be default-constructible","2024-06 (St. Louis)","|Complete|","19.0","" +"`LWG4106 `__","``basic_format_args`` should not be default-constructible","2024-06 (St. Louis)","|Complete|","19","" "","","","","","" -"`LWG3343 `__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Adopted Yet","|Complete|","16.0","" -"`LWG4139 `__","§[time.zone.leap] recursive constraint in <=>","Not Adopted Yet","|Complete|","20.0","" -"`LWG3456 `__","Pattern used by std::from_chars is underspecified (option B)",,"Not Yet Adopted","|Complete|","20.0","" +"`LWG3343 `__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Adopted Yet","|Complete|","16","" +"`LWG4139 `__","§[time.zone.leap] recursive constraint in <=>","Not Adopted Yet","|Complete|","20","" +"`LWG3456 `__","Pattern used by std::from_chars is underspecified (option B)",,"Not Yet Adopted","|Complete|","20","" "","","","","","" diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index d5d5cdda065ae..6659d815612d0 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -1,13 +1,13 @@ "Paper #","Paper Name","Meeting","Status","First released version","Notes" -"`P2497R0 `__","Testing for success or failure of ```` functions","2023-06 (Varna)","|Complete|","18.0","" +"`P2497R0 `__","Testing for success or failure of ```` functions","2023-06 (Varna)","|Complete|","18","" "`P2592R3 `__","Hashing support for ``std::chrono`` value classes","2023-06 (Varna)","","","" "`P2587R3 `__","``to_string`` or not ``to_string``","2023-06 (Varna)","","","" "`P2562R1 `__","``constexpr`` Stable Sorting","2023-06 (Varna)","","","" "`P2545R4 `__","Read-Copy Update (RCU)","2023-06 (Varna)","","","" "`P2530R3 `__","Hazard Pointers for C++26","2023-06 (Varna)","","","" -"`P2538R1 `__","ADL-proof ``std::projected``","2023-06 (Varna)","|Complete|","18.0","" -"`P2495R3 `__","Interfacing ``stringstream``\s with ``string_view``","2023-06 (Varna)","|Complete|","19.0","" -"`P2510R3 `__","Formatting pointers","2023-06 (Varna)","|Complete|","17.0","Implemented as a DR against C++20. (MSVC STL and libstdc++ will do the same.)" +"`P2538R1 `__","ADL-proof ``std::projected``","2023-06 (Varna)","|Complete|","18","" +"`P2495R3 `__","Interfacing ``stringstream``\s with ``string_view``","2023-06 (Varna)","|Complete|","19","" +"`P2510R3 `__","Formatting pointers","2023-06 (Varna)","|Complete|","17","Implemented as a DR against C++20. (MSVC STL and libstdc++ will do the same.)" "`P2198R7 `__","Freestanding Feature-Test Macros and Implementation-Defined Extensions","2023-06 (Varna)","","","" "`P2338R4 `__","Freestanding Library: Character primitives and the C library","2023-06 (Varna)","","","" "`P2013R5 `__","Freestanding Language: Optional ``::operator new``","2023-06 (Varna)","","","" @@ -17,62 +17,62 @@ "`P0792R14 `__","``function_ref``: a type-erased callable reference","2023-06 (Varna)","","","" "`P2874R2 `__","Mandating Annex D Require No More","2023-06 (Varna)","","","" "`P2757R3 `__","Type-checking format args","2023-06 (Varna)","","","" -"`P2637R3 `__","Member ``visit``","2023-06 (Varna)","|Complete|","19.0","Change of ``__cpp_lib_variant`` is completed in LLVM 20. Change of ``__cpp_lib_format`` is blocked by `P2419R2 `__." +"`P2637R3 `__","Member ``visit``","2023-06 (Varna)","|Complete|","19","Change of ``__cpp_lib_variant`` is completed in LLVM 20. Change of ``__cpp_lib_format`` is blocked by `P2419R2 `__." "`P2641R4 `__","Checking if a ``union`` alternative is active","2023-06 (Varna)","","","" -"`P1759R6 `__","Native handles and file streams","2023-06 (Varna)","|Complete|","18.0","" -"`P2697R1 `__","Interfacing ``bitset`` with ``string_view``","2023-06 (Varna)","|Complete|","18.0","" +"`P1759R6 `__","Native handles and file streams","2023-06 (Varna)","|Complete|","18","" +"`P2697R1 `__","Interfacing ``bitset`` with ``string_view``","2023-06 (Varna)","|Complete|","18","" "`P1383R2 `__","More ``constexpr`` for ```` and ````","2023-06 (Varna)","","","" -"`P2734R0 `__","Adding the new SI prefixes","2023-06 (Varna)","|Complete|","17.0","" +"`P2734R0 `__","Adding the new SI prefixes","2023-06 (Varna)","|Complete|","17","" "`P2548R6 `__","``copyable_function``","2023-06 (Varna)","","","" "`P2714R1 `__","Bind front and back to NTTP callables","2023-06 (Varna)","","","" "`P2630R4 `__","``submdspan``","2023-06 (Varna)","","","" "","","","","","" -"`P0543R3 `__","Saturation arithmetic","2023-11 (Kona)","|Complete|","18.0","" +"`P0543R3 `__","Saturation arithmetic","2023-11 (Kona)","|Complete|","18","" "`P2407R5 `__","Freestanding Library: Partial Classes","2023-11 (Kona)","","","" "`P2546R5 `__","Debugging Support","2023-11 (Kona)","","","" -"`P2905R2 `__","Runtime format strings","2023-11 (Kona)","|Complete|","18.0","" -"`P2918R2 `__","Runtime format strings II","2023-11 (Kona)","|Complete|","18.0","" -"`P2909R4 `__","Fix formatting of code units as integers (Dude, where’s my ``char``?)","2023-11 (Kona)","|Complete|","18.0","" +"`P2905R2 `__","Runtime format strings","2023-11 (Kona)","|Complete|","18","" +"`P2918R2 `__","Runtime format strings II","2023-11 (Kona)","|Complete|","18","" +"`P2909R4 `__","Fix formatting of code units as integers (Dude, where’s my ``char``?)","2023-11 (Kona)","|Complete|","18","" "`P0952R2 `__","A new specification for ``std::generate_canonical``","2023-11 (Kona)","","","" -"`P2447R6 `__","``std::span`` over an initializer list","2023-11 (Kona)","|Complete|","18.0","" -"`P2821R5 `__","``span.at()``","2023-11 (Kona)","|Complete|","18.0","" -"`P2868R3 `__","Remove Deprecated ``std::allocator`` Typedef From C++26","2023-11 (Kona)","|Complete|","18.0","" -"`P2870R3 `__","Remove ``basic_string::reserve()`` From C++26","2023-11 (Kona)","|Complete|","18.0","" -"`P2871R3 `__","Remove Deprecated Unicode Conversion Facets from C++26","2023-11 (Kona)","|Complete|","18.0","" -"`P2819R2 `__","Add tuple protocol to complex","2023-11 (Kona)","|Complete|","19.0","" +"`P2447R6 `__","``std::span`` over an initializer list","2023-11 (Kona)","|Complete|","18","" +"`P2821R5 `__","``span.at()``","2023-11 (Kona)","|Complete|","18","" +"`P2868R3 `__","Remove Deprecated ``std::allocator`` Typedef From C++26","2023-11 (Kona)","|Complete|","18","" +"`P2870R3 `__","Remove ``basic_string::reserve()`` From C++26","2023-11 (Kona)","|Complete|","18","" +"`P2871R3 `__","Remove Deprecated Unicode Conversion Facets from C++26","2023-11 (Kona)","|Complete|","18","" +"`P2819R2 `__","Add tuple protocol to complex","2023-11 (Kona)","|Complete|","19","" "`P2937R0 `__","Freestanding: Remove ``strtok``","2023-11 (Kona)","","","" "`P2833R2 `__","Freestanding Library: inout expected span","2023-11 (Kona)","","","" "`P2836R1 `__","``std::basic_const_iterator`` should follow its underlying type's convertibility","2023-11 (Kona)","","","" "`P2264R7 `__","Make ``assert()`` macro user friendly for C and C++","2023-11 (Kona)","","","" "`P1673R13 `__","A free function linear algebra interface based on the BLAS","2023-11 (Kona)","","","" "","","","","","" -"`P2875R4 `__","Undeprecate ``polymorphic_allocator::destroy`` for C++26","2024-03 (Tokyo)","|Complete|","15.0","" -"`P2867R2 `__","Remove Deprecated ``strstreams`` From C++26","2024-03 (Tokyo)","|Complete|","19.0","" +"`P2875R4 `__","Undeprecate ``polymorphic_allocator::destroy`` for C++26","2024-03 (Tokyo)","|Complete|","15","" +"`P2867R2 `__","Remove Deprecated ``strstreams`` From C++26","2024-03 (Tokyo)","|Complete|","19","" "`P2869R4 `__","Remove Deprecated ``shared_ptr`` Atomic Access APIs from C++26","2024-03 (Tokyo)","","","" -"`P2872R3 `__","Remove ``wstring_convert`` From C++26","2024-03 (Tokyo)","|Complete|","19.0","" +"`P2872R3 `__","Remove ``wstring_convert`` From C++26","2024-03 (Tokyo)","|Complete|","19","" "`P3107R5 `__","Permit an efficient implementation of ``std::print``","2024-03 (Tokyo)","","","" -"`P3142R0 `__","Printing Blank Lines with ``println``","2024-03 (Tokyo)","|Complete|","19.0","Implemented as a DR against C++23. (MSVC STL and libstdc++ will do the same.)" +"`P3142R0 `__","Printing Blank Lines with ``println``","2024-03 (Tokyo)","|Complete|","19","Implemented as a DR against C++23. (MSVC STL and libstdc++ will do the same.)" "`P2845R8 `__","Formatting of ``std::filesystem::path``","2024-03 (Tokyo)","","","" "`P0493R5 `__","Atomic minimum/maximum","2024-03 (Tokyo)","","","" "`P2542R8 `__","``views::concat``","2024-03 (Tokyo)","","","" -"`P2591R5 `__","Concatenation of strings and string views","2024-03 (Tokyo)","|Complete|","19.0","" +"`P2591R5 `__","Concatenation of strings and string views","2024-03 (Tokyo)","|Complete|","19","" "`P2248R8 `__","Enabling list-initialization for algorithms","2024-03 (Tokyo)","","","" "`P2810R4 `__","``is_debugger_present`` ``is_replaceable``","2024-03 (Tokyo)","","","" "`P1068R11 `__","Vector API for random number generation","2024-03 (Tokyo)","","","" -"`P2944R3 `__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Partial|","19.0","Implemented comparisons for ``reference_wrapper`` only" +"`P2944R3 `__","Comparisons for ``reference_wrapper``","2024-03 (Tokyo)","|Partial|","19","Implemented comparisons for ``reference_wrapper`` only" "`P2642R6 `__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","","","" -"`P3029R1 `__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19.0","" +"`P3029R1 `__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19","" "","","","","","" -"`P2747R2 `__","``constexpr`` placement new","2024-06 (St. Louis)","|Complete|","20.0","" -"`P2997R1 `__","Removing the common reference requirement from the indirectly invocable concepts","2024-06 (St. Louis)","|Complete|","19.0","Implemented as a DR against C++20. (MSVC STL and libstdc++ will do the same.)" -"`P2389R2 `__","``dextents`` Index Type Parameter","2024-06 (St. Louis)","|Complete|","19.0","" +"`P2747R2 `__","``constexpr`` placement new","2024-06 (St. Louis)","|Complete|","20","" +"`P2997R1 `__","Removing the common reference requirement from the indirectly invocable concepts","2024-06 (St. Louis)","|Complete|","19","Implemented as a DR against C++20. (MSVC STL and libstdc++ will do the same.)" +"`P2389R2 `__","``dextents`` Index Type Parameter","2024-06 (St. Louis)","|Complete|","19","" "`P3168R2 `__","Give ``std::optional`` Range Support","2024-06 (St. Louis)","","","" "`P3217R0 `__","Adjoints to 'Enabling list-initialization for algorithms': find_last","2024-06 (St. Louis)","","","" -"`P2985R0 `__","A type trait for detecting virtual base classes","2024-06 (St. Louis)","|Complete|","20.0","" +"`P2985R0 `__","A type trait for detecting virtual base classes","2024-06 (St. Louis)","|Complete|","20","" "`P0843R14 `__","``inplace_vector``","2024-06 (St. Louis)","","","" "`P3235R3 `__","``std::print`` more types faster with less memory","2024-06 (St. Louis)","","","" -"`P2968R2 `__","Make ``std::ignore`` a first-class object","2024-06 (St. Louis)","|Complete|","19.0","" +"`P2968R2 `__","Make ``std::ignore`` a first-class object","2024-06 (St. Louis)","|Complete|","19","" "`P2075R6 `__","Philox as an extension of the C++ RNG engines","2024-06 (St. Louis)","","","" -"`P2422R1 `__","Remove ``nodiscard`` annotations from the standard library specification","2024-06 (St. Louis)","|Complete|","19.0","``nodiscard`` attributes were kept as a conforming extension" +"`P2422R1 `__","Remove ``nodiscard`` annotations from the standard library specification","2024-06 (St. Louis)","|Complete|","19","``nodiscard`` attributes were kept as a conforming extension" "`P2300R10 `__","``std::execution``","2024-06 (St. Louis)","","","" "","","","","","" diff --git a/libcxx/docs/Status/FormatIssues.csv b/libcxx/docs/Status/FormatIssues.csv index 3780c1ed5c127..d618fadc3d0ad 100644 --- a/libcxx/docs/Status/FormatIssues.csv +++ b/libcxx/docs/Status/FormatIssues.csv @@ -1,27 +1,27 @@ Number,Name,Standard,Assignee,Status,First released version -`P0645 `_,"Text Formatting","C++20",Mark de Wever,|Complete|,14.0 -`P1652 `_,"Printf corner cases in std::format","C++20",Mark de Wever,|Complete|,14.0 -`P1892 `_,"Extended locale-specific presentation specifiers for std::format","C++20",Mark de Wever,|Complete|,14.0 -`P1868 `_,"width: clarifying units of width and precision in std::format (Implements the unicode support.)","C++20",Mark de Wever,|Complete|,14.0 -`P2216 `_,"std::format improvements","C++20",Mark de Wever,|Complete|,15.0 -`P2418 `__,"Add support for ``std::generator``-like types to ``std::format``","C++20",Mark de Wever,|Complete|,15.0 -"`P2093R14 `__","Formatted output","C++23",Mark de Wever,|Complete|,"18.0" -"`P2286R8 `__","Formatting Ranges","C++23","Mark de Wever","|Complete|",16.0 -"`P2508R1 `__","Exposing ``std::basic-format-string``","C++23","Mark de Wever","|Complete|",15.0 -"`P2585R0 `__","Improving default container formatting","C++23","Mark de Wever","|Complete|",17.0 -"`P2539R4 `__","Should the output of ``std::print`` to a terminal be synchronized with the underlying stream?","C++23","Mark de Wever","|Complete|","18.0" -"`P2713R1 `__","Escaping improvements in ``std::format``","C++23","Mark de Wever","|Complete|",19.0 -"`P2675R1 `__","``format``'s width estimation is too approximate and not forward compatible","C++23","Mark de Wever","|Complete|",17.0 -"`P2572R1 `__","``std::format`` fill character allowances","C++23","Mark de Wever","|Complete|",17.0 +`P0645 `_,"Text Formatting","C++20",Mark de Wever,|Complete|,14 +`P1652 `_,"Printf corner cases in std::format","C++20",Mark de Wever,|Complete|,14 +`P1892 `_,"Extended locale-specific presentation specifiers for std::format","C++20",Mark de Wever,|Complete|,14 +`P1868 `_,"width: clarifying units of width and precision in std::format (Implements the unicode support.)","C++20",Mark de Wever,|Complete|,14 +`P2216 `_,"std::format improvements","C++20",Mark de Wever,|Complete|,15 +`P2418 `__,"Add support for ``std::generator``-like types to ``std::format``","C++20",Mark de Wever,|Complete|,15 +"`P2093R14 `__","Formatted output","C++23",Mark de Wever,|Complete|,"18" +"`P2286R8 `__","Formatting Ranges","C++23","Mark de Wever","|Complete|",16 +"`P2508R1 `__","Exposing ``std::basic-format-string``","C++23","Mark de Wever","|Complete|",15 +"`P2585R0 `__","Improving default container formatting","C++23","Mark de Wever","|Complete|",17 +"`P2539R4 `__","Should the output of ``std::print`` to a terminal be synchronized with the underlying stream?","C++23","Mark de Wever","|Complete|","18" +"`P2713R1 `__","Escaping improvements in ``std::format``","C++23","Mark de Wever","|Complete|",19 +"`P2675R1 `__","``format``'s width estimation is too approximate and not forward compatible","C++23","Mark de Wever","|Complete|",17 +"`P2572R1 `__","``std::format`` fill character allowances","C++23","Mark de Wever","|Complete|",17 "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``","C++23","Mark de Wever","|In Progress|" -"`P2510R3 `__","Formatting pointers","C++26","Mark de Wever","|Complete|",17.0 +"`P2510R3 `__","Formatting pointers","C++26","Mark de Wever","|Complete|",17 "`P2757R3 `__","Type-checking format args","C++26","","", -"`P2637R3 `__","Member ``visit``","C++26","Hristo Hristov","|Complete|",19.0 -"`P2905R2 `__","Runtime format strings","C++26 DR","Mark de Wever","|Complete|",18.0 -"`P2918R2 `__","Runtime format strings II","C++26","Mark de Wever","|Complete|",18.0 -"`P2909R4 `__","Fix formatting of code units as integers (Dude, where’s my ``char``?)","C++26 DR","Mark de Wever","|Complete|",18.0 +"`P2637R3 `__","Member ``visit``","C++26","Hristo Hristov","|Complete|",19 +"`P2905R2 `__","Runtime format strings","C++26 DR","Mark de Wever","|Complete|",18 +"`P2918R2 `__","Runtime format strings II","C++26","Mark de Wever","|Complete|",18 +"`P2909R4 `__","Fix formatting of code units as integers (Dude, where’s my ``char``?)","C++26 DR","Mark de Wever","|Complete|",18 "`P3107R5 `__","Permit an efficient implementation of ``std::print``","C++26 DR","Mark de Wever","|In Progress|","" -"`P3142R0 `__","Printing Blank Lines with ``println``","C++26 DR","Hristo Hristov","|Complete|",19.0 +"`P3142R0 `__","Printing Blank Lines with ``println``","C++26 DR","Hristo Hristov","|Complete|",19 "`P2845R8 `__","Formatting of ``std::filesystem::path``","C++26","Mark de Wever","","" `P1361 `_,"Integration of chrono with text formatting","C++20",Mark de Wever,|In Progress|, diff --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv index fb96b1fff30ad..7f5f46d834d3e 100644 --- a/libcxx/docs/Status/FormatPaper.csv +++ b/libcxx/docs/Status/FormatPaper.csv @@ -1,33 +1,33 @@ Section,Description,Dependencies,Assignee,Status,First released version `P1361 `__ `P2372 `__,"Formatting chrono" -`[time.syn] `_,"Formatter ``chrono::duration``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::sys_time``",,Mark de Wever,|Complete|,17.0 +`[time.syn] `_,"Formatter ``chrono::duration``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::sys_time``",,Mark de Wever,|Complete|,17 `[time.syn] `_,"Formatter ``chrono::utc_time``",A ```` implementation,Mark de Wever,,, `[time.syn] `_,"Formatter ``chrono::tai_time``",A ```` implementation,Mark de Wever,,, `[time.syn] `_,"Formatter ``chrono::gps_time``",A ```` implementation,Mark de Wever,,, -`[time.syn] `_,"Formatter ``chrono::file_time``",,Mark de Wever,|Complete|,17.0 -`[time.syn] `_,"Formatter ``chrono::local_time``",,Mark de Wever,|Complete|,17.0 +`[time.syn] `_,"Formatter ``chrono::file_time``",,Mark de Wever,|Complete|,17 +`[time.syn] `_,"Formatter ``chrono::local_time``",,Mark de Wever,|Complete|,17 `[time.syn] `_,"Formatter ``chrono::local-time-format-t``",,,|Nothing To Do|, -`[time.syn] `_,"Formatter ``chrono::day``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::month``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::year``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::weekday``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::weekday_indexed``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::weekday_last``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::month_day``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::month_day_last``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::month_weekday``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::month_weekday_last``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::year_month``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::year_month_day``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::year_month_day_last``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::year_month_weekday``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::year_month_weekday_last``",,Mark de Wever,|Complete|,16.0 -`[time.syn] `_,"Formatter ``chrono::hh_mm_ss>``",,Mark de Wever,|Complete|,17.0 -`[time.syn] `_,"Formatter ``chrono::sys_info``",,Mark de Wever,|Complete|,19.0 -`[time.syn] `_,"Formatter ``chrono::local_info``",,Mark de Wever,|Complete|,19.0 -`[time.syn] `_,"Formatter ``chrono::zoned_time``",,Mark de Wever,|Complete|,19.0 +`[time.syn] `_,"Formatter ``chrono::day``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::month``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::year``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::weekday``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::weekday_indexed``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::weekday_last``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::month_day``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::month_day_last``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::month_weekday``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::month_weekday_last``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::year_month``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::year_month_day``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::year_month_day_last``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::year_month_weekday``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::year_month_weekday_last``",,Mark de Wever,|Complete|,16 +`[time.syn] `_,"Formatter ``chrono::hh_mm_ss>``",,Mark de Wever,|Complete|,17 +`[time.syn] `_,"Formatter ``chrono::sys_info``",,Mark de Wever,|Complete|,19 +`[time.syn] `_,"Formatter ``chrono::local_info``",,Mark de Wever,|Complete|,19 +`[time.syn] `_,"Formatter ``chrono::zoned_time``",,Mark de Wever,|Complete|,19 "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``" -`[thread.thread.id] `_,"Formatting ``thread::id``",,Mark de Wever,|Complete|,17.0 +`[thread.thread.id] `_,"Formatting ``thread::id``",,Mark de Wever,|Complete|,17 `[stacktrace.format] `_,"Formatting ``stacktrace``",A ```` implementation,Mark de Wever,, diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h index 62c129f5921de..7095d56c6dc39 100644 --- a/libcxx/include/__configuration/abi.h +++ b/libcxx/include/__configuration/abi.h @@ -186,6 +186,8 @@ // of types can be checked. // // ABI impact: This causes the layout of std::unique_ptr to change and its size to increase. +// This also affects the representation of a few library types that use std::unique_ptr +// internally, such as the unordered containers. // #define _LIBCPP_ABI_BOUNDED_UNIQUE_PTR #if defined(_LIBCPP_COMPILER_CLANG_BASED) diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 8e4cb3c914dc4..a0c72f4c20541 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -36,6 +36,7 @@ #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_pointer.h> #include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> #include <__type_traits/remove_const.h> #include <__type_traits/remove_cvref.h> diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index e5adbedce1a2d..31650a50ff637 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -42,9 +42,11 @@ #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> #include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> #include <__type_traits/is_unbounded_array.h> #include <__type_traits/nat.h> #include <__type_traits/negation.h> +#include <__type_traits/remove_cv.h> #include <__type_traits/remove_extent.h> #include <__type_traits/remove_reference.h> #include <__utility/declval.h> @@ -957,7 +959,7 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count { template _LIBCPP_HIDE_FROM_ABI shared_ptr<_Array> __allocate_shared_unbounded_array(const _Alloc& __a, size_t __n, _Arg&&... __arg) { - static_assert(__libcpp_is_unbounded_array<_Array>::value); + static_assert(__is_unbounded_array_v<_Array>); // We compute the number of bytes necessary to hold the control block and the // array elements. Then, we allocate an array of properly-aligned dummy structs // large enough to hold the control block and array. This allows shifting the @@ -1034,7 +1036,7 @@ struct __bounded_array_control_block<_Tp[_Count], _Alloc> : __shared_weak_count template _LIBCPP_HIDE_FROM_ABI shared_ptr<_Array> __allocate_shared_bounded_array(const _Alloc& __a, _Arg&&... __arg) { - static_assert(__libcpp_is_bounded_array<_Array>::value); + static_assert(__is_bounded_array_v<_Array>); using _ControlBlock = __bounded_array_control_block<_Array, _Alloc>; using _ControlBlockAlloc = __allocator_traits_rebind_t<_Alloc, _ControlBlock>; diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h index 3fa948ecc43cf..627ee44e808d9 100644 --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -25,6 +25,7 @@ #include <__type_traits/extent.h> #include <__type_traits/is_array.h> #include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_same.h> #include <__type_traits/is_trivially_assignable.h> #include <__type_traits/is_trivially_constructible.h> #include <__type_traits/is_trivially_relocatable.h> @@ -375,7 +376,7 @@ __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter __first, _Bidir return; if constexpr (is_array_v<_ValueType>) { - static_assert(!__libcpp_is_unbounded_array<_ValueType>::value, + static_assert(!__is_unbounded_array_v<_ValueType>, "arrays of unbounded arrays don't exist, but if they did we would mess up here"); using _Element = remove_extent_t<_ValueType>; diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h index 4ed6393b1209f..28c62e13566e2 100644 --- a/libcxx/include/__memory/unique_ptr.h +++ b/libcxx/include/__memory/unique_ptr.h @@ -32,6 +32,7 @@ #include <__type_traits/integral_constant.h> #include <__type_traits/is_array.h> #include <__type_traits/is_assignable.h> +#include <__type_traits/is_bounded_array.h> #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> @@ -41,6 +42,7 @@ #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivially_relocatable.h> +#include <__type_traits/is_unbounded_array.h> #include <__type_traits/is_void.h> #include <__type_traits/remove_extent.h> #include <__type_traits/type_identity.h> @@ -544,7 +546,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { reset(__u.release()); __deleter_ = std::forward(__u.get_deleter()); - __checker_ = std::move(std::move(__u.__checker_)); + __checker_ = std::move(__u.__checker_); return *this; } @@ -758,55 +760,36 @@ operator<=>(const unique_ptr<_T1, _D1>& __x, nullptr_t) { #if _LIBCPP_STD_VER >= 14 -template -struct __unique_if { - typedef unique_ptr<_Tp> __unique_single; -}; - -template -struct __unique_if<_Tp[]> { - typedef unique_ptr<_Tp[]> __unique_array_unknown_bound; -}; - -template -struct __unique_if<_Tp[_Np]> { - typedef void __unique_array_known_bound; -}; - -template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_single -make_unique(_Args&&... __args) { +template ::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique(_Args&&... __args) { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } -template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_array_unknown_bound -make_unique(size_t __n) { +template , int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique(size_t __n) { typedef __remove_extent_t<_Tp> _Up; return unique_ptr<_Tp>(__private_constructor_tag(), new _Up[__n](), __n); } -template -typename __unique_if<_Tp>::__unique_array_known_bound make_unique(_Args&&...) = delete; +template , int> = 0> +void make_unique(_Args&&...) = delete; #endif // _LIBCPP_STD_VER >= 14 #if _LIBCPP_STD_VER >= 20 -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_single -make_unique_for_overwrite() { +template , int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique_for_overwrite() { return unique_ptr<_Tp>(new _Tp); } -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_array_unknown_bound -make_unique_for_overwrite(size_t __n) { +template , int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique_for_overwrite(size_t __n) { return unique_ptr<_Tp>(__private_constructor_tag(), new __remove_extent_t<_Tp>[__n], __n); } -template -typename __unique_if<_Tp>::__unique_array_known_bound make_unique_for_overwrite(_Args&&...) = delete; +template , int> = 0> +void make_unique_for_overwrite(_Args&&...) = delete; #endif // _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index 6fc3d9255946c..2a2f2625c748b 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -108,12 +108,6 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer(); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __alloc_rr& __alloc() _NOEXCEPT { return __alloc_; } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const __alloc_rr& __alloc() const _NOEXCEPT { return __alloc_; } - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT { return __end_cap_; } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT { return __end_cap_; } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __begin_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __begin_; } @@ -129,7 +123,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __end_ == __begin_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const { - return static_cast(__end_cap() - __first_); + return static_cast(__end_cap_ - __first_); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const { @@ -137,7 +131,7 @@ public: } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const { - return static_cast(__end_cap() - __end_); + return static_cast(__end_cap_ - __end_); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__begin_; } @@ -147,11 +141,9 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(const_reference __x); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x); + template + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_front(_Args&&... __args); template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args); @@ -198,7 +190,7 @@ public: private: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { - __alloc() = std::move(__c.__alloc()); + __alloc_ = std::move(__c.__alloc_); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {} @@ -227,14 +219,14 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __split_buffer<_Tp, _Allocator>::__invariants return false; if (__end_ != nullptr) return false; - if (__end_cap() != nullptr) + if (__end_cap_ != nullptr) return false; } else { if (__begin_ < __first_) return false; if (__end_ < __begin_) return false; - if (__end_cap() < __end_) + if (__end_cap_ < __end_) return false; } return true; @@ -249,7 +241,7 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) { _ConstructTransaction __tx(&this->__end_, __n); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { - __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_)); + __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_)); } } @@ -264,7 +256,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) { _ConstructTransaction __tx(&this->__end_, __n); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { - __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), __x); + __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), __x); } } @@ -279,14 +271,14 @@ template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) { - __alloc_rr& __a = this->__alloc(); + __alloc_rr& __a = __alloc_; for (; __first != __last; ++__first) { - if (__end_ == __end_cap()) { - size_type __old_cap = __end_cap() - __first_; + if (__end_ == __end_cap_) { + size_type __old_cap = __end_cap_ - __first_; size_type __new_cap = std::max(2 * __old_cap, 8); __split_buffer __buf(__new_cap, 0, __a); for (pointer __p = __begin_; __p != __end_; ++__p, (void)++__buf.__end_) - __alloc_traits::construct(__buf.__alloc(), std::__to_address(__buf.__end_), std::move(*__p)); + __alloc_traits::construct(__buf.__alloc_, std::__to_address(__buf.__end_), std::move(*__p)); swap(__buf); } __alloc_traits::construct(__a, std::__to_address(this->__end_), *__first); @@ -306,7 +298,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) { _ConstructTransaction __tx(&this->__end_, __n); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__first) { - __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), *__first); + __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), *__first); } } @@ -314,7 +306,7 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) { while (__begin_ != __new_begin) - __alloc_traits::destroy(__alloc(), std::__to_address(__begin_++)); + __alloc_traits::destroy(__alloc_, std::__to_address(__begin_++)); } template @@ -327,7 +319,7 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT { while (__new_last != __end_) - __alloc_traits::destroy(__alloc(), std::__to_address(--__end_)); + __alloc_traits::destroy(__alloc_, std::__to_address(--__end_)); } template @@ -343,19 +335,19 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __sta if (__cap == 0) { __first_ = nullptr; } else { - auto __allocation = std::__allocate_at_least(__alloc(), __cap); + auto __allocation = std::__allocate_at_least(__alloc_, __cap); __first_ = __allocation.ptr; __cap = __allocation.count; } __begin_ = __end_ = __first_ + __start; - __end_cap() = __first_ + __cap; + __end_cap_ = __first_ + __cap; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::~__split_buffer() { clear(); if (__first_) - __alloc_traits::deallocate(__alloc(), __first_, capacity()); + __alloc_traits::deallocate(__alloc_, __first_, capacity()); } template @@ -366,30 +358,30 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__ __end_(std::move(__c.__end_)), __end_cap_(std::move(__c.__end_cap_)), __alloc_(std::move(__c.__alloc_)) { - __c.__first_ = nullptr; - __c.__begin_ = nullptr; - __c.__end_ = nullptr; - __c.__end_cap() = nullptr; + __c.__first_ = nullptr; + __c.__begin_ = nullptr; + __c.__end_ = nullptr; + __c.__end_cap_ = nullptr; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a) : __end_cap_(nullptr), __alloc_(__a) { - if (__a == __c.__alloc()) { - __first_ = __c.__first_; - __begin_ = __c.__begin_; - __end_ = __c.__end_; - __end_cap() = __c.__end_cap(); - __c.__first_ = nullptr; - __c.__begin_ = nullptr; - __c.__end_ = nullptr; - __c.__end_cap() = nullptr; + if (__a == __c.__alloc_) { + __first_ = __c.__first_; + __begin_ = __c.__begin_; + __end_ = __c.__end_; + __end_cap_ = __c.__end_cap_; + __c.__first_ = nullptr; + __c.__begin_ = nullptr; + __c.__end_ = nullptr; + __c.__end_cap_ = nullptr; } else { - auto __allocation = std::__allocate_at_least(__alloc(), __c.size()); + auto __allocation = std::__allocate_at_least(__alloc_, __c.size()); __first_ = __allocation.ptr; __begin_ = __end_ = __first_; - __end_cap() = __first_ + __allocation.count; + __end_cap_ = __first_ + __allocation.count; typedef move_iterator _Ip; __construct_at_end(_Ip(__c.begin()), _Ip(__c.end())); } @@ -403,12 +395,12 @@ __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) !__alloc_traits::propagate_on_container_move_assignment::value) { clear(); shrink_to_fit(); - __first_ = __c.__first_; - __begin_ = __c.__begin_; - __end_ = __c.__end_; - __end_cap() = __c.__end_cap(); + __first_ = __c.__first_; + __begin_ = __c.__begin_; + __end_ = __c.__end_; + __end_cap_ = __c.__end_cap_; __move_assign_alloc(__c, integral_constant()); - __c.__first_ = __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr; + __c.__first_ = __c.__begin_ = __c.__end_ = __c.__end_cap_ = nullptr; return *this; } @@ -418,19 +410,19 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::swap(__split std::swap(__first_, __x.__first_); std::swap(__begin_, __x.__begin_); std::swap(__end_, __x.__end_); - std::swap(__end_cap(), __x.__end_cap()); - std::__swap_allocator(__alloc(), __x.__alloc()); + std::swap(__end_cap_, __x.__end_cap_); + std::__swap_allocator(__alloc_, __x.__alloc_); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::reserve(size_type __n) { if (__n < capacity()) { - __split_buffer __t(__n, 0, __alloc()); + __split_buffer __t(__n, 0, __alloc_); __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); std::swap(__first_, __t.__first_); std::swap(__begin_, __t.__begin_); std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); + std::swap(__end_cap_, __t.__end_cap_); } } @@ -440,13 +432,13 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi #if _LIBCPP_HAS_EXCEPTIONS try { #endif // _LIBCPP_HAS_EXCEPTIONS - __split_buffer __t(size(), 0, __alloc()); + __split_buffer __t(size(), 0, __alloc_); __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); __t.__end_ = __t.__begin_ + (__end_ - __begin_); std::swap(__first_, __t.__first_); std::swap(__begin_, __t.__begin_); std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); + std::swap(__end_cap_, __t.__end_cap_); #if _LIBCPP_HAS_EXCEPTIONS } catch (...) { } @@ -455,114 +447,48 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi } template -_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) { - if (__begin_ == __first_) { - if (__end_ < __end_cap()) { - difference_type __d = __end_cap() - __end_; - __d = (__d + 1) / 2; - __begin_ = std::move_backward(__begin_, __end_, __end_ + __d); - __end_ += __d; - } else { - size_type __c = std::max(2 * static_cast(__end_cap() - __first_), 1); - __split_buffer __t(__c, (__c + 3) / 4, __alloc()); - __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); - std::swap(__first_, __t.__first_); - std::swap(__begin_, __t.__begin_); - std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); - } - } - __alloc_traits::construct(__alloc(), std::__to_address(__begin_ - 1), __x); - --__begin_; -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) { +template +_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_front(_Args&&... __args) { if (__begin_ == __first_) { - if (__end_ < __end_cap()) { - difference_type __d = __end_cap() - __end_; + if (__end_ < __end_cap_) { + difference_type __d = __end_cap_ - __end_; __d = (__d + 1) / 2; __begin_ = std::move_backward(__begin_, __end_, __end_ + __d); __end_ += __d; } else { - size_type __c = std::max(2 * static_cast(__end_cap() - __first_), 1); - __split_buffer __t(__c, (__c + 3) / 4, __alloc()); + size_type __c = std::max(2 * static_cast(__end_cap_ - __first_), 1); + __split_buffer __t(__c, (__c + 3) / 4, __alloc_); __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); std::swap(__first_, __t.__first_); std::swap(__begin_, __t.__begin_); std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); + std::swap(__end_cap_, __t.__end_cap_); } } - __alloc_traits::construct(__alloc(), std::__to_address(__begin_ - 1), std::move(__x)); + __alloc_traits::construct(__alloc_, std::__to_address(__begin_ - 1), std::forward<_Args>(__args)...); --__begin_; } -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void -__split_buffer<_Tp, _Allocator>::push_back(const_reference __x) { - if (__end_ == __end_cap()) { - if (__begin_ > __first_) { - difference_type __d = __begin_ - __first_; - __d = (__d + 1) / 2; - __end_ = std::move(__begin_, __end_, __begin_ - __d); - __begin_ -= __d; - } else { - size_type __c = std::max(2 * static_cast(__end_cap() - __first_), 1); - __split_buffer __t(__c, __c / 4, __alloc()); - __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); - std::swap(__first_, __t.__first_); - std::swap(__begin_, __t.__begin_); - std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); - } - } - __alloc_traits::construct(__alloc(), std::__to_address(__end_), __x); - ++__end_; -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) { - if (__end_ == __end_cap()) { - if (__begin_ > __first_) { - difference_type __d = __begin_ - __first_; - __d = (__d + 1) / 2; - __end_ = std::move(__begin_, __end_, __begin_ - __d); - __begin_ -= __d; - } else { - size_type __c = std::max(2 * static_cast(__end_cap() - __first_), 1); - __split_buffer __t(__c, __c / 4, __alloc()); - __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); - std::swap(__first_, __t.__first_); - std::swap(__begin_, __t.__begin_); - std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); - } - } - __alloc_traits::construct(__alloc(), std::__to_address(__end_), std::move(__x)); - ++__end_; -} - template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) { - if (__end_ == __end_cap()) { + if (__end_ == __end_cap_) { if (__begin_ > __first_) { difference_type __d = __begin_ - __first_; __d = (__d + 1) / 2; __end_ = std::move(__begin_, __end_, __begin_ - __d); __begin_ -= __d; } else { - size_type __c = std::max(2 * static_cast(__end_cap() - __first_), 1); - __split_buffer __t(__c, __c / 4, __alloc()); + size_type __c = std::max(2 * static_cast(__end_cap_ - __first_), 1); + __split_buffer __t(__c, __c / 4, __alloc_); __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); std::swap(__first_, __t.__first_); std::swap(__begin_, __t.__begin_); std::swap(__end_, __t.__end_); - std::swap(__end_cap(), __t.__end_cap()); + std::swap(__end_cap_, __t.__end_cap_); } } - __alloc_traits::construct(__alloc(), std::__to_address(__end_), std::forward<_Args>(__args)...); + __alloc_traits::construct(__alloc_, std::__to_address(__end_), std::forward<_Args>(__args)...); ++__end_; } diff --git a/libcxx/include/__tuple/make_tuple_types.h b/libcxx/include/__tuple/make_tuple_types.h index 53e98c3d6e975..024e9c524b527 100644 --- a/libcxx/include/__tuple/make_tuple_types.h +++ b/libcxx/include/__tuple/make_tuple_types.h @@ -18,7 +18,7 @@ #include <__tuple/tuple_size.h> #include <__tuple/tuple_types.h> #include <__type_traits/copy_cvref.h> -#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> #include <__type_traits/remove_reference.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -58,7 +58,7 @@ template >::value)> struct __make_tuple_types { static_assert(_Sp <= _Ep, "__make_tuple_types input error"); - using _RawTp = __remove_cv_t<__libcpp_remove_reference_t<_Tp> >; + using _RawTp = __remove_cvref_t<_Tp>; using _Maker = __make_tuple_types_flat<_RawTp, typename __make_tuple_indices<_Ep, _Sp>::type>; using type = typename _Maker::template __apply_quals<_Tp>; }; diff --git a/libcxx/include/__type_traits/aligned_storage.h b/libcxx/include/__type_traits/aligned_storage.h index 49b4e971bbb67..2e39afb7f8808 100644 --- a/libcxx/include/__type_traits/aligned_storage.h +++ b/libcxx/include/__type_traits/aligned_storage.h @@ -11,7 +11,6 @@ #include <__config> #include <__cstddef/size_t.h> -#include <__type_traits/conditional.h> #include <__type_traits/integral_constant.h> #include <__type_traits/nat.h> #include <__type_traits/type_list.h> @@ -50,22 +49,6 @@ typedef __type_list<__align_type, > > > > > > > > > > __all_types; // clang-format on -template -struct _ALIGNAS(_Align) __fallback_overaligned {}; - -template -struct __find_pod; - -template -struct __find_pod<__type_list<_Hp, __nat>, _Align> { - typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, __fallback_overaligned<_Align> > type; -}; - -template -struct __find_pod<__type_list<_Hp, _Tp>, _Align> { - typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, typename __find_pod<_Tp, _Align>::type> type; -}; - template struct __find_max_align; @@ -88,9 +71,7 @@ struct __find_max_align<__type_list<_Hp, _Tp>, _Len> template ::value> struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage { - typedef typename __find_pod<__all_types, _Align>::type _Aligner; - union type { - _Aligner __align; + union _ALIGNAS(_Align) type { unsigned char __data[(_Len + _Align - 1) / _Align * _Align]; }; }; @@ -104,35 +85,6 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP #endif -#define _CREATE_ALIGNED_STORAGE_SPECIALIZATION(n) \ - template \ - struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage<_Len, n> { \ - struct _ALIGNAS(n) type { \ - unsigned char __lx[(_Len + n - 1) / n * n]; \ - }; \ - } - -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x1); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x2); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x4); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x8); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x10); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x20); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x40); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x80); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x100); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x200); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x400); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x800); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x1000); -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x2000); -// PE/COFF does not support alignment beyond 8192 (=0x2000) -#if !defined(_LIBCPP_OBJECT_FORMAT_COFF) -_CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x4000); -#endif // !defined(_LIBCPP_OBJECT_FORMAT_COFF) - -#undef _CREATE_ALIGNED_STORAGE_SPECIALIZATION - _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_ALIGNED_STORAGE_H diff --git a/libcxx/include/__type_traits/is_bounded_array.h b/libcxx/include/__type_traits/is_bounded_array.h index a78b52e7062b8..fd794eb9a6935 100644 --- a/libcxx/include/__type_traits/is_bounded_array.h +++ b/libcxx/include/__type_traits/is_bounded_array.h @@ -20,9 +20,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array : false_type {}; +inline const bool __is_bounded_array_v = false; template -struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array<_Tp[_Np]> : true_type {}; +inline const bool __is_bounded_array_v<_Tp[_Np]> = true; #if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__type_traits/is_unbounded_array.h b/libcxx/include/__type_traits/is_unbounded_array.h index d58bb09e10428..b0879476bd23e 100644 --- a/libcxx/include/__type_traits/is_unbounded_array.h +++ b/libcxx/include/__type_traits/is_unbounded_array.h @@ -19,9 +19,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array : false_type {}; +inline const bool __is_unbounded_array_v = false; template -struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array<_Tp[]> : true_type {}; +inline const bool __is_unbounded_array_v<_Tp[]> = true; #if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__utility/is_pointer_in_range.h b/libcxx/include/__utility/is_pointer_in_range.h index 4130b4ac70700..55fac6256b74e 100644 --- a/libcxx/include/__utility/is_pointer_in_range.h +++ b/libcxx/include/__utility/is_pointer_in_range.h @@ -57,6 +57,14 @@ __is_pointer_in_range(const _Tp* __begin, const _Tp* __end, const _Up* __ptr) { reinterpret_cast(__ptr) < reinterpret_cast(__end); } +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool +__is_overlapping_range(const _Tp* __begin, const _Tp* __end, const _Up* __begin2) { + auto __size = __end - __begin; + auto __end2 = __begin2 + __size; + return std::__is_pointer_in_range(__begin, __end, __begin2) || std::__is_pointer_in_range(__begin2, __end2, __begin); +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h index cca6490476db1..f9d0f4e472311 100644 --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -17,8 +17,6 @@ #include <__fwd/array.h> #include <__fwd/pair.h> #include <__fwd/tuple.h> -#include <__tuple/sfinae_helpers.h> -#include <__tuple/tuple_element.h> #include <__tuple/tuple_indices.h> #include <__tuple/tuple_like_no_subrange.h> #include <__tuple/tuple_size.h> @@ -132,8 +130,7 @@ struct _LIBCPP_TEMPLATE_VIS pair }; template - using _CheckArgsDep _LIBCPP_NODEBUG = - typename conditional< _MaybeEnable, _CheckArgs, __check_tuple_constructor_fail>::type; + using _CheckArgsDep _LIBCPP_NODEBUG = __conditional_t<_MaybeEnable, _CheckArgs, void>; template ::__enable_default(), int> = 0> explicit(!_CheckArgsDep<_Dummy>::__enable_implicit_default()) _LIBCPP_HIDE_FROM_ABI constexpr pair() noexcept( diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h index 844e5d6a21056..876490afbeb3e 100644 --- a/libcxx/include/__vector/vector.h +++ b/libcxx/include/__vector/vector.h @@ -84,6 +84,9 @@ class _LIBCPP_TEMPLATE_VIS vector { typedef allocator<_Tp> __default_allocator_type; public: + // + // Types + // typedef vector __self; typedef _Tp value_type; typedef _Allocator allocator_type; @@ -120,6 +123,9 @@ class _LIBCPP_TEMPLATE_VIS vector { static_assert(is_same::value, "Allocator::value_type must be same type as value_type"); + // + // [vector.cons], construct/copy/destroy + // _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector() _NOEXCEPT_(is_nothrow_default_constructible::value) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(const allocator_type& __a) @@ -177,20 +183,29 @@ class _LIBCPP_TEMPLATE_VIS vector { __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value && is_constructible::reference>::value, int> = 0> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_InputIterator __first, _InputIterator __last); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_InputIterator __first, _InputIterator __last) { + __init_with_sentinel(__first, __last); + } + template ::value && is_constructible::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a); + vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a) + : __alloc_(__a) { + __init_with_sentinel(__first, __last); + } template < class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible::reference>::value, int> = 0> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_ForwardIterator __first, _ForwardIterator __last) { + size_type __n = static_cast(std::distance(__first, __last)); + __init_with_size(__first, __last, __n); + } template < class _ForwardIterator, @@ -198,7 +213,11 @@ class _LIBCPP_TEMPLATE_VIS vector { is_constructible::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a); + vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a) + : __alloc_(__a) { + size_type __n = static_cast(std::distance(__first, __last)); + __init_with_size(__first, __last, __n); + } #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_Tp> _Range> @@ -235,16 +254,27 @@ class _LIBCPP_TEMPLATE_VIS vector { public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector (*this)(); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x) + : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc())) { + __init_with_size(__x.__begin_, __x.__end_, __x.size()); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - vector(const vector& __x, const __type_identity_t& __a); + vector(const vector& __x, const __type_identity_t& __a) + : __alloc_(__a) { + __init_with_size(__x.__begin_, __x.__end_, __x.size()); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(const vector& __x); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(initializer_list __il); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(initializer_list __il) { + __init_with_size(__il.begin(), __il.end(), __il.size()); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - vector(initializer_list __il, const allocator_type& __a); + vector(initializer_list __il, const allocator_type& __a) + : __alloc_(__a) { + __init_with_size(__il.begin(), __il.end(), __il.size()); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(initializer_list __il) { assign(__il.begin(), __il.end()); @@ -262,19 +292,26 @@ class _LIBCPP_TEMPLATE_VIS vector { _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(vector&& __x, const __type_identity_t& __a); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(vector&& __x) - _NOEXCEPT_(__noexcept_move_assign_container<_Allocator, __alloc_traits>::value); + _NOEXCEPT_(__noexcept_move_assign_container<_Allocator, __alloc_traits>::value) { + __move_assign(__x, integral_constant()); + return *this; + } template ::value && is_constructible::reference>::value, int> = 0> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_InputIterator __first, _InputIterator __last); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_InputIterator __first, _InputIterator __last) { + __assign_with_sentinel(__first, __last); + } template < class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible::reference>::value, int> = 0> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_ForwardIterator __first, _ForwardIterator __last) { + __assign_with_size(__first, __last, std::distance(__first, __last)); + } #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_Tp> _Range> @@ -301,10 +338,17 @@ class _LIBCPP_TEMPLATE_VIS vector { return this->__alloc(); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT; + // + // Iterators + // + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __make_iter(this->__begin_); } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { + return __make_iter(this->__begin_); + } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __make_iter(this->__end_); } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { + return __make_iter(this->__end_); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT { return reverse_iterator(end()); @@ -326,6 +370,9 @@ class _LIBCPP_TEMPLATE_VIS vector { } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const _NOEXCEPT { return rend(); } + // + // [vector.capacity], capacity + // _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return static_cast(this->__end_ - this->__begin_); } @@ -335,14 +382,33 @@ class _LIBCPP_TEMPLATE_VIS vector { [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return this->__begin_ == this->__end_; } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT; + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { + return std::min(__alloc_traits::max_size(this->__alloc()), numeric_limits::max()); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const; + // + // element access + // + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds"); + return this->__begin_[__n]; + } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds"); + return this->__begin_[__n]; + } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) { + if (__n >= size()) + this->__throw_out_of_range(); + return this->__begin_[__n]; + } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const { + if (__n >= size()) + this->__throw_out_of_range(); + return this->__begin_[__n]; + } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector"); @@ -361,6 +427,9 @@ class _LIBCPP_TEMPLATE_VIS vector { return *(this->__end_ - 1); } + // + // [vector.data], data access + // _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT { return std::__to_address(this->__begin_); } @@ -369,6 +438,9 @@ class _LIBCPP_TEMPLATE_VIS vector { return std::__to_address(this->__begin_); } + // + // [vector.modifiers], modifiers + // _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x) { emplace_back(__x); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x) { emplace_back(std::move(__x)); } @@ -390,7 +462,10 @@ class _LIBCPP_TEMPLATE_VIS vector { } #endif - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back(); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector"); + this->__destruct_at_end(this->__end_ - 1); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, const_reference __x); @@ -406,7 +481,19 @@ class _LIBCPP_TEMPLATE_VIS vector { is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator - insert(const_iterator __position, _InputIterator __first, _InputIterator __last); + insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { + return __insert_with_sentinel(__position, __first, __last); + } + + template < + class _ForwardIterator, + __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && + is_constructible< value_type, typename iterator_traits<_ForwardIterator>::reference>::value, + int> = 0> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator + insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last) { + return __insert_with_size(__position, __first, __last, std::distance(__first, __last)); + } #if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_Tp> _Range> @@ -421,14 +508,6 @@ class _LIBCPP_TEMPLATE_VIS vector { } #endif - template < - class _ForwardIterator, - __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && - is_constructible< value_type, typename iterator_traits<_ForwardIterator>::reference>::value, - int> = 0> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator - insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); - #ifndef _LIBCPP_CXX03_LANG _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, initializer_list __il) { @@ -743,7 +822,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer__begin_, __v.__begin_); std::swap(this->__end_, __v.__end_); - std::swap(this->__end_cap(), __v.__end_cap()); + std::swap(this->__end_cap(), __v.__end_cap_); __v.__first_ = __v.__begin_; __annotate_new(size()); } @@ -773,7 +852,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer__begin_, __v.__begin_); std::swap(this->__end_, __v.__end_); - std::swap(this->__end_cap(), __v.__end_cap()); + std::swap(this->__end_cap(), __v.__end_cap_); __v.__first_ = __v.__begin_; __annotate_new(size()); return __ret; @@ -789,12 +868,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOE } } -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::size_type -vector<_Tp, _Allocator>::max_size() const _NOEXCEPT { - return std::min(__alloc_traits::max_size(this->__alloc()), numeric_limits::max()); -} - // Precondition: __new_size > capacity() template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::size_type @@ -878,61 +951,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__append(size_type _ } } -template -template ::value && - is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last) { - __init_with_sentinel(__first, __last); -} - -template -template ::value && - is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 -vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a) - : __alloc_(__a) { - __init_with_sentinel(__first, __last); -} - -template -template ::value && - is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last) { - size_type __n = static_cast(std::distance(__first, __last)); - __init_with_size(__first, __last, __n); -} - -template -template ::value && - is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 -vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a) - : __alloc_(__a) { - size_type __n = static_cast(std::distance(__first, __last)); - __init_with_size(__first, __last, __n); -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(const vector& __x) - : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc())) { - __init_with_size(__x.__begin_, __x.__end_, __x.size()); -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 -vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t& __a) - : __alloc_(__a) { - __init_with_size(__x.__begin_, __x.__end_, __x.size()); -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(vector&& __x) #if _LIBCPP_STD_VER >= 17 @@ -964,31 +982,6 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI -vector<_Tp, _Allocator>::vector(initializer_list __il) { - __init_with_size(__il.begin(), __il.end(), __il.size()); -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI -vector<_Tp, _Allocator>::vector(initializer_list __il, const allocator_type& __a) - : __alloc_(__a) { - __init_with_size(__il.begin(), __il.end(), __il.size()); -} - -#endif // _LIBCPP_CXX03_LANG - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>& -vector<_Tp, _Allocator>::operator=(vector&& __x) - _NOEXCEPT_(__noexcept_move_assign_container<_Allocator, __alloc_traits>::value) { - __move_assign(__x, integral_constant()); - return *this; -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value) { @@ -1020,15 +1013,6 @@ vector<_Tp, _Allocator>::operator=(const vector& __x) { return *this; } -template -template ::value && - is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { - __assign_with_sentinel(__first, __last); -} - template template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void @@ -1038,15 +1022,6 @@ vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __l emplace_back(*__first); } -template -template ::value && - is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { - __assign_with_size(__first, __last, std::distance(__first, __last)); -} - template template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void @@ -1084,59 +1059,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n } } -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator -vector<_Tp, _Allocator>::begin() _NOEXCEPT { - return __make_iter(this->__begin_); -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_iterator -vector<_Tp, _Allocator>::begin() const _NOEXCEPT { - return __make_iter(this->__begin_); -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator -vector<_Tp, _Allocator>::end() _NOEXCEPT { - return __make_iter(this->__end_); -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_iterator -vector<_Tp, _Allocator>::end() const _NOEXCEPT { - return __make_iter(this->__end_); -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::reference -vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT { - _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds"); - return this->__begin_[__n]; -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_reference -vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds"); - return this->__begin_[__n]; -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::at(size_type __n) { - if (__n >= size()) - this->__throw_out_of_range(); - return this->__begin_[__n]; -} - -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::const_reference -vector<_Tp, _Allocator>::at(size_type __n) const { - if (__n >= size()) - this->__throw_out_of_range(); - return this->__begin_[__n]; -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __n) { if (__n > capacity()) { @@ -1203,12 +1125,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline #endif } -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void vector<_Tp, _Allocator>::pop_back() { - _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector"); - this->__destruct_at_end(this->__end_ - 1); -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __position) { @@ -1263,7 +1179,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) } else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); - __v.push_back(__x); + __v.emplace_back(__x); __p = __swap_out_circular_buffer(__v, __p); } return __make_iter(__p); @@ -1283,7 +1199,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) { } else { allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); - __v.push_back(std::move(__x)); + __v.emplace_back(std::move(__x)); __p = __swap_out_circular_buffer(__v, __p); } return __make_iter(__p); @@ -1341,15 +1257,6 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_ } return __make_iter(__p); } -template -template ::value && - is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator -vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { - return __insert_with_sentinel(__position, __first, __last); -} template template @@ -1385,16 +1292,6 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu return begin() + __off; } -template -template ::value && - is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator -vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last) { - return __insert_with_size(__position, __first, __last, std::distance(__first, __last)); -} - template template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator diff --git a/libcxx/include/deque b/libcxx/include/deque index 11219d1a99244..0ded69cffdeab 100644 --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -1229,8 +1229,8 @@ private: clear(); shrink_to_fit(); } - __alloc() = __c.__alloc(); - __map_.__alloc() = __c.__map_.__alloc(); + __alloc() = __c.__alloc(); + __map_.__alloc_ = __c.__map_.__alloc_; } _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const deque&, false_type) {} @@ -1309,7 +1309,7 @@ deque<_Tp, _Allocator>::deque(const deque& __c) : __map_(__pointer_allocator(__alloc_traits::select_on_container_copy_construction(__c.__alloc()))), __start_(0), __size_(0), - __alloc_(__map_.__alloc()) { + __alloc_(__map_.__alloc_) { __annotate_new(0); __append(__c.begin(), __c.end()); } @@ -2041,39 +2041,39 @@ void deque<_Tp, _Allocator>::__add_front_capacity() { __start_ += __block_size; pointer __pt = __map_.back(); __map_.pop_back(); - __map_.push_front(__pt); + __map_.emplace_front(__pt); } // Else if __map_.size() < __map_.capacity() then we need to allocate 1 buffer else if (__map_.size() < __map_.capacity()) { // we can put the new buffer into the map, but don't shift things around // until all buffers are allocated. If we throw, we don't need to fix // anything up (any added buffers are undetectible) if (__map_.__front_spare() > 0) - __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_front(__alloc_traits::allocate(__a, __block_size)); else { - __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_back(__alloc_traits::allocate(__a, __block_size)); // Done allocating, reorder capacity pointer __pt = __map_.back(); __map_.pop_back(); - __map_.push_front(__pt); + __map_.emplace_front(__pt); } __start_ = __map_.size() == 1 ? __block_size / 2 : __start_ + __block_size; } // Else need to allocate 1 buffer, *and* we need to reallocate __map_. else { __split_buffer __buf( - std::max(2 * __map_.capacity(), 1), 0, __map_.__alloc()); + std::max(2 * __map_.capacity(), 1), 0, __map_.__alloc_); typedef __allocator_destructor<_Allocator> _Dp; unique_ptr __hold(__alloc_traits::allocate(__a, __block_size), _Dp(__a, __block_size)); - __buf.push_back(__hold.get()); + __buf.emplace_back(__hold.get()); __hold.release(); for (__map_pointer __i = __map_.begin(); __i != __map_.end(); ++__i) - __buf.push_back(*__i); + __buf.emplace_back(*__i); std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); - std::swap(__map_.__end_cap(), __buf.__end_cap()); + std::swap(__map_.__end_cap_, __buf.__end_cap_); __start_ = __map_.size() == 1 ? __block_size / 2 : __start_ + __block_size; } __annotate_whole_block(0, __asan_poison); @@ -2095,7 +2095,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { for (; __back_capacity > 0; --__back_capacity) { pointer __pt = __map_.back(); __map_.pop_back(); - __map_.push_front(__pt); + __map_.emplace_front(__pt); } } // Else if __nb <= __map_.capacity() - __map_.size() then we need to allocate __nb buffers @@ -2106,17 +2106,17 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { for (; __nb > 0; --__nb, __start_ += __block_size - (__map_.size() == 1)) { if (__map_.__front_spare() == 0) break; - __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_front(__alloc_traits::allocate(__a, __block_size)); __annotate_whole_block(0, __asan_poison); } for (; __nb > 0; --__nb, ++__back_capacity) - __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_back(__alloc_traits::allocate(__a, __block_size)); // Done allocating, reorder capacity __start_ += __back_capacity * __block_size; for (; __back_capacity > 0; --__back_capacity) { pointer __pt = __map_.back(); __map_.pop_back(); - __map_.push_front(__pt); + __map_.emplace_front(__pt); __annotate_whole_block(0, __asan_poison); } } @@ -2124,12 +2124,12 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { else { size_type __ds = (__nb + __back_capacity) * __block_size - __map_.empty(); __split_buffer __buf( - std::max(2 * __map_.capacity(), __nb + __map_.size()), 0, __map_.__alloc()); + std::max(2 * __map_.capacity(), __nb + __map_.size()), 0, __map_.__alloc_); #if _LIBCPP_HAS_EXCEPTIONS try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __nb > 0; --__nb) { - __buf.push_back(__alloc_traits::allocate(__a, __block_size)); + __buf.emplace_back(__alloc_traits::allocate(__a, __block_size)); // ASan: this is empty container, we have to poison whole block __annotate_poison_block(std::__to_address(__buf.back()), std::__to_address(__buf.back() + __block_size)); } @@ -2142,15 +2142,15 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { } #endif // _LIBCPP_HAS_EXCEPTIONS for (; __back_capacity > 0; --__back_capacity) { - __buf.push_back(__map_.back()); + __buf.emplace_back(__map_.back()); __map_.pop_back(); } for (__map_pointer __i = __map_.begin(); __i != __map_.end(); ++__i) - __buf.push_back(*__i); + __buf.emplace_back(*__i); std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); - std::swap(__map_.__end_cap(), __buf.__end_cap()); + std::swap(__map_.__end_cap_, __buf.__end_cap_); __start_ += __ds; } } @@ -2164,39 +2164,39 @@ void deque<_Tp, _Allocator>::__add_back_capacity() { __start_ -= __block_size; pointer __pt = __map_.front(); __map_.pop_front(); - __map_.push_back(__pt); + __map_.emplace_back(__pt); } // Else if __nb <= __map_.capacity() - __map_.size() then we need to allocate __nb buffers else if (__map_.size() < __map_.capacity()) { // we can put the new buffer into the map, but don't shift things around // until it is allocated. If we throw, we don't need to fix // anything up (any added buffers are undetectible) if (__map_.__back_spare() != 0) - __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_back(__alloc_traits::allocate(__a, __block_size)); else { - __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_front(__alloc_traits::allocate(__a, __block_size)); // Done allocating, reorder capacity pointer __pt = __map_.front(); __map_.pop_front(); - __map_.push_back(__pt); + __map_.emplace_back(__pt); } __annotate_whole_block(__map_.size() - 1, __asan_poison); } // Else need to allocate 1 buffer, *and* we need to reallocate __map_. else { __split_buffer __buf( - std::max(2 * __map_.capacity(), 1), __map_.size(), __map_.__alloc()); + std::max(2 * __map_.capacity(), 1), __map_.size(), __map_.__alloc_); typedef __allocator_destructor<_Allocator> _Dp; unique_ptr __hold(__alloc_traits::allocate(__a, __block_size), _Dp(__a, __block_size)); - __buf.push_back(__hold.get()); + __buf.emplace_back(__hold.get()); __hold.release(); for (__map_pointer __i = __map_.end(); __i != __map_.begin();) - __buf.push_front(*--__i); + __buf.emplace_front(*--__i); std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); - std::swap(__map_.__end_cap(), __buf.__end_cap()); + std::swap(__map_.__end_cap_, __buf.__end_cap_); __annotate_whole_block(__map_.size() - 1, __asan_poison); } } @@ -2217,7 +2217,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { for (; __front_capacity > 0; --__front_capacity) { pointer __pt = __map_.front(); __map_.pop_front(); - __map_.push_back(__pt); + __map_.emplace_back(__pt); } } // Else if __nb <= __map_.capacity() - __map_.size() then we need to allocate __nb buffers @@ -2228,11 +2228,11 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { for (; __nb > 0; --__nb) { if (__map_.__back_spare() == 0) break; - __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_back(__alloc_traits::allocate(__a, __block_size)); __annotate_whole_block(__map_.size() - 1, __asan_poison); } for (; __nb > 0; --__nb, ++__front_capacity, __start_ += __block_size - (__map_.size() == 1)) { - __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __map_.emplace_front(__alloc_traits::allocate(__a, __block_size)); __annotate_whole_block(0, __asan_poison); } // Done allocating, reorder capacity @@ -2240,7 +2240,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { for (; __front_capacity > 0; --__front_capacity) { pointer __pt = __map_.front(); __map_.pop_front(); - __map_.push_back(__pt); + __map_.emplace_back(__pt); } } // Else need to allocate __nb buffers, *and* we need to reallocate __map_. @@ -2249,12 +2249,12 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { __split_buffer __buf( std::max(2 * __map_.capacity(), __nb + __map_.size()), __map_.size() - __front_capacity, - __map_.__alloc()); + __map_.__alloc_); #if _LIBCPP_HAS_EXCEPTIONS try { #endif // _LIBCPP_HAS_EXCEPTIONS for (; __nb > 0; --__nb) { - __buf.push_back(__alloc_traits::allocate(__a, __block_size)); + __buf.emplace_back(__alloc_traits::allocate(__a, __block_size)); // ASan: this is an empty container, we have to poison the whole block __annotate_poison_block(std::__to_address(__buf.back()), std::__to_address(__buf.back() + __block_size)); } @@ -2267,15 +2267,15 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { } #endif // _LIBCPP_HAS_EXCEPTIONS for (; __front_capacity > 0; --__front_capacity) { - __buf.push_back(__map_.front()); + __buf.emplace_back(__map_.front()); __map_.pop_front(); } for (__map_pointer __i = __map_.end(); __i != __map_.begin();) - __buf.push_front(*--__i); + __buf.emplace_front(*--__i); std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); - std::swap(__map_.__end_cap(), __buf.__end_cap()); + std::swap(__map_.__end_cap_, __buf.__end_cap_); __start_ -= __ds; } } diff --git a/libcxx/include/new b/libcxx/include/new index 290ad9e97f8de..5318ce533ea92 100644 --- a/libcxx/include/new +++ b/libcxx/include/new @@ -90,8 +90,7 @@ void operator delete[](void* ptr, void*) noexcept; #include <__cstddef/size_t.h> #include <__exception/exception.h> #include <__type_traits/is_function.h> -#include <__type_traits/is_same.h> -#include <__type_traits/remove_cv.h> +#include <__type_traits/is_void.h> #include <__verbose_abort> #include @@ -342,7 +341,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __libcpp_deallocate_unsized(void* __ptr, size_ template [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __launder(_Tp* __p) _NOEXCEPT { static_assert(!(is_function<_Tp>::value), "can't launder functions"); - static_assert(!(is_same >::value), "can't launder cv-void"); + static_assert(!is_void<_Tp>::value, "can't launder cv-void"); return __builtin_launder(__p); } diff --git a/libcxx/include/optional b/libcxx/include/optional index b9dcf9053633f..7ad6a9e116941 100644 --- a/libcxx/include/optional +++ b/libcxx/include/optional @@ -207,6 +207,7 @@ namespace std { #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_object.h> #include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> #include <__type_traits/is_scalar.h> #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivially_assignable.h> @@ -215,6 +216,7 @@ namespace std { #include <__type_traits/is_trivially_relocatable.h> #include <__type_traits/negation.h> #include <__type_traits/remove_const.h> +#include <__type_traits/remove_cv.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/remove_reference.h> #include <__utility/declval.h> diff --git a/libcxx/include/string b/libcxx/include/string index 4b5017f5e7753..e4b2d7a8d964c 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1912,6 +1912,9 @@ private: #ifndef _LIBCPP_CXX03_LANG if constexpr (__libcpp_is_contiguous_iterator<_ForwardIter>::value && is_same>::value && is_same<_ForwardIter, _Sent>::value) { + _LIBCPP_ASSERT_INTERNAL( + !std::__is_overlapping_range(std::__to_address(__first), std::__to_address(__last), __dest), + "__copy_non_overlapping_range called with an overlapping range!"); traits_type::copy(__dest, std::__to_address(__first), __last - __first); return __dest + (__last - __first); } @@ -1966,9 +1969,12 @@ private: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_size(size_type __s) _NOEXCEPT { __rep_.__l.__size_ = __s; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_size() const _NOEXCEPT { + _LIBCPP_ASSERT_INTERNAL(__rep_.__l.__is_long_, "String has to be long when trying to get the long size"); return __rep_.__l.__size_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_size(size_type __s) _NOEXCEPT { if (__is_long()) __set_long_size(__s); @@ -1977,11 +1983,13 @@ private: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_long_cap(size_type __s) _NOEXCEPT { + _LIBCPP_ASSERT_INTERNAL(!__fits_in_sso(__s), "Long capacity should always be larger than the SSO"); __rep_.__l.__cap_ = __s / __endian_factor; __rep_.__l.__is_long_ = true; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_long_cap() const _NOEXCEPT { + _LIBCPP_ASSERT_INTERNAL(__rep_.__l.__is_long_, "String has to be long when trying to get the long capacity"); return __rep_.__l.__cap_ * __endian_factor; } @@ -1990,10 +1998,12 @@ private: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pointer __get_long_pointer() _NOEXCEPT { + _LIBCPP_ASSERT_INTERNAL(__rep_.__l.__is_long_, "String has to be long when trying to get the long pointer"); return _LIBCPP_ASAN_VOLATILE_WRAPPER(__rep_.__l.__data_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_pointer __get_long_pointer() const _NOEXCEPT { + _LIBCPP_ASSERT_INTERNAL(__rep_.__l.__is_long_, "String has to be long when trying to get the long pointer"); return _LIBCPP_ASAN_VOLATILE_WRAPPER(__rep_.__l.__data_); } @@ -2073,6 +2083,8 @@ private: size_type __guess = __align_it<__boundary>(__s + 1) - 1; if (__guess == __min_cap) __guess += __endian_factor; + + _LIBCPP_ASSERT_INTERNAL(__guess >= __s, "recommendation is below the requested size"); return __guess; } @@ -2137,6 +2149,7 @@ private: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_no_alias(const value_type* __s, size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __erase_to_end(size_type __pos) { + _LIBCPP_ASSERT_INTERNAL(__pos <= capacity(), "Trying to erase at position outside the strings capacity!"); __null_terminate_at(std::__to_address(__get_pointer()), __pos); } @@ -3335,12 +3348,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::re if (__requested_capacity <= capacity()) return; - size_type __target_capacity = std::max(__requested_capacity, size()); - __target_capacity = __recommend(__target_capacity); - if (__target_capacity == capacity()) - return; - - __shrink_or_extend(__target_capacity); + __shrink_or_extend(__recommend(__requested_capacity)); } template diff --git a/libcxx/include/variant b/libcxx/include/variant index ee80fb0b5ab5b..6e752556a888d 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -245,6 +245,7 @@ namespace std { #include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivially_assignable.h> #include <__type_traits/is_trivially_constructible.h> diff --git a/libcxx/include/version b/libcxx/include/version index cb75f3b2db681..571b6e39381d1 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -443,7 +443,7 @@ __cpp_lib_void_t 201411L # undef __cpp_lib_shared_ptr_arrays # define __cpp_lib_shared_ptr_arrays 201707L # define __cpp_lib_shift 201806L -// # define __cpp_lib_smart_ptr_for_overwrite 202002L +# define __cpp_lib_smart_ptr_for_overwrite 202002L # define __cpp_lib_source_location 201907L # define __cpp_lib_span 202002L # define __cpp_lib_ssize 201902L diff --git a/libcxx/test/benchmarks/CartesianBenchmarks.h b/libcxx/test/benchmarks/CartesianBenchmarks.h index eca4e15cd009b..c712230843ebf 100644 --- a/libcxx/test/benchmarks/CartesianBenchmarks.h +++ b/libcxx/test/benchmarks/CartesianBenchmarks.h @@ -27,11 +27,11 @@ constexpr auto makeEnumValueTuple(std::index_sequence) { } template -static auto skip(const B& Bench, int) -> decltype(Bench.skip()) { +auto skip(const B& Bench, int) -> decltype(Bench.skip()) { return Bench.skip(); } template -static auto skip(const B& Bench, char) { +auto skip(const B&, char) { return false; } @@ -51,7 +51,7 @@ void makeBenchmarkFromValues(const std::vector >& A) { } template