diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-03-31 20:49:22 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-03-31 20:49:22 +0000 |
commit | 11ee15ea4ee1ea5555f8d7ba1ec5ffe956df2a8c (patch) | |
tree | df70bd53f42f50adc3a1fa830f6aec7bfa533c06 | |
parent | 11edbfca22fe6e8280caeb77832f4dfbb68ed274 (diff) |
Vendor import of llvm-project branch release/16.x llvmorg-16.0.0-0-g08d094a0e457 (aka 16.0.0 release).vendor/llvm-project/llvmorg-16.0.0-0-g08d094a0e457
120 files changed, 1808 insertions, 1271 deletions
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 23752823e88f..652c15afcce8 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4559,6 +4559,8 @@ def mnvs : Flag<["-"], "mnvs">, Group<m_hexagon_Features_Group>, Flags<[CC1Option]>, HelpText<"Enable generation of new-value stores">; def mno_nvs : Flag<["-"], "mno-nvs">, Group<m_hexagon_Features_Group>, Flags<[CC1Option]>, HelpText<"Disable generation of new-value stores">; +def mcabac: Flag<["-"], "mcabac">, Group<m_hexagon_Features_Group>, + HelpText<"Enable CABAC instructions">; // SPARC feature flags def mfpu : Flag<["-"], "mfpu">, Group<m_sparc_Features_Group>; diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index f383a2e5b530..322626802eab 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -193,11 +193,6 @@ class Preprocessor { LangOptions::FPEvalMethodKind CurrentFPEvalMethod = LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine; - // Keeps the value of the last evaluation method before a - // `pragma float_control (precise,off) is applied. - LangOptions::FPEvalMethodKind LastFPEvalMethod = - LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine; - // The most recent pragma location where the floating point evaluation // method was modified. This is used to determine whether the // 'pragma clang fp eval_method' was used whithin the current scope. @@ -313,6 +308,9 @@ private: /// The import path for named module that we're currently processing. SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> NamedModuleImportPath; + /// Whether the import is an `@import` or a standard c++ modules import. + bool IsAtImport = false; + /// Whether the last token we lexed was an '@'. bool LastTokenWasAt = false; @@ -456,6 +454,144 @@ private: TrackGMF TrackGMFState = TrackGMF::BeforeGMFIntroducer; + /// Track the status of the c++20 module decl. + /// + /// module-declaration: + /// 'export'[opt] 'module' module-name module-partition[opt] + /// attribute-specifier-seq[opt] ';' + /// + /// module-name: + /// module-name-qualifier[opt] identifier + /// + /// module-partition: + /// ':' module-name-qualifier[opt] identifier + /// + /// module-name-qualifier: + /// identifier '.' + /// module-name-qualifier identifier '.' + /// + /// Transition state: + /// + /// NotAModuleDecl --- export ---> FoundExport + /// NotAModuleDecl --- module ---> ImplementationCandidate + /// FoundExport --- module ---> InterfaceCandidate + /// ImplementationCandidate --- Identifier ---> ImplementationCandidate + /// ImplementationCandidate --- period ---> ImplementationCandidate + /// ImplementationCandidate --- colon ---> ImplementationCandidate + /// InterfaceCandidate --- Identifier ---> InterfaceCandidate + /// InterfaceCandidate --- period ---> InterfaceCandidate + /// InterfaceCandidate --- colon ---> InterfaceCandidate + /// ImplementationCandidate --- Semi ---> NamedModuleImplementation + /// NamedModuleInterface --- Semi ---> NamedModuleInterface + /// NamedModuleImplementation --- Anything ---> NamedModuleImplementation + /// NamedModuleInterface --- Anything ---> NamedModuleInterface + /// + /// FIXME: We haven't handle attribute-specifier-seq here. It may not be bad + /// soon since we don't support any module attributes yet. + class ModuleDeclSeq { + enum ModuleDeclState : int { + NotAModuleDecl, + FoundExport, + InterfaceCandidate, + ImplementationCandidate, + NamedModuleInterface, + NamedModuleImplementation, + }; + + public: + ModuleDeclSeq() : State(NotAModuleDecl) {} + + void handleExport() { + if (State == NotAModuleDecl) + State = FoundExport; + else if (!isNamedModule()) + reset(); + } + + void handleModule() { + if (State == FoundExport) + State = InterfaceCandidate; + else if (State == NotAModuleDecl) + State = ImplementationCandidate; + else if (!isNamedModule()) + reset(); + } + + void handleIdentifier(IdentifierInfo *Identifier) { + if (isModuleCandidate() && Identifier) + Name += Identifier->getName().str(); + else if (!isNamedModule()) + reset(); + } + + void handleColon() { + if (isModuleCandidate()) + Name += ":"; + else if (!isNamedModule()) + reset(); + } + + void handlePeriod() { + if (isModuleCandidate()) + Name += "."; + else if (!isNamedModule()) + reset(); + } + + void handleSemi() { + if (!Name.empty() && isModuleCandidate()) { + if (State == InterfaceCandidate) + State = NamedModuleInterface; + else if (State == ImplementationCandidate) + State = NamedModuleImplementation; + else + llvm_unreachable("Unimaged ModuleDeclState."); + } else if (!isNamedModule()) + reset(); + } + + void handleMisc() { + if (!isNamedModule()) + reset(); + } + + bool isModuleCandidate() const { + return State == InterfaceCandidate || State == ImplementationCandidate; + } + + bool isNamedModule() const { + return State == NamedModuleInterface || + State == NamedModuleImplementation; + } + + bool isNamedInterface() const { return State == NamedModuleInterface; } + + bool isImplementationUnit() const { + return State == NamedModuleImplementation && !getName().contains(':'); + } + + StringRef getName() const { + assert(isNamedModule() && "Can't get name from a non named module"); + return Name; + } + + StringRef getPrimaryName() const { + assert(isNamedModule() && "Can't get name from a non named module"); + return getName().split(':').first; + } + + void reset() { + Name.clear(); + State = NotAModuleDecl; + } + + private: + ModuleDeclState State; + std::string Name; + }; + + ModuleDeclSeq ModuleDeclState; + /// Whether the module import expects an identifier next. Otherwise, /// it expects a '.' or ';'. bool ModuleImportExpectsIdentifier = false; @@ -2194,14 +2330,6 @@ public: return LastFPEvalPragmaLocation; } - LangOptions::FPEvalMethodKind getLastFPEvalMethod() const { - return LastFPEvalMethod; - } - - void setLastFPEvalMethod(LangOptions::FPEvalMethodKind Val) { - LastFPEvalMethod = Val; - } - void setCurrentFPEvalMethod(SourceLocation PragmaLoc, LangOptions::FPEvalMethodKind Val) { assert(Val != LangOptions::FEM_UnsetOnCommandLine && @@ -2225,6 +2353,36 @@ public: /// Retrieves the module whose implementation we're current compiling, if any. Module *getCurrentModuleImplementation(); + /// If we are preprocessing a named module. + bool isInNamedModule() const { return ModuleDeclState.isNamedModule(); } + + /// If we are proprocessing a named interface unit. + /// Note that a module implementation partition is not considered as an + /// named interface unit here although it is importable + /// to ease the parsing. + bool isInNamedInterfaceUnit() const { + return ModuleDeclState.isNamedInterface(); + } + + /// Get the named module name we're preprocessing. + /// Requires we're preprocessing a named module. + StringRef getNamedModuleName() const { return ModuleDeclState.getName(); } + + /// If we are implementing an implementation module unit. + /// Note that the module implementation partition is not considered as an + /// implementation unit. + bool isInImplementationUnit() const { + return ModuleDeclState.isImplementationUnit(); + } + + /// If we're importing a standard C++20 Named Modules. + bool isInImportingCXXNamedModules() const { + // NamedModuleImportPath will be non-empty only if we're importing + // Standard C++ named modules. + return !NamedModuleImportPath.empty() && getLangOpts().CPlusPlusModules && + !IsAtImport; + } + /// Allocate a new MacroInfo object with the provided SourceLocation. MacroInfo *AllocateMacroInfo(SourceLocation L); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 66b018d8fba1..d40dacb5aa0f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -238,11 +238,9 @@ namespace threadSafety { // FIXME: No way to easily map from TemplateTypeParmTypes to // TemplateTypeParmDecls, so we have this horrible PointerUnion. -using UnexpandedParameterPack = std::pair< - llvm::PointerUnion< - const TemplateTypeParmType *, const SubstTemplateTypeParmPackType *, - const SubstNonTypeTemplateParmPackExpr *, const NamedDecl *>, - SourceLocation>; +typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType *, NamedDecl *>, + SourceLocation> + UnexpandedParameterPack; /// Describes whether we've seen any nullability information for the given /// file. diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h index 4eca50919dc7..842eec099540 100644 --- a/clang/include/clang/Sema/SemaInternal.h +++ b/clang/include/clang/Sema/SemaInternal.h @@ -62,7 +62,7 @@ inline InheritableAttr *getDLLAttr(Decl *D) { } /// Retrieve the depth and index of a template parameter. -inline std::pair<unsigned, unsigned> getDepthAndIndex(const NamedDecl *ND) { +inline std::pair<unsigned, unsigned> getDepthAndIndex(NamedDecl *ND) { if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) return std::make_pair(TTP->getDepth(), TTP->getIndex()); @@ -79,7 +79,7 @@ getDepthAndIndex(UnexpandedParameterPack UPP) { if (const auto *TTP = UPP.first.dyn_cast<const TemplateTypeParmType *>()) return std::make_pair(TTP->getDepth(), TTP->getIndex()); - return getDepthAndIndex(UPP.first.get<const NamedDecl *>()); + return getDepthAndIndex(UPP.first.get<NamedDecl *>()); } class TypoCorrectionConsumer : public VisibleDeclConsumer { diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h index ea05b9f8ee3f..fcc9c02999b3 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h @@ -454,7 +454,9 @@ public: llvm::SMTExprRef OperandExp = getSymExpr(Solver, Ctx, USE->getOperand(), &OperandTy, hasComparison); llvm::SMTExprRef UnaryExp = - fromUnOp(Solver, USE->getOpcode(), OperandExp); + OperandTy->isRealFloatingType() + ? fromFloatUnOp(Solver, USE->getOpcode(), OperandExp) + : fromUnOp(Solver, USE->getOpcode(), OperandExp); // Currently, without the `support-symbolic-integer-casts=true` option, // we do not emit `SymbolCast`s for implicit casts. diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h index a8cb15847b78..109cf049a652 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h @@ -35,9 +35,13 @@ enum class ScanningOutputFormat { /// intermodule dependency information. Make, - /// This outputs the full module dependency graph suitable for use for + /// This outputs the full clang module dependency graph suitable for use for /// explicitly building modules. Full, + + /// This outputs the dependency graph for standard c++ modules in P1689R5 + /// format. + P1689, }; /// The dependency scanning service contains shared configuration and state that diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h index 6af878dbda95..b1a4df141edc 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h @@ -67,6 +67,12 @@ struct FullDependenciesResult { std::vector<ModuleDeps> DiscoveredModules; }; +struct P1689Rule { + std::string PrimaryOutput; + std::optional<P1689ModuleInfo> Provides; + std::vector<P1689ModuleInfo> Requires; +}; + /// The high-level implementation of the dependency discovery tool that runs on /// an individual worker thread. class DependencyScanningTool { @@ -87,9 +93,24 @@ public: getDependencyFile(const std::vector<std::string> &CommandLine, StringRef CWD, std::optional<StringRef> ModuleName = std::nullopt); - /// Collect the full module dependency graph for the input, ignoring any - /// modules which have already been seen. If \p ModuleName isn't empty, this - /// function returns the full dependency information of module \p ModuleName. + /// Collect the module dependency in P1689 format for C++20 named modules. + /// + /// \param MakeformatOutput The output parameter for dependency information + /// in make format if the command line requires to generate make-format + /// dependency information by `-MD -MF <dep_file>`. + /// + /// \param MakeformatOutputPath The output parameter for the path to + /// \param MakeformatOutput. + /// + /// \returns A \c StringError with the diagnostic output if clang errors + /// occurred, P1689 dependency format rules otherwise. + llvm::Expected<P1689Rule> + getP1689ModuleDependencyFile( + const clang::tooling::CompileCommand &Command, StringRef CWD, + std::string &MakeformatOutput, std::string &MakeformatOutputPath); + + /// Given a Clang driver command-line for a translation unit, gather the + /// modular dependencies and return the information needed for explicit build. /// /// \param AlreadySeen This stores modules which have previously been /// reported. Use the same instance for all calls to this diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h index 458c4d936c83..6edf2cbe6b53 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h @@ -41,7 +41,11 @@ class DependencyConsumer { public: virtual ~DependencyConsumer() {} - virtual void handleBuildCommand(Command Cmd) = 0; + virtual void handleProvidedAndRequiredStdCXXModules( + std::optional<P1689ModuleInfo> Provided, + std::vector<P1689ModuleInfo> Requires) {} + + virtual void handleBuildCommand(Command Cmd) {} virtual void handleDependencyOutputOpts(const DependencyOutputOptions &Opts) = 0; diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h index 6e4cec25961d..bce3e066372f 100644 --- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -62,6 +62,27 @@ struct ModuleID { } }; +/// P1689ModuleInfo - Represents the needed information of standard C++20 +/// modules for P1689 format. +struct P1689ModuleInfo { + /// The name of the module. This may include `:` for partitions. + std::string ModuleName; + + /// Optional. The source path to the module. + std::string SourcePath; + + /// If this module is a standard c++ interface unit. + bool IsStdCXXModuleInterface = true; + + enum class ModuleType { + NamedCXXModule + // To be supported + // AngleHeaderUnit, + // QuoteHeaderUnit + }; + ModuleType Type = ModuleType::NamedCXXModule; +}; + /// An output from a module compilation, such as the path of the module file. enum class ModuleOutputKind { /// The module file (.pcm). Required. @@ -181,7 +202,7 @@ public: ModuleDepCollector(std::unique_ptr<DependencyOutputOptions> Opts, CompilerInstance &ScanInstance, DependencyConsumer &C, CompilerInvocation OriginalCI, bool OptimizeArgs, - bool EagerLoadModules); + bool EagerLoadModules, bool IsStdModuleP1689Format); void attachToPreprocessor(Preprocessor &PP) override; void attachToASTReader(ASTReader &R) override; @@ -219,6 +240,12 @@ private: bool OptimizeArgs; /// Whether to set up command-lines to load PCM files eagerly. bool EagerLoadModules; + /// If we're generating dependency output in P1689 format + /// for standard C++ modules. + bool IsStdModuleP1689Format; + + std::optional<P1689ModuleInfo> ProvidedStdCXXModule; + std::vector<P1689ModuleInfo> RequiredStdCXXModules; /// Checks whether the module is known as being prebuilt. bool isPrebuiltModule(const Module *M); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 912a210fd254..9c56ab12529c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -10913,7 +10913,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, for (unsigned I = OldElts; I < N; ++I) Value->getArrayInitializedElt(I) = Filler; - if (HasTrivialConstructor && N == FinalSize) { + if (HasTrivialConstructor && N == FinalSize && FinalSize != 1) { // If we have a trivial constructor, only evaluate it once and copy // the result into all the array elements. APValue &FirstResult = Value->getArrayInitializedElt(0); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index a713d6e3bd03..54e62a1939f7 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2487,11 +2487,13 @@ bool QualType::isTrivialType(const ASTContext &Context) const { return true; if (const auto *RT = CanonicalType->getAs<RecordType>()) { if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - // C++11 [class]p6: - // A trivial class is a class that has a default constructor, - // has no non-trivial default constructors, and is trivially - // copyable. - return ClassDecl->hasDefaultConstructor() && + // C++20 [class]p6: + // A trivial class is a class that is trivially copyable, and + // has one or more eligible default constructors such that each is + // trivial. + // FIXME: We should merge this definition of triviality into + // CXXRecordDecl::isTrivial. Currently it computes the wrong thing. + return ClassDecl->hasTrivialDefaultConstructor() && !ClassDecl->hasNonTrivialDefaultConstructor() && ClassDecl->isTriviallyCopyable(); } diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index cc185fdadfcb..c8197154fff7 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -428,7 +428,10 @@ public: ABI = "elfv2"; } else { DataLayout = "E-m:e-i64:64-n32:64"; - ABI = "elfv1"; + if (Triple.isPPC64ELFv2ABI()) + ABI = "elfv2"; + else + ABI = "elfv1"; } if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) { diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index a600768b2074..78646996eac2 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -379,9 +379,8 @@ public: /// zero if no specific type is applicable, e.g. if the ABI expects the "this" /// parameter to point to some artificial offset in a complete object due to /// vbases being reordered. - virtual const CXXRecordDecl * - getThisArgumentTypeForMethod(const CXXMethodDecl *MD) { - return MD->getParent(); + virtual const CXXRecordDecl *getThisArgumentTypeForMethod(GlobalDecl GD) { + return cast<CXXMethodDecl>(GD.getDecl())->getParent(); } /// Perform ABI-specific "this" argument adjustment required prior to diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index dfa552161d7c..ee5b76ab2120 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -322,7 +322,9 @@ CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) { SmallVector<CanQualType, 16> argTypes; SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; - argTypes.push_back(DeriveThisType(MD->getParent(), MD)); + + const CXXRecordDecl *ThisType = TheCXXABI.getThisArgumentTypeForMethod(GD); + argTypes.push_back(DeriveThisType(ThisType, MD)); bool PassParams = true; diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index b889a4e05ee1..a9f3434589f2 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -33,10 +33,12 @@ struct MemberCallInfo { } static MemberCallInfo -commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD, +commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE, CallArgList &Args, CallArgList *RtlArgs) { + auto *MD = cast<CXXMethodDecl>(GD.getDecl()); + assert(CE == nullptr || isa<CXXMemberCallExpr>(CE) || isa<CXXOperatorCallExpr>(CE)); assert(MD->isInstance() && @@ -44,7 +46,7 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD, // Push the this ptr. const CXXRecordDecl *RD = - CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(MD); + CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(GD); Args.add(RValue::get(This), CGF.getTypes().DeriveThisType(RD, MD)); // If there is an implicit parameter (e.g. VTT), emit it. @@ -110,7 +112,7 @@ RValue CodeGenFunction::EmitCXXDestructorCall( } CallArgList Args; - commonEmitCXXMemberOrOperatorCall(*this, DtorDecl, This, ImplicitParam, + commonEmitCXXMemberOrOperatorCall(*this, Dtor, This, ImplicitParam, ImplicitParamTy, CE, Args, nullptr); return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee, ReturnValueSlot(), Args, nullptr, CE && CE == MustTailCall, @@ -285,7 +287,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( assert(ReturnValue.isNull() && "Constructor shouldn't have return value"); CallArgList Args; commonEmitCXXMemberOrOperatorCall( - *this, Ctor, This.getPointer(*this), /*ImplicitParam=*/nullptr, + *this, {Ctor, Ctor_Complete}, This.getPointer(*this), + /*ImplicitParam=*/nullptr, /*ImplicitParamTy=*/QualType(), CE, Args, nullptr); EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false, diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index ae785cce09f9..52d442cc587f 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -235,11 +235,24 @@ public: void EmitCXXDestructors(const CXXDestructorDecl *D) override; - const CXXRecordDecl * - getThisArgumentTypeForMethod(const CXXMethodDecl *MD) override { - if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) { + const CXXRecordDecl *getThisArgumentTypeForMethod(GlobalDecl GD) override { + auto *MD = cast<CXXMethodDecl>(GD.getDecl()); + + if (MD->isVirtual()) { + GlobalDecl LookupGD = GD; + if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) { + // Complete dtors take a pointer to the complete object, + // thus don't need adjustment. + if (GD.getDtorType() == Dtor_Complete) + return MD->getParent(); + + // There's only Dtor_Deleting in vftable but it shares the this + // adjustment with the base one, so look up the deleting one instead. + LookupGD = GlobalDecl(DD, Dtor_Deleting); + } MethodVFTableLocation ML = - CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD); + CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD); + // The vbases might be ordered differently in the final overrider object // and the complete object, so the "this" argument may sometimes point to // memory that has no particular type (e.g. past the complete object). diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index a9119abad81d..9e2d7a85d100 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -2381,9 +2381,7 @@ class X86_64ABIInfo : public ABIInfo { return false; const llvm::Triple &Triple = getTarget().getTriple(); - if (Triple.isOSDarwin() || Triple.isPS()) - return false; - if (Triple.isOSFreeBSD() && Triple.getOSMajorVersion() >= 10) + if (Triple.isOSDarwin() || Triple.isPS() || Triple.isOSFreeBSD()) return false; return true; } diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 661d9977fbc5..a268f2fa8fc5 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1873,14 +1873,12 @@ int Driver::ExecuteCompilation( C.CleanupFileMap(C.getFailureResultFiles(), JA, true); } -#if LLVM_ON_UNIX - // llvm/lib/Support/Unix/Signals.inc will exit with a special return code + // llvm/lib/Support/*/Signals.inc will exit with a special return code // for SIGPIPE. Do not print diagnostics for this case. if (CommandRes == EX_IOERR) { Res = CommandRes; continue; } -#endif // Print extra information about abnormal failures, if possible. // diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 52bee6a755ff..068a34a54a92 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/SpecialCaseList.h" #include "llvm/Support/TargetParser.h" #include "llvm/Support/VirtualFileSystem.h" +#include "llvm/TargetParser/RISCVTargetParser.h" #include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h" #include <memory> @@ -545,7 +546,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, if ((Kinds & SanitizerKind::ShadowCallStack) && ((TC.getTriple().isAArch64() && !llvm::AArch64::isX18ReservedByDefault(TC.getTriple())) || - TC.getTriple().isRISCV()) && + (TC.getTriple().isRISCV() && + !llvm::RISCV::isX18ReservedByDefault(TC.getTriple()))) && !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) { D.Diag(diag::err_drv_argument_only_allowed_with) << lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack) diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/clang/lib/Driver/ToolChains/Arch/PPC.cpp index 6ec736bc701b..e3c025fb2468 100644 --- a/clang/lib/Driver/ToolChains/Arch/PPC.cpp +++ b/clang/lib/Driver/ToolChains/Arch/PPC.cpp @@ -34,53 +34,60 @@ static std::string getPPCGenericTargetCPU(const llvm::Triple &T) { return "ppc"; } -/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting. -std::string ppc::getPPCTargetCPU(const ArgList &Args, const llvm::Triple &T) { - if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { - StringRef CPUName = A->getValue(); - - // Clang/LLVM does not actually support code generation - // for the 405 CPU. However, there are uses of this CPU ID - // in projects that previously used GCC and rely on Clang - // accepting it. Clang has always ignored it and passed the - // generic CPU ID to the back end. - if (CPUName == "generic" || CPUName == "405") +static std::string normalizeCPUName(StringRef CPUName, const llvm::Triple &T) { + // Clang/LLVM does not actually support code generation + // for the 405 CPU. However, there are uses of this CPU ID + // in projects that previously used GCC and rely on Clang + // accepting it. Clang has always ignored it and passed the + // generic CPU ID to the back end. + if (CPUName == "generic" || CPUName == "405") + return getPPCGenericTargetCPU(T); + + if (CPUName == "native") { + std::string CPU = std::string(llvm::sys::getHostCPUName()); + if (!CPU.empty() && CPU != "generic") + return CPU; + else return getPPCGenericTargetCPU(T); + } - if (CPUName == "native") { - std::string CPU = std::string(llvm::sys::getHostCPUName()); - if (!CPU.empty() && CPU != "generic") - return CPU; - else - return getPPCGenericTargetCPU(T); - } + return llvm::StringSwitch<const char *>(CPUName) + .Case("common", "generic") + .Case("440fp", "440") + .Case("630", "pwr3") + .Case("G3", "g3") + .Case("G4", "g4") + .Case("G4+", "g4+") + .Case("8548", "e500") + .Case("G5", "g5") + .Case("power3", "pwr3") + .Case("power4", "pwr4") + .Case("power5", "pwr5") + .Case("power5x", "pwr5x") + .Case("power6", "pwr6") + .Case("power6x", "pwr6x") + .Case("power7", "pwr7") + .Case("power8", "pwr8") + .Case("power9", "pwr9") + .Case("power10", "pwr10") + .Case("future", "future") + .Case("powerpc", "ppc") + .Case("powerpc64", "ppc64") + .Case("powerpc64le", "ppc64le") + .Default(CPUName.data()); +} - return llvm::StringSwitch<const char *>(CPUName) - .Case("common", "generic") - .Case("440fp", "440") - .Case("630", "pwr3") - .Case("G3", "g3") - .Case("G4", "g4") - .Case("G4+", "g4+") - .Case("8548", "e500") - .Case("G5", "g5") - .Case("power3", "pwr3") - .Case("power4", "pwr4") - .Case("power5", "pwr5") - .Case("power5x", "pwr5x") - .Case("power6", "pwr6") - .Case("power6x", "pwr6x") - .Case("power7", "pwr7") - .Case("power8", "pwr8") - .Case("power9", "pwr9") - .Case("power10", "pwr10") - .Case("future", "future") - .Case("powerpc", "ppc") - .Case("powerpc64", "ppc64") - .Case("powerpc64le", "ppc64le") - .Default(CPUName.data()); - } +/// Get the (LLVM) name of the PowerPC cpu we are tuning for. +std::string ppc::getPPCTuneCPU(const ArgList &Args, const llvm::Triple &T) { + if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) + return normalizeCPUName(A->getValue(), T); + return getPPCGenericTargetCPU(T); +} +/// Get the (LLVM) name of the PowerPC cpu we are targeting. +std::string ppc::getPPCTargetCPU(const ArgList &Args, const llvm::Triple &T) { + if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) + return normalizeCPUName(A->getValue(), T); return getPPCGenericTargetCPU(T); } diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.h b/clang/lib/Driver/ToolChains/Arch/PPC.h index cd2b47d392b6..97ac45083852 100644 --- a/clang/lib/Driver/ToolChains/Arch/PPC.h +++ b/clang/lib/Driver/ToolChains/Arch/PPC.h @@ -37,6 +37,8 @@ FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args); std::string getPPCTargetCPU(const llvm::opt::ArgList &Args, const llvm::Triple &T); +std::string getPPCTuneCPU(const llvm::opt::ArgList &Args, + const llvm::Triple &T); const char *getPPCAsmModeForCPU(StringRef Name); ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3d40e19c83a5..ec6860113b7e 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1989,22 +1989,19 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, void Clang::AddPPCTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + const llvm::Triple &T = getToolChain().getTriple(); if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) { CmdArgs.push_back("-tune-cpu"); - if (strcmp(A->getValue(), "native") == 0) - CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName())); - else - CmdArgs.push_back(A->getValue()); + std::string CPU = ppc::getPPCTuneCPU(Args, T); + CmdArgs.push_back(Args.MakeArgString(CPU)); } // Select the ABI to use. const char *ABIName = nullptr; - const llvm::Triple &T = getToolChain().getTriple(); if (T.isOSBinFormatELF()) { switch (getToolChain().getArch()) { case llvm::Triple::ppc64: { - if ((T.isOSFreeBSD() && T.getOSMajorVersion() >= 13) || - T.isOSOpenBSD() || T.isMusl()) + if (T.isPPC64ELFv2ABI()) ABIName = "elfv2"; else ABIName = "elfv1"; diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 9a231c06a074..aa125bb308e8 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -446,13 +446,8 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, std::string OutputFileName = TC.getInputFilename(Output); // If we are invoking `nvlink` internally we need to output a `.cubin` file. - // Checking if the output is a temporary is the cleanest way to determine - // this. Putting this logic in `getInputFilename` isn't an option because it - // relies on the compilation. // FIXME: This should hopefully be removed if NVIDIA updates their tooling. - if (Output.isFilename() && - llvm::find(C.getTempFiles(), Output.getFilename()) != - C.getTempFiles().end()) { + if (!C.getInputArgs().getLastArg(options::OPT_c)) { SmallString<256> Filename(Output.getFilename()); llvm::sys::path::replace_extension(Filename, "cubin"); OutputFileName = Filename.str(); diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp index 64935227b07e..9a5af638c399 100644 --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -176,10 +176,8 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("/libexec/ld-elf.so.1"); } const llvm::Triple &T = ToolChain.getTriple(); - if (T.getOSMajorVersion() >= 9) { - if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || T.isX86()) - CmdArgs.push_back("--hash-style=both"); - } + if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || T.isX86()) + CmdArgs.push_back("--hash-style=both"); CmdArgs.push_back("--enable-new-dtags"); } @@ -396,17 +394,11 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple, getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib")); } -ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const { - unsigned Major = getTriple().getOSMajorVersion(); - if (Major >= 10 || Major == 0) - return ToolChain::CST_Libcxx; - return ToolChain::CST_Libstdcxx; -} - unsigned FreeBSD::GetDefaultDwarfVersion() const { - if (getTriple().getOSMajorVersion() < 12) - return 2; - return 4; + unsigned Major = getTriple().getOSMajorVersion(); + if (Major >= 12 || Major == 0) + return 4; + return 2; } void FreeBSD::AddClangSystemIncludeArgs( @@ -449,30 +441,14 @@ void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, concat(getDriver().SysRoot, "/usr/include/c++/v1")); } -void FreeBSD::addLibStdCxxIncludePaths( - const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const { - addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/usr/include/c++/4.2"), - "", "", DriverArgs, CC1Args); -} - void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - CXXStdlibType Type = GetCXXStdlibType(Args); unsigned Major = getTriple().getOSMajorVersion(); bool Profiling = Args.hasArg(options::OPT_pg) && Major != 0 && Major < 14; - switch (Type) { - case ToolChain::CST_Libcxx: - CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++"); - if (Args.hasArg(options::OPT_fexperimental_library)) - CmdArgs.push_back("-lc++experimental"); - break; - - case ToolChain::CST_Libstdcxx: - CmdArgs.push_back(Profiling ? "-lstdc++_p" : "-lstdc++"); - break; - } + CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++"); + if (Args.hasArg(options::OPT_fexperimental_library)) + CmdArgs.push_back("-lc++experimental"); } void FreeBSD::AddCudaIncludeArgs(const ArgList &DriverArgs, @@ -550,8 +526,9 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const { void FreeBSD::addClangTargetOptions(const ArgList &DriverArgs, ArgStringList &CC1Args, Action::OffloadKind) const { + unsigned Major = getTriple().getOSMajorVersion(); if (!DriverArgs.hasFlag(options::OPT_fuse_init_array, options::OPT_fno_use_init_array, - getTriple().getOSMajorVersion() >= 12)) + (Major >= 12 || Major == 0))) CC1Args.push_back("-fno-use-init-array"); } diff --git a/clang/lib/Driver/ToolChains/FreeBSD.h b/clang/lib/Driver/ToolChains/FreeBSD.h index 18832dad9884..9b24ef1a1e1c 100644 --- a/clang/lib/Driver/ToolChains/FreeBSD.h +++ b/clang/lib/Driver/ToolChains/FreeBSD.h @@ -61,12 +61,16 @@ public: void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; - CXXStdlibType GetDefaultCXXStdlibType() const override; + + RuntimeLibType GetDefaultRuntimeLibType() const override { + return ToolChain::RLT_CompilerRT; + } + CXXStdlibType GetDefaultCXXStdlibType() const override { + return ToolChain::CST_Libcxx; + } + void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; - void - addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const override; void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp index 9bdc3a791779..ea6d7d697770 100644 --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -447,13 +447,13 @@ SanitizerMask Fuchsia::getDefaultSanitizers() const { SanitizerMask Res; switch (getTriple().getArch()) { case llvm::Triple::aarch64: + case llvm::Triple::riscv64: Res |= SanitizerKind::ShadowCallStack; break; case llvm::Triple::x86_64: Res |= SanitizerKind::SafeStack; break; default: - // TODO: Enable SafeStack on RISC-V once tested. break; } return Res; diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp index ef07ab06760b..05e37c34a8a0 100644 --- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp +++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp @@ -132,8 +132,11 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env, continue; if (Start > 0) Location = Location.getLocWithOffset(Start); - cantFail(Result.add(tooling::Replacement(SourceMgr, Location, Length, - format(Text, DigitsPerGroup)))); + if (const auto &Formatted = format(Text, DigitsPerGroup); + Formatted != Text) { + cantFail(Result.add( + tooling::Replacement(SourceMgr, Location, Length, Formatted))); + } } return {Result, 0}; diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp index cef8b36ff758..609b412380f8 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -280,8 +280,11 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( // The case `const Foo &&` -> `Foo const &&` // The case `const std::Foo &&` -> `std::Foo const &&` // The case `const std::Foo<T> &&` -> `std::Foo<T> const &&` - while (Next && Next->isOneOf(tok::identifier, tok::coloncolon)) + // However, `const Bar::*` remains the same. + while (Next && Next->isOneOf(tok::identifier, tok::coloncolon) && + !Next->startsSequence(tok::coloncolon, tok::star)) { Next = Next->Next; + } if (Next && Next->is(TT_TemplateOpener)) { Next = Next->MatchingParen; // Move to the end of any template class members e.g. diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 3e58b6f90559..7e3957e62d3a 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -3849,13 +3849,13 @@ void UnwrappedLineParser::parseJavaEnumBody() { void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { const FormatToken &InitialToken = *FormatTok; nextToken(); + handleAttributes(); // The actual identifier can be a nested name specifier, and in macros // it is often token-pasted. - // An [[attribute]] can be before the identifier. while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash, tok::kw___attribute, tok::kw___declspec, - tok::kw_alignas, tok::l_square, tok::r_square) || + tok::kw_alignas) || ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) && FormatTok->isOneOf(tok::period, tok::comma))) { if (Style.isJavaScript() && @@ -3873,15 +3873,10 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) { FormatTok->is(tok::identifier) && FormatTok->TokenText != FormatTok->TokenText.upper(); nextToken(); - // We can have macros or attributes in between 'class' and the class name. + // We can have macros in between 'class' and the class name. if (!IsNonMacroIdentifier) { if (FormatTok->is(tok::l_paren)) { parseParens(); - } else if (FormatTok->is(TT_AttributeSquare)) { - parseSquare(); - // Consume the closing TT_AttributeSquare. - if (FormatTok->Next && FormatTok->is(TT_AttributeSquare)) - nextToken(); } } } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index ecc1c4cf51c1..ac9f8f8ed51c 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1983,14 +1983,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Module = PP->getHeaderSearchInfo().lookupModule( ModuleName, ImportLoc, /*AllowSearch*/ true, /*AllowExtraModuleMapSearch*/ !IsInclusionDirective); - /// FIXME: perhaps we should (a) look for a module using the module name - // to file map (PrebuiltModuleFiles) and (b) diagnose if still not found? - //if (Module == nullptr) { - // getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) - // << ModuleName; - // DisableGeneratingGlobalModuleIndex = true; - // return ModuleLoadResult(); - //} + MM.cacheModuleLoad(*Path[0].first, Module); } else { ModuleLoadResult Result = findOrCompileModuleAndReadAST( diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index bbc271e5611e..76d0d53ed31d 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1637,35 +1637,14 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Tok.setKind(tok::string_literal); } else if (II == Ident__FLT_EVAL_METHOD__) { // __FLT_EVAL_METHOD__ is set to the default value. - if (getTUFPEvalMethod() == - LangOptions::FPEvalMethodKind::FEM_Indeterminable) { - // This is possible if `AllowFPReassoc` or `AllowReciprocal` is enabled. - // These modes can be triggered via the command line option `-ffast-math` - // or via a `pragam float_control`. - // __FLT_EVAL_METHOD__ expands to -1. - // The `minus` operator is the next token we read from the stream. - auto Toks = std::make_unique<Token[]>(1); - OS << "-"; - Tok.setKind(tok::minus); - // Push the token `1` to the stream. - Token NumberToken; - NumberToken.startToken(); - NumberToken.setKind(tok::numeric_constant); - NumberToken.setLiteralData("1"); - NumberToken.setLength(1); - Toks[0] = NumberToken; - EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion*/ false, - /*IsReinject*/ false); - } else { - OS << getTUFPEvalMethod(); - // __FLT_EVAL_METHOD__ expands to a simple numeric value. - Tok.setKind(tok::numeric_constant); - if (getLastFPEvalPragmaLocation().isValid()) { - // The program is ill-formed. The value of __FLT_EVAL_METHOD__ is - // altered by the pragma. - Diag(Tok, diag::err_illegal_use_of_flt_eval_macro); - Diag(getLastFPEvalPragmaLocation(), diag::note_pragma_entered_here); - } + OS << getTUFPEvalMethod(); + // __FLT_EVAL_METHOD__ expands to a simple numeric value. + Tok.setKind(tok::numeric_constant); + if (getLastFPEvalPragmaLocation().isValid()) { + // The program is ill-formed. The value of __FLT_EVAL_METHOD__ is altered + // by the pragma. + Diag(Tok, diag::err_illegal_use_of_flt_eval_macro); + Diag(getLastFPEvalPragmaLocation(), diag::note_pragma_entered_here); } } else if (II == Ident__COUNTER__) { // __COUNTER__ expands to a simple numeric value. diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index fe9adb5685e3..0d411abf8f1c 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -207,11 +207,6 @@ void Preprocessor::Initialize(const TargetInfo &Target, else // Set initial value of __FLT_EVAL_METHOD__ from the command line. setCurrentFPEvalMethod(SourceLocation(), getLangOpts().getFPEvalMethod()); - // When `-ffast-math` option is enabled, it triggers several driver math - // options to be enabled. Among those, only one the following two modes - // affect the eval-method: reciprocal or reassociate. - if (getLangOpts().AllowFPReassoc || getLangOpts().AllowRecip) - setCurrentFPEvalMethod(SourceLocation(), LangOptions::FEM_Indeterminable); } void Preprocessor::InitializeForModelFile() { @@ -873,6 +868,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { CurLexerKind != CLK_CachingLexer) { ModuleImportLoc = Identifier.getLocation(); NamedModuleImportPath.clear(); + IsAtImport = true; ModuleImportExpectsIdentifier = true; CurLexerKind = CLK_LexAfterModuleImport; } @@ -940,6 +936,7 @@ void Preprocessor::Lex(Token &Result) { case tok::semi: TrackGMFState.handleSemi(); StdCXXImportSeqState.handleSemi(); + ModuleDeclState.handleSemi(); break; case tok::header_name: case tok::annot_header_unit: @@ -948,6 +945,13 @@ void Preprocessor::Lex(Token &Result) { case tok::kw_export: TrackGMFState.handleExport(); StdCXXImportSeqState.handleExport(); + ModuleDeclState.handleExport(); + break; + case tok::colon: + ModuleDeclState.handleColon(); + break; + case tok::period: + ModuleDeclState.handlePeriod(); break; case tok::identifier: if (Result.getIdentifierInfo()->isModulesImport()) { @@ -956,18 +960,25 @@ void Preprocessor::Lex(Token &Result) { if (StdCXXImportSeqState.afterImportSeq()) { ModuleImportLoc = Result.getLocation(); NamedModuleImportPath.clear(); + IsAtImport = false; ModuleImportExpectsIdentifier = true; CurLexerKind = CLK_LexAfterModuleImport; } break; } else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) { TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq()); + ModuleDeclState.handleModule(); break; + } else { + ModuleDeclState.handleIdentifier(Result.getIdentifierInfo()); + if (ModuleDeclState.isModuleCandidate()) + break; } [[fallthrough]]; default: TrackGMFState.handleMisc(); StdCXXImportSeqState.handleMisc(); + ModuleDeclState.handleMisc(); break; } } @@ -1151,6 +1162,15 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { if (NamedModuleImportPath.empty() && getLangOpts().CPlusPlusModules) { if (LexHeaderName(Result)) return true; + + if (Result.is(tok::colon) && ModuleDeclState.isNamedModule()) { + std::string Name = ModuleDeclState.getPrimaryName().str(); + Name += ":"; + NamedModuleImportPath.push_back( + {getIdentifierInfo(Name), Result.getLocation()}); + CurLexerKind = CLK_LexAfterModuleImport; + return true; + } } else { Lex(Result); } @@ -1164,9 +1184,10 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { /*DisableMacroExpansion*/ true, /*IsReinject*/ false); }; + bool ImportingHeader = Result.is(tok::header_name); // Check for a header-name. SmallVector<Token, 32> Suffix; - if (Result.is(tok::header_name)) { + if (ImportingHeader) { // Enter the header-name token into the token stream; a Lex action cannot // both return a token and cache tokens (doing so would corrupt the token // cache if the call to Lex comes from CachingLex / PeekAhead). @@ -1244,8 +1265,8 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { if (ModuleImportExpectsIdentifier && Result.getKind() == tok::identifier) { // We expected to see an identifier here, and we did; continue handling // identifiers. - NamedModuleImportPath.push_back(std::make_pair(Result.getIdentifierInfo(), - Result.getLocation())); + NamedModuleImportPath.push_back( + std::make_pair(Result.getIdentifierInfo(), Result.getLocation())); ModuleImportExpectsIdentifier = false; CurLexerKind = CLK_LexAfterModuleImport; return true; @@ -1285,7 +1306,8 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { std::string FlatModuleName; if (getLangOpts().ModulesTS || getLangOpts().CPlusPlusModules) { for (auto &Piece : NamedModuleImportPath) { - if (!FlatModuleName.empty()) + // If the FlatModuleName ends with colon, it implies it is a partition. + if (!FlatModuleName.empty() && FlatModuleName.back() != ':') FlatModuleName += "."; FlatModuleName += Piece.first->getName(); } @@ -1296,7 +1318,8 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { } Module *Imported = nullptr; - if (getLangOpts().Modules) { + // We don't/shouldn't load the standard c++20 modules when preprocessing. + if (getLangOpts().Modules && !isInImportingCXXNamedModules()) { Imported = TheModuleLoader.loadModule(ModuleImportLoc, NamedModuleImportPath, Module::Hidden, @@ -1304,6 +1327,7 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { if (Imported) makeModuleVisible(Imported, SemiLoc); } + if (Callbacks) Callbacks->moduleImport(ModuleImportLoc, NamedModuleImportPath, Imported); diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index c6968b9f417e..ebe7dd66c118 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -1020,8 +1020,16 @@ static void updateConsecutiveMacroArgTokens(SourceManager &SM, SourceLocation Limit = SM.getComposedLoc(BeginFID, SM.getFileIDSize(BeginFID)); Partition = All.take_while([&](const Token &T) { - return T.getLocation() >= BeginLoc && T.getLocation() < Limit && - NearLast(T.getLocation()); + // NOTE: the Limit is included! The lexer recovery only ever inserts a + // single token past the end of the FileID, specifically the ) when a + // macro-arg containing a comma should be guarded by parentheses. + // + // It is safe to include the Limit here because SourceManager allocates + // FileSize + 1 for each SLocEntry. + // + // See https://github.com/llvm/llvm-project/issues/60722. + return T.getLocation() >= BeginLoc && T.getLocation() <= Limit + && NearLast(T.getLocation()); }); } assert(!Partition.empty()); diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 42f582724564..3ea97f6aa8f2 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -565,13 +565,6 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc, case PFC_Precise: NewFPFeatures.setFPPreciseEnabled(true); FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); - if (PP.getCurrentFPEvalMethod() == - LangOptions::FPEvalMethodKind::FEM_Indeterminable && - PP.getLastFPEvalPragmaLocation().isValid()) - // A preceding `pragma float_control(precise,off)` has changed - // the value of the evaluation method. - // Set it back to its old value. - PP.setCurrentFPEvalMethod(SourceLocation(), PP.getLastFPEvalMethod()); break; case PFC_NoPrecise: if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict) @@ -581,10 +574,6 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc, else NewFPFeatures.setFPPreciseEnabled(false); FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); - PP.setLastFPEvalMethod(PP.getCurrentFPEvalMethod()); - // `AllowFPReassoc` or `AllowReciprocal` option is enabled. - PP.setCurrentFPEvalMethod( - Loc, LangOptions::FPEvalMethodKind::FEM_Indeterminable); break; case PFC_Except: if (!isPreciseFPEnabled()) @@ -608,12 +597,6 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc, } FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); NewFPFeatures = FpPragmaStack.CurrentValue; - if (CurFPFeatures.getAllowFPReassociate() || - CurFPFeatures.getAllowReciprocal()) - // Since we are popping the pragma, we don't want to be passing - // a location here. - PP.setCurrentFPEvalMethod(SourceLocation(), - CurFPFeatures.getFPEvalMethod()); break; } CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index f52c0247f01c..194239ab0e10 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -337,20 +337,29 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, } case ModuleDeclKind::Implementation: { - std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc( - PP.getIdentifierInfo(ModuleName), Path[0].second); // C++20 A module-declaration that contains neither an export- // keyword nor a module-partition implicitly imports the primary // module interface unit of the module as if by a module-import- // declaration. + std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc( + PP.getIdentifierInfo(ModuleName), Path[0].second); + + // The module loader will assume we're trying to import the module that + // we're building if `LangOpts.CurrentModule` equals to 'ModuleName'. + // Change the value for `LangOpts.CurrentModule` temporarily to make the + // module loader work properly. + const_cast<LangOptions&>(getLangOpts()).CurrentModule = ""; Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc}, Module::AllVisible, /*IsInclusionDirective=*/false); + const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName; + if (!Mod) { Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName; // Create an empty module interface unit for error recovery. Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName); } + } break; case ModuleDeclKind::PartitionImplementation: diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b40bd0978a8a..890cea1dfb0e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2540,8 +2540,6 @@ private: TInfo->getType(), TInfo, LocEnd, Ctor); Guide->setImplicit(); Guide->setParams(Params); - if (Ctor && Ctor->getTrailingRequiresClause()) - Guide->setTrailingRequiresClause(Ctor->getTrailingRequiresClause()); for (auto *Param : Params) Param->setDeclContext(Guide); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 9e48a2a35a34..1fe2d3fac685 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -756,11 +756,8 @@ private: SmallVector<UnexpandedParameterPack, 2> Unexpanded; S.collectUnexpandedParameterPacks(Pattern, Unexpanded); for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { - UnexpandedParameterPack U = Unexpanded[I]; - if (U.first.is<const SubstTemplateTypeParmPackType *>() || - U.first.is<const SubstNonTypeTemplateParmPackExpr *>()) - continue; - auto [Depth, Index] = getDepthAndIndex(U); + unsigned Depth, Index; + std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]); if (Depth == Info.getDeducedDepth()) AddPack(Index); } diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 01a435668d88..86268b504cbb 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -89,23 +89,6 @@ namespace { return true; } - bool - VisitSubstTemplateTypeParmPackTypeLoc(SubstTemplateTypeParmPackTypeLoc TL) { - Unexpanded.push_back({TL.getTypePtr(), TL.getNameLoc()}); - return true; - } - - bool VisitSubstTemplateTypeParmPackType(SubstTemplateTypeParmPackType *T) { - Unexpanded.push_back({T, SourceLocation()}); - return true; - } - - bool - VisitSubstNonTypeTemplateParmPackExpr(SubstNonTypeTemplateParmPackExpr *E) { - Unexpanded.push_back({E, E->getParameterPackLocation()}); - return true; - } - /// Record occurrences of function and non-type template /// parameter packs in an expression. bool VisitDeclRefExpr(DeclRefExpr *E) { @@ -324,8 +307,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, auto *TTPD = dyn_cast<TemplateTypeParmDecl>(LocalPack); return TTPD && TTPD->getTypeForDecl() == TTPT; } - return declaresSameEntity(Pack.first.get<const NamedDecl *>(), - LocalPack); + return declaresSameEntity(Pack.first.get<NamedDecl *>(), LocalPack); }; if (llvm::any_of(LSI->LocalPacks, DeclaresThisPack)) LambdaParamPackReferences.push_back(Pack); @@ -377,7 +359,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) Name = TTP->getIdentifier(); else - Name = Unexpanded[I].first.get<const NamedDecl *>()->getIdentifier(); + Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier(); if (Name && NamesKnown.insert(Name).second) Names.push_back(Name); @@ -440,7 +422,7 @@ bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) { llvm::SmallPtrSet<NamedDecl*, 8> ParmSet(Parms.begin(), Parms.end()); SmallVector<UnexpandedParameterPack, 2> UnexpandedParms; for (auto Parm : Unexpanded) - if (ParmSet.contains(Parm.first.dyn_cast<const NamedDecl *>())) + if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl *>())) UnexpandedParms.push_back(Parm); if (UnexpandedParms.empty()) return false; @@ -692,95 +674,109 @@ bool Sema::CheckParameterPacksForExpansion( bool &RetainExpansion, std::optional<unsigned> &NumExpansions) { ShouldExpand = true; RetainExpansion = false; - std::pair<const IdentifierInfo *, SourceLocation> FirstPack; - std::optional<std::pair<unsigned, SourceLocation>> PartialExpansion; - std::optional<unsigned> CurNumExpansions; + std::pair<IdentifierInfo *, SourceLocation> FirstPack; + bool HaveFirstPack = false; + std::optional<unsigned> NumPartialExpansions; + SourceLocation PartiallySubstitutedPackLoc; - for (auto [P, Loc] : Unexpanded) { + for (UnexpandedParameterPack ParmPack : Unexpanded) { // Compute the depth and index for this parameter pack. - std::optional<std::pair<unsigned, unsigned>> Pos; + unsigned Depth = 0, Index = 0; + IdentifierInfo *Name; + bool IsVarDeclPack = false; + + if (const TemplateTypeParmType *TTP = + ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) { + Depth = TTP->getDepth(); + Index = TTP->getIndex(); + Name = TTP->getIdentifier(); + } else { + NamedDecl *ND = ParmPack.first.get<NamedDecl *>(); + if (isa<VarDecl>(ND)) + IsVarDeclPack = true; + else + std::tie(Depth, Index) = getDepthAndIndex(ND); + + Name = ND->getIdentifier(); + } + + // Determine the size of this argument pack. unsigned NewPackSize; - const auto *ND = P.dyn_cast<const NamedDecl *>(); - if (ND && isa<VarDecl>(ND)) { - const auto *DAP = - CurrentInstantiationScope->findInstantiationOf(ND) - ->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>(); - if (!DAP) { + if (IsVarDeclPack) { + // Figure out whether we're instantiating to an argument pack or not. + typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; + + llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation = + CurrentInstantiationScope->findInstantiationOf( + ParmPack.first.get<NamedDecl *>()); + if (Instantiation->is<DeclArgumentPack *>()) { + // We could expand this function parameter pack. + NewPackSize = Instantiation->get<DeclArgumentPack *>()->size(); + } else { // We can't expand this function parameter pack, so we can't expand // the pack expansion. ShouldExpand = false; continue; } - NewPackSize = DAP->size(); - } else if (ND) { - Pos = getDepthAndIndex(ND); - } else if (const auto *TTP = P.dyn_cast<const TemplateTypeParmType *>()) { - Pos = {TTP->getDepth(), TTP->getIndex()}; - ND = TTP->getDecl(); - // FIXME: We either should have some fallback for canonical TTP, or - // never have canonical TTP here. - } else if (const auto *STP = - P.dyn_cast<const SubstTemplateTypeParmPackType *>()) { - NewPackSize = STP->getNumArgs(); - ND = STP->getReplacedParameter(); } else { - const auto *SEP = P.get<const SubstNonTypeTemplateParmPackExpr *>(); - NewPackSize = SEP->getArgumentPack().pack_size(); - ND = SEP->getParameterPack(); - } - - if (Pos) { // If we don't have a template argument at this depth/index, then we // cannot expand the pack expansion. Make a note of this, but we still // want to check any parameter packs we *do* have arguments for. - if (Pos->first >= TemplateArgs.getNumLevels() || - !TemplateArgs.hasTemplateArgument(Pos->first, Pos->second)) { + if (Depth >= TemplateArgs.getNumLevels() || + !TemplateArgs.hasTemplateArgument(Depth, Index)) { ShouldExpand = false; continue; } + // Determine the size of the argument pack. - NewPackSize = TemplateArgs(Pos->first, Pos->second).pack_size(); - // C++0x [temp.arg.explicit]p9: - // Template argument deduction can extend the sequence of template - // arguments corresponding to a template parameter pack, even when the - // sequence contains explicitly specified template arguments. - if (CurrentInstantiationScope) - if (const NamedDecl *PartialPack = - CurrentInstantiationScope->getPartiallySubstitutedPack(); - PartialPack && getDepthAndIndex(PartialPack) == *Pos) { + NewPackSize = TemplateArgs(Depth, Index).pack_size(); + } + + // C++0x [temp.arg.explicit]p9: + // Template argument deduction can extend the sequence of template + // arguments corresponding to a template parameter pack, even when the + // sequence contains explicitly specified template arguments. + if (!IsVarDeclPack && CurrentInstantiationScope) { + if (NamedDecl *PartialPack = + CurrentInstantiationScope->getPartiallySubstitutedPack()) { + unsigned PartialDepth, PartialIndex; + std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack); + if (PartialDepth == Depth && PartialIndex == Index) { RetainExpansion = true; // We don't actually know the new pack size yet. - PartialExpansion = {NewPackSize, Loc}; + NumPartialExpansions = NewPackSize; + PartiallySubstitutedPackLoc = ParmPack.second; continue; } + } } - // FIXME: Workaround for Canonical TTP. - const IdentifierInfo *Name = ND ? ND->getIdentifier() : nullptr; - if (!CurNumExpansions) { + if (!NumExpansions) { // The is the first pack we've seen for which we have an argument. // Record it. - CurNumExpansions = NewPackSize; - FirstPack = {Name, Loc}; - } else if (NewPackSize != *CurNumExpansions) { + NumExpansions = NewPackSize; + FirstPack.first = Name; + FirstPack.second = ParmPack.second; + HaveFirstPack = true; + continue; + } + + if (NewPackSize != *NumExpansions) { // C++0x [temp.variadic]p5: // All of the parameter packs expanded by a pack expansion shall have // the same number of arguments specified. - Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict) - << FirstPack.first << Name << *CurNumExpansions << NewPackSize - << SourceRange(FirstPack.second) << SourceRange(Loc); + if (HaveFirstPack) + Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict) + << FirstPack.first << Name << *NumExpansions << NewPackSize + << SourceRange(FirstPack.second) << SourceRange(ParmPack.second); + else + Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel) + << Name << *NumExpansions << NewPackSize + << SourceRange(ParmPack.second); return true; } } - if (NumExpansions && CurNumExpansions && - *NumExpansions != *CurNumExpansions) { - Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel) - << FirstPack.first << *CurNumExpansions << *NumExpansions - << SourceRange(FirstPack.second); - return true; - } - // If we're performing a partial expansion but we also have a full expansion, // expand to the number of common arguments. For example, given: // @@ -790,18 +786,17 @@ bool Sema::CheckParameterPacksForExpansion( // // ... a call to 'A<int, int>().f<int>' should expand the pack once and // retain an expansion. - if (PartialExpansion) { - if (CurNumExpansions && *CurNumExpansions < PartialExpansion->first) { + if (NumPartialExpansions) { + if (NumExpansions && *NumExpansions < *NumPartialExpansions) { NamedDecl *PartialPack = CurrentInstantiationScope->getPartiallySubstitutedPack(); Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial) - << PartialPack << PartialExpansion->first << *CurNumExpansions - << SourceRange(PartialExpansion->second); + << PartialPack << *NumPartialExpansions << *NumExpansions + << SourceRange(PartiallySubstitutedPackLoc); return true; } - NumExpansions = PartialExpansion->first; - } else { - NumExpansions = CurNumExpansions; + + NumExpansions = NumPartialExpansions; } return false; @@ -814,48 +809,47 @@ std::optional<unsigned> Sema::getNumArgumentsInExpansion( CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern); std::optional<unsigned> Result; - auto setResultSz = [&Result](unsigned Size) { - assert((!Result || *Result == Size) && "inconsistent pack sizes"); - Result = Size; - }; - auto setResultPos = [&](const std::pair<unsigned, unsigned> &Pos) -> bool { - unsigned Depth = Pos.first, Index = Pos.second; - if (Depth >= TemplateArgs.getNumLevels() || - !TemplateArgs.hasTemplateArgument(Depth, Index)) - // The pattern refers to an unknown template argument. We're not ready to - // expand this pack yet. - return true; - // Determine the size of the argument pack. - setResultSz(TemplateArgs(Depth, Index).pack_size()); - return false; - }; + for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { + // Compute the depth and index for this parameter pack. + unsigned Depth; + unsigned Index; - for (auto [I, _] : Unexpanded) { - if (const auto *TTP = I.dyn_cast<const TemplateTypeParmType *>()) { - if (setResultPos({TTP->getDepth(), TTP->getIndex()})) - return std::nullopt; - } else if (const auto *STP = - I.dyn_cast<const SubstTemplateTypeParmPackType *>()) { - setResultSz(STP->getNumArgs()); - } else if (const auto *SEP = - I.dyn_cast<const SubstNonTypeTemplateParmPackExpr *>()) { - setResultSz(SEP->getArgumentPack().pack_size()); + if (const TemplateTypeParmType *TTP = + Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) { + Depth = TTP->getDepth(); + Index = TTP->getIndex(); } else { - const auto *ND = I.get<const NamedDecl *>(); - // Function parameter pack or init-capture pack. + NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>(); if (isa<VarDecl>(ND)) { - const auto *DAP = - CurrentInstantiationScope->findInstantiationOf(ND) - ->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>(); - if (!DAP) + // Function parameter pack or init-capture pack. + typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; + + llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation = + CurrentInstantiationScope->findInstantiationOf( + Unexpanded[I].first.get<NamedDecl *>()); + if (Instantiation->is<Decl *>()) // The pattern refers to an unexpanded pack. We're not ready to expand // this pack yet. return std::nullopt; - setResultSz(DAP->size()); - } else if (setResultPos(getDepthAndIndex(ND))) { - return std::nullopt; + + unsigned Size = Instantiation->get<DeclArgumentPack *>()->size(); + assert((!Result || *Result == Size) && "inconsistent pack sizes"); + Result = Size; + continue; } + + std::tie(Depth, Index) = getDepthAndIndex(ND); } + if (Depth >= TemplateArgs.getNumLevels() || + !TemplateArgs.hasTemplateArgument(Depth, Index)) + // The pattern refers to an unknown template argument. We're not ready to + // expand this pack yet. + return std::nullopt; + + // Determine the size of the argument pack. + unsigned Size = TemplateArgs(Depth, Index).pack_size(); + assert((!Result || *Result == Size) && "inconsistent pack sizes"); + Result = Size; } return Result; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 6a05ecc5370f..48bb28b56cd3 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4569,7 +4569,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument( getSema(), Uneval ? Sema::ExpressionEvaluationContext::Unevaluated : Sema::ExpressionEvaluationContext::ConstantEvaluated, - /*LambdaContextDecl=*/nullptr, /*ExprContext=*/ + Sema::ReuseLambdaContextDecl, /*ExprContext=*/ Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument); Expr *InputExpr = Input.getSourceExpression(); @@ -5897,7 +5897,6 @@ bool TreeTransform<Derived>::TransformFunctionTypeParams( = dyn_cast<PackExpansionType>(OldType)) { // We have a function parameter pack that may need to be expanded. QualType Pattern = Expansion->getPattern(); - NumExpansions = Expansion->getNumExpansions(); SmallVector<UnexpandedParameterPack, 2> Unexpanded; getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded); diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp index b35ab1fe23ce..b85d0adb8eaf 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp @@ -41,6 +41,10 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS, if (!RetE) return; + // Skip "body farmed" functions. + if (RetE->getSourceRange().isInvalid()) + return; + SVal V = C.getSVal(RetE); const MemRegion *R = V.getAsRegion(); diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index a7f149b87e79..c3bd4876faf2 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -766,7 +766,7 @@ PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForSwitchOP( case Stmt::CaseStmtClass: { os << "Control jumps to 'case "; const auto *Case = cast<CaseStmt>(S); - const Expr *LHS = Case->getLHS()->IgnoreParenCasts(); + const Expr *LHS = Case->getLHS()->IgnoreParenImpCasts(); // Determine if it is an enum. bool GetRawInt = true; diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index 1017dff2b0f3..a275d36286d3 100644 --- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -2678,7 +2678,18 @@ EquivalenceClass::simplify(SValBuilder &SVB, RangeSet::Factory &F, if (OldState == State) continue; - assert(find(State, MemberSym) == find(State, SimplifiedMemberSym)); + // Be aware that `SimplifiedMemberSym` might refer to an already dead + // symbol. In that case, the eqclass of that might not be the same as the + // eqclass of `MemberSym`. This is because the dead symbols are not + // preserved in the `ClassMap`, hence + // `find(State, SimplifiedMemberSym)` will result in a trivial eqclass + // compared to the eqclass of `MemberSym`. + // These eqclasses should be the same if `SimplifiedMemberSym` is alive. + // --> assert(find(State, MemberSym) == find(State, SimplifiedMemberSym)) + // + // Note that `MemberSym` must be alive here since that is from the + // `ClassMembers` where all the symbols are alive. + // Remove the old and more complex symbol. State = find(State, MemberSym).removeMember(State, MemberSym); diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp index 3fcef00a5780..ae1662237e87 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp @@ -40,67 +40,69 @@ DependencyScanningTool::DependencyScanningTool( llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) : Worker(Service, std::move(FS)) {} -llvm::Expected<std::string> DependencyScanningTool::getDependencyFile( - const std::vector<std::string> &CommandLine, StringRef CWD, - std::optional<StringRef> ModuleName) { - /// Prints out all of the gathered dependencies into a string. - class MakeDependencyPrinterConsumer : public DependencyConsumer { - public: - void handleBuildCommand(Command) override {} +namespace { +/// Prints out all of the gathered dependencies into a string. +class MakeDependencyPrinterConsumer : public DependencyConsumer { +public: + void handleBuildCommand(Command) override {} + + void + handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override { + this->Opts = std::make_unique<DependencyOutputOptions>(Opts); + } - void - handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override { - this->Opts = std::make_unique<DependencyOutputOptions>(Opts); - } + void handleFileDependency(StringRef File) override { + Dependencies.push_back(std::string(File)); + } - void handleFileDependency(StringRef File) override { - Dependencies.push_back(std::string(File)); - } + void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override { + // Same as `handleModuleDependency`. + } - void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override { - // Same as `handleModuleDependency`. - } + void handleModuleDependency(ModuleDeps MD) override { + // These are ignored for the make format as it can't support the full + // set of deps, and handleFileDependency handles enough for implicitly + // built modules to work. + } - void handleModuleDependency(ModuleDeps MD) override { - // These are ignored for the make format as it can't support the full - // set of deps, and handleFileDependency handles enough for implicitly - // built modules to work. - } + void handleContextHash(std::string Hash) override {} - void handleContextHash(std::string Hash) override {} + std::string lookupModuleOutput(const ModuleID &ID, + ModuleOutputKind Kind) override { + llvm::report_fatal_error("unexpected call to lookupModuleOutput"); + } - std::string lookupModuleOutput(const ModuleID &ID, - ModuleOutputKind Kind) override { - llvm::report_fatal_error("unexpected call to lookupModuleOutput"); - } + void printDependencies(std::string &S) { + assert(Opts && "Handled dependency output options."); - void printDependencies(std::string &S) { - assert(Opts && "Handled dependency output options."); - - class DependencyPrinter : public DependencyFileGenerator { - public: - DependencyPrinter(DependencyOutputOptions &Opts, - ArrayRef<std::string> Dependencies) - : DependencyFileGenerator(Opts) { - for (const auto &Dep : Dependencies) - addDependency(Dep); - } - - void printDependencies(std::string &S) { - llvm::raw_string_ostream OS(S); - outputDependencyFile(OS); - } - }; - - DependencyPrinter Generator(*Opts, Dependencies); - Generator.printDependencies(S); - } + class DependencyPrinter : public DependencyFileGenerator { + public: + DependencyPrinter(DependencyOutputOptions &Opts, + ArrayRef<std::string> Dependencies) + : DependencyFileGenerator(Opts) { + for (const auto &Dep : Dependencies) + addDependency(Dep); + } - private: - std::unique_ptr<DependencyOutputOptions> Opts; - std::vector<std::string> Dependencies; - }; + void printDependencies(std::string &S) { + llvm::raw_string_ostream OS(S); + outputDependencyFile(OS); + } + }; + + DependencyPrinter Generator(*Opts, Dependencies); + Generator.printDependencies(S); + } + +protected: + std::unique_ptr<DependencyOutputOptions> Opts; + std::vector<std::string> Dependencies; +}; +} // anonymous namespace +llvm::Expected<std::string> DependencyScanningTool::getDependencyFile( + const std::vector<std::string> &CommandLine, StringRef CWD, + std::optional<StringRef> ModuleName) { MakeDependencyPrinterConsumer Consumer; auto Result = Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName); @@ -111,6 +113,50 @@ llvm::Expected<std::string> DependencyScanningTool::getDependencyFile( return Output; } +llvm::Expected<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile( + const CompileCommand &Command, StringRef CWD, + std::string &MakeformatOutput, std::string &MakeformatOutputPath) { + class P1689ModuleDependencyPrinterConsumer + : public MakeDependencyPrinterConsumer { + public: + P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule, + const CompileCommand &Command) + : Filename(Command.Filename), Rule(Rule) { + Rule.PrimaryOutput = Command.Output; + } + + void handleProvidedAndRequiredStdCXXModules( + std::optional<P1689ModuleInfo> Provided, + std::vector<P1689ModuleInfo> Requires) override { + Rule.Provides = Provided; + if (Rule.Provides) + Rule.Provides->SourcePath = Filename.str(); + Rule.Requires = Requires; + } + + StringRef getMakeFormatDependencyOutputPath() { + if (Opts->OutputFormat != DependencyOutputFormat::Make) + return {}; + return Opts->OutputFile; + } + + private: + StringRef Filename; + P1689Rule &Rule; + }; + + P1689Rule Rule; + P1689ModuleDependencyPrinterConsumer Consumer(Rule, Command); + auto Result = Worker.computeDependencies(CWD, Command.CommandLine, Consumer); + if (Result) + return std::move(Result); + + MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath(); + if (!MakeformatOutputPath.empty()) + Consumer.printDependencies(MakeformatOutput); + return Rule; +} + llvm::Expected<FullDependenciesResult> DependencyScanningTool::getFullDependencies( const std::vector<std::string> &CommandLine, StringRef CWD, diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index b54b8de9157e..8eb0328d6322 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -247,10 +247,12 @@ public: std::make_shared<DependencyConsumerForwarder>( std::move(Opts), WorkingDirectory, Consumer)); break; + case ScanningOutputFormat::P1689: case ScanningOutputFormat::Full: MDC = std::make_shared<ModuleDepCollector>( std::move(Opts), ScanInstance, Consumer, OriginalInvocation, - OptimizeArgs, EagerLoadModules); + OptimizeArgs, EagerLoadModules, + Format == ScanningOutputFormat::P1689); ScanInstance.addDependencyCollector(MDC); break; } diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index cb1c66b8d63f..d1cbf79a843e 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -339,6 +339,14 @@ void ModuleDepCollectorPP::InclusionDirective( void ModuleDepCollectorPP::moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, const Module *Imported) { + if (MDC.ScanInstance.getPreprocessor().isInImportingCXXNamedModules()) { + P1689ModuleInfo RequiredModule; + RequiredModule.ModuleName = Path[0].first->getName().str(); + RequiredModule.Type = P1689ModuleInfo::ModuleType::NamedCXXModule; + MDC.RequiredStdCXXModules.push_back(RequiredModule); + return; + } + handleImport(Imported); } @@ -361,6 +369,21 @@ void ModuleDepCollectorPP::EndOfMainFile() { .getFileEntryForID(MainFileID) ->getName()); + auto &PP = MDC.ScanInstance.getPreprocessor(); + if (PP.isInNamedModule()) { + P1689ModuleInfo ProvidedModule; + ProvidedModule.ModuleName = PP.getNamedModuleName(); + ProvidedModule.Type = P1689ModuleInfo::ModuleType::NamedCXXModule; + ProvidedModule.IsStdCXXModuleInterface = PP.isInNamedInterfaceUnit(); + // Don't put implementation (non partition) unit as Provide. + // Put the module as required instead. Since the implementation + // unit will import the primary module implicitly. + if (PP.isInImplementationUnit()) + MDC.RequiredStdCXXModules.push_back(ProvidedModule); + else + MDC.ProvidedStdCXXModule = ProvidedModule; + } + if (!MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty()) MDC.addFileDep(MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude); @@ -374,6 +397,10 @@ void ModuleDepCollectorPP::EndOfMainFile() { MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts); + if (MDC.IsStdModuleP1689Format) + MDC.Consumer.handleProvidedAndRequiredStdCXXModules( + MDC.ProvidedStdCXXModule, MDC.RequiredStdCXXModules); + for (auto &&I : MDC.ModularDeps) MDC.Consumer.handleModuleDependency(*I.second); @@ -548,10 +575,12 @@ void ModuleDepCollectorPP::addAffectingClangModule( ModuleDepCollector::ModuleDepCollector( std::unique_ptr<DependencyOutputOptions> Opts, CompilerInstance &ScanInstance, DependencyConsumer &C, - CompilerInvocation OriginalCI, bool OptimizeArgs, bool EagerLoadModules) + CompilerInvocation OriginalCI, bool OptimizeArgs, bool EagerLoadModules, + bool IsStdModuleP1689Format) : ScanInstance(ScanInstance), Consumer(C), Opts(std::move(Opts)), OriginalInvocation(std::move(OriginalCI)), OptimizeArgs(OptimizeArgs), - EagerLoadModules(EagerLoadModules) {} + EagerLoadModules(EagerLoadModules), + IsStdModuleP1689Format(IsStdModuleP1689Format) {} void ModuleDepCollector::attachToPreprocessor(Preprocessor &PP) { PP.addPPCallbacks(std::make_unique<ModuleDepCollectorPP>(*this)); diff --git a/compiler-rt/lib/builtins/cpu_model.c b/compiler-rt/lib/builtins/cpu_model.c index c5d7ae31afce..f5ad530c7e88 100644 --- a/compiler-rt/lib/builtins/cpu_model.c +++ b/compiler-rt/lib/builtins/cpu_model.c @@ -924,6 +924,9 @@ int CONSTRUCTOR_ATTRIBUTE __cpu_indicator_init(void) { #define HWCAP_SB (1 << 29) #endif +#ifndef AT_HWCAP2 +#define AT_HWCAP2 26 +#endif #ifndef HWCAP2_DCPODP #define HWCAP2_DCPODP (1 << 0) #endif diff --git a/libcxx/include/__algorithm/ranges_binary_search.h b/libcxx/include/__algorithm/ranges_binary_search.h index b2a8977652fb..d72d4e057401 100644 --- a/libcxx/include/__algorithm/ranges_binary_search.h +++ b/libcxx/include/__algorithm/ranges_binary_search.h @@ -36,7 +36,7 @@ struct __fn { _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); - return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first)); + return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); } template <forward_range _Range, class _Type, class _Proj = identity, @@ -46,7 +46,7 @@ struct __fn { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); - return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first)); + return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); } }; } // namespace __binary_search diff --git a/libcxx/include/__config b/libcxx/include/__config index 51b100fa5569..ac6a1422bfe3 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -904,7 +904,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // Try to find out if RTTI is disabled. # if !defined(__cpp_rtti) || __cpp_rtti < 199711L -# define _LIBCPP_NO_RTTI +# define _LIBCPP_HAS_NO_RTTI # endif # ifndef _LIBCPP_WEAK @@ -1259,6 +1259,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") #endif +// TODO(varconst): currently, there are bugs in Clang's intrinsics when handling Objective-C++ `id`, so don't use +// compiler intrinsics in the Objective-C++ mode. +# ifdef __OBJC__ +# define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS +# endif + #endif // __cplusplus #endif // _LIBCPP___CONFIG diff --git a/libcxx/include/__format/concepts.h b/libcxx/include/__format/concepts.h index fe4a7b9625ce..ba8d8e316226 100644 --- a/libcxx/include/__format/concepts.h +++ b/libcxx/include/__format/concepts.h @@ -66,9 +66,8 @@ concept formattable = __formattable<_Tp, _CharT>; // TODO FMT Add a test to validate we fail when using that concept after P2165 // has been implemented. template <class _Tp> -concept __fmt_pair_like = __is_specialization_v<_Tp, pair> || - // Use a requires since tuple_size_v may fail to instantiate, - (__is_specialization_v<_Tp, tuple> && requires { tuple_size_v<_Tp> == 2; }); +concept __fmt_pair_like = + __is_specialization_v<_Tp, pair> || (__is_specialization_v<_Tp, tuple> && tuple_size_v<_Tp> == 2); # endif //_LIBCPP_STD_VER > 20 #endif //_LIBCPP_STD_VER > 17 diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h index a544b53f7e6d..ca065723e198 100644 --- a/libcxx/include/__format/formatter_floating_point.h +++ b/libcxx/include/__format/formatter_floating_point.h @@ -404,7 +404,6 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_ // In fixed mode the algorithm truncates trailing spaces and possibly the // radix point. There's no good guess for the position of the radix point // therefore scan the output after the first digit. - __result.__radix_point = _VSTD::find(__first, __result.__last, '.'); } } @@ -665,7 +664,7 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif if (__result.__exponent == __result.__last) // if P > X >= -4, the conversion is with style f or F and precision P - 1 - X. // By including the radix point it calculates P - (1 + X) - __p -= __result.__radix_point - __buffer.begin(); + __p -= __result.__radix_point - __result.__integral; else // otherwise, the conversion is with style e or E and precision P - 1. --__p; diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h index ca79d334a028..9f92f6181468 100644 --- a/libcxx/include/__functional/function.h +++ b/libcxx/include/__functional/function.h @@ -268,10 +268,10 @@ public: virtual void destroy() _NOEXCEPT = 0; virtual void destroy_deallocate() _NOEXCEPT = 0; virtual _Rp operator()(_ArgTypes&& ...) = 0; -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI virtual const void* target(const type_info&) const _NOEXCEPT = 0; virtual const std::type_info& target_type() const _NOEXCEPT = 0; -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; // __func implements __base for a given functor type. @@ -305,10 +305,10 @@ public: virtual void destroy() _NOEXCEPT; virtual void destroy_deallocate() _NOEXCEPT; virtual _Rp operator()(_ArgTypes&&... __arg); -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI virtual const void* target(const type_info&) const _NOEXCEPT; virtual const std::type_info& target_type() const _NOEXCEPT; -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> @@ -356,7 +356,7 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) return __f_(_VSTD::forward<_ArgTypes>(__arg)...); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> const void* @@ -374,7 +374,7 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT return typeid(_Fp); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI // __value_func creates a value-type from a __func. @@ -553,7 +553,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT { return __f_ != nullptr; } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI _LIBCPP_INLINE_VISIBILITY const std::type_info& target_type() const _NOEXCEPT { @@ -569,7 +569,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> return nullptr; return (const _Tp*)__f_->target(typeid(_Tp)); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; // Storage for a functor object, to be used with __policy to manage copy and @@ -616,7 +616,7 @@ struct __policy { static const _LIBCPP_CONSTEXPR __policy __policy_ = {nullptr, nullptr, true, -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI &typeid(void) #else nullptr @@ -642,7 +642,7 @@ struct __policy __choose_policy(/* is_small = */ false_type) { static const _LIBCPP_CONSTEXPR __policy __policy_ = { &__large_clone<_Fun>, &__large_destroy<_Fun>, false, -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI &typeid(typename _Fun::_Target) #else nullptr @@ -657,7 +657,7 @@ struct __policy { static const _LIBCPP_CONSTEXPR __policy __policy_ = { nullptr, nullptr, false, -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI &typeid(typename _Fun::_Target) #else nullptr @@ -861,7 +861,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> return !__policy_->__is_null; } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI _LIBCPP_INLINE_VISIBILITY const std::type_info& target_type() const _NOEXCEPT { @@ -878,7 +878,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> else return reinterpret_cast<const _Tp*>(&__buf_.__small); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; #if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) @@ -945,7 +945,7 @@ public: return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__arg)...); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI virtual const void* target(type_info const& __ti) const _NOEXCEPT { if (__ti == typeid(__func::__block_type)) return &__f_; @@ -955,7 +955,7 @@ public: virtual const std::type_info& target_type() const _NOEXCEPT { return typeid(__func::__block_type); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; #endif // _LIBCPP_HAS_EXTENSION_BLOCKS @@ -1056,12 +1056,12 @@ public: // function invocation: _Rp operator()(_ArgTypes...) const; -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI // function target access: const std::type_info& target_type() const _NOEXCEPT; template <typename _Tp> _Tp* target() _NOEXCEPT; template <typename _Tp> const _Tp* target() const _NOEXCEPT; -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; #if _LIBCPP_STD_VER >= 17 @@ -1156,7 +1156,7 @@ function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const return __f_(_VSTD::forward<_ArgTypes>(__arg)...); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template<class _Rp, class ..._ArgTypes> const std::type_info& @@ -1181,7 +1181,7 @@ function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT return __f_.template target<_Tp>(); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template <class _Rp, class... _ArgTypes> inline _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__memory/construct_at.h b/libcxx/include/__memory/construct_at.h index ffee0022c243..14484dd6aa0d 100644 --- a/libcxx/include/__memory/construct_at.h +++ b/libcxx/include/__memory/construct_at.h @@ -83,6 +83,16 @@ _ForwardIterator __destroy(_ForwardIterator __first, _ForwardIterator __last) { return __first; } +template <class _BidirectionalIterator> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_BidirectionalIterator __reverse_destroy(_BidirectionalIterator __first, _BidirectionalIterator __last) { + while (__last != __first) { + --__last; + std::__destroy_at(std::addressof(*__last)); + } + return __last; +} + #if _LIBCPP_STD_VER > 14 template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0> diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index b77ce9230bff..f0ffa26abfeb 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -219,7 +219,7 @@ public: __shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a) : __data_(__compressed_pair<_Tp, _Dp>(__p, _VSTD::move(__d)), _VSTD::move(__a)) {} -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI const void* __get_deleter(const type_info&) const _NOEXCEPT override; #endif @@ -228,7 +228,7 @@ private: void __on_zero_shared_weak() _NOEXCEPT override; }; -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template <class _Tp, class _Dp, class _Alloc> const void* @@ -237,7 +237,7 @@ __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__get_deleter(const type_info& __t) cons return __t == typeid(_Dp) ? _VSTD::addressof(__data_.first().second()) : nullptr; } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template <class _Tp, class _Dp, class _Alloc> void @@ -260,7 +260,10 @@ __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT __a.deallocate(_PTraits::pointer_to(*this), 1); } -struct __default_initialize_tag {}; +// This tag is used to instantiate an allocator type. The various shared_ptr control blocks +// detect that the allocator has been instantiated for this type and perform alternative +// initialization/destruction based on that. +struct __for_overwrite_tag {}; template <class _Tp, class _Alloc> struct __shared_ptr_emplace @@ -271,25 +274,20 @@ struct __shared_ptr_emplace explicit __shared_ptr_emplace(_Alloc __a, _Args&& ...__args) : __storage_(_VSTD::move(__a)) { -#if _LIBCPP_STD_VER > 17 - using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; - _TpAlloc __tmp(*__get_alloc()); - allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...); +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + static_assert(sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite"); + ::new ((void*)__get_elem()) _Tp; + } else { + using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; + _TpAlloc __tmp(*__get_alloc()); + allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...); + } #else ::new ((void*)__get_elem()) _Tp(_VSTD::forward<_Args>(__args)...); #endif } - -#if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI - explicit __shared_ptr_emplace(__default_initialize_tag, _Alloc __a) - : __storage_(std::move(__a)) - { - ::new ((void*)__get_elem()) _Tp; - } -#endif - _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); } @@ -299,9 +297,13 @@ struct __shared_ptr_emplace private: void __on_zero_shared() _NOEXCEPT override { #if _LIBCPP_STD_VER > 17 - using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; - _TpAlloc __tmp(*__get_alloc()); - allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + __get_elem()->~_Tp(); + } else { + using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; + _TpAlloc __tmp(*__get_alloc()); + allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); + } #else __get_elem()->~_Tp(); #endif @@ -367,13 +369,57 @@ public: template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; -template<class _Tp, class _Up> +// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.general-6 +// A pointer type Y* is said to be compatible with a pointer type T* +// when either Y* is convertible to T* or Y is U[N] and T is cv U[]. +#if _LIBCPP_STD_VER >= 17 +template <class _Yp, class _Tp> +struct __bounded_convertible_to_unbounded : false_type {}; + +template <class _Up, std::size_t _Np, class _Tp> +struct __bounded_convertible_to_unbounded<_Up[_Np], _Tp> + : is_same<__remove_cv_t<_Tp>, _Up[]> {}; + +template <class _Yp, class _Tp> struct __compatible_with -#if _LIBCPP_STD_VER > 14 - : is_convertible<remove_extent_t<_Tp>*, remove_extent_t<_Up>*> {}; + : _Or< + is_convertible<_Yp*, _Tp*>, + __bounded_convertible_to_unbounded<_Yp, _Tp> + > {}; #else - : is_convertible<_Tp*, _Up*> {}; -#endif // _LIBCPP_STD_VER > 14 +template <class _Yp, class _Tp> +struct __compatible_with + : is_convertible<_Yp*, _Tp*> {}; +#endif // _LIBCPP_STD_VER >= 17 + +// Constructors that take raw pointers have a different set of "compatible" constraints +// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.const-9.1 +// - If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*, +// or T is U[] and Y(*)[] is convertible to T*. +// - If T is not an array type, then Y* is convertible to T*. +#if _LIBCPP_STD_VER >= 17 +template <class _Yp, class _Tp, class = void> +struct __raw_pointer_compatible_with : _And< + _Not<is_array<_Tp>>, + is_convertible<_Yp*, _Tp*> + > {}; + +template <class _Yp, class _Up, std::size_t _Np> +struct __raw_pointer_compatible_with<_Yp, _Up[_Np], __enable_if_t< + is_convertible<_Yp(*)[_Np], _Up(*)[_Np]>::value> > + : true_type {}; + +template <class _Yp, class _Up> +struct __raw_pointer_compatible_with<_Yp, _Up[], __enable_if_t< + is_convertible<_Yp(*)[], _Up(*)[]>::value> > + : true_type {}; + +#else +template <class _Yp, class _Tp> +struct __raw_pointer_compatible_with + : is_convertible<_Yp*, _Tp*> {}; +#endif // _LIBCPP_STD_VER >= 17 + template <class _Ptr, class = void> struct __is_deletable : false_type { }; @@ -395,12 +441,12 @@ static false_type __well_formed_deleter_test(...); template <class _Dp, class _Pt> struct __well_formed_deleter : decltype(std::__well_formed_deleter_test<_Dp, _Pt>(0)) {}; -template<class _Dp, class _Tp, class _Yp> +template<class _Dp, class _Yp, class _Tp> struct __shared_ptr_deleter_ctor_reqs { - static const bool value = __compatible_with<_Tp, _Yp>::value && + static const bool value = __raw_pointer_compatible_with<_Yp, _Tp>::value && is_move_constructible<_Dp>::value && - __well_formed_deleter<_Dp, _Tp*>::value; + __well_formed_deleter<_Dp, _Yp*>::value; }; #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) @@ -439,7 +485,7 @@ public: template<class _Yp, class = __enable_if_t< _And< - __compatible_with<_Yp, _Tp> + __raw_pointer_compatible_with<_Yp, _Tp> // In C++03 we get errors when trying to do SFINAE with the // delete operator, so we always pretend that it's deletable. // The same happens on GCC. @@ -457,7 +503,7 @@ public: __enable_weak_this(__p, __p); } - template<class _Yp, class _Dp, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> > + template<class _Yp, class _Dp, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d) : __ptr_(__p) @@ -484,7 +530,7 @@ public: #endif // _LIBCPP_NO_EXCEPTIONS } - template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> > + template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d, _Alloc __a) : __ptr_(__p) @@ -646,6 +692,7 @@ public: template <class _Yp, class _Dp, class = __enable_if_t< !is_lvalue_reference<_Dp>::value && + __compatible_with<_Yp, _Tp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value > > _LIBCPP_HIDE_FROM_ABI @@ -668,6 +715,7 @@ public: template <class _Yp, class _Dp, class = void, class = __enable_if_t< is_lvalue_reference<_Dp>::value && + __compatible_with<_Yp, _Tp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value > > _LIBCPP_HIDE_FROM_ABI @@ -740,9 +788,10 @@ public: } #endif - template <class _Yp, class _Dp, class = __enable_if_t< - is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value - > > + template <class _Yp, class _Dp, class = __enable_if_t<_And< + __compatible_with<_Yp, _Tp>, + is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*> + >::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(unique_ptr<_Yp, _Dp>&& __r) { @@ -764,7 +813,7 @@ public: } template<class _Yp, class = __enable_if_t< - __compatible_with<_Yp, _Tp>::value + __raw_pointer_compatible_with<_Yp, _Tp>::value > > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p) @@ -773,8 +822,7 @@ public: } template<class _Yp, class _Dp, class = __enable_if_t< - __compatible_with<_Yp, _Tp>::value - > > + __shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d) { @@ -782,8 +830,7 @@ public: } template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t< - __compatible_with<_Yp, _Tp>::value - > > + __shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d, _Alloc __a) { @@ -858,7 +905,7 @@ public: } #endif -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template <class _Dp> _LIBCPP_HIDE_FROM_ABI _Dp* __get_deleter() const _NOEXCEPT @@ -867,7 +914,7 @@ public: ? const_cast<void *>(__cntrl_->__get_deleter(typeid(_Dp))) : nullptr); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template<class _Yp, class _CntrlBlk> _LIBCPP_HIDE_FROM_ABI @@ -963,12 +1010,9 @@ template<class _Tp, class _Alloc, __enable_if_t<!is_array<_Tp>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) { - using _ControlBlock = __shared_ptr_emplace<_Tp, _Alloc>; - using _ControlBlockAllocator = typename __allocator_traits_rebind<_Alloc, _ControlBlock>::type; - __allocation_guard<_ControlBlockAllocator> __guard(__a, 1); - ::new ((void*)_VSTD::addressof(*__guard.__get())) _ControlBlock(__default_initialize_tag{}, __a); - auto __control_block = __guard.__release_ptr(); - return shared_ptr<_Tp>::__create_with_control_block((*__control_block).__get_elem(), _VSTD::addressof(*__control_block)); + using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; + _ForOverwriteAllocator __alloc(__a); + return std::allocate_shared<_Tp>(__alloc); } template<class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0> @@ -1000,26 +1044,25 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count, _Tp const& __arg) : __alloc_(__alloc), __count_(__count) { - std::__uninitialized_allocator_fill_n(__alloc_, std::begin(__data_), __count_, __arg); + std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::begin(__data_), __count_, __arg); } _LIBCPP_HIDE_FROM_ABI explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count) : __alloc_(__alloc), __count_(__count) { - std::__uninitialized_allocator_value_construct_n(__alloc_, std::begin(__data_), __count_); - } - #if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI - explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count, __default_initialize_tag) - : __alloc_(__alloc), __count_(__count) - { - // We are purposefully not using an allocator-aware default construction because the spec says so. - // There's currently no way of expressing default initialization in an allocator-aware manner anyway. - std::uninitialized_default_construct_n(std::begin(__data_), __count_); - } + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + // We are purposefully not using an allocator-aware default construction because the spec says so. + // There's currently no way of expressing default initialization in an allocator-aware manner anyway. + std::uninitialized_default_construct_n(std::begin(__data_), __count_); + } else { + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_); + } +#else + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_); #endif + } // Returns the number of bytes required to store a control block followed by the given number // of elements of _Tp, with the whole storage being aligned to a multiple of _Tp's alignment. @@ -1042,8 +1085,17 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count private: void __on_zero_shared() _NOEXCEPT override { +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + std::__reverse_destroy(__data_, __data_ + __count_); + } else { + __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); + std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_); + } +#else __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_); +#endif } void __on_zero_shared_weak() _NOEXCEPT override { @@ -1096,30 +1148,40 @@ struct __bounded_array_control_block<_Tp[_Count], _Alloc> _LIBCPP_HIDE_FROM_ABI explicit __bounded_array_control_block(_Alloc const& __alloc, _Tp const& __arg) : __alloc_(__alloc) { - std::__uninitialized_allocator_fill_n(__alloc_, std::addressof(__data_[0]), _Count, __arg); + std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count, __arg); } _LIBCPP_HIDE_FROM_ABI explicit __bounded_array_control_block(_Alloc const& __alloc) : __alloc_(__alloc) { - std::__uninitialized_allocator_value_construct_n(__alloc_, std::addressof(__data_[0]), _Count); - } - #if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI - explicit __bounded_array_control_block(_Alloc const& __alloc, __default_initialize_tag) : __alloc_(__alloc) { - // We are purposefully not using an allocator-aware default construction because the spec says so. - // There's currently no way of expressing default initialization in an allocator-aware manner anyway. - std::uninitialized_default_construct_n(std::addressof(__data_[0]), _Count); - } + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + // We are purposefully not using an allocator-aware default construction because the spec says so. + // There's currently no way of expressing default initialization in an allocator-aware manner anyway. + std::uninitialized_default_construct_n(std::addressof(__data_[0]), _Count); + } else { + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count); + } +#else + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count); #endif + } _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~__bounded_array_control_block() override { } // can't be `= default` because of the sometimes-non-trivial union member __data_ private: void __on_zero_shared() _NOEXCEPT override { +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + std::__reverse_destroy(__data_, __data_ + _Count); + } else { + __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); + std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count); + } +#else __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count); +#endif } void __on_zero_shared_weak() _NOEXCEPT override { @@ -1175,7 +1237,9 @@ template<class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, in _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) { - return std::__allocate_shared_bounded_array<_Tp>(__a, __default_initialize_tag{}); + using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; + _ForOverwriteAllocator __alloc(__a); + return std::__allocate_shared_bounded_array<_Tp>(__alloc); } template<class _Tp, class = __enable_if_t<is_bounded_array<_Tp>::value>> @@ -1196,7 +1260,7 @@ template<class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() { - return std::__allocate_shared_bounded_array<_Tp>(allocator<_Tp>(), __default_initialize_tag{}); + return std::__allocate_shared_bounded_array<_Tp>(allocator<__for_overwrite_tag>()); } // unbounded array variants @@ -1218,7 +1282,9 @@ template<class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value, _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a, size_t __n) { - return std::__allocate_shared_unbounded_array<_Tp>(__a, __n, __default_initialize_tag{}); + using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; + _ForOverwriteAllocator __alloc(__a); + return std::__allocate_shared_unbounded_array<_Tp>(__alloc, __n); } template<class _Tp, class = __enable_if_t<is_unbounded_array<_Tp>::value>> @@ -1239,7 +1305,7 @@ template<class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite(size_t __n) { - return std::__allocate_shared_unbounded_array<_Tp>(allocator<_Tp>(), __n, __default_initialize_tag{}); + return std::__allocate_shared_unbounded_array<_Tp>(allocator<__for_overwrite_tag>(), __n); } #endif // _LIBCPP_STD_VER > 17 @@ -1465,7 +1531,7 @@ reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT typename shared_ptr<_Tp>::element_type*>(__r.get())); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template<class _Dp, class _Tp> inline _LIBCPP_INLINE_VISIBILITY @@ -1475,7 +1541,7 @@ get_deleter(const shared_ptr<_Tp>& __p) _NOEXCEPT return __p.template __get_deleter<_Dp>(); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template<class _Tp> class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h index 63a45b2ac87b..0067780c3f5d 100644 --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -410,7 +410,7 @@ constexpr void __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter // This function assumes that the allocator is bound to the correct type. template<class _Alloc, class _Tp> _LIBCPP_HIDE_FROM_ABI -constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) { +constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc) { static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, "The allocator should already be rebound to the correct type"); @@ -426,7 +426,7 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) { }); for (; __i != extent_v<_Tp>; ++__i) { - std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i])); + std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i])); } __guard.__complete(); } else { @@ -446,13 +446,13 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) { // This function assumes that the allocator is bound to the correct type. template<class _Alloc, class _Tp, class _Arg> _LIBCPP_HIDE_FROM_ABI -constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) { +constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) { static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, "The allocator should already be rebound to the correct type"); if constexpr (is_array_v<_Tp>) { static_assert(is_array_v<_Arg>, - "Provided non-array initialization argument to __allocator_construct_at when " + "Provided non-array initialization argument to __allocator_construct_at_multidimensional when " "trying to construct an array."); using _Element = remove_extent_t<_Tp>; @@ -465,7 +465,7 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); }); for (; __i != extent_v<_Tp>; ++__i) { - std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i]), __arg[__i]); + std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]), __arg[__i]); } __guard.__complete(); } else { @@ -481,8 +481,8 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& // initialization using allocator_traits destruction. If the elements in the range are C-style // arrays, they are initialized element-wise using allocator construction, and recursively so. template<class _Alloc, class _BidirIter, class _Tp, class _Size = typename iterator_traits<_BidirIter>::difference_type> -_LIBCPP_HIDE_FROM_ABI -constexpr void __uninitialized_allocator_fill_n(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) { +_LIBCPP_HIDE_FROM_ABI constexpr void +__uninitialized_allocator_fill_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) { using _ValueType = typename iterator_traits<_BidirIter>::value_type; __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); _BidirIter __begin = __it; @@ -490,16 +490,16 @@ constexpr void __uninitialized_allocator_fill_n(_Alloc& __alloc, _BidirIter __it // If an exception is thrown, destroy what we have constructed so far in reverse order. __exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); for (; __n != 0; --__n, ++__it) { - std::__allocator_construct_at(__value_alloc, std::addressof(*__it), __value); + std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it), __value); } __guard.__complete(); } -// Same as __uninitialized_allocator_fill_n, but doesn't pass any initialization argument +// Same as __uninitialized_allocator_fill_n_multidimensional, but doesn't pass any initialization argument // to the allocator's construct method, which results in value initialization. -template<class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type> -_LIBCPP_HIDE_FROM_ABI -constexpr void __uninitialized_allocator_value_construct_n(_Alloc& __alloc, _BidirIter __it, _Size __n) { +template <class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type> +_LIBCPP_HIDE_FROM_ABI constexpr void +__uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n) { using _ValueType = typename iterator_traits<_BidirIter>::value_type; __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); _BidirIter __begin = __it; @@ -507,7 +507,7 @@ constexpr void __uninitialized_allocator_value_construct_n(_Alloc& __alloc, _Bid // If an exception is thrown, destroy what we have constructed so far in reverse order. __exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); for (; __n != 0; --__n, ++__it) { - std::__allocator_construct_at(__value_alloc, std::addressof(*__it)); + std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it)); } __guard.__complete(); } diff --git a/libcxx/include/__ranges/elements_view.h b/libcxx/include/__ranges/elements_view.h index 3afd6ddbe8f2..997380ee9c65 100644 --- a/libcxx/include/__ranges/elements_view.h +++ b/libcxx/include/__ranges/elements_view.h @@ -49,12 +49,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { -template <class _View, size_t _Np, bool _Const> -class __elements_view_iterator; - -template <class _View, size_t _Np, bool _Const> -class __elements_view_sentinel; - template <class _Tp, size_t _Np> concept __has_tuple_element = __tuple_like<_Tp> && _Np < tuple_size<_Tp>::value; @@ -66,6 +60,13 @@ template <input_range _View, size_t _Np> __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && __returnable_element<range_reference_t<_View>, _Np> class elements_view : public view_interface<elements_view<_View, _Np>> { +private: + template <bool> + class __iterator; + + template <bool> + class __sentinel; + public: _LIBCPP_HIDE_FROM_ABI elements_view() requires default_initializable<_View> @@ -130,12 +131,6 @@ public: } private: - template <bool _Const> - using __iterator = __elements_view_iterator<_View, _Np, _Const>; - - template <bool _Const> - using __sentinel = __elements_view_sentinel<_View, _Np, _Const>; - _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); }; @@ -160,13 +155,18 @@ struct __elements_view_iterator_category_base<_Base, _Np> { using iterator_category = decltype(__get_iterator_category()); }; -template <class _View, size_t _Np, bool _Const> -class __elements_view_iterator : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> { - template <class, size_t, bool > - friend class __elements_view_iterator; +template <input_range _View, size_t _Np> + requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && + __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && + __returnable_element<range_reference_t<_View>, _Np> +template <bool _Const> +class elements_view<_View, _Np>::__iterator + : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> { + template <bool> + friend class __iterator; - template <class, size_t, bool > - friend class __elements_view_sentinel; + template <bool> + friend class __sentinel; using _Base = __maybe_const<_Const, _View>; @@ -198,14 +198,13 @@ public: using value_type = remove_cvref_t<tuple_element_t<_Np, range_value_t<_Base>>>; using difference_type = range_difference_t<_Base>; - _LIBCPP_HIDE_FROM_ABI __elements_view_iterator() + _LIBCPP_HIDE_FROM_ABI __iterator() requires default_initializable<iterator_t<_Base>> = default; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __elements_view_iterator(iterator_t<_Base> __current) - : __current_(std::move(__current)) {} + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {} - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator(__elements_view_iterator<_View, _Np, !_Const> __i) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> : __current_(std::move(__i.__current_)) {} @@ -215,14 +214,14 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return __get_element(__current_); } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { ++__current_; return *this; } _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator operator++(int) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) requires forward_range<_Base> { auto temp = *this; @@ -230,14 +229,14 @@ public: return temp; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator--() + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() requires bidirectional_range<_Base> { --__current_; return *this; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator operator--(int) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) requires bidirectional_range<_Base> { auto temp = *this; @@ -245,14 +244,14 @@ public: return temp; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator+=(difference_type __n) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) requires random_access_range<_Base> { __current_ += __n; return *this; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator-=(difference_type __n) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) requires random_access_range<_Base> { __current_ -= __n; @@ -265,99 +264,91 @@ public: return __get_element(__current_ + __n); } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) requires equality_comparable<iterator_t<_Base>> { return __x.__current_ == __y.__current_; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator<(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ < __y.__current_; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator>(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __y < __x; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator<=(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return !(__y < __x); } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator>=(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return !(__x < __y); } - _LIBCPP_HIDE_FROM_ABI friend constexpr auto - operator<=>(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> { return __x.__current_ <=> __y.__current_; } - _LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator - operator+(const __elements_view_iterator& __x, difference_type __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __x, difference_type __y) requires random_access_range<_Base> { - return __elements_view_iterator{__x} += __y; + return __iterator{__x} += __y; } - _LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator - operator+(difference_type __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __x, const __iterator& __y) requires random_access_range<_Base> { return __y + __x; } - _LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator - operator-(const __elements_view_iterator& __x, difference_type __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __x, difference_type __y) requires random_access_range<_Base> { - return __elements_view_iterator{__x} -= __y; + return __iterator{__x} -= __y; } - _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type - operator-(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> { return __x.__current_ - __y.__current_; } }; -template <class _View, size_t _Np, bool _Const> -class __elements_view_sentinel { +template <input_range _View, size_t _Np> + requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && + __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && + __returnable_element<range_reference_t<_View>, _Np> +template <bool _Const> +class elements_view<_View, _Np>::__sentinel { private: using _Base = __maybe_const<_Const, _View>; _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>(); - template <class, size_t, bool > - friend class __elements_view_sentinel; + template <bool> + friend class __sentinel; template <bool _AnyConst> - _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) - __get_current(const __elements_view_iterator<_View, _Np, _AnyConst>& __iter) { + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_current(const __iterator<_AnyConst>& __iter) { return (__iter.__current_); } public: - _LIBCPP_HIDE_FROM_ABI __elements_view_sentinel() = default; + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __elements_view_sentinel(sentinel_t<_Base> __end) - : __end_(std::move(__end)) {} + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {} - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_sentinel(__elements_view_sentinel<_View, _Np, !_Const> __other) + _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __other) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__other.__end_)) {} @@ -365,22 +356,21 @@ public: template <bool _OtherConst> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __elements_view_iterator<_View, _Np, _OtherConst>& __x, const __elements_view_sentinel& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __get_current(__x) == __y.__end_; } template <bool _OtherConst> requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __elements_view_iterator<_View, _Np, _OtherConst>& __x, const __elements_view_sentinel& __y) { + operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __get_current(__x) - __y.__end_; } template <bool _OtherConst> requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __elements_view_sentinel& __x, const __elements_view_iterator<_View, _Np, _OtherConst>& __y) { + operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { return __x.__end_ - __get_current(__y); } }; diff --git a/libcxx/include/__ranges/filter_view.h b/libcxx/include/__ranges/filter_view.h index f8633a3fee84..e14a9abeb9e7 100644 --- a/libcxx/include/__ranges/filter_view.h +++ b/libcxx/include/__ranges/filter_view.h @@ -46,15 +46,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 namespace ranges { - - template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> - requires view<_View> && is_object_v<_Pred> - class __filter_view_iterator; - - template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> - requires view<_View> && is_object_v<_Pred> - class __filter_view_sentinel; - template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> class filter_view : public view_interface<filter_view<_View, _Pred>> { @@ -67,11 +58,8 @@ namespace ranges { using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache(); - using __iterator = __filter_view_iterator<_View, _Pred>; - using __sentinel = __filter_view_sentinel<_View, _Pred>; - - friend __iterator; - friend __sentinel; + class __iterator; + class __sentinel; public: _LIBCPP_HIDE_FROM_ABI @@ -131,13 +119,11 @@ namespace ranges { template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> - class __filter_view_iterator : public __filter_iterator_category<_View> { - - using __filter_view = filter_view<_View, _Pred>; + class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<_View> { public: _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>(); - _LIBCPP_NO_UNIQUE_ADDRESS __filter_view* __parent_ = nullptr; + _LIBCPP_NO_UNIQUE_ADDRESS filter_view* __parent_ = nullptr; using iterator_concept = _If<bidirectional_range<_View>, bidirectional_iterator_tag, @@ -149,10 +135,10 @@ namespace ranges { using difference_type = range_difference_t<_View>; _LIBCPP_HIDE_FROM_ABI - __filter_view_iterator() requires default_initializable<iterator_t<_View>> = default; + __iterator() requires default_initializable<iterator_t<_View>> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator(__filter_view& __parent, iterator_t<_View> __current) + constexpr __iterator(filter_view& __parent, iterator_t<_View> __current) : __current_(std::move(__current)), __parent_(std::addressof(__parent)) { } @@ -171,7 +157,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator& operator++() { + constexpr __iterator& operator++() { __current_ = ranges::find_if(std::move(++__current_), ranges::end(__parent_->__base_), std::ref(*__parent_->__pred_)); return *this; @@ -179,42 +165,42 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; } _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator operator++(int) requires forward_range<_View> { + constexpr __iterator operator++(int) requires forward_range<_View> { auto __tmp = *this; ++*this; return __tmp; } _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator& operator--() requires bidirectional_range<_View> { + constexpr __iterator& operator--() requires bidirectional_range<_View> { do { --__current_; } while (!std::invoke(*__parent_->__pred_, *__current_)); return *this; } _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator operator--(int) requires bidirectional_range<_View> { + constexpr __iterator operator--(int) requires bidirectional_range<_View> { auto tmp = *this; --*this; return tmp; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(__filter_view_iterator const& __x, __filter_view_iterator const& __y) + friend constexpr bool operator==(__iterator const& __x, __iterator const& __y) requires equality_comparable<iterator_t<_View>> { return __x.__current_ == __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr range_rvalue_reference_t<_View> iter_move(__filter_view_iterator const& __it) + friend constexpr range_rvalue_reference_t<_View> iter_move(__iterator const& __it) noexcept(noexcept(ranges::iter_move(__it.__current_))) { return ranges::iter_move(__it.__current_); } _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(__filter_view_iterator const& __x, __filter_view_iterator const& __y) + friend constexpr void iter_swap(__iterator const& __x, __iterator const& __y) noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) requires indirectly_swappable<iterator_t<_View>> { @@ -224,17 +210,15 @@ namespace ranges { template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> - class __filter_view_sentinel { - using __filter_view = filter_view<_View, _Pred>; - + class filter_view<_View, _Pred>::__sentinel { public: sentinel_t<_View> __end_ = sentinel_t<_View>(); _LIBCPP_HIDE_FROM_ABI - __filter_view_sentinel() = default; + __sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __filter_view_sentinel(__filter_view& __parent) + constexpr explicit __sentinel(filter_view& __parent) : __end_(ranges::end(__parent.__base_)) { } @@ -242,7 +226,7 @@ namespace ranges { constexpr sentinel_t<_View> base() const { return __end_; } _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(__filter_view_iterator<_View, _Pred> const& __x, __filter_view_sentinel const& __y) { + operator==(__iterator const& __x, __sentinel const& __y) { return __x.__current_ == __y.__end_; } }; diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h index 3654096b7e17..8f9148a6849c 100644 --- a/libcxx/include/__ranges/iota_view.h +++ b/libcxx/include/__ranges/iota_view.h @@ -83,14 +83,6 @@ namespace ranges { { __j - __j } -> convertible_to<_IotaDiffT<_Iter>>; }; - template <weakly_incrementable _Start> - requires copyable<_Start> - struct __iota_view_iterator; - - template <weakly_incrementable _Start, semiregular _BoundSentinel> - requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start> - struct __iota_view_sentinel; - template<class> struct __iota_iterator_category {}; @@ -102,9 +94,211 @@ namespace ranges { template <weakly_incrementable _Start, semiregular _BoundSentinel = unreachable_sentinel_t> requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start> class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> { + struct __iterator : public __iota_iterator_category<_Start> { + friend class iota_view; + + using iterator_concept = + _If<__advanceable<_Start>, random_access_iterator_tag, + _If<__decrementable<_Start>, bidirectional_iterator_tag, + _If<incrementable<_Start>, forward_iterator_tag, + /*Else*/ input_iterator_tag>>>; + + using value_type = _Start; + using difference_type = _IotaDiffT<_Start>; + + _Start __value_ = _Start(); + + _LIBCPP_HIDE_FROM_ABI + __iterator() requires default_initializable<_Start> = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) { + return __value_; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator++() { + ++__value_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr void operator++(int) { ++*this; } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator operator++(int) requires incrementable<_Start> { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator--() requires __decrementable<_Start> { + --__value_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator operator--(int) requires __decrementable<_Start> { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator+=(difference_type __n) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { + if (__n >= difference_type(0)) { + __value_ += static_cast<_Start>(__n); + } else { + __value_ -= static_cast<_Start>(-__n); + } + } else { + __value_ += __n; + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator-=(difference_type __n) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { + if (__n >= difference_type(0)) { + __value_ -= static_cast<_Start>(__n); + } else { + __value_ += static_cast<_Start>(-__n); + } + } else { + __value_ -= __n; + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr _Start operator[](difference_type __n) const + requires __advanceable<_Start> + { + return _Start(__value_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + requires equality_comparable<_Start> + { + return __x.__value_ == __y.__value_; + } - using __iterator = __iota_view_iterator<_Start>; - using __sentinel = __iota_view_sentinel<_Start, _BoundSentinel>; + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return __x.__value_ < __y.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return __y < __x; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return !(__y < __x); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return !(__x < __y); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> && three_way_comparable<_Start> + { + return __x.__value_ <=> __y.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator+(__iterator __i, difference_type __n) + requires __advanceable<_Start> + { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator+(difference_type __n, __iterator __i) + requires __advanceable<_Start> + { + return __i + __n; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator-(__iterator __i, difference_type __n) + requires __advanceable<_Start> + { + __i -= __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start>) { + if constexpr (__signed_integer_like<_Start>) { + return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_)); + } + if (__y.__value_ > __x.__value_) { + return difference_type(-difference_type(__y.__value_ - __x.__value_)); + } + return difference_type(__x.__value_ - __y.__value_); + } + return __x.__value_ - __y.__value_; + } + }; + + struct __sentinel { + friend class iota_view; + + private: + _BoundSentinel __bound_sentinel_ = _BoundSentinel(); + + public: + _LIBCPP_HIDE_FROM_ABI + __sentinel() = default; + constexpr explicit __sentinel(_BoundSentinel __bound_sentinel) : __bound_sentinel_(std::move(__bound_sentinel)) {} + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { + return __x.__value_ == __y.__bound_sentinel_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __sentinel& __y) + requires sized_sentinel_for<_BoundSentinel, _Start> + { + return __x.__value_ - __y.__bound_sentinel_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_Start> operator-(const __sentinel& __x, const __iterator& __y) + requires sized_sentinel_for<_BoundSentinel, _Start> + { + return -(__y - __x); + } + }; _Start __value_ = _Start(); _BoundSentinel __bound_sentinel_ = _BoundSentinel(); @@ -185,224 +379,6 @@ namespace ranges { template <class _Start, class _BoundSentinel> inline constexpr bool enable_borrowed_range<iota_view<_Start, _BoundSentinel>> = true; - template <weakly_incrementable _Start> - requires copyable<_Start> - struct __iota_view_iterator : public __iota_iterator_category<_Start> { - - template <weakly_incrementable _StartT, semiregular _BoundSentinelT> - requires __weakly_equality_comparable_with<_StartT, _BoundSentinelT> && copyable<_StartT> - friend class iota_view; - - using iterator_concept = - _If<__advanceable<_Start>, random_access_iterator_tag, - _If<__decrementable<_Start>, bidirectional_iterator_tag, - _If<incrementable<_Start>, forward_iterator_tag, - /*Else*/ input_iterator_tag>>>; - - using value_type = _Start; - using difference_type = _IotaDiffT<_Start>; - - _Start __value_ = _Start(); - - _LIBCPP_HIDE_FROM_ABI - __iota_view_iterator() requires default_initializable<_Start> = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __iota_view_iterator(_Start __value) : __value_(std::move(__value)) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) { - return __value_; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator& operator++() { - ++__value_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr void operator++(int) { ++*this; } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator operator++(int) requires incrementable<_Start> { - auto __tmp = *this; - ++*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator& operator--() requires __decrementable<_Start> { - --__value_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator operator--(int) requires __decrementable<_Start> { - auto __tmp = *this; - --*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator& operator+=(difference_type __n) - requires __advanceable<_Start> - { - if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { - if (__n >= difference_type(0)) { - __value_ += static_cast<_Start>(__n); - } else { - __value_ -= static_cast<_Start>(-__n); - } - } else { - __value_ += __n; - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator& operator-=(difference_type __n) - requires __advanceable<_Start> - { - if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { - if (__n >= difference_type(0)) { - __value_ -= static_cast<_Start>(__n); - } else { - __value_ += static_cast<_Start>(-__n); - } - } else { - __value_ -= __n; - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr _Start operator[](difference_type __n) const - requires __advanceable<_Start> - { - return _Start(__value_ + __n); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires equality_comparable<_Start> - { - return __x.__value_ == __y.__value_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> - { - return __x.__value_ < __y.__value_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> - { - return __y < __x; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<=(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> - { - return !(__y < __x); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>=(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> - { - return !(__x < __y); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr auto operator<=>(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> && three_way_comparable<_Start> - { - return __x.__value_ <=> __y.__value_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iota_view_iterator operator+(__iota_view_iterator __i, difference_type __n) - requires __advanceable<_Start> - { - __i += __n; - return __i; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iota_view_iterator operator+(difference_type __n, __iota_view_iterator __i) - requires __advanceable<_Start> - { - return __i + __n; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iota_view_iterator operator-(__iota_view_iterator __i, difference_type __n) - requires __advanceable<_Start> - { - __i -= __n; - return __i; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr difference_type operator-(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires __advanceable<_Start> - { - if constexpr (__integer_like<_Start>) { - if constexpr (__signed_integer_like<_Start>) { - return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_)); - } - if (__y.__value_ > __x.__value_) { - return difference_type(-difference_type(__y.__value_ - __x.__value_)); - } - return difference_type(__x.__value_ - __y.__value_); - } - return __x.__value_ - __y.__value_; - } - }; - - template <weakly_incrementable _Start, semiregular _BoundSentinel> - requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start> - struct __iota_view_sentinel { - - template <weakly_incrementable _StartT, semiregular _BoundSentinelT> - requires __weakly_equality_comparable_with<_StartT, _BoundSentinelT> && copyable<_StartT> - friend class iota_view; - - using __iterator = __iota_view_iterator<_Start>; - - private: - _BoundSentinel __bound_sentinel_ = _BoundSentinel(); - - public: - _LIBCPP_HIDE_FROM_ABI - __iota_view_sentinel() = default; - constexpr explicit __iota_view_sentinel(_BoundSentinel __bound_sentinel) : __bound_sentinel_(std::move(__bound_sentinel)) {} - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator& __x, const __iota_view_sentinel& __y) { - return __x.__value_ == __y.__bound_sentinel_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __iota_view_sentinel& __y) - requires sized_sentinel_for<_BoundSentinel, _Start> - { - return __x.__value_ - __y.__bound_sentinel_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr iter_difference_t<_Start> operator-(const __iota_view_sentinel& __x, const __iterator& __y) - requires sized_sentinel_for<_BoundSentinel, _Start> - { - return -(__y - __x); - } - }; - namespace views { namespace __iota { struct __fn { diff --git a/libcxx/include/__ranges/istream_view.h b/libcxx/include/__ranges/istream_view.h index 69a9df35a4d2..66cd91527616 100644 --- a/libcxx/include/__ranges/istream_view.h +++ b/libcxx/include/__ranges/istream_view.h @@ -36,18 +36,10 @@ namespace ranges { template <class _Val, class _CharT, class _Traits> concept __stream_extractable = requires(basic_istream<_CharT, _Traits>& __is, _Val& __t) { __is >> __t; }; -template <movable _Val, class _CharT, class _Traits> - requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> -class __basic_istream_view_iterator; - template <movable _Val, class _CharT, class _Traits = char_traits<_CharT>> requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> { - using __iterator = __basic_istream_view_iterator<_Val, _CharT, _Traits>; - - template <movable _ValueType, class _CharType, class _TraitsType> - requires default_initializable<_ValueType> && __stream_extractable<_ValueType, _CharType, _TraitsType> - friend class __basic_istream_view_iterator; + class __iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit basic_istream_view(basic_istream<_CharT, _Traits>& __stream) @@ -67,23 +59,23 @@ private: template <movable _Val, class _CharT, class _Traits> requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> -class __basic_istream_view_iterator { +class basic_istream_view<_Val, _CharT, _Traits>::__iterator { public: using iterator_concept = input_iterator_tag; using difference_type = ptrdiff_t; using value_type = _Val; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __basic_istream_view_iterator( + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator( basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept : __parent_(std::addressof(__parent)) {} - __basic_istream_view_iterator(const __basic_istream_view_iterator&) = delete; - _LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator(__basic_istream_view_iterator&&) = default; + __iterator(const __iterator&) = delete; + _LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&) = default; - __basic_istream_view_iterator& operator=(const __basic_istream_view_iterator&) = delete; - _LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator=(__basic_istream_view_iterator&&) = default; + __iterator& operator=(const __iterator&) = delete; + _LIBCPP_HIDE_FROM_ABI __iterator& operator=(__iterator&&) = default; - _LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI __iterator& operator++() { *__parent_->__stream_ >> __parent_->__value_; return *this; } @@ -92,7 +84,7 @@ public: _LIBCPP_HIDE_FROM_ABI _Val& operator*() const { return __parent_->__value_; } - _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __basic_istream_view_iterator& __x, default_sentinel_t) { + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __x, default_sentinel_t) { return !*__x.__get_parent_stream(); } diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h index 9d56e13b8439..7c078422e900 100644 --- a/libcxx/include/__ranges/join_view.h +++ b/libcxx/include/__ranges/join_view.h @@ -69,14 +69,6 @@ namespace ranges { >; }; - template <input_range _View, bool _Const> - requires view<_View> && input_range<range_reference_t<_View>> - struct __join_view_iterator; - - template <input_range _View, bool _Const> - requires view<_View> && input_range<range_reference_t<_View>> - struct __join_view_sentinel; - template<input_range _View> requires view<_View> && input_range<range_reference_t<_View>> class join_view @@ -84,19 +76,9 @@ namespace ranges { private: using _InnerRange = range_reference_t<_View>; - template<bool _Const> - using __iterator = __join_view_iterator<_View, _Const>; - - template<bool _Const> - using __sentinel = __join_view_sentinel<_View, _Const>; + template<bool> struct __iterator; - template <input_range _View2, bool _Const2> - requires view<_View2> && input_range<range_reference_t<_View2>> - friend struct __join_view_iterator; - - template <input_range _View2, bool _Const2> - requires view<_View2> && input_range<range_reference_t<_View2>> - friend struct __join_view_sentinel; + template<bool> struct __sentinel; template <class> friend struct std::__segmented_iterator_traits; @@ -167,12 +149,12 @@ namespace ranges { } }; - template<input_range _View, bool _Const> + template<input_range _View> requires view<_View> && input_range<range_reference_t<_View>> - struct __join_view_sentinel { - template<input_range _View2, bool> - requires view<_View2> && input_range<range_reference_t<_View2>> - friend struct __join_view_sentinel; + template<bool _Const> + struct join_view<_View>::__sentinel { + template<bool> + friend struct __sentinel; private: using _Parent = __maybe_const<_Const, join_view<_View>>; @@ -181,37 +163,42 @@ namespace ranges { public: _LIBCPP_HIDE_FROM_ABI - __join_view_sentinel() = default; + __sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __join_view_sentinel(_Parent& __parent) + constexpr explicit __sentinel(_Parent& __parent) : __end_(ranges::end(__parent.__base_)) {} _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_sentinel(__join_view_sentinel<_View, !_Const> __s) + constexpr __sentinel(__sentinel<!_Const> __s) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__s.__end_)) {} template<bool _OtherConst> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __join_view_iterator<_View, _OtherConst>& __x, const __join_view_sentinel& __y) { + friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __x.__outer_ == __y.__end_; } }; - template<input_range _View, bool _Const> + // https://reviews.llvm.org/D142811#inline-1383022 + // To simplify the segmented iterator traits specialization, + // make the iterator `final` + template<input_range _View> requires view<_View> && input_range<range_reference_t<_View>> - struct __join_view_iterator + template<bool _Const> + struct join_view<_View>::__iterator final : public __join_view_iterator_category<__maybe_const<_Const, _View>> { - template<input_range _View2, bool> - requires view<_View2> && input_range<range_reference_t<_View2>> - friend struct __join_view_iterator; + template<bool> + friend struct __iterator; template <class> friend struct std::__segmented_iterator_traits; + static constexpr bool __is_join_view_iterator = true; + private: using _Parent = __maybe_const<_Const, join_view<_View>>; using _Base = __maybe_const<_Const, _View>; @@ -246,7 +233,7 @@ namespace ranges { __inner_.reset(); } - _LIBCPP_HIDE_FROM_ABI constexpr __join_view_iterator(_Parent* __parent, _Outer __outer, _Inner __inner) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent* __parent, _Outer __outer, _Inner __inner) : __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {} public: @@ -267,17 +254,17 @@ namespace ranges { range_difference_t<_Base>, range_difference_t<range_reference_t<_Base>>>; _LIBCPP_HIDE_FROM_ABI - __join_view_iterator() requires default_initializable<_Outer> = default; + __iterator() requires default_initializable<_Outer> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator(_Parent& __parent, _Outer __outer) + constexpr __iterator(_Parent& __parent, _Outer __outer) : __outer_(std::move(__outer)) , __parent_(std::addressof(__parent)) { __satisfy(); } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator(__join_view_iterator<_View, !_Const> __i) + constexpr __iterator(__iterator<!_Const> __i) requires _Const && convertible_to<iterator_t<_View>, _Outer> && convertible_to<iterator_t<_InnerRange>, _Inner> @@ -298,7 +285,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator& operator++() { + constexpr __iterator& operator++() { auto&& __inner = [&]() -> auto&& { if constexpr (__ref_is_glvalue) return *__outer_; @@ -318,7 +305,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator operator++(int) + constexpr __iterator operator++(int) requires __ref_is_glvalue && forward_range<_Base> && forward_range<range_reference_t<_Base>> @@ -329,7 +316,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator& operator--() + constexpr __iterator& operator--() requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && @@ -348,7 +335,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator operator--(int) + constexpr __iterator operator--(int) requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && @@ -360,7 +347,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __join_view_iterator& __x, const __join_view_iterator& __y) + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) requires __ref_is_glvalue && equality_comparable<iterator_t<_Base>> && equality_comparable<iterator_t<range_reference_t<_Base>>> @@ -369,14 +356,14 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - friend constexpr decltype(auto) iter_move(const __join_view_iterator& __i) + friend constexpr decltype(auto) iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__inner_))) { return ranges::iter_move(*__i.__inner_); } _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(const __join_view_iterator& __x, const __join_view_iterator& __y) + friend constexpr void iter_swap(const __iterator& __x, const __iterator& __y) noexcept(noexcept(ranges::iter_swap(*__x.__inner_, *__y.__inner_))) requires indirectly_swappable<_Inner> { @@ -404,12 +391,12 @@ inline namespace __cpo { } // namespace views } // namespace ranges -template <class _View, bool _Const> - requires(ranges::common_range<typename ranges::__join_view_iterator<_View, _Const>::_Parent> && - __is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Outer>::value && - __is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Inner>::value) -struct __segmented_iterator_traits<ranges::__join_view_iterator<_View, _Const>> { - using _JoinViewIterator = ranges::__join_view_iterator<_View, _Const>; +template <class _JoinViewIterator> + requires(_JoinViewIterator::__is_join_view_iterator && + ranges::common_range<typename _JoinViewIterator::_Parent> && + __is_cpp17_random_access_iterator<typename _JoinViewIterator::_Outer>::value && + __is_cpp17_random_access_iterator<typename _JoinViewIterator::_Inner>::value) +struct __segmented_iterator_traits<_JoinViewIterator> { using __segment_iterator = _LIBCPP_NODEBUG __iterator_with_data<typename _JoinViewIterator::_Outer, typename _JoinViewIterator::_Parent*>; diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h index 9758ee935f29..6ebe5a43ed22 100644 --- a/libcxx/include/__ranges/split_view.h +++ b/libcxx/include/__ranges/split_view.h @@ -42,12 +42,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { -template <class _View, class _Pattern> -struct __split_view_iterator; - -template <class _View, class _Pattern> -struct __split_view_sentinel; - template <forward_range _View, forward_range _Pattern> requires view<_View> && view<_Pattern> && indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> @@ -59,13 +53,13 @@ private: _Cache __cached_begin_ = _Cache(); template <class, class> - friend struct __split_view_iterator; + friend struct __iterator; template <class, class> - friend struct __split_view_sentinel; + friend struct __sentinel; - using __iterator = __split_view_iterator<_View, _Pattern>; - using __sentinel = __split_view_sentinel<_View, _Pattern>; + struct __iterator; + struct __sentinel; _LIBCPP_HIDE_FROM_ABI constexpr subrange<iterator_t<_View>> __find_next(iterator_t<_View> __it) { auto [__begin, __end] = ranges::search(subrange(__it, ranges::end(__base_)), __pattern_); @@ -120,16 +114,17 @@ split_view(_Range&&, _Pattern&&) -> split_view<views::all_t<_Range>, views::all_ template <forward_range _Range> split_view(_Range&&, range_value_t<_Range>) -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; -template <class _View, class _Pattern> -struct __split_view_iterator { +template <forward_range _View, forward_range _Pattern> + requires view<_View> && view<_Pattern> && + indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> +struct split_view<_View, _Pattern>::__iterator { private: - split_view<_View, _Pattern>* __parent_ = nullptr; + split_view* __parent_ = nullptr; _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __cur_ = iterator_t<_View>(); _LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>(); bool __trailing_empty_ = false; - template <class, class> - friend struct __split_view_sentinel; + friend struct __sentinel; public: using iterator_concept = forward_iterator_tag; @@ -137,9 +132,9 @@ public: using value_type = subrange<iterator_t<_View>>; using difference_type = range_difference_t<_View>; - _LIBCPP_HIDE_FROM_ABI __split_view_iterator() = default; + _LIBCPP_HIDE_FROM_ABI __iterator() = default; - _LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator( + _LIBCPP_HIDE_FROM_ABI constexpr __iterator( split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next) : __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {} @@ -147,7 +142,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; } - _LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { __cur_ = __next_.begin(); if (__cur_ != ranges::end(__parent_->__base_)) { __cur_ = __next_.end(); @@ -163,36 +158,35 @@ public: return *this; } - _LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { auto __tmp = *this; ++*this; return __tmp; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __split_view_iterator& __x, const __split_view_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { return __x.__cur_ == __y.__cur_ && __x.__trailing_empty_ == __y.__trailing_empty_; } }; -template <class _View, class _Pattern> -struct __split_view_sentinel { +template <forward_range _View, forward_range _Pattern> + requires view<_View> && view<_Pattern> && + indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> +struct split_view<_View, _Pattern>::__sentinel { private: _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>(); - _LIBCPP_HIDE_FROM_ABI static constexpr bool - __equals(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) { + _LIBCPP_HIDE_FROM_ABI static constexpr bool __equals(const __iterator& __x, const __sentinel& __y) { return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_; } public: - _LIBCPP_HIDE_FROM_ABI __split_view_sentinel() = default; + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __split_view_sentinel(split_view<_View, _Pattern>& __parent) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent) : __end_(ranges::end(__parent.__base_)) {} - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { return __equals(__x, __y); } }; diff --git a/libcxx/include/__ranges/take_while_view.h b/libcxx/include/__ranges/take_while_view.h index 59c0a4f82889..77d7390dceb9 100644 --- a/libcxx/include/__ranges/take_while_view.h +++ b/libcxx/include/__ranges/take_while_view.h @@ -53,17 +53,11 @@ template <class _View, class _Pred> concept __take_while_const_is_range = range<const _View> && indirect_unary_predicate<const _Pred, iterator_t<const _View>>; -template <class, class, bool> -class __take_while_view_sentinel; - template <view _View, class _Pred> requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>> class take_while_view : public view_interface<take_while_view<_View, _Pred>> { - template <class, class, bool> - friend class __take_while_view_sentinel; - - template <bool _Const> - using __sentinel = __take_while_view_sentinel<_View, _Pred, _Const>; + template <bool> + class __sentinel; _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; @@ -114,37 +108,37 @@ public: template <class _Range, class _Pred> take_while_view(_Range&&, _Pred) -> take_while_view<views::all_t<_Range>, _Pred>; -template <class _View, class _Pred, bool _Const> -class __take_while_view_sentinel { +template <view _View, class _Pred> + requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>> +template <bool _Const> +class take_while_view<_View, _Pred>::__sentinel { using _Base = __maybe_const<_Const, _View>; sentinel_t<_Base> __end_ = sentinel_t<_Base>(); const _Pred* __pred_ = nullptr; - template <class, class, bool> - friend class __take_while_view_sentinel; + friend class __sentinel<!_Const>; public: - _LIBCPP_HIDE_FROM_ABI __take_while_view_sentinel() = default; + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __take_while_view_sentinel(sentinel_t<_Base> __end, const _Pred* __pred) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred) : __end_(std::move(__end)), __pred_(__pred) {} - _LIBCPP_HIDE_FROM_ABI constexpr __take_while_view_sentinel(__take_while_view_sentinel<_View, _Pred, !_Const> __s) + _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__s.__end_)), __pred_(__s.__pred_) {} _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const iterator_t<_Base>& __x, const __take_while_view_sentinel& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const iterator_t<_Base>& __x, const __sentinel& __y) { return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x); } template <bool _OtherConst = !_Const> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __take_while_view_sentinel& __y) { + operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __sentinel& __y) { return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x); } }; diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h index 66d9e80e6e61..0b5ced3df428 100644 --- a/libcxx/include/__ranges/transform_view.h +++ b/libcxx/include/__ranges/transform_view.h @@ -57,31 +57,11 @@ concept __transform_view_constraints = regular_invocable<_Fn&, range_reference_t<_View>> && __can_reference<invoke_result_t<_Fn&, range_reference_t<_View>>>; -template <input_range _View, copy_constructible _Function, bool _IsConst> - requires __transform_view_constraints<_View, _Function> -class __transform_view_iterator; - -template <input_range _View, copy_constructible _Function, bool _IsConst> - requires __transform_view_constraints<_View, _Function> -class __transform_view_sentinel; - template<input_range _View, copy_constructible _Fn> requires __transform_view_constraints<_View, _Fn> class transform_view : public view_interface<transform_view<_View, _Fn>> { - - template <bool _IsConst> - using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>; - - template <bool _IsConst> - using __sentinel = __transform_view_sentinel<_View, _Fn, _IsConst>; - - template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_iterator; - - template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_sentinel; + template<bool> class __iterator; + template<bool> class __sentinel; _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Fn> __func_; _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); @@ -176,23 +156,22 @@ struct __transform_view_iterator_category_base<_View, _Fn> { >; }; -template<input_range _View, copy_constructible _Fn, bool _Const> +template<input_range _View, copy_constructible _Fn> requires __transform_view_constraints<_View, _Fn> -class __transform_view_iterator +template<bool _Const> +class transform_view<_View, _Fn>::__iterator : public __transform_view_iterator_category_base<_View, _Fn> { - using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>; + using _Parent = __maybe_const<_Const, transform_view>; using _Base = __maybe_const<_Const, _View>; _Parent *__parent_ = nullptr; - template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_iterator; + template<bool> + friend class transform_view<_View, _Fn>::__iterator; - template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_sentinel; + template<bool> + friend class transform_view<_View, _Fn>::__sentinel; public: iterator_t<_Base> __current_ = iterator_t<_Base>(); @@ -202,17 +181,17 @@ public: using difference_type = range_difference_t<_Base>; _LIBCPP_HIDE_FROM_ABI - __transform_view_iterator() requires default_initializable<iterator_t<_Base>> = default; + __iterator() requires default_initializable<iterator_t<_Base>> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator(_Parent& __parent, iterator_t<_Base> __current) + constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current) : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {} - // Note: `__i` should always be `__transform_view_iterator<false>`, but directly using - // `__transform_view_iterator<false>` is ill-formed when `_Const` is false + // Note: `__i` should always be `__iterator<false>`, but directly using + // `__iterator<false>` is ill-formed when `_Const` is false // (see http://wg21.link/class.copy.ctor#5). _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator(__transform_view_iterator<_View, _Fn, !_Const> __i) + constexpr __iterator(__iterator<!_Const> __i) requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {} @@ -234,7 +213,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator& operator++() { + constexpr __iterator& operator++() { ++__current_; return *this; } @@ -243,7 +222,7 @@ public: constexpr void operator++(int) { ++__current_; } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator operator++(int) + constexpr __iterator operator++(int) requires forward_range<_Base> { auto __tmp = *this; @@ -252,7 +231,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator& operator--() + constexpr __iterator& operator--() requires bidirectional_range<_Base> { --__current_; @@ -260,7 +239,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator operator--(int) + constexpr __iterator operator--(int) requires bidirectional_range<_Base> { auto __tmp = *this; @@ -269,7 +248,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator& operator+=(difference_type __n) + constexpr __iterator& operator+=(difference_type __n) requires random_access_range<_Base> { __current_ += __n; @@ -277,7 +256,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator& operator-=(difference_type __n) + constexpr __iterator& operator-=(difference_type __n) requires random_access_range<_Base> { __current_ -= __n; @@ -293,77 +272,77 @@ public: } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) requires equality_comparable<iterator_t<_Base>> { return __x.__current_ == __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ < __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ > __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<=(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ <= __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>=(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ >= __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr auto operator<=>(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> { return __x.__current_ <=> __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __transform_view_iterator operator+(__transform_view_iterator __i, difference_type __n) + friend constexpr __iterator operator+(__iterator __i, difference_type __n) requires random_access_range<_Base> { - return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n}; + return __iterator{*__i.__parent_, __i.__current_ + __n}; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __transform_view_iterator operator+(difference_type __n, __transform_view_iterator __i) + friend constexpr __iterator operator+(difference_type __n, __iterator __i) requires random_access_range<_Base> { - return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n}; + return __iterator{*__i.__parent_, __i.__current_ + __n}; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __transform_view_iterator operator-(__transform_view_iterator __i, difference_type __n) + friend constexpr __iterator operator-(__iterator __i, difference_type __n) requires random_access_range<_Base> { - return __transform_view_iterator{*__i.__parent_, __i.__current_ - __n}; + return __iterator{*__i.__parent_, __i.__current_ - __n}; } _LIBCPP_HIDE_FROM_ABI - friend constexpr difference_type operator-(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> { return __x.__current_ - __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr decltype(auto) iter_move(const __transform_view_iterator& __i) + friend constexpr decltype(auto) iter_move(const __iterator& __i) noexcept(noexcept(*__i)) { if constexpr (is_lvalue_reference_v<decltype(*__i)>) @@ -373,37 +352,33 @@ public: } }; -template<input_range _View, copy_constructible _Fn, bool _Const> +template<input_range _View, copy_constructible _Fn> requires __transform_view_constraints<_View, _Fn> -class __transform_view_sentinel { - using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>; +template<bool _Const> +class transform_view<_View, _Fn>::__sentinel { + using _Parent = __maybe_const<_Const, transform_view>; using _Base = __maybe_const<_Const, _View>; - template <bool _IsConst> - using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>; - sentinel_t<_Base> __end_ = sentinel_t<_Base>(); - template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_iterator; + template<bool> + friend class transform_view<_View, _Fn>::__iterator; - template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_sentinel; + template<bool> + friend class transform_view<_View, _Fn>::__sentinel; public: _LIBCPP_HIDE_FROM_ABI - __transform_view_sentinel() = default; + __sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __transform_view_sentinel(sentinel_t<_Base> __end) : __end_(__end) {} + constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {} - // Note: `__i` should always be `__transform_view_sentinel<false>`, but directly using - // `__transform_view_sentinel<false>` is ill-formed when `_Const` is false + // Note: `__i` should always be `__sentinel<false>`, but directly using + // `__sentinel<false>` is ill-formed when `_Const` is false // (see http://wg21.link/class.copy.ctor#5). _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_sentinel(__transform_view_sentinel<_View, _Fn, !_Const> __i) + constexpr __sentinel(__sentinel<!_Const> __i) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__i.__end_)) {} @@ -413,7 +388,7 @@ public: template<bool _OtherConst> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) { + friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __x.__current_ == __y.__end_; } @@ -421,7 +396,7 @@ public: requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) { + operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __x.__current_ - __y.__end_; } @@ -429,7 +404,7 @@ public: requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __transform_view_sentinel& __x, const __iterator<_OtherConst>& __y) { + operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { return __x.__end_ - __y.__current_; } }; diff --git a/libcxx/include/__type_traits/add_pointer.h b/libcxx/include/__type_traits/add_pointer.h index 9d0c2010077b..1af5eca65c63 100644 --- a/libcxx/include/__type_traits/add_pointer.h +++ b/libcxx/include/__type_traits/add_pointer.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__add_pointer) +#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer) template <class _Tp> using __add_pointer_t = __add_pointer(_Tp); @@ -39,7 +39,7 @@ template <class _Tp> struct __add_pointer_impl<_Tp, false> template <class _Tp> using __add_pointer_t = typename __add_pointer_impl<_Tp>::type; -#endif // __has_builtin(__add_pointer) +#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer) template <class _Tp> struct add_pointer { diff --git a/libcxx/include/__type_traits/remove_pointer.h b/libcxx/include/__type_traits/remove_pointer.h index 33ddb7103f0d..2f810ba666bb 100644 --- a/libcxx/include/__type_traits/remove_pointer.h +++ b/libcxx/include/__type_traits/remove_pointer.h @@ -17,7 +17,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__remove_pointer) +#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer) template <class _Tp> struct remove_pointer { using type _LIBCPP_NODEBUG = __remove_pointer(_Tp); @@ -34,7 +34,7 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* const volat template <class _Tp> using __remove_pointer_t = typename remove_pointer<_Tp>::type; -#endif // __has_builtin(__remove_pointer) +#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer) #if _LIBCPP_STD_VER > 11 template <class _Tp> using remove_pointer_t = __remove_pointer_t<_Tp>; diff --git a/libcxx/include/any b/libcxx/include/any index 92cbc9a6c92d..50a44d7f4d70 100644 --- a/libcxx/include/any +++ b/libcxx/include/any @@ -175,7 +175,7 @@ namespace __any_imp inline _LIBCPP_INLINE_VISIBILITY bool __compare_typeid(type_info const* __id, const void* __fallback_id) { -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) if (__id && *__id == typeid(_Tp)) return true; #endif @@ -294,7 +294,7 @@ public: _LIBCPP_INLINE_VISIBILITY bool has_value() const _NOEXCEPT { return __h_ != nullptr; } -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) _LIBCPP_INLINE_VISIBILITY const type_info & type() const _NOEXCEPT { if (__h_) { @@ -426,7 +426,7 @@ namespace __any_imp _LIBCPP_INLINE_VISIBILITY static void* __type_info() { -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); #else return nullptr; @@ -514,7 +514,7 @@ namespace __any_imp _LIBCPP_INLINE_VISIBILITY static void* __type_info() { -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); #else return nullptr; @@ -680,7 +680,7 @@ any_cast(any * __any) _NOEXCEPT typedef add_pointer_t<_ValueType> _ReturnType; if (__any && __any->__h_) { void *__p = __any->__call(_Action::_Get, nullptr, -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) &typeid(_ValueType), #else nullptr, diff --git a/libcxx/include/version b/libcxx/include/version index 9705229a1c52..28c4a50cdab7 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -139,6 +139,7 @@ __cpp_lib_polymorphic_allocator 201902L <memory_resource __cpp_lib_quoted_string_io 201304L <iomanip> __cpp_lib_ranges 202106L <algorithm> <functional> <iterator> <memory> <ranges> +__cpp_lib_ranges_as_rvalue 202207L <ranges> __cpp_lib_ranges_chunk 202202L <ranges> __cpp_lib_ranges_chunk_by 202202L <ranges> __cpp_lib_ranges_iota 202202L <numeric> @@ -401,6 +402,7 @@ __cpp_lib_void_t 201411L <type_traits> # undef __cpp_lib_optional # define __cpp_lib_optional 202110L // # define __cpp_lib_out_ptr 202106L +# define __cpp_lib_ranges_as_rvalue 202207L // # define __cpp_lib_ranges_chunk 202202L // # define __cpp_lib_ranges_chunk_by 202202L // # define __cpp_lib_ranges_iota 202202L diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 6c478ad4109b..87887b314a5a 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -846,9 +846,7 @@ public: static void mergeArch(RISCVISAInfo::OrderedExtensionMap &mergedExts, unsigned &mergedXlen, const InputSectionBase *sec, StringRef s) { - auto maybeInfo = - RISCVISAInfo::parseArchString(s, /*EnableExperimentalExtension=*/true, - /*ExperimentalExtensionVersionCheck=*/true); + auto maybeInfo = RISCVISAInfo::parseNormalizedArchString(s); if (!maybeInfo) { errorOrWarn(toString(sec) + ": " + s + ": " + llvm::toString(maybeInfo.takeError())); @@ -863,8 +861,6 @@ static void mergeArch(RISCVISAInfo::OrderedExtensionMap &mergedExts, } else { for (const auto &ext : info.getExtensions()) { if (auto it = mergedExts.find(ext.first); it != mergedExts.end()) { - // TODO This is untested because RISCVISAInfo::parseArchString does not - // accept unsupported versions yet. if (std::tie(it->second.MajorVersion, it->second.MinorVersion) >= std::tie(ext.second.MajorVersion, ext.second.MinorVersion)) continue; diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp index d7a85bcf844f..c2b0ce9b12b9 100644 --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -323,8 +323,9 @@ bool ICF<ELFT>::equalsConstant(const InputSection *a, const InputSection *b) { const RelsOrRelas<ELFT> ra = a->template relsOrRelas<ELFT>(); const RelsOrRelas<ELFT> rb = b->template relsOrRelas<ELFT>(); - return ra.areRelocsRel() ? constantEq(a, ra.rels, b, rb.rels) - : constantEq(a, ra.relas, b, rb.relas); + return ra.areRelocsRel() || rb.areRelocsRel() + ? constantEq(a, ra.rels, b, rb.rels) + : constantEq(a, ra.relas, b, rb.relas); } // Compare two lists of relocations. Returns true if all pairs of @@ -371,8 +372,9 @@ template <class ELFT> bool ICF<ELFT>::equalsVariable(const InputSection *a, const InputSection *b) { const RelsOrRelas<ELFT> ra = a->template relsOrRelas<ELFT>(); const RelsOrRelas<ELFT> rb = b->template relsOrRelas<ELFT>(); - return ra.areRelocsRel() ? variableEq(a, ra.rels, b, rb.rels) - : variableEq(a, ra.relas, b, rb.relas); + return ra.areRelocsRel() || rb.areRelocsRel() + ? variableEq(a, ra.rels, b, rb.rels) + : variableEq(a, ra.relas, b, rb.relas); } template <class ELFT> size_t ICF<ELFT>::findBoundary(size_t begin, size_t end) { diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index f09d0d7f9095..f616245233b1 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -277,8 +277,8 @@ void SymbolTable::scanVersionScript() { pat.isExternCpp, /*hasWildCard=*/false}, id, ver, /*includeNonDefault=*/true); if (!found && !config->undefinedVersion) - errorOrWarn("version script assignment of '" + ver + "' to symbol '" + - pat.name + "' failed: symbol not defined"); + warn("version script assignment of '" + ver + "' to symbol '" + + pat.name + "' failed: symbol not defined"); }; for (SymbolVersion &pat : v.nonLocalPatterns) if (!pat.hasWildcard) diff --git a/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp b/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp index bd9ff99db67b..c5170757496f 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp @@ -8,7 +8,6 @@ #include "Coroutines.h" -#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/VariableList.h" @@ -17,38 +16,37 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; -static ValueObjectSP GetCoroFramePtrFromHandle(ValueObject &valobj) { - ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); +static lldb::addr_t GetCoroFramePtrFromHandle(ValueObjectSP valobj_sp) { if (!valobj_sp) - return nullptr; + return LLDB_INVALID_ADDRESS; // We expect a single pointer in the `coroutine_handle` class. // We don't care about its name. if (valobj_sp->GetNumChildren() != 1) - return nullptr; + return LLDB_INVALID_ADDRESS; ValueObjectSP ptr_sp(valobj_sp->GetChildAtIndex(0, true)); if (!ptr_sp) - return nullptr; + return LLDB_INVALID_ADDRESS; if (!ptr_sp->GetCompilerType().IsPointerType()) - return nullptr; - - return ptr_sp; -} - -static Function *ExtractDestroyFunction(ValueObjectSP &frame_ptr_sp) { - lldb::TargetSP target_sp = frame_ptr_sp->GetTargetSP(); - lldb::ProcessSP process_sp = frame_ptr_sp->GetProcessSP(); - auto ptr_size = process_sp->GetAddressByteSize(); + return LLDB_INVALID_ADDRESS; AddressType addr_type; - lldb::addr_t frame_ptr_addr = frame_ptr_sp->GetPointerValue(&addr_type); + lldb::addr_t frame_ptr_addr = ptr_sp->GetPointerValue(&addr_type); if (!frame_ptr_addr || frame_ptr_addr == LLDB_INVALID_ADDRESS) - return nullptr; + return LLDB_INVALID_ADDRESS; lldbassert(addr_type == AddressType::eAddressTypeLoad); + if (addr_type != AddressType::eAddressTypeLoad) + return LLDB_INVALID_ADDRESS; + + return frame_ptr_addr; +} + +static Function *ExtractDestroyFunction(lldb::TargetSP target_sp, + lldb::addr_t frame_ptr_addr) { + lldb::ProcessSP process_sp = target_sp->GetProcessSP(); + auto ptr_size = process_sp->GetAddressByteSize(); Status error; - // The destroy pointer is the 2nd pointer inside the compiler-generated - // `pair<resumePtr,destroyPtr>`. auto destroy_func_ptr_addr = frame_ptr_addr + ptr_size; lldb::addr_t destroy_func_addr = process_sp->ReadPointerFromMemory(destroy_func_ptr_addr, error); @@ -59,12 +57,7 @@ static Function *ExtractDestroyFunction(ValueObjectSP &frame_ptr_sp) { if (!target_sp->ResolveLoadAddress(destroy_func_addr, destroy_func_address)) return nullptr; - Function *destroy_func = - destroy_func_address.CalculateSymbolContextFunction(); - if (!destroy_func) - return nullptr; - - return destroy_func; + return destroy_func_address.CalculateSymbolContextFunction(); } static CompilerType InferPromiseType(Function &destroy_func) { @@ -85,44 +78,25 @@ static CompilerType InferPromiseType(Function &destroy_func) { return promise_type->GetForwardCompilerType(); } -static CompilerType GetCoroutineFrameType(TypeSystemClang &ast_ctx, - CompilerType promise_type) { - CompilerType void_type = ast_ctx.GetBasicType(lldb::eBasicTypeVoid); - CompilerType coro_func_type = ast_ctx.CreateFunctionType( - /*result_type=*/void_type, /*args=*/&void_type, /*num_args=*/1, - /*is_variadic=*/false, /*qualifiers=*/0); - CompilerType coro_abi_type; - if (promise_type.IsVoidType()) { - coro_abi_type = ast_ctx.CreateStructForIdentifier( - ConstString(), {{"resume", coro_func_type.GetPointerType()}, - {"destroy", coro_func_type.GetPointerType()}}); - } else { - coro_abi_type = ast_ctx.CreateStructForIdentifier( - ConstString(), {{"resume", coro_func_type.GetPointerType()}, - {"destroy", coro_func_type.GetPointerType()}, - {"promise", promise_type}}); - } - return coro_abi_type; -} - bool lldb_private::formatters::StdlibCoroutineHandleSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { - ValueObjectSP ptr_sp(GetCoroFramePtrFromHandle(valobj)); - if (!ptr_sp) + lldb::addr_t frame_ptr_addr = + GetCoroFramePtrFromHandle(valobj.GetNonSyntheticValue()); + if (frame_ptr_addr == LLDB_INVALID_ADDRESS) return false; - if (!ptr_sp->GetValueAsUnsigned(0)) { + if (frame_ptr_addr == 0) { stream << "nullptr"; } else { - stream.Printf("coro frame = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); + stream.Printf("coro frame = 0x%" PRIx64, frame_ptr_addr); } + return true; } lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: StdlibCoroutineHandleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), - m_ast_importer(std::make_unique<ClangASTImporter>()) { + : SyntheticChildrenFrontEnd(*valobj_sp) { if (valobj_sp) Update(); } @@ -132,32 +106,61 @@ lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: size_t lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: CalculateNumChildren() { - if (!m_frame_ptr_sp) + if (!m_resume_ptr_sp || !m_destroy_ptr_sp) return 0; - return m_frame_ptr_sp->GetNumChildren(); + return m_promise_ptr_sp ? 3 : 2; } lldb::ValueObjectSP lldb_private::formatters:: StdlibCoroutineHandleSyntheticFrontEnd::GetChildAtIndex(size_t idx) { - if (!m_frame_ptr_sp) - return lldb::ValueObjectSP(); - - return m_frame_ptr_sp->GetChildAtIndex(idx, true); + switch (idx) { + case 0: + return m_resume_ptr_sp; + case 1: + return m_destroy_ptr_sp; + case 2: + return m_promise_ptr_sp; + } + return lldb::ValueObjectSP(); } bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: Update() { - m_frame_ptr_sp.reset(); + m_resume_ptr_sp.reset(); + m_destroy_ptr_sp.reset(); + m_promise_ptr_sp.reset(); - ValueObjectSP valobj_sp = m_backend.GetSP(); + ValueObjectSP valobj_sp = m_backend.GetNonSyntheticValue(); if (!valobj_sp) return false; - ValueObjectSP ptr_sp(GetCoroFramePtrFromHandle(m_backend)); - if (!ptr_sp) + lldb::addr_t frame_ptr_addr = GetCoroFramePtrFromHandle(valobj_sp); + if (frame_ptr_addr == 0 || frame_ptr_addr == LLDB_INVALID_ADDRESS) + return false; + + auto ts = valobj_sp->GetCompilerType().GetTypeSystem(); + auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>(); + if (!ast_ctx) return false; + // Create the `resume` and `destroy` children. + lldb::TargetSP target_sp = m_backend.GetTargetSP(); + auto &exe_ctx = m_backend.GetExecutionContextRef(); + lldb::ProcessSP process_sp = target_sp->GetProcessSP(); + auto ptr_size = process_sp->GetAddressByteSize(); + CompilerType void_type = ast_ctx->GetBasicType(lldb::eBasicTypeVoid); + CompilerType coro_func_type = ast_ctx->CreateFunctionType( + /*result_type=*/void_type, /*args=*/&void_type, /*num_args=*/1, + /*is_variadic=*/false, /*qualifiers=*/0); + CompilerType coro_func_ptr_type = coro_func_type.GetPointerType(); + m_resume_ptr_sp = CreateValueObjectFromAddress( + "resume", frame_ptr_addr + 0 * ptr_size, exe_ctx, coro_func_ptr_type); + lldbassert(m_resume_ptr_sp); + m_destroy_ptr_sp = CreateValueObjectFromAddress( + "destroy", frame_ptr_addr + 1 * ptr_size, exe_ctx, coro_func_ptr_type); + lldbassert(m_destroy_ptr_sp); + // Get the `promise_type` from the template argument CompilerType promise_type( valobj_sp->GetCompilerType().GetTypeTemplateArgument(0)); @@ -165,23 +168,31 @@ bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: return false; // Try to infer the promise_type if it was type-erased - auto ts = valobj_sp->GetCompilerType().GetTypeSystem(); - auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>(); - if (!ast_ctx) - return false; if (promise_type.IsVoidType()) { - if (Function *destroy_func = ExtractDestroyFunction(ptr_sp)) { + if (Function *destroy_func = + ExtractDestroyFunction(target_sp, frame_ptr_addr)) { if (CompilerType inferred_type = InferPromiseType(*destroy_func)) { - // Copy the type over to the correct `TypeSystemClang` instance - promise_type = m_ast_importer->CopyType(*ast_ctx, inferred_type); + promise_type = inferred_type; } } } - // Build the coroutine frame type - CompilerType coro_frame_type = GetCoroutineFrameType(*ast_ctx, promise_type); + // If we don't know the promise type, we don't display the `promise` member. + // `CreateValueObjectFromAddress` below would fail for `void` types. + if (promise_type.IsVoidType()) { + return false; + } - m_frame_ptr_sp = ptr_sp->Cast(coro_frame_type.GetPointerType()); + // Add the `promise` member. We intentionally add `promise` as a pointer type + // instead of a value type, and don't automatically dereference this pointer. + // We do so to avoid potential very deep recursion in case there is a cycle + // formed between `std::coroutine_handle`s and their promises. + lldb::ValueObjectSP promise = CreateValueObjectFromAddress( + "promise", frame_ptr_addr + 2 * ptr_size, exe_ctx, promise_type); + Status error; + lldb::ValueObjectSP promisePtr = promise->AddressOf(error); + if (error.Success()) + m_promise_ptr_sp = promisePtr->Clone(ConstString("promise")); return false; } @@ -193,10 +204,17 @@ bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd:: size_t StdlibCoroutineHandleSyntheticFrontEnd::GetIndexOfChildWithName( ConstString name) { - if (!m_frame_ptr_sp) + if (!m_resume_ptr_sp || !m_destroy_ptr_sp) return UINT32_MAX; - return m_frame_ptr_sp->GetIndexOfChildWithName(name); + if (name == ConstString("resume")) + return 0; + if (name == ConstString("destroy")) + return 1; + if (name == ConstString("promise_ptr") && m_promise_ptr_sp) + return 2; + + return UINT32_MAX; } SyntheticChildrenFrontEnd * diff --git a/lldb/source/Plugins/Language/CPlusPlus/Coroutines.h b/lldb/source/Plugins/Language/CPlusPlus/Coroutines.h index c052bd23f4ca..b26cc9ed6132 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/Coroutines.h +++ b/lldb/source/Plugins/Language/CPlusPlus/Coroutines.h @@ -16,8 +16,6 @@ namespace lldb_private { -class ClangASTImporter; - namespace formatters { /// Summary provider for `std::coroutine_handle<T>` from libc++, libstdc++ and @@ -47,8 +45,9 @@ public: size_t GetIndexOfChildWithName(ConstString name) override; private: - lldb::ValueObjectSP m_frame_ptr_sp; - std::unique_ptr<lldb_private::ClangASTImporter> m_ast_importer; + lldb::ValueObjectSP m_resume_ptr_sp; + lldb::ValueObjectSP m_destroy_ptr_sp; + lldb::ValueObjectSP m_promise_ptr_sp; }; SyntheticChildrenFrontEnd * diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h index c4bd0fa3e07c..51b67d1756b9 100644 --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -1297,10 +1297,17 @@ public: bool loopIsFiniteByAssumption(const Loop *L); class FoldID { - SmallVector<unsigned, 4> Bits; + SmallVector<unsigned, 5> Bits; public: - void addInteger(unsigned long I) { Bits.push_back(I); } + void addInteger(unsigned long I) { + if (sizeof(long) == sizeof(int)) + addInteger(unsigned(I)); + else if (sizeof(long) == sizeof(long long)) + addInteger((unsigned long long)I); + else + llvm_unreachable("unexpected sizeof(long)"); + } void addInteger(unsigned I) { Bits.push_back(I); } void addInteger(int I) { Bits.push_back(I); } diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h index 2603c4542e8d..68dfefba3b3c 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h @@ -15,7 +15,6 @@ #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H #include "llvm/DebugInfo/LogicalView/Core/LVObject.h" -#include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h" #include "llvm/Support/Casting.h" #include <map> #include <set> diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h index 671ccf5d0e15..4c596b5b1dde 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVStringPool.h @@ -71,11 +71,6 @@ public: return (Index >= Entries.size()) ? StringRef() : Entries[Index]->getKey(); } - static LVStringPool &getInstance() { - static LVStringPool Instance; - return Instance; - } - void print(raw_ostream &OS) const { if (!Entries.empty()) { OS << "\nString Pool:\n"; @@ -90,8 +85,6 @@ public: #endif }; -inline LVStringPool &getStringPool() { return LVStringPool::getInstance(); } - } // namespace logicalview } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h index bff1499c1a60..a2274ec1a62f 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h @@ -16,6 +16,7 @@ #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" +#include "llvm/DebugInfo/LogicalView/Core/LVStringPool.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/Path.h" @@ -27,6 +28,9 @@ namespace llvm { namespace logicalview { +// Returns the unique string pool instance. +LVStringPool &getStringPool(); + template <typename T> using TypeIsValid = std::bool_constant<std::is_pointer<T>::value>; diff --git a/llvm/include/llvm/Support/ExitCodes.h b/llvm/include/llvm/Support/ExitCodes.h index b9041f5557d5..4eb5dedc688b 100644 --- a/llvm/include/llvm/Support/ExitCodes.h +++ b/llvm/include/llvm/Support/ExitCodes.h @@ -20,9 +20,9 @@ #if HAVE_SYSEXITS_H #include <sysexits.h> -#elif __MVS__ -// <sysexits.h> does not exist on z/OS. The only value used in LLVM is -// EX_IOERR, which is used to signal a special error condition (broken pipe). +#elif __MVS__ || defined(_WIN32) +// <sysexits.h> does not exist on z/OS and Windows. The only value used in LLVM +// is EX_IOERR, which is used to signal a special error condition (broken pipe). // Define the macro with its usual value from BSD systems, which is chosen to // not clash with more standard exit codes like 1. #define EX_IOERR 74 diff --git a/llvm/include/llvm/Support/RISCVISAInfo.h b/llvm/include/llvm/Support/RISCVISAInfo.h index 9070b88d710e..219435979698 100644 --- a/llvm/include/llvm/Support/RISCVISAInfo.h +++ b/llvm/include/llvm/Support/RISCVISAInfo.h @@ -51,6 +51,12 @@ public: bool ExperimentalExtensionVersionCheck = true, bool IgnoreUnknown = false); + /// Parse RISCV ISA info from an arch string that is already in normalized + /// form (as defined in the psABI). Unlike parseArchString, this function + /// will not error for unrecognized extension names or extension versions. + static llvm::Expected<std::unique_ptr<RISCVISAInfo>> + parseNormalizedArchString(StringRef Arch); + /// Parse RISCV ISA info from feature vector. static llvm::Expected<std::unique_ptr<RISCVISAInfo>> parseFeatures(unsigned XLen, const std::vector<std::string> &Features); diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 937e0572d4a7..70749ce30184 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -102,14 +102,17 @@ namespace sys { /// functions. A null handler pointer disables the current installed /// function. Note also that the handler may be executed on a /// different thread on some platforms. - /// - /// This is a no-op on Windows. void SetOneShotPipeSignalFunction(void (*Handler)()); - /// On Unix systems, this function exits with an "IO error" exit code. - /// This is a no-op on Windows. + /// On Unix systems and Windows, this function exits with an "IO error" exit + /// code. void DefaultOneShotPipeSignalHandler(); +#ifdef _WIN32 + /// Windows does not support signals and this handler must be called manually. + void CallOneShotPipeSignalHandler(); +#endif + /// This function does the following: /// - clean up any temporary files registered with RemoveFileOnSignal() /// - dump the callstack from the exception context diff --git a/llvm/include/llvm/TargetParser/RISCVTargetParser.h b/llvm/include/llvm/TargetParser/RISCVTargetParser.h index da2ecd8c1339..f50576b8fee1 100644 --- a/llvm/include/llvm/TargetParser/RISCVTargetParser.h +++ b/llvm/include/llvm/TargetParser/RISCVTargetParser.h @@ -18,6 +18,9 @@ #include <vector> namespace llvm { + +class Triple; + namespace RISCV { // We use 64 bits as the known part in the scalable vector types. @@ -38,6 +41,8 @@ void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64); void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64); bool getCPUFeaturesExceptStdExt(CPUKind Kind, std::vector<StringRef> &Features); +bool isX18ReservedByDefault(const Triple &TT); + } // namespace RISCV } // namespace llvm diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 8d600989c8cf..59513fa2f206 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -882,6 +882,14 @@ public: return getArch() == Triple::ppc64 || getArch() == Triple::ppc64le; } + /// Tests whether the target 64-bit PowerPC big endian ABI is ELFv2. + bool isPPC64ELFv2ABI() const { + return (getArch() == Triple::ppc64 && + ((getOS() == Triple::FreeBSD && + (getOSMajorVersion() >= 13 || getOSVersion().empty())) || + getOS() == Triple::OpenBSD || isMusl())); + } + /// Tests whether the target is 32-bit RISC-V. bool isRISCV32() const { return getArch() == Triple::riscv32; } diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index f1587cecf9fb..0e9fab667e6e 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -1673,11 +1673,6 @@ ConstantRange LazyValueInfo::getConstantRangeAtUse(const Use &U, // TODO: Use non-local query? CondVal = getEdgeValueLocal(V, PHI->getIncomingBlock(*CurrU), PHI->getParent()); - } else if (!isSafeToSpeculativelyExecute(CurrI)) { - // Stop walking if we hit a non-speculatable instruction. Even if the - // result is only used under a specific condition, executing the - // instruction itself may cause side effects or UB already. - break; } if (CondVal && CondVal->isConstantRange()) CR = CR.intersectWith(CondVal->getConstantRange()); @@ -1685,7 +1680,13 @@ ConstantRange LazyValueInfo::getConstantRangeAtUse(const Use &U, // Only follow one-use chain, to allow direct intersection of conditions. // If there are multiple uses, we would have to intersect with the union of // all conditions at different uses. - if (!CurrI->hasOneUse()) + // Stop walking if we hit a non-speculatable instruction. Even if the + // result is only used under a specific condition, executing the + // instruction itself may cause side effects or UB already. + // This also disallows looking through phi nodes: If the phi node is part + // of a cycle, we might end up reasoning about values from different cycle + // iterations (PR60629). + if (!CurrI->hasOneUse() || !isSafeToSpeculativelyExecute(CurrI)) break; CurrU = &*CurrI->use_begin(); } diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0a3ebd73d272..eed3d820c120 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10447,7 +10447,8 @@ SDValue DAGCombiner::combineMinNumMaxNum(const SDLoc &DL, EVT VT, SDValue LHS, if (NegRHS == False) { SDValue Combined = combineMinNumMaxNumImpl(DL, VT, LHS, RHS, NegTrue, False, CC, TLI, DAG); - return DAG.getNode(ISD::FNEG, DL, VT, Combined); + if (Combined) + return DAG.getNode(ISD::FNEG, DL, VT, Combined); } } } @@ -12453,7 +12454,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG) { SDValue N00 = N0.getOperand(0); EVT ExtVT = cast<VTSDNode>(N0->getOperand(1))->getVT(); - if (N00.getOpcode() == ISD::TRUNCATE && (!LegalOperations || TLI.isTypeLegal(ExtVT))) { + if (N00.getOpcode() == ISD::TRUNCATE && + (!LegalTypes || TLI.isTypeLegal(ExtVT))) { SDValue T = DAG.getNode(ISD::TRUNCATE, DL, ExtVT, N00.getOperand(0)); return DAG.getNode(ISD::SIGN_EXTEND, DL, VT, T); } diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index da8b87babc2d..abd3273509ce 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -724,7 +724,9 @@ TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm) : TM(tm) { // with the Target-specific changes necessary. MaxAtomicSizeInBitsSupported = 1024; - MaxDivRemBitWidthSupported = llvm::IntegerType::MAX_INT_BITS; + // Assume that even with libcalls, no target supports wider than 128 bit + // division. + MaxDivRemBitWidthSupported = 128; MaxLargeFPConvertBitWidthSupported = llvm::IntegerType::MAX_INT_BITS; diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp index 9fa1f28eb089..6d55b755ed46 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp @@ -20,6 +20,12 @@ using namespace llvm::logicalview; #define DEBUG_TYPE "Support" +namespace { +// Unique string pool instance used by all logical readers. +LVStringPool StringPool; +} // namespace +LVStringPool &llvm::logicalview::getStringPool() { return StringPool; } + // Perform the following transformations to the given 'Path': // - all characters to lowercase. // - '\\' into '/' (Platform independent). diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index 72c008d9835e..a92dfbcc5c64 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -649,22 +649,29 @@ namespace { // vectorcall - foo@@12 // These are all different linkage names for 'foo'. StringRef demanglePE32ExternCFunc(StringRef SymbolName) { - // Remove any '_' or '@' prefix. char Front = SymbolName.empty() ? '\0' : SymbolName[0]; - if (Front == '_' || Front == '@') - SymbolName = SymbolName.drop_front(); // Remove any '@[0-9]+' suffix. + bool HasAtNumSuffix = false; if (Front != '?') { size_t AtPos = SymbolName.rfind('@'); if (AtPos != StringRef::npos && - all_of(drop_begin(SymbolName, AtPos + 1), isDigit)) + all_of(drop_begin(SymbolName, AtPos + 1), isDigit)) { SymbolName = SymbolName.substr(0, AtPos); + HasAtNumSuffix = true; + } } // Remove any ending '@' for vectorcall. - if (SymbolName.endswith("@")) + bool IsVectorCall = false; + if (HasAtNumSuffix && SymbolName.endswith("@")) { SymbolName = SymbolName.drop_back(); + IsVectorCall = true; + } + + // If not vectorcall, remove any '_' or '@' prefix. + if (!IsVectorCall && (Front == '_' || Front == '@')) + SymbolName = SymbolName.drop_front(); return SymbolName; } @@ -692,8 +699,14 @@ LLVMSymbolizer::DemangleName(const std::string &Name, return Result; } - if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module()) - return std::string(demanglePE32ExternCFunc(Name)); + if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module()) { + std::string DemangledCName(demanglePE32ExternCFunc(Name)); + // On i386 Windows, the C name mangling for different calling conventions + // may also be applied on top of the Itanium or Rust name mangling. + if (nonMicrosoftDemangle(DemangledCName.c_str(), Result)) + return Result; + return DemangledCName; + } return Name; } diff --git a/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_unix.S b/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_unix.S index 449e07492832..69fc0936d73c 100644 --- a/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_unix.S +++ b/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_unix.S @@ -1,5 +1,7 @@ #if defined(__x86_64__) +#include "llvm_blake3_prefix.h" + #if defined(__ELF__) && defined(__linux__) .section .note.GNU-stack,"",%progbits #endif diff --git a/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_windows_gnu.S b/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_windows_gnu.S index bb58d2ae64b1..5ad1c641a7fc 100644 --- a/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_windows_gnu.S +++ b/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_windows_gnu.S @@ -1,3 +1,5 @@ +#include "llvm_blake3_prefix.h" + .intel_syntax noprefix .global _blake3_hash_many_avx2 .global blake3_hash_many_avx2 diff --git a/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_windows_msvc.asm b/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_windows_msvc.asm index 352298edd2e8..46bad1d98f38 100644 --- a/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_windows_msvc.asm +++ b/llvm/lib/Support/BLAKE3/blake3_avx2_x86-64_windows_msvc.asm @@ -1,11 +1,11 @@ -public _blake3_hash_many_avx2 -public blake3_hash_many_avx2 +public _llvm_blake3_hash_many_avx2 +public llvm_blake3_hash_many_avx2 _TEXT SEGMENT ALIGN(16) 'CODE' ALIGN 16 -blake3_hash_many_avx2 PROC -_blake3_hash_many_avx2 PROC +llvm_blake3_hash_many_avx2 PROC +_llvm_blake3_hash_many_avx2 PROC push r15 push r14 push r13 @@ -1785,8 +1785,8 @@ endroundloop1: vmovdqu xmmword ptr [rbx+10H], xmm1 jmp unwind -_blake3_hash_many_avx2 ENDP -blake3_hash_many_avx2 ENDP +_llvm_blake3_hash_many_avx2 ENDP +llvm_blake3_hash_many_avx2 ENDP _TEXT ENDS _RDATA SEGMENT READONLY PAGE ALIAS(".rdata") 'CONST' diff --git a/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_unix.S b/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_unix.S index 3afc0e2250e2..f04a135dd1bc 100644 --- a/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_unix.S +++ b/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_unix.S @@ -1,5 +1,7 @@ #if defined(__x86_64__) +#include "llvm_blake3_prefix.h" + #if defined(__ELF__) && defined(__linux__) .section .note.GNU-stack,"",%progbits #endif diff --git a/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_windows_gnu.S b/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_windows_gnu.S index e10b9f36cbcc..53c586141fbe 100644 --- a/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_windows_gnu.S +++ b/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_windows_gnu.S @@ -1,3 +1,5 @@ +#include "llvm_blake3_prefix.h" + .intel_syntax noprefix .global _blake3_hash_many_avx512 diff --git a/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_windows_msvc.asm b/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_windows_msvc.asm index b19efbaaeb36..f13d1b260ab8 100644 --- a/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_windows_msvc.asm +++ b/llvm/lib/Support/BLAKE3/blake3_avx512_x86-64_windows_msvc.asm @@ -1,15 +1,15 @@ -public _blake3_hash_many_avx512 -public blake3_hash_many_avx512 -public blake3_compress_in_place_avx512 -public _blake3_compress_in_place_avx512 -public blake3_compress_xof_avx512 -public _blake3_compress_xof_avx512 +public _llvm_blake3_hash_many_avx512 +public llvm_blake3_hash_many_avx512 +public llvm_blake3_compress_in_place_avx512 +public _llvm_blake3_compress_in_place_avx512 +public llvm_blake3_compress_xof_avx512 +public _llvm_blake3_compress_xof_avx512 _TEXT SEGMENT ALIGN(16) 'CODE' ALIGN 16 -blake3_hash_many_avx512 PROC -_blake3_hash_many_avx512 PROC +llvm_blake3_hash_many_avx512 PROC +_llvm_blake3_hash_many_avx512 PROC push r15 push r14 push r13 @@ -2404,12 +2404,12 @@ endroundloop1: vmovdqu xmmword ptr [rbx+10H], xmm1 jmp unwind -_blake3_hash_many_avx512 ENDP -blake3_hash_many_avx512 ENDP +_llvm_blake3_hash_many_avx512 ENDP +llvm_blake3_hash_many_avx512 ENDP ALIGN 16 -blake3_compress_in_place_avx512 PROC -_blake3_compress_in_place_avx512 PROC +llvm_blake3_compress_in_place_avx512 PROC +_llvm_blake3_compress_in_place_avx512 PROC sub rsp, 72 vmovdqa xmmword ptr [rsp], xmm6 vmovdqa xmmword ptr [rsp+10H], xmm7 @@ -2498,12 +2498,12 @@ _blake3_compress_in_place_avx512 PROC vmovdqa xmm9, xmmword ptr [rsp+30H] add rsp, 72 ret -_blake3_compress_in_place_avx512 ENDP -blake3_compress_in_place_avx512 ENDP +_llvm_blake3_compress_in_place_avx512 ENDP +llvm_blake3_compress_in_place_avx512 ENDP ALIGN 16 -blake3_compress_xof_avx512 PROC -_blake3_compress_xof_avx512 PROC +llvm_blake3_compress_xof_avx512 PROC +_llvm_blake3_compress_xof_avx512 PROC sub rsp, 72 vmovdqa xmmword ptr [rsp], xmm6 vmovdqa xmmword ptr [rsp+10H], xmm7 @@ -2597,8 +2597,8 @@ _blake3_compress_xof_avx512 PROC vmovdqa xmm9, xmmword ptr [rsp+30H] add rsp, 72 ret -_blake3_compress_xof_avx512 ENDP -blake3_compress_xof_avx512 ENDP +_llvm_blake3_compress_xof_avx512 ENDP +llvm_blake3_compress_xof_avx512 ENDP _TEXT ENDS diff --git a/llvm/lib/Support/BLAKE3/blake3_impl.h b/llvm/lib/Support/BLAKE3/blake3_impl.h index 180d0a6eeda8..8e5456d745cd 100644 --- a/llvm/lib/Support/BLAKE3/blake3_impl.h +++ b/llvm/lib/Support/BLAKE3/blake3_impl.h @@ -11,15 +11,7 @@ // For \p LLVM_LIBRARY_VISIBILITY #include "llvm/Support/Compiler.h" -// Remove the 'llvm_' prefix for the rest of the internal implementation. -#define BLAKE3_VERSION_STRING LLVM_BLAKE3_VERSION_STRING -#define BLAKE3_KEY_LEN LLVM_BLAKE3_KEY_LEN -#define BLAKE3_OUT_LEN LLVM_BLAKE3_OUT_LEN -#define BLAKE3_BLOCK_LEN LLVM_BLAKE3_BLOCK_LEN -#define BLAKE3_CHUNK_LEN LLVM_BLAKE3_CHUNK_LEN -#define BLAKE3_MAX_DEPTH LLVM_BLAKE3_MAX_DEPTH -#define blake3_hasher llvm_blake3_hasher -#define blake3_chunk_state llvm_blake3_chunk_state +#include "llvm_blake3_prefix.h" // internal flags enum blake3_flags { diff --git a/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_unix.S b/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_unix.S index 0106b13ba851..9a4f5eb7318b 100644 --- a/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_unix.S +++ b/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_unix.S @@ -1,5 +1,7 @@ #if defined(__x86_64__) +#include "llvm_blake3_prefix.h" + #if defined(__ELF__) && defined(__linux__) .section .note.GNU-stack,"",%progbits #endif diff --git a/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_windows_gnu.S b/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_windows_gnu.S index 8852ba5976e1..bf3b4523a9f1 100644 --- a/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_windows_gnu.S +++ b/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_windows_gnu.S @@ -1,3 +1,5 @@ +#include "llvm_blake3_prefix.h" + .intel_syntax noprefix .global blake3_hash_many_sse2 .global _blake3_hash_many_sse2 diff --git a/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_windows_msvc.asm b/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_windows_msvc.asm index 507502f11a80..1069c8df4ed6 100644 --- a/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_windows_msvc.asm +++ b/llvm/lib/Support/BLAKE3/blake3_sse2_x86-64_windows_msvc.asm @@ -1,15 +1,15 @@ -public _blake3_hash_many_sse2 -public blake3_hash_many_sse2 -public blake3_compress_in_place_sse2 -public _blake3_compress_in_place_sse2 -public blake3_compress_xof_sse2 -public _blake3_compress_xof_sse2 +public _llvm_blake3_hash_many_sse2 +public llvm_blake3_hash_many_sse2 +public llvm_blake3_compress_in_place_sse2 +public _llvm_blake3_compress_in_place_sse2 +public llvm_blake3_compress_xof_sse2 +public _llvm_blake3_compress_xof_sse2 _TEXT SEGMENT ALIGN(16) 'CODE' ALIGN 16 -blake3_hash_many_sse2 PROC -_blake3_hash_many_sse2 PROC +llvm_blake3_hash_many_sse2 PROC +_llvm_blake3_hash_many_sse2 PROC push r15 push r14 push r13 @@ -2034,11 +2034,11 @@ endroundloop1: movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+10H], xmm1 jmp unwind -_blake3_hash_many_sse2 ENDP -blake3_hash_many_sse2 ENDP +_llvm_blake3_hash_many_sse2 ENDP +llvm_blake3_hash_many_sse2 ENDP -blake3_compress_in_place_sse2 PROC -_blake3_compress_in_place_sse2 PROC +llvm_blake3_compress_in_place_sse2 PROC +_llvm_blake3_compress_in_place_sse2 PROC sub rsp, 120 movdqa xmmword ptr [rsp], xmm6 movdqa xmmword ptr [rsp+10H], xmm7 @@ -2164,12 +2164,12 @@ _blake3_compress_in_place_sse2 PROC movdqa xmm15, xmmword ptr [rsp+60H] add rsp, 120 ret -_blake3_compress_in_place_sse2 ENDP -blake3_compress_in_place_sse2 ENDP +_llvm_blake3_compress_in_place_sse2 ENDP +llvm_blake3_compress_in_place_sse2 ENDP ALIGN 16 -blake3_compress_xof_sse2 PROC -_blake3_compress_xof_sse2 PROC +llvm_blake3_compress_xof_sse2 PROC +_llvm_blake3_compress_xof_sse2 PROC sub rsp, 120 movdqa xmmword ptr [rsp], xmm6 movdqa xmmword ptr [rsp+10H], xmm7 @@ -2302,8 +2302,8 @@ _blake3_compress_xof_sse2 PROC movdqa xmm15, xmmword ptr [rsp+60H] add rsp, 120 ret -_blake3_compress_xof_sse2 ENDP -blake3_compress_xof_sse2 ENDP +_llvm_blake3_compress_xof_sse2 ENDP +llvm_blake3_compress_xof_sse2 ENDP _TEXT ENDS diff --git a/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_unix.S b/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_unix.S index 4e918c5bb2cc..1be4ed744426 100644 --- a/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_unix.S +++ b/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_unix.S @@ -1,5 +1,7 @@ #if defined(__x86_64__) +#include "llvm_blake3_prefix.h" + #if defined(__ELF__) && defined(__linux__) .section .note.GNU-stack,"",%progbits #endif diff --git a/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_windows_gnu.S b/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_windows_gnu.S index 60d0a4042e71..28bdf3890a29 100644 --- a/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_windows_gnu.S +++ b/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_windows_gnu.S @@ -1,3 +1,5 @@ +#include "llvm_blake3_prefix.h" + .intel_syntax noprefix .global blake3_hash_many_sse41 .global _blake3_hash_many_sse41 diff --git a/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_windows_msvc.asm b/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_windows_msvc.asm index 8966c7b84406..770935372cd9 100644 --- a/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_windows_msvc.asm +++ b/llvm/lib/Support/BLAKE3/blake3_sse41_x86-64_windows_msvc.asm @@ -1,15 +1,15 @@ -public _blake3_hash_many_sse41 -public blake3_hash_many_sse41 -public blake3_compress_in_place_sse41 -public _blake3_compress_in_place_sse41 -public blake3_compress_xof_sse41 -public _blake3_compress_xof_sse41 +public _llvm_blake3_hash_many_sse41 +public llvm_blake3_hash_many_sse41 +public llvm_blake3_compress_in_place_sse41 +public _llvm_blake3_compress_in_place_sse41 +public llvm_blake3_compress_xof_sse41 +public _llvm_blake3_compress_xof_sse41 _TEXT SEGMENT ALIGN(16) 'CODE' ALIGN 16 -blake3_hash_many_sse41 PROC -_blake3_hash_many_sse41 PROC +llvm_blake3_hash_many_sse41 PROC +_llvm_blake3_hash_many_sse41 PROC push r15 push r14 push r13 @@ -1797,11 +1797,11 @@ endroundloop1: movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+10H], xmm1 jmp unwind -_blake3_hash_many_sse41 ENDP -blake3_hash_many_sse41 ENDP +_llvm_blake3_hash_many_sse41 ENDP +llvm_blake3_hash_many_sse41 ENDP -blake3_compress_in_place_sse41 PROC -_blake3_compress_in_place_sse41 PROC +llvm_blake3_compress_in_place_sse41 PROC +_llvm_blake3_compress_in_place_sse41 PROC sub rsp, 120 movdqa xmmword ptr [rsp], xmm6 movdqa xmmword ptr [rsp+10H], xmm7 @@ -1916,12 +1916,12 @@ _blake3_compress_in_place_sse41 PROC movdqa xmm15, xmmword ptr [rsp+60H] add rsp, 120 ret -_blake3_compress_in_place_sse41 ENDP -blake3_compress_in_place_sse41 ENDP +_llvm_blake3_compress_in_place_sse41 ENDP +llvm_blake3_compress_in_place_sse41 ENDP ALIGN 16 -blake3_compress_xof_sse41 PROC -_blake3_compress_xof_sse41 PROC +llvm_blake3_compress_xof_sse41 PROC +_llvm_blake3_compress_xof_sse41 PROC sub rsp, 120 movdqa xmmword ptr [rsp], xmm6 movdqa xmmword ptr [rsp+10H], xmm7 @@ -2043,8 +2043,8 @@ _blake3_compress_xof_sse41 PROC movdqa xmm15, xmmword ptr [rsp+60H] add rsp, 120 ret -_blake3_compress_xof_sse41 ENDP -blake3_compress_xof_sse41 ENDP +_llvm_blake3_compress_xof_sse41 ENDP +llvm_blake3_compress_xof_sse41 ENDP _TEXT ENDS diff --git a/llvm/lib/Support/BLAKE3/llvm_blake3_prefix.h b/llvm/lib/Support/BLAKE3/llvm_blake3_prefix.h new file mode 100644 index 000000000000..3cee3691e4cf --- /dev/null +++ b/llvm/lib/Support/BLAKE3/llvm_blake3_prefix.h @@ -0,0 +1,41 @@ +#ifndef LLVM_BLAKE3_PREFIX_H +#define LLVM_BLAKE3_PREFIX_H + +#define BLAKE3_VERSION_STRING LLVM_BLAKE3_VERSION_STRING +#define BLAKE3_KEY_LEN LLVM_BLAKE3_KEY_LEN +#define BLAKE3_OUT_LEN LLVM_BLAKE3_OUT_LEN +#define BLAKE3_BLOCK_LEN LLVM_BLAKE3_BLOCK_LEN +#define BLAKE3_CHUNK_LEN LLVM_BLAKE3_CHUNK_LEN +#define BLAKE3_MAX_DEPTH LLVM_BLAKE3_MAX_DEPTH +#define blake3_hasher llvm_blake3_hasher +#define blake3_chunk_state llvm_blake3_chunk_state +#define blake3_compress_in_place llvm_blake3_compress_in_place +#define blake3_compress_xof llvm_blake3_compress_xof +#define blake3_hash_many llvm_blake3_hash_many +#define blake3_simd_degree llvm_blake3_simd_degree +#define blake3_compress_in_place_portable llvm_blake3_compress_in_place_portable +#define blake3_compress_xof_portable llvm_blake3_compress_xof_portable +#define blake3_hash_many_portable llvm_blake3_hash_many_portable +#define blake3_compress_in_place_sse2 llvm_blake3_compress_in_place_sse2 +#define _blake3_compress_in_place_sse2 _llvm_blake3_compress_in_place_sse2 +#define blake3_compress_xof_sse2 llvm_blake3_compress_xof_sse2 +#define _blake3_compress_xof_sse2 _llvm_blake3_compress_xof_sse2 +#define blake3_hash_many_sse2 llvm_blake3_hash_many_sse2 +#define _blake3_hash_many_sse2 _llvm_blake3_hash_many_sse2 +#define blake3_compress_in_place_sse41 llvm_blake3_compress_in_place_sse41 +#define _blake3_compress_in_place_sse41 _llvm_blake3_compress_in_place_sse41 +#define blake3_compress_xof_sse41 llvm_blake3_compress_xof_sse41 +#define _blake3_compress_xof_sse41 _llvm_blake3_compress_xof_sse41 +#define blake3_hash_many_sse41 llvm_blake3_hash_many_sse41 +#define _blake3_hash_many_sse41 _llvm_blake3_hash_many_sse41 +#define blake3_hash_many_avx2 llvm_blake3_hash_many_avx2 +#define _blake3_hash_many_avx2 _llvm_blake3_hash_many_avx2 +#define blake3_compress_in_place_avx512 llvm_blake3_compress_in_place_avx512 +#define _blake3_compress_in_place_avx512 _llvm_blake3_compress_in_place_avx512 +#define blake3_compress_xof_avx512 llvm_blake3_compress_xof_avx512 +#define _blake3_compress_xof_avx512 _llvm_blake3_compress_xof_avx512 +#define blake3_hash_many_avx512 llvm_blake3_hash_many_avx512 +#define _blake3_hash_many_avx512 _llvm_blake3_hash_many_avx512 +#define blake3_hash_many_neon llvm_blake3_hash_many_neon + +#endif /* LLVM_BLAKE3_PREFIX_H */ diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index 1b1bff023d2f..b14fe1358d1f 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -503,6 +503,67 @@ RISCVISAInfo::parseFeatures(unsigned XLen, } llvm::Expected<std::unique_ptr<RISCVISAInfo>> +RISCVISAInfo::parseNormalizedArchString(StringRef Arch) { + if (llvm::any_of(Arch, isupper)) { + return createStringError(errc::invalid_argument, + "string must be lowercase"); + } + // Must start with a valid base ISA name. + unsigned XLen; + if (Arch.startswith("rv32i") || Arch.startswith("rv32e")) + XLen = 32; + else if (Arch.startswith("rv64i") || Arch.startswith("rv64e")) + XLen = 64; + else + return createStringError(errc::invalid_argument, + "arch string must begin with valid base ISA"); + std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); + // Discard rv32/rv64 prefix. + Arch = Arch.substr(4); + + // Each extension is of the form ${name}${major_version}p${minor_version} + // and separated by _. Split by _ and then extract the name and version + // information for each extension. + SmallVector<StringRef, 8> Split; + Arch.split(Split, '_'); + for (StringRef Ext : Split) { + StringRef Prefix, MinorVersionStr; + std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p'); + if (MinorVersionStr.empty()) + return createStringError(errc::invalid_argument, + "extension lacks version in expected format"); + unsigned MajorVersion, MinorVersion; + if (MinorVersionStr.getAsInteger(10, MinorVersion)) + return createStringError(errc::invalid_argument, + "failed to parse minor version number"); + + // Split Prefix into the extension name and the major version number + // (the trailing digits of Prefix). + int TrailingDigits = 0; + StringRef ExtName = Prefix; + while (!ExtName.empty()) { + if (!isDigit(ExtName.back())) + break; + ExtName = ExtName.drop_back(1); + TrailingDigits++; + } + if (!TrailingDigits) + return createStringError(errc::invalid_argument, + "extension lacks version in expected format"); + + StringRef MajorVersionStr = Prefix.take_back(TrailingDigits); + if (MajorVersionStr.getAsInteger(10, MajorVersion)) + return createStringError(errc::invalid_argument, + "failed to parse major version number"); + ISAInfo->addExtension(ExtName, MajorVersion, MinorVersion); + } + ISAInfo->updateFLen(); + ISAInfo->updateMinVLen(); + ISAInfo->updateMaxELen(); + return std::move(ISAInfo); +} + +llvm::Expected<std::unique_ptr<RISCVISAInfo>> RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck, bool IgnoreUnknown) { diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc index 92cf4fcda5a6..7106a67b576a 100644 --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -650,8 +650,6 @@ bool equivalent(file_status A, file_status B) { return A.FileIndexHigh == B.FileIndexHigh && A.FileIndexLow == B.FileIndexLow && A.FileSizeHigh == B.FileSizeHigh && A.FileSizeLow == B.FileSizeLow && - A.LastAccessedTimeHigh == B.LastAccessedTimeHigh && - A.LastAccessedTimeLow == B.LastAccessedTimeLow && A.LastWriteTimeHigh == B.LastWriteTimeHigh && A.LastWriteTimeLow == B.LastWriteTimeLow && A.VolumeSerialNumber == B.VolumeSerialNumber; diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc index ba93afe0803b..cb82f55fc38b 100644 --- a/llvm/lib/Support/Windows/Signals.inc +++ b/llvm/lib/Support/Windows/Signals.inc @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/ExitCodes.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" @@ -204,6 +205,9 @@ static bool RegisteredUnhandledExceptionFilter = false; static bool CleanupExecuted = false; static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; +/// The function to call on "SIGPIPE" (one-time use only). +static std::atomic<void (*)()> OneShotPipeSignalFunction(nullptr); + // Windows creates a new thread to execute the console handler when an event // (such as CTRL/C) occurs. This causes concurrency issues with the above // globals which this critical section addresses. @@ -575,11 +579,16 @@ void llvm::sys::SetInfoSignalFunction(void (*Handler)()) { } void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) { - // Unimplemented. + OneShotPipeSignalFunction.exchange(Handler); } void llvm::sys::DefaultOneShotPipeSignalHandler() { - // Unimplemented. + llvm::sys::Process::Exit(EX_IOERR, /*NoCleanup=*/true); +} + +void llvm::sys::CallOneShotPipeSignalHandler() { + if (auto OldOneShotPipeFunction = OneShotPipeSignalFunction.exchange(nullptr)) + OldOneShotPipeFunction(); } /// Add a function to be called when a signal is delivered to the process. The @@ -816,7 +825,15 @@ WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) { } void sys::CleanupOnSignal(uintptr_t Context) { - LLVMUnhandledExceptionFilter((LPEXCEPTION_POINTERS)Context); + LPEXCEPTION_POINTERS EP = (LPEXCEPTION_POINTERS)Context; + // Broken pipe is not a crash. + // + // 0xE0000000 is combined with the return code in the exception raised in + // CrashRecoveryContext::HandleExit(). + unsigned RetCode = EP->ExceptionRecord->ExceptionCode; + if (RetCode == (0xE0000000 | EX_IOERR)) + return; + LLVMUnhandledExceptionFilter(EP); } static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { diff --git a/llvm/lib/Support/Z3Solver.cpp b/llvm/lib/Support/Z3Solver.cpp index a49bedcfd2b0..eb671fe2596d 100644 --- a/llvm/lib/Support/Z3Solver.cpp +++ b/llvm/lib/Support/Z3Solver.cpp @@ -729,7 +729,7 @@ public: const Z3_sort Z3Sort = toZ3Sort(*getBitvectorSort(BitWidth)).Sort; // Slow path, when 64 bits are not enough. - if (LLVM_UNLIKELY(Int.getBitWidth() > 64u)) { + if (LLVM_UNLIKELY(!Int.isRepresentableByInt64())) { SmallString<40> Buffer; Int.toString(Buffer, 10); return newExprRef(Z3Expr( diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp index 8943c4478c7f..7b9b8b2f53fb 100644 --- a/llvm/lib/Support/raw_ostream.cpp +++ b/llvm/lib/Support/raw_ostream.cpp @@ -56,6 +56,7 @@ #ifdef _WIN32 #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/Windows/WindowsSupport.h" #endif @@ -775,6 +776,15 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { ) continue; +#ifdef _WIN32 + // Windows equivalents of SIGPIPE/EPIPE. + DWORD WinLastError = GetLastError(); + if (WinLastError == ERROR_BROKEN_PIPE || + (WinLastError == ERROR_NO_DATA && errno == EINVAL)) { + llvm::sys::CallOneShotPipeSignalHandler(); + errno = EPIPE; + } +#endif // Otherwise it's a non-recoverable error. Note it and quit. error_detected(std::error_code(errno, std::generic_category())); break; diff --git a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp index 248bd3130c25..9a2cf94edfe6 100644 --- a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp +++ b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp @@ -71,7 +71,7 @@ static cl::opt<bool> ErrorMissingParenthesis( static cl::opt<bool> WarnSignedMismatch( "mwarn-sign-mismatch", cl::desc("Warn for mismatching a signed and unsigned value"), - cl::init(true)); + cl::init(false)); static cl::opt<bool> WarnNoncontigiousRegister( "mwarn-noncontigious-register", cl::desc("Warn for register names that arent contigious"), cl::init(true)); diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp index 9aea5af8a60a..b17e2766a7a1 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -237,7 +237,10 @@ static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, case Triple::ppc64le: return PPCTargetMachine::PPC_ABI_ELFv2; case Triple::ppc64: - return PPCTargetMachine::PPC_ABI_ELFv1; + if (TT.isPPC64ELFv2ABI()) + return PPCTargetMachine::PPC_ABI_ELFv2; + else + return PPCTargetMachine::PPC_ABI_ELFv1; default: return PPCTargetMachine::PPC_ABI_UNKNOWN; } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index a8720d070acb..6eea169f8919 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -14211,6 +14211,25 @@ bool RISCVTargetLowering::preferScalarizeSplat(unsigned Opc) const { return true; } +static Value *useTpOffset(IRBuilderBase &IRB, unsigned Offset) { + Module *M = IRB.GetInsertBlock()->getParent()->getParent(); + Function *ThreadPointerFunc = + Intrinsic::getDeclaration(M, Intrinsic::thread_pointer); + return IRB.CreatePointerCast( + IRB.CreateConstGEP1_32(IRB.getInt8Ty(), + IRB.CreateCall(ThreadPointerFunc), Offset), + IRB.getInt8PtrTy()->getPointerTo(0)); +} + +Value *RISCVTargetLowering::getIRStackGuard(IRBuilderBase &IRB) const { + // Fuchsia provides a fixed TLS slot for the stack cookie. + // <zircon/tls.h> defines ZX_TLS_STACK_GUARD_OFFSET with this value. + if (Subtarget.isTargetFuchsia()) + return useTpOffset(IRB, -0x10); + + return TargetLowering::getIRStackGuard(IRB); +} + #define GET_REGISTER_MATCHER #include "RISCVGenAsmMatcher.inc" diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index acf92cab3598..5086e6c0bdaf 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -618,6 +618,10 @@ public: return Scale == 1; } + /// If the target has a standard location for the stack protector cookie, + /// returns the address of that location. Otherwise, returns nullptr. + Value *getIRStackGuard(IRBuilderBase &IRB) const override; + private: /// RISCVCCAssignFn - This target-specific function extends the default /// CCValAssign with additional information used to lower RISC-V calling diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp index c935dad1687f..d0bb4634d03d 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp @@ -83,6 +83,9 @@ RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, FrameLowering( initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) { + if (RISCV::isX18ReservedByDefault(TT)) + UserReservedRegister.set(RISCV::X18); + CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering())); Legalizer.reset(new RISCVLegalizerInfo(*this)); diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index 678d218a6719..290c7b03ea81 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -176,6 +176,8 @@ public: const LegalizerInfo *getLegalizerInfo() const override; const RegisterBankInfo *getRegBankInfo() const override; + bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); } + bool useConstantPoolForLargeInts() const; // Maximum cost used for building integers, integers will be put into constant diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index d69e2c3ed493..181de6abb2c5 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -4020,7 +4020,10 @@ bool X86DAGToDAGISel::tryShiftAmountMod(SDNode *N) { EVT OpVT = ShiftAmt.getValueType(); - NewShiftAmt = CurDAG->getNOT(DL, Add0C == nullptr ? Add0 : Add1, OpVT); + SDValue AllOnes = CurDAG->getAllOnesConstant(DL, OpVT); + NewShiftAmt = CurDAG->getNode(ISD::XOR, DL, OpVT, + Add0C == nullptr ? Add0 : Add1, AllOnes); + insertDAGNode(*CurDAG, OrigShiftAmt, AllOnes); insertDAGNode(*CurDAG, OrigShiftAmt, NewShiftAmt); // If we are shifting by N-X where N == 0 mod Size, then just shift by // -X to generate a NEG instead of a SUB of a constant. diff --git a/llvm/lib/TargetParser/RISCVTargetParser.cpp b/llvm/lib/TargetParser/RISCVTargetParser.cpp index 89cd5c082d72..933a82b7c6cb 100644 --- a/llvm/lib/TargetParser/RISCVTargetParser.cpp +++ b/llvm/lib/TargetParser/RISCVTargetParser.cpp @@ -14,6 +14,7 @@ #include "llvm/TargetParser/RISCVTargetParser.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/TargetParser/Triple.h" namespace llvm { namespace RISCV { @@ -100,5 +101,10 @@ bool getCPUFeaturesExceptStdExt(CPUKind Kind, return true; } +bool isX18ReservedByDefault(const Triple &TT) { + // X18 is reserved for the ShadowCallStack ABI (even when not enabled). + return TT.isOSFuchsia(); +} + } // namespace RISCV } // namespace llvm diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index b9134ce26e80..84013a8909db 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -396,6 +396,18 @@ static bool getPotentialCopiesOfMemoryValue( NullOnly = false; }; + auto AdjustWrittenValueType = [&](const AAPointerInfo::Access &Acc, + Value &V) { + Value *AdjV = AA::getWithType(V, *I.getType()); + if (!AdjV) { + LLVM_DEBUG(dbgs() << "Underlying object written but stored value " + "cannot be converted to read type: " + << *Acc.getRemoteInst() << " : " << *I.getType() + << "\n";); + } + return AdjV; + }; + auto CheckAccess = [&](const AAPointerInfo::Access &Acc, bool IsExact) { if ((IsLoad && !Acc.isWriteOrAssumption()) || (!IsLoad && !Acc.isRead())) return true; @@ -417,7 +429,10 @@ static bool getPotentialCopiesOfMemoryValue( if (IsLoad) { assert(isa<LoadInst>(I) && "Expected load or store instruction only!"); if (!Acc.isWrittenValueUnknown()) { - NewCopies.push_back(Acc.getWrittenValue()); + Value *V = AdjustWrittenValueType(Acc, *Acc.getWrittenValue()); + if (!V) + return false; + NewCopies.push_back(V); NewCopyOrigins.push_back(Acc.getRemoteInst()); return true; } @@ -428,7 +443,10 @@ static bool getPotentialCopiesOfMemoryValue( << *Acc.getRemoteInst() << "\n";); return false; } - NewCopies.push_back(SI->getValueOperand()); + Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand()); + if (!V) + return false; + NewCopies.push_back(V); NewCopyOrigins.push_back(SI); } else { assert(isa<StoreInst>(I) && "Expected load or store instruction only!"); diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index a28099d8ba7d..148f2c545b41 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -5953,7 +5953,7 @@ LoopVectorizationCostModel::calculateRegisterUsage(ArrayRef<ElementCount> VFs) { // Saves the list of values that are used in the loop but are defined outside // the loop (not including non-instruction values such as arguments and // constants). - SmallPtrSet<Value *, 8> LoopInvariants; + SmallPtrSet<Instruction *, 8> LoopInvariants; for (BasicBlock *BB : make_range(DFS.beginRPO(), DFS.endRPO())) { for (Instruction &I : BB->instructionsWithoutDebug()) { @@ -6079,11 +6079,16 @@ LoopVectorizationCostModel::calculateRegisterUsage(ArrayRef<ElementCount> VFs) { for (auto *Inst : LoopInvariants) { // FIXME: The target might use more than one register for the type // even in the scalar case. - unsigned Usage = - VFs[i].isScalar() ? 1 : GetRegUsage(Inst->getType(), VFs[i]); + bool IsScalar = all_of(Inst->users(), [&](User *U) { + auto *I = cast<Instruction>(U); + return TheLoop != LI->getLoopFor(I->getParent()) || + isScalarAfterVectorization(I, VFs[i]); + }); + + ElementCount VF = IsScalar ? ElementCount::getFixed(1) : VFs[i]; unsigned ClassID = - TTI.getRegisterClassForType(VFs[i].isVector(), Inst->getType()); - Invariant[ClassID] += Usage; + TTI.getRegisterClassForType(VF.isVector(), Inst->getType()); + Invariant[ClassID] += GetRegUsage(Inst->getType(), VF); } LLVM_DEBUG({ diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index 7366059cd242..7b71d5ad4554 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -635,7 +635,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { "dump-collected-objects", cl::Optional, cl::Hidden, cl::desc("Show the collected coverage object files")); - cl::list<std::string> InputSourceFiles(cl::Positional, + cl::list<std::string> InputSourceFiles("sources", cl::Positional, cl::desc("<Source files>")); cl::opt<bool> DebugDumpCollectedPaths( diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h index 1b07dca9031d..c78f3eeaf7cd 100644 --- a/openmp/runtime/src/kmp_os.h +++ b/openmp/runtime/src/kmp_os.h @@ -610,7 +610,7 @@ inline kmp_int32 __kmp_compare_and_store_ptr(void *volatile *p, void *cv, #define KMP_XCHG_FIXED8(p, v) \ _InterlockedExchange8((volatile kmp_int8 *)(p), (kmp_int8)(v)); #define KMP_XCHG_FIXED16(p, v) _InterlockedExchange16((p), (v)); -#define KMP_XCHG_REAL64(p, v) __kmp_xchg_real64((p), (v))); +#define KMP_XCHG_REAL64(p, v) __kmp_xchg_real64((p), (v)); inline kmp_real64 __kmp_xchg_real64(volatile kmp_real64 *p, kmp_real64 v) { kmp_int64 tmp = _InterlockedExchange64((volatile kmp_int64 *)p, *(kmp_int64 diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index 7393dba90b87..88b9e58fca54 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -24,7 +24,6 @@ #include "kmp_wait_release.h" #include "kmp_wrapper_getpid.h" #include "kmp_dispatch.h" -#include <cstdio> #if KMP_USE_HIER_SCHED #include "kmp_dispatch_hier.h" #endif @@ -6917,12 +6916,11 @@ void __kmp_unregister_library(void) { // File did not open. Try the temporary file. use_shm = false; KMP_DEBUG_ASSERT(temp_reg_status_file_name); - FILE *tf = fopen(temp_reg_status_file_name, O_RDONLY); - if (!tf) { + fd1 = open(temp_reg_status_file_name, O_RDONLY); + if (fd1 == -1) { // give it up now. return; } - fd1 = fileno(tf); } char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0); if (data1 != MAP_FAILED) { diff --git a/openmp/runtime/src/kmp_safe_c_api.h b/openmp/runtime/src/kmp_safe_c_api.h index 3db1ada37b07..72f26fd9897d 100644 --- a/openmp/runtime/src/kmp_safe_c_api.h +++ b/openmp/runtime/src/kmp_safe_c_api.h @@ -30,6 +30,7 @@ #define KMP_SSCANF sscanf_s #define KMP_STRCPY_S strcpy_s #define KMP_STRNCPY_S strncpy_s +#define KMP_STRNCAT_S strncat_s // Use this only when buffer size is unknown #define KMP_MEMCPY(dst, src, cnt) memcpy_s(dst, cnt, src, cnt) @@ -61,6 +62,7 @@ template <typename T> struct kmp_get_rmax_t<T, true> { #define KMP_SSCANF sscanf #define KMP_STRCPY_S(dst, bsz, src) strcpy(dst, src) #define KMP_STRNCPY_S(dst, bsz, src, cnt) strncpy(dst, src, cnt) +#define KMP_STRNCAT_S(dst, bsz, src, cnt) strncat(dst, src, cnt) #define KMP_VSNPRINTF vsnprintf #define KMP_STRNCPY strncpy #define KMP_STRLEN strlen diff --git a/openmp/runtime/src/kmp_str.cpp b/openmp/runtime/src/kmp_str.cpp index e64f989fbc69..4cba56964a09 100644 --- a/openmp/runtime/src/kmp_str.cpp +++ b/openmp/runtime/src/kmp_str.cpp @@ -137,8 +137,8 @@ void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, size_t len) { KMP_DEBUG_ASSERT(len >= 0); __kmp_str_buf_reserve(buffer, buffer->used + len + 1); - KMP_MEMCPY(buffer->str + buffer->used, str, len); - buffer->str[buffer->used + len] = 0; + buffer->str[buffer->used] = '\0'; + KMP_STRNCAT_S(buffer->str + buffer->used, len + 1, str, len); __kmp_type_convert(buffer->used + len, &(buffer->used)); KMP_STR_BUF_INVARIANT(buffer); } // __kmp_str_buf_cat @@ -151,8 +151,8 @@ void __kmp_str_buf_catbuf(kmp_str_buf_t *dest, const kmp_str_buf_t *src) { if (!src->str || !src->used) return; __kmp_str_buf_reserve(dest, dest->used + src->used + 1); - KMP_MEMCPY(dest->str + dest->used, src->str, src->used); - dest->str[dest->used + src->used] = 0; + dest->str[dest->used] = '\0'; + KMP_STRNCAT_S(dest->str + dest->used, src->used + 1, src->str, src->used); dest->used += src->used; KMP_STR_BUF_INVARIANT(dest); } // __kmp_str_buf_catbuf diff --git a/openmp/runtime/src/z_Linux_asm.S b/openmp/runtime/src/z_Linux_asm.S index 557f3784b3c4..8aa48d10c3af 100644 --- a/openmp/runtime/src/z_Linux_asm.S +++ b/openmp/runtime/src/z_Linux_asm.S @@ -1426,7 +1426,10 @@ __tid = 8 // for when we call pkfn below push {r3-r11,lr} // Load p_argv and &exit_frame - ldrd r4, r5, [sp, #10*4] + ldr r4, [sp, #10*4] +# if OMPT_SUPPORT + ldr r5, [sp, #11*4] +# endif # if KMP_OS_DARWIN || (defined(__thumb__) && !KMP_OS_WINDOWS) # define FP r7 |