mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Vendor import of llvm-project branch release/16.x llvmorg-16.0.0-0-g08d094a0e457 (aka 16.0.0 release).
This commit is contained in:
parent
11edbfca22
commit
11ee15ea4e
120 changed files with 1821 additions and 1284 deletions
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
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);
|
||||
|
||||
// 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")
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
RetainExpansion = true;
|
||||
// We don't actually know the new pack size yet.
|
||||
PartialExpansion = {NewPackSize, Loc};
|
||||
continue;
|
||||
}
|
||||
NewPackSize = TemplateArgs(Depth, Index).pack_size();
|
||||
}
|
||||
|
||||
// FIXME: Workaround for Canonical TTP.
|
||||
const IdentifierInfo *Name = ND ? ND->getIdentifier() : nullptr;
|
||||
if (!CurNumExpansions) {
|
||||
// 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.
|
||||
NumPartialExpansions = NewPackSize;
|
||||
PartiallySubstitutedPackLoc = ParmPack.second;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
|
||||
// Compute the depth and index for this parameter pack.
|
||||
unsigned Depth;
|
||||
unsigned Index;
|
||||
|
||||
if (const TemplateTypeParmType *TTP =
|
||||
Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
|
||||
Depth = TTP->getDepth();
|
||||
Index = TTP->getIndex();
|
||||
} else {
|
||||
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
|
||||
if (isa<VarDecl>(ND)) {
|
||||
// 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;
|
||||
|
||||
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 true;
|
||||
// Determine the size of the argument pack.
|
||||
setResultSz(TemplateArgs(Depth, Index).pack_size());
|
||||
return false;
|
||||
};
|
||||
return std::nullopt;
|
||||
|
||||
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());
|
||||
} else {
|
||||
const auto *ND = I.get<const NamedDecl *>();
|
||||
// Function parameter pack or init-capture pack.
|
||||
if (isa<VarDecl>(ND)) {
|
||||
const auto *DAP =
|
||||
CurrentInstantiationScope->findInstantiationOf(ND)
|
||||
->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>();
|
||||
if (!DAP)
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,67 +40,69 @@ DependencyScanningTool::DependencyScanningTool(
|
|||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
|
||||
: Worker(Service, std::move(FS)) {}
|
||||
|
||||
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 handleFileDependency(StringRef File) override {
|
||||
Dependencies.push_back(std::string(File));
|
||||
}
|
||||
|
||||
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 handleContextHash(std::string Hash) override {}
|
||||
|
||||
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.");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
/// 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 handleFileDependency(StringRef File) override {
|
||||
Dependencies.push_back(std::string(File));
|
||||
}
|
||||
|
||||
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 handleContextHash(std::string Hash) override {}
|
||||
|
||||
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.");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<DependencyOutputOptions> Opts;
|
||||
std::vector<std::string> Dependencies;
|
||||
};
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 = __iota_view_iterator<_Start>;
|
||||
using __sentinel = __iota_view_sentinel<_Start, _BoundSentinel>;
|
||||
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_;
|
||||
}
|
||||
|
||||
_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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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> struct __iterator;
|
||||
|
||||
template<bool _Const>
|
||||
using __sentinel = __join_view_sentinel<_View, _Const>;
|
||||
|
||||
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*>;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#if defined(__x86_64__)
|
||||
|
||||
#include "llvm_blake3_prefix.h"
|
||||
|
||||
#if defined(__ELF__) && defined(__linux__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include "llvm_blake3_prefix.h"
|
||||
|
||||
.intel_syntax noprefix
|
||||
.global _blake3_hash_many_avx2
|
||||
.global blake3_hash_many_avx2
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#if defined(__x86_64__)
|
||||
|
||||
#include "llvm_blake3_prefix.h"
|
||||
|
||||
#if defined(__ELF__) && defined(__linux__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include "llvm_blake3_prefix.h"
|
||||
|
||||
.intel_syntax noprefix
|
||||
|
||||
.global _blake3_hash_many_avx512
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#if defined(__x86_64__)
|
||||
|
||||
#include "llvm_blake3_prefix.h"
|
||||
|
||||
#if defined(__ELF__) && defined(__linux__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include "llvm_blake3_prefix.h"
|
||||
|
||||
.intel_syntax noprefix
|
||||
.global blake3_hash_many_sse2
|
||||
.global _blake3_hash_many_sse2
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#if defined(__x86_64__)
|
||||
|
||||
#include "llvm_blake3_prefix.h"
|
||||
|
||||
#if defined(__ELF__) && defined(__linux__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include "llvm_blake3_prefix.h"
|
||||
|
||||
.intel_syntax noprefix
|
||||
.global blake3_hash_many_sse41
|
||||
.global _blake3_hash_many_sse41
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
41
llvm/lib/Support/BLAKE3/llvm_blake3_prefix.h
Normal file
41
llvm/lib/Support/BLAKE3/llvm_blake3_prefix.h
Normal file
|
|
@ -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 */
|
||||
|
|
@ -502,6 +502,67 @@ RISCVISAInfo::parseFeatures(unsigned XLen,
|
|||
return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue