15 changes: 10 additions & 5 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1165,19 +1165,19 @@ def client__name : JoinedOrSeparate<["-"], "client_name">;
def combine : Flag<["-", "--"], "combine">, Flags<[NoXarchOption, Unsupported]>;
def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
def config : Joined<["--"], "config=">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, CLOption, DXCOption]>, MetaVarName<"<file>">,
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, MetaVarName<"<file>">,
HelpText<"Specify configuration file">;
def : Separate<["--"], "config">, Alias<config>;
def : Separate<["--"], "config">, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Alias<config>;
def no_default_config : Flag<["--"], "no-default-config">,
Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption]>,
Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
HelpText<"Disable loading default configuration files">;
def config_system_dir_EQ : Joined<["--"], "config-system-dir=">,
Flags<[NoXarchOption, HelpHidden]>,
Visibility<[ClangOption, CLOption, DXCOption]>,
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
HelpText<"System directory for configuration files">;
def config_user_dir_EQ : Joined<["--"], "config-user-dir=">,
Flags<[NoXarchOption, HelpHidden]>,
Visibility<[ClangOption, CLOption, DXCOption]>,
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
HelpText<"User directory for configuration files">;
def coverage : Flag<["-", "--"], "coverage">, Group<Link_Group>,
Visibility<[ClangOption, CLOption]>;
Expand Down Expand Up @@ -5089,6 +5089,11 @@ def mspe : Flag<["-"], "mspe">, Group<m_ppc_Features_Group>;
def mno_spe : Flag<["-"], "mno-spe">, Group<m_ppc_Features_Group>;
def mefpu2 : Flag<["-"], "mefpu2">, Group<m_ppc_Features_Group>;
} // let Flags = [TargetSpecific]
def msave_reg_params : Flag<["-"], "msave-reg-params">, Group<m_Group>,
Flags<[TargetSpecific]>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Save arguments passed by registers to ABI-defined stack positions">,
MarshallingInfoFlag<CodeGenOpts<"SaveRegParams">>;
def mabi_EQ_quadword_atomics : Flag<["-"], "mabi=quadword-atomics">,
Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Enable quadword atomics ABI on AIX (AIX PPC64 only). Uses lqarx/stqcx. instructions.">,
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Sema/Overload.h
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,9 @@ class Sema;
private:
friend class OverloadCandidateSet;
OverloadCandidate()
: IsSurrogate(false), IsADLCandidate(CallExpr::NotADL), RewriteKind(CRK_None) {}
: IsSurrogate(false), IgnoreObjectArgument(false),
TookAddressOfOverload(false), IsADLCandidate(CallExpr::NotADL),
RewriteKind(CRK_None) {}
};

/// OverloadCandidateSet - A set of overload candidates, used in C++
Expand Down
9 changes: 7 additions & 2 deletions clang/lib/AST/Interp/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {
return Ctx->emitGetPtrLocal(Offset, E);
case K_Decl:
return Ctx->visitDeclRef(D, E);
case K_Elem:
if (!Ctx->emitConstUint32(Offset, E))
return false;
return Ctx->emitArrayElemPtrUint32(E);
default:
llvm_unreachable("Unhandled InitLink kind");
}
Expand Down Expand Up @@ -1556,6 +1560,7 @@ bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex,
return this->emitInitElem(*T, ElemIndex, Init);
}

InitLinkScope<Emitter> ILS(this, InitLink::Elem(ElemIndex));
// Advance the pointer currently on the stack to the given
// dimension.
if (!this->emitConstUint32(ElemIndex, Init))
Expand Down Expand Up @@ -5281,8 +5286,8 @@ template <class Emitter>
unsigned Compiler<Emitter>::collectBaseOffset(const QualType BaseType,
const QualType DerivedType) {
const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {
if (const auto *PT = dyn_cast<PointerType>(Ty))
return PT->getPointeeType()->getAsCXXRecordDecl();
if (const auto *R = Ty->getPointeeCXXRecordDecl())
return R;
return Ty->getAsCXXRecordDecl();
};
const CXXRecordDecl *BaseDecl = extractRecordDecl(BaseType);
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/Interp/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct InitLink {
K_Field = 1,
K_Temp = 2,
K_Decl = 3,
K_Elem = 5,
};

static InitLink This() { return InitLink{K_This}; }
Expand All @@ -68,6 +69,11 @@ struct InitLink {
IL.D = D;
return IL;
}
static InitLink Elem(unsigned Index) {
InitLink IL{K_Elem};
IL.Offset = Index;
return IL;
}

InitLink(uint8_t Kind) : Kind(Kind) {}
template <class Emitter>
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC) {
assert(false && "Can't get arguments from that expression type");

assert(NumArgs >= CurFunc->getNumWrittenParams());
NumVarArgs = NumArgs - CurFunc->getNumWrittenParams();
NumVarArgs = NumArgs - (CurFunc->getNumWrittenParams() +
isa<CXXOperatorCallExpr>(CallSite));
for (unsigned I = 0; I != NumVarArgs; ++I) {
const Expr *A = Args[NumArgs - 1 - I];
popArg(S, A);
Expand Down
217 changes: 86 additions & 131 deletions clang/lib/AST/MicrosoftMangle.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/NVPTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
}

BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
return TargetInfo::CharPtrBuiltinVaList;
}

bool isValidCPUName(StringRef Name) const override {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2025,6 +2025,9 @@ static void getTrivialDefaultFunctionAttributes(
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
}

if (CodeGenOpts.SaveRegParams && !AttrOnCallSite)
FuncAttrs.addAttribute("save-reg-params");

for (StringRef Attr : CodeGenOpts.DefaultFunctionAttrs) {
StringRef Var, Value;
std::tie(Var, Value) = Attr.split('=');
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1695,7 +1695,8 @@ void CGOpenMPRuntimeGPU::emitReduction(
CGF.AllocaInsertPt->getIterator());
InsertPointTy CodeGenIP(CGF.Builder.GetInsertBlock(),
CGF.Builder.GetInsertPoint());
llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
llvm::OpenMPIRBuilder::LocationDescription OmpLoc(
CodeGenIP, CGF.SourceLocToDebugLoc(Loc));
llvm::SmallVector<llvm::OpenMPIRBuilder::ReductionInfo> ReductionInfos;

CodeGenFunction::OMPPrivateScope Scope(CGF);
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/AIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,9 @@ void AIX::addClangTargetOptions(
options::OPT_mtocdata))
addTocDataOptions(Args, CC1Args, getDriver());

if (Args.hasArg(options::OPT_msave_reg_params))
CC1Args.push_back("-msave-reg-params");

if (Args.hasFlag(options::OPT_fxl_pragma_pack,
options::OPT_fno_xl_pragma_pack, true))
CC1Args.push_back("-fxl-pragma-pack");
Expand Down
90 changes: 53 additions & 37 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2867,6 +2867,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
// If one wasn't given by the user, don't pass it here.
StringRef FPContract;
StringRef LastSeenFfpContractOption;
StringRef LastFpContractOverrideOption;
bool SeenUnsafeMathModeOption = false;
if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
!JA.isOffloading(Action::OFK_HIP))
Expand Down Expand Up @@ -2908,6 +2909,27 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
SeenUnsafeMathModeOption = true;
};

// Lambda to consolidate common handling for fp-contract
auto restoreFPContractState = [&]() {
// CUDA and HIP don't rely on the frontend to pass an ffp-contract option.
// For other targets, if the state has been changed by one of the
// unsafe-math umbrella options a subsequent -fno-fast-math or
// -fno-unsafe-math-optimizations option reverts to the last value seen for
// the -ffp-contract option or "on" if we have not seen the -ffp-contract
// option. If we have not seen an unsafe-math option or -ffp-contract,
// we leave the FPContract state unchanged.
if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
!JA.isOffloading(Action::OFK_HIP)) {
if (LastSeenFfpContractOption != "")
FPContract = LastSeenFfpContractOption;
else if (SeenUnsafeMathModeOption)
FPContract = "on";
}
// In this case, we're reverting to the last explicit fp-contract option
// or the platform default
LastFpContractOverrideOption = "";
};

if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
CmdArgs.push_back(A->getValue());
Expand Down Expand Up @@ -3009,7 +3031,6 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
FPContract = "on";

StringRef Val = A->getValue();
if (OFastEnabled && Val != "fast") {
Expand All @@ -3026,14 +3047,18 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (Val == "fast") {
FPModel = Val;
applyFastMath();
// applyFastMath sets fp-contract="fast"
LastFpContractOverrideOption = "-ffp-model=fast";
} else if (Val == "precise") {
FPModel = Val;
FPContract = "on";
LastFpContractOverrideOption = "-ffp-model=precise";
} else if (Val == "strict") {
StrictFPModel = true;
FPExceptionBehavior = "strict";
FPModel = Val;
FPContract = "off";
LastFpContractOverrideOption = "-ffp-model=strict";
TrappingMath = true;
RoundingFPMath = true;
} else
Expand Down Expand Up @@ -3112,8 +3137,15 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
StringRef Val = A->getValue();
if (Val == "fast" || Val == "on" || Val == "off" ||
Val == "fast-honor-pragmas") {
if (Val != FPContract && LastFpContractOverrideOption != "") {
D.Diag(clang::diag::warn_drv_overriding_option)
<< LastFpContractOverrideOption
<< Args.MakeArgString("-ffp-contract=" + Val);
}

FPContract = Val;
LastSeenFfpContractOption = Val;
LastFpContractOverrideOption = "";
} else
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getSpelling() << Val;
Expand Down Expand Up @@ -3192,32 +3224,29 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
TrappingMath = false;
FPExceptionBehavior = "";
FPContract = "fast";
LastFpContractOverrideOption = "-funsafe-math-optimizations";
SeenUnsafeMathModeOption = true;
break;
case options::OPT_fno_unsafe_math_optimizations:
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
ApproxFunc = false;

if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
!JA.isOffloading(Action::OFK_HIP)) {
if (LastSeenFfpContractOption != "") {
FPContract = LastSeenFfpContractOption;
} else if (SeenUnsafeMathModeOption)
FPContract = "on";
}
restoreFPContractState();
break;

case options::OPT_Ofast:
// If -Ofast is the optimization level, then -ffast-math should be enabled
if (!OFastEnabled)
continue;
[[fallthrough]];
case options::OPT_ffast_math: {
case options::OPT_ffast_math:
applyFastMath();
if (A->getOption().getID() == options::OPT_Ofast)
LastFpContractOverrideOption = "-Ofast";
else
LastFpContractOverrideOption = "-ffast-math";
break;
}
case options::OPT_fno_fast_math:
HonorINFs = true;
HonorNaNs = true;
Expand All @@ -3229,16 +3258,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
ReciprocalMath = false;
ApproxFunc = false;
SignedZeros = true;
// -fno_fast_math restores default fpcontract handling
if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
!JA.isOffloading(Action::OFK_HIP)) {
if (LastSeenFfpContractOption != "") {
FPContract = LastSeenFfpContractOption;
} else if (SeenUnsafeMathModeOption)
FPContract = "on";
}
restoreFPContractState();
LastFpContractOverrideOption = "";
break;
}
} // End switch (A->getOption().getID())

// The StrictFPModel local variable is needed to report warnings
// in the way we intend. If -ffp-model=strict has been used, we
// want to report a warning for the next option encountered that
Expand All @@ -3256,12 +3280,17 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
else {
StrictFPModel = false;
FPModel = "";
// The warning for -ffp-contract would have been reported by the
// OPT_ffp_contract_EQ handler above. A special check here is needed
// to avoid duplicating the warning.
auto RHS = (A->getNumValues() == 0)
? A->getSpelling()
: Args.MakeArgString(A->getSpelling() + A->getValue());
if (RHS != "-ffp-model=strict")
D.Diag(clang::diag::warn_drv_overriding_option)
<< "-ffp-model=strict" << RHS;
if (A->getSpelling() != "-ffp-contract=") {
if (RHS != "-ffp-model=strict")
D.Diag(clang::diag::warn_drv_overriding_option)
<< "-ffp-model=strict" << RHS;
}
}
}

Expand Down Expand Up @@ -3343,21 +3372,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
// individual features enabled by -ffast-math instead of the option itself as
// that's consistent with gcc's behaviour.
if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath && ApproxFunc &&
ReciprocalMath && !SignedZeros && !TrappingMath && !RoundingFPMath) {
ReciprocalMath && !SignedZeros && !TrappingMath && !RoundingFPMath)
CmdArgs.push_back("-ffast-math");
if (FPModel == "fast") {
if (FPContract == "fast")
// All set, do nothing.
;
else if (FPContract.empty())
// Enable -ffp-contract=fast
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
else
D.Diag(clang::diag::warn_drv_overriding_option)
<< "-ffp-model=fast"
<< Args.MakeArgString("-ffp-contract=" + FPContract);
}
}

// Handle __FINITE_MATH_ONLY__ similarly.
if (!HonorINFs && !HonorNaNs)
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Headers/stdatomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,11 @@ typedef _Atomic(uintmax_t) atomic_uintmax_t;

typedef struct atomic_flag { atomic_bool _Value; } atomic_flag;

#ifdef __cplusplus
#define ATOMIC_FLAG_INIT {false}
#else
#define ATOMIC_FLAG_INIT { 0 }
#endif

/* These should be provided by the libc implementation. */
#ifdef __cplusplus
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Sema/CheckExprLifetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "CheckExprLifetime.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Sema/Initialization.h"
Expand Down Expand Up @@ -548,6 +549,14 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
EnableLifetimeWarnings);
}

if (auto *M = dyn_cast<MemberExpr>(Init)) {
// Lifetime of a non-reference type field is same as base object.
if (auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
F && !F->getType()->isReferenceType())
visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true,
EnableLifetimeWarnings);
}

if (isa<CallExpr>(Init)) {
if (EnableLifetimeWarnings)
handleGslAnnotatedTypes(Path, Init, Visit);
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5730,7 +5730,6 @@ static bool isParenthetizedAndQualifiedAddressOfExpr(Expr *Fn) {
if (!UO || UO->getOpcode() != clang::UO_AddrOf)
return false;
if (auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) {
assert(isa<FunctionDecl>(DRE->getDecl()) && "expected a function");
return DRE->hasQualifier();
}
if (auto *OVL = dyn_cast<OverloadExpr>(UO->getSubExpr()->IgnoreParens()))
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Sema/SemaExprObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3206,9 +3206,10 @@ ExprResult SemaObjC::BuildInstanceMessage(
}
if (!isDesignatedInitChain) {
const ObjCMethodDecl *InitMethod = nullptr;
auto *CurMD = SemaRef.getCurMethodDecl();
assert(CurMD && "Current method declaration should not be null");
bool isDesignated =
SemaRef.getCurMethodDecl()->isDesignatedInitializerForTheInterface(
&InitMethod);
CurMD->isDesignatedInitializerForTheInterface(&InitMethod);
assert(isDesignated && InitMethod);
(void)isDesignated;
Diag(SelLoc, SuperLoc.isValid() ?
Expand Down
20 changes: 1 addition & 19 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6857,10 +6857,7 @@ void Sema::AddOverloadCandidate(
Candidate.Viable = true;
Candidate.RewriteKind =
CandidateSet.getRewriteInfo().getRewriteKind(Function, PO);
Candidate.IsSurrogate = false;
Candidate.IsADLCandidate = IsADLCandidate;
Candidate.IgnoreObjectArgument = false;
Candidate.TookAddressOfOverload = false;
Candidate.ExplicitCallArguments = Args.size();

// Explicit functions are not actually candidates at all if we're not
Expand Down Expand Up @@ -7422,8 +7419,6 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
Candidate.Function = Method;
Candidate.RewriteKind =
CandidateSet.getRewriteInfo().getRewriteKind(Method, PO);
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.TookAddressOfOverload =
CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet;
Candidate.ExplicitCallArguments = Args.size();
Expand Down Expand Up @@ -7617,7 +7612,6 @@ void Sema::AddMethodTemplateCandidate(
Candidate.IgnoreObjectArgument =
cast<CXXMethodDecl>(Candidate.Function)->isStatic() ||
ObjectType.isNull();
Candidate.TookAddressOfOverload = false;
Candidate.ExplicitCallArguments = Args.size();
if (Result == TemplateDeductionResult::NonDependentConversionFailure)
Candidate.FailureKind = ovl_fail_bad_conversion;
Expand Down Expand Up @@ -7705,7 +7699,6 @@ void Sema::AddTemplateOverloadCandidate(
Candidate.IgnoreObjectArgument =
isa<CXXMethodDecl>(Candidate.Function) &&
!isa<CXXConstructorDecl>(Candidate.Function);
Candidate.TookAddressOfOverload = false;
Candidate.ExplicitCallArguments = Args.size();
if (Result == TemplateDeductionResult::NonDependentConversionFailure)
Candidate.FailureKind = ovl_fail_bad_conversion;
Expand Down Expand Up @@ -7886,9 +7879,6 @@ void Sema::AddConversionCandidate(
OverloadCandidate &Candidate = CandidateSet.addCandidate(1);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Conversion;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.TookAddressOfOverload = false;
Candidate.FinalConversion.setAsIdentityConversion();
Candidate.FinalConversion.setFromType(ConvType);
Candidate.FinalConversion.setAllToTypes(ToType);
Expand Down Expand Up @@ -8084,9 +8074,6 @@ void Sema::AddTemplateConversionCandidate(
Candidate.Function = FunctionTemplate->getTemplatedDecl();
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.TookAddressOfOverload = false;
Candidate.ExplicitCallArguments = 1;
Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
Info);
Expand Down Expand Up @@ -8119,10 +8106,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
Candidate.FoundDecl = FoundDecl;
Candidate.Function = nullptr;
Candidate.Surrogate = Conversion;
Candidate.Viable = true;
Candidate.IsSurrogate = true;
Candidate.IgnoreObjectArgument = false;
Candidate.TookAddressOfOverload = false;
Candidate.Viable = true;
Candidate.ExplicitCallArguments = Args.size();

// Determine the implicit conversion sequence for the implicit
Expand Down Expand Up @@ -8328,9 +8313,6 @@ void Sema::AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args,
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
Candidate.FoundDecl = DeclAccessPair::make(nullptr, AS_none);
Candidate.Function = nullptr;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.TookAddressOfOverload = false;
std::copy(ParamTys, ParamTys + Args.size(), Candidate.BuiltinParamTypes);

// Determine the implicit conversion sequences for each of the
Expand Down
14 changes: 14 additions & 0 deletions clang/test/AST/Interp/cxx20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -827,3 +827,17 @@ namespace CheckingNullPtrForInitialization {
return x;
}
}

namespace VariadicCallOperator {
class F {
public:
constexpr void operator()(int a, int b, ...) {}
};
constexpr int foo() {
F f;

f(1,2, 3);
return 1;
}
constexpr int A = foo();
}
19 changes: 19 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1537,3 +1537,22 @@ namespace BitSet {
Bitset()
};
}

namespace ArrayInitChain {
struct StringLiteral {
const char *S;
};

struct CustomOperandVal {
StringLiteral Str;
unsigned Width;
unsigned Mask = Width + 1;
};

constexpr CustomOperandVal A[] = {
{},
};
static_assert(A[0].Str.S == nullptr, "");
static_assert(A[0].Width == 0, "");
static_assert(A[0].Mask == 1, "");
}
10 changes: 10 additions & 0 deletions clang/test/CodeGen/PowerPC/save-reg-params.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -o - %s -msave-reg-params | FileCheck -check-prefix=SAVE %s
// RUN: %clang_cc1 -triple powerpc-ibm-aix -emit-llvm -o - %s -msave-reg-params | FileCheck -check-prefix=SAVE %s
// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -o - %s | FileCheck -check-prefix=NOSAVE %s
// RUN: %clang_cc1 -triple powerpc-ibm-aix -emit-llvm -o - %s | FileCheck -check-prefix=NOSAVE %s

void bar(int);
void foo(int x) { bar(x); }

// SAVE: attributes #{{[0-9]+}} = { {{.+}} "save-reg-params" {{.+}} }
// NOSAVE-NOT: "save-reg-params"
19 changes: 19 additions & 0 deletions clang/test/CodeGen/ms_mangler_templatearg_opte.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -emit-llvm -std=c++20 -x c++ < %s | FileCheck -check-prefix=WIN64 %s

struct A {
const int* ptr;
};

template<A> void tfn() {};

// WIN64: ??$tfn@$2UA@@PEBH5CE?ints@@3QBHB06@@@@@YAXXZ
constexpr int ints[] = { 1, 2, 7, 8, 9, -17, -10 };

// WIN64: ??$tfn@$2UA@@PEBH5E?one_int@@3HB@@@@YAXXZ
constexpr int one_int = 7;

void template_instance() {
tfn<A{ints + sizeof(ints)/sizeof(int)}>();
tfn<A{&one_int + 1}>();
}

2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/aarch64-mangle-sve-vectors-msvc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

template<typename T> struct S {};

// CHECK: cannot mangle this built-in __SVInt8_t type yet
// CHECK: cannot mangle this built-in type: __SVInt8_t yet
void f1(S<__SVInt8_t>) {}
7 changes: 7 additions & 0 deletions clang/test/Driver/aix-save-reg-params.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: %clang -### -target powerpc-ibm-aix-xcoff -msave-reg-params -c %s -o /dev/null 2>&1 | FileCheck %s
// RUN: %clang -### -target powerpc64-ibm-aix-xcoff -msave-reg-params -c %s -o /dev/null 2>&1 | FileCheck %s
// RUN: %clang -### -target powerpc-ibm-aix-xcoff -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DISABLE
// RUN: %clang -### -target powerpc64-ibm-aix-xcoff -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DISABLE

// CHECK: "-msave-reg-params"
// DISABLE-NOT: "-msave-reg-params"
108 changes: 64 additions & 44 deletions clang/test/Driver/fp-contract.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
// the options -ffast-math, -fno-fast-math, funsafe-math-optimizations,
// fno-unsafe-math-optimizations.

// These warning checks are above the run lines because the warning is reported
// before the drive options that are checked below the run lines.
// WARN_FM_OFF: warning: overriding '-ffast-math' option with '-ffp-contract=off'
// WARN_FM_ON: warning: overriding '-ffast-math' option with '-ffp-contract=on'
// WARN_FM_FHP: warning: overriding '-ffast-math' option with '-ffp-contract=fast-honor-pragmas'
// WARN_UM_OFF: warning: overriding '-funsafe-math-optimizations' option with '-ffp-contract=off'
// WARN_UM_ON: warning: overriding '-funsafe-math-optimizations' option with '-ffp-contract=on'

// ffast-math, fno-fast-math
// RUN: %clang -### -ffast-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s
Expand All @@ -10,19 +18,19 @@
// RUN: %clang -### -fno-fast-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s

// RUN: %clang -### -Werror -ffast-math -ffp-contract=on -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s
// RUN: %clang -### -ffast-math -ffp-contract=on -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-ON,WARN_FM_ON %s
// CHECK-FPC-ON: "-ffp-contract=on"

// RUN: %clang -### -Werror -ffast-math -ffp-contract=off -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s
// RUN: %clang -### -ffast-math -ffp-contract=off -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-OFF,WARN_FM_OFF %s
// CHECK-FPC-OFF: "-ffp-contract=off"

// RUN: %clang -### -Werror -ffast-math -ffp-contract=fast -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s

// RUN: %clang -### -Werror -ffast-math -ffp-contract=fast-honor-pragmas -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST-HONOR %s
// RUN: %clang -### -ffast-math -ffp-contract=fast-honor-pragmas -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-FAST-HONOR,WARN_FM_FHP %s
// CHECK-FPC-FAST-HONOR: "-ffp-contract=fast-honor-pragmas"

// RUN: %clang -### -Werror -ffp-contract=fast -ffast-math -c %s 2>&1 \
Expand All @@ -43,23 +51,23 @@
// RUN: %clang -### -Werror -ffast-math -ffp-contract=fast -ffp-contract=on -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s

// RUN: %clang -### -Werror -ffast-math -ffp-contract=on -ffp-contract=off -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s
// RUN: %clang -### -ffast-math -ffp-contract=on -ffp-contract=off -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-OFF,WARN_FM_ON %s

// RUN: %clang -### -Werror -ffast-math -ffp-contract=on -ffp-contract=fast -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s
// RUN: %clang -### -ffast-math -ffp-contract=on -ffp-contract=fast -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-FAST,WARN_FM_ON %s

// RUN: %clang -### -Werror -ffast-math -ffp-contract=off -ffp-contract=on -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s
// RUN: %clang -### -ffast-math -ffp-contract=off -ffp-contract=on -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-ON,WARN_FM_OFF %s

// RUN: %clang -### -Werror -ffast-math -ffp-contract=off -ffp-contract=fast \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-FAST %s
// RUN: %clang -### -ffast-math -ffp-contract=off -ffp-contract=fast \
// RUN: -c %s 2>&1 | FileCheck --check-prefixes=CHECK-FPC-FAST,WARN_FM_OFF %s

// RUN: %clang -### -Werror -ffast-math -ffp-contract=on -fno-fast-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s
// RUN: %clang -### -ffast-math -ffp-contract=on -fno-fast-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-ON,WARN_FM_ON %s

// RUN: %clang -### -Werror -ffast-math -ffp-contract=off -fno-fast-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s
// RUN: %clang -### -ffast-math -ffp-contract=off -fno-fast-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-OFF,WARN_FM_OFF %s

// RUN: %clang -### -Werror -ffast-math -ffp-contract=fast -fno-fast-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s
Expand Down Expand Up @@ -112,24 +120,24 @@
// RUN: %clang -### -Werror -fno-fast-math -ffast-math -ffp-contract=fast \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-FAST %s

// RUN: %clang -### -Werror -fno-fast-math -ffast-math -ffp-contract=on \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-ON %s
// RUN: %clang -### -fno-fast-math -ffast-math -ffp-contract=on \
// RUN: -c %s 2>&1 | FileCheck --check-prefixes=CHECK-FPC-ON,WARN_FM_ON %s

// RUN: %clang -### -Werror -fno-fast-math -ffast-math -ffp-contract=off \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-OFF %s
// RUN: %clang -### -fno-fast-math -ffast-math -ffp-contract=off \
// RUN: -c %s 2>&1 | FileCheck --check-prefixes=CHECK-FPC-OFF,WARN_FM_OFF %s

// funsafe-math-optimizations, fno-unsafe-math-optimizations
// RUN: %clang -### -funsafe-math-optimizations -c %s 2>&1 \
// RUN: %clang -### -Werror -funsafe-math-optimizations -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s

// RUN: %clang -### -fno-unsafe-math-optimizations -c %s 2>&1 \
// RUN: %clang -### -Werror -fno-unsafe-math-optimizations -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=on -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s
// RUN: %clang -### -funsafe-math-optimizations -ffp-contract=on -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-ON,WARN_UM_ON %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=off -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s
// RUN: %clang -### -funsafe-math-optimizations -ffp-contract=off -c %s 2>&1 \
// RUN: | FileCheck --check-prefixes=CHECK-FPC-OFF,WARN_UM_OFF %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=fast -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s
Expand All @@ -151,27 +159,27 @@
// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=fast \
// RUN: -ffp-contract=on -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-ON %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=on \
// RUN: -ffp-contract=off -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-OFF %s
// RUN: %clang -### -funsafe-math-optimizations -ffp-contract=on \
// RUN: -ffp-contract=off -c %s 2>&1 | FileCheck --check-prefixes=CHECK-FPC-OFF,WARN_UM_ON %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=on \
// RUN: %clang -### -funsafe-math-optimizations -ffp-contract=on \
// RUN: -ffp-contract=fast -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s
// RUN: | FileCheck --check-prefixes=CHECK-FPC-FAST,WARN_UM_ON %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=off \
// RUN: -ffp-contract=on -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-ON %s
// RUN: %clang -### -funsafe-math-optimizations -ffp-contract=off \
// RUN: -ffp-contract=on -c %s 2>&1 | FileCheck --check-prefixes=CHECK-FPC-ON,WARN_UM_OFF %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=off \
// RUN: %clang -### -funsafe-math-optimizations -ffp-contract=off \
// RUN: -ffp-contract=fast \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-FAST %s
// RUN: -c %s 2>&1 | FileCheck --check-prefixes=CHECK-FPC-FAST,WARN_UM_OFF %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=on \
// RUN: %clang -### -funsafe-math-optimizations -ffp-contract=on \
// RUN: -fno-unsafe-math-optimizations -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s
// RUN: | FileCheck --check-prefixes=CHECK-FPC-ON,WARN_UM_ON %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=off \
// RUN: %clang -### -funsafe-math-optimizations -ffp-contract=off \
// RUN: -fno-unsafe-math-optimizations -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s
// RUN: | FileCheck --check-prefixes=CHECK-FPC-OFF,WARN_UM_OFF %s

// RUN: %clang -### -Werror -funsafe-math-optimizations -ffp-contract=fast \
// RUN: -fno-unsafe-math-optimizations -c %s 2>&1 \
Expand Down Expand Up @@ -229,9 +237,21 @@
// RUN: -ffp-contract=fast \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-FAST %s

// RUN: %clang -### -Werror -fno-unsafe-math-optimizations -funsafe-math-optimizations \
// RUN: -ffp-contract=on -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-ON %s
// RUN: %clang -### -fno-unsafe-math-optimizations -funsafe-math-optimizations \
// RUN: -ffp-contract=on -c %s 2>&1 | FileCheck --check-prefixes=CHECK-FPC-ON,WARN_UM_ON %s

// RUN: %clang -### -Werror -fno-unsafe-math-optimizations -funsafe-math-optimizations \
// RUN: -ffp-contract=off -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-OFF %s
// RUN: %clang -### -fno-unsafe-math-optimizations -funsafe-math-optimizations \
// RUN: -ffp-contract=off -c %s 2>&1 | FileCheck --check-prefixes=CHECK-FPC-OFF,WARN_UM_OFF %s

// RUN: %clang -### -funsafe-math-optimizations -ffp-contract=off -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=WARN_UM_OFF %s

// This case should not warn
// RUN: %clang -### -Werror -funsafe-math-optimizations \
// RUN: -fno-unsafe-math-optimizations -ffp-contract=off -c %s

// RUN: %clang -### -ffast-math -ffp-contract=off -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=WARN_FM_OFF %s

// This case should not warn
// RUN: %clang -### -Werror -ffast-math -fno-fast-math -ffp-contract=off -c %s
13 changes: 13 additions & 0 deletions clang/test/Driver/fp-model.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,19 @@
// RUN: | FileCheck --check-prefix=WARN13 %s
// WARN13: warning: overriding '-ffp-model=strict' option with '-fapprox-func' [-Woverriding-option]

// RUN: %clang -### -ffp-model=precise -ffp-contract=off -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=WARN14 %s
// WARN14: warning: overriding '-ffp-model=precise' option with '-ffp-contract=off' [-Woverriding-option]

// RUN: %clang -### -ffp-model=precise -ffp-contract=fast -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=WARN15 %s
// WARN15: warning: overriding '-ffp-model=precise' option with '-ffp-contract=fast' [-Woverriding-option]

// RUN: %clang -### -ffp-model=strict -fassociative-math -ffp-contract=on \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN16 %s
// WARN16: warning: overriding '-ffp-model=strict' option with '-fassociative-math' [-Woverriding-option]
// WARN16: warning: overriding '-ffp-model=strict' option with '-ffp-contract=on' [-Woverriding-option]

// RUN: %clang -### -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOROUND %s
// CHECK-NOROUND: "-cc1"
Expand Down
7 changes: 4 additions & 3 deletions clang/test/Driver/linker-wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,12 @@ __attribute__((visibility("protected"), used)) int x;
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \
// RUN: -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu \
// RUN: --linker-path=/usr/bin/ld --device-linker=a --device-linker=nvptx64-nvidia-cuda=b \
// RUN: --linker-path=/usr/bin/ld --device-linker=foo=bar --device-linker=a \
// RUN: --device-linker=nvptx64-nvidia-cuda=b \
// RUN: %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=LINKER-ARGS

// LINKER-ARGS: clang{{.*}}--target=amdgcn-amd-amdhsa{{.*}}a
// LINKER-ARGS: clang{{.*}}--target=nvptx64-nvidia-cuda{{.*}}a b
// LINKER-ARGS: clang{{.*}}--target=amdgcn-amd-amdhsa{{.*}}foo=bar{{.*}}a
// LINKER-ARGS: clang{{.*}}--target=nvptx64-nvidia-cuda{{.*}}foo=bar{{.*}}a b

// RUN: not clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu -ldummy \
// RUN: --linker-path=/usr/bin/ld --device-linker=a --device-linker=nvptx64-nvidia-cuda=b \
Expand Down
4 changes: 4 additions & 0 deletions clang/test/Driver/ppc-unsupported.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@
// RUN: -c %s 2>&1 | FileCheck %s
// RUN: not %clang -target powerpc-unknown-aix -mabi=quadword-atomics \
// RUN: -c %s 2>&1 | FileCheck %s
// RUN: not %clang -target powerpc64le-unknown-linux-gnu -msave-reg-params \
// RUN: -c %s 2>&1 | FileCheck %s
// RUN: not %clang -target powerpc-unknown-unknown -msave-reg-params \
// RUN: -c %s 2>&1 | FileCheck %s
// CHECK: unsupported option
5 changes: 5 additions & 0 deletions clang/test/Headers/stdatomic.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -std=c11 -E %s | FileCheck %s
// RUN: %clang_cc1 -std=c11 -fms-compatibility -E %s | FileCheck %s
// RUN: %clang_cc1 -std=c11 %s -verify
// RUN: %clang_cc1 -x c++ -std=c++11 %s -verify
// expected-no-diagnostics
#include <stdatomic.h>

int bool_lock_free = ATOMIC_BOOL_LOCK_FREE;
Expand Down Expand Up @@ -31,3 +34,5 @@ int llong_lock_free = ATOMIC_LLONG_LOCK_FREE;

int pointer_lock_free = ATOMIC_POINTER_LOCK_FREE;
// CHECK: pointer_lock_free = {{ *[012] *;}}

atomic_flag f = ATOMIC_FLAG_INIT;
26 changes: 26 additions & 0 deletions clang/test/SemaCXX/attr-lifetimebound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,31 @@ namespace usage_ok {
q = A(); // expected-warning {{object backing the pointer q will be destroyed at the end of the full-expression}}
r = A(1); // expected-warning {{object backing the pointer r will be destroyed at the end of the full-expression}}
}

struct FieldCheck {
struct Set {
int a;
};
struct Pair {
const int& a;
int b;
Set c;
int * d;
};
Pair p;
FieldCheck(const int& a): p(a){}
Pair& getR() [[clang::lifetimebound]] { return p; }
Pair* getP() [[clang::lifetimebound]] { return &p; }
Pair* getNoLB() { return &p; }
};
void test_field_access() {
int x = 0;
const int& a = FieldCheck{x}.getR().a;
const int& b = FieldCheck{x}.getP()->b; // expected-warning {{temporary bound to local reference 'b' will be destroyed at the end of the full-expression}}
const int& c = FieldCheck{x}.getP()->c.a; // expected-warning {{temporary bound to local reference 'c' will be destroyed at the end of the full-expression}}
const int& d = FieldCheck{x}.getNoLB()->c.a;
const int* e = FieldCheck{x}.getR().d;
}
}

# 1 "<std>" 1 3
Expand Down Expand Up @@ -239,3 +264,4 @@ namespace move_forward_et_al_examples {
S X;
S *AddressOfOk = std::addressof(X);
} // namespace move_forward_et_al_examples

6 changes: 6 additions & 0 deletions clang/test/SemaCXX/cxx2b-deducing-this.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,10 @@ void g() {
}

namespace P2797 {

int bar(void) { return 55; }
int (&fref)(void) = bar;

struct C {
void c(this const C&); // #first
void c() &; // #second
Expand All @@ -915,6 +919,8 @@ struct C {
(&C::c)(C{});
(&C::c)(*this); // expected-error {{call to non-static member function without an object argument}}
(&C::c)();

(&fref)();
}
};
}
Expand Down
8 changes: 8 additions & 0 deletions clang/test/SemaCXX/decltype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ namespace GH58674 {
}
}

namespace GH97646 {
template<bool B>
void f() {
decltype(B) x = false;
!x;
}
}

template<typename>
class conditional {
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,11 @@
typeof_unqual(int) u = 12; // expected-error {{expected function body after function declarator}}
__typeof_unqual(int) _u = 12;
__typeof_unqual__(int) __u = 12;

namespace GH97646 {
template<bool B>
void f() {
__typeof__(B) x = false;
!x;
}
}
8 changes: 7 additions & 1 deletion clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,13 @@ DerivedArgList getLinkerArgs(ArrayRef<OffloadFile> Input,
// Forward '-Xoffload-linker' options to the appropriate backend.
for (StringRef Arg : Args.getAllArgValues(OPT_device_linker_args_EQ)) {
auto [Triple, Value] = Arg.split('=');
if (Value.empty())
llvm::Triple TT(Triple);
// If this isn't a recognized triple then it's an `arg=value` option.
if (TT.getArch() <= Triple::ArchType::UnknownArch ||
TT.getArch() > Triple::ArchType::LastArchType)
DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_linker_arg_EQ),
Args.MakeArgString(Arg));
else if (Value.empty())
DAL.AddJoinedArg(nullptr, Tbl.getOption(OPT_linker_arg_EQ),
Args.MakeArgString(Triple));
else if (Triple == DAL.getLastArgValue(OPT_triple_EQ))
Expand Down
5 changes: 5 additions & 0 deletions compiler-rt/lib/builtins/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@ switch32
switch8
switchu8

// This function generates a custom trampoline function with the specific
// realFunc and localsPtr values.
void __trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,
const void* realFunc, void* localsPtr);

// There is no C interface to the *_vfp_d8_d15_regs functions. There are
// called in the prolog and epilog of Thumb1 functions. When the C++ ABI use
// SJLJ for exceptions, each function with a catch clause or destructors needs
Expand Down
28 changes: 0 additions & 28 deletions compiler-rt/lib/builtins/aarch64/sme-abi-vg.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@ struct FEATURES {

extern struct FEATURES __aarch64_cpu_features;

struct SME_STATE {
long PSTATE;
long TPIDR2_EL0;
};

extern struct SME_STATE __arm_sme_state(void) __arm_streaming_compatible;

extern bool __aarch64_has_sme_and_tpidr2_el0;

#if __GNUC__ >= 9
#pragma GCC diagnostic ignored "-Wprio-ctor-dtor"
#endif
Expand All @@ -28,22 +19,3 @@ __attribute__((constructor(90))) static void get_aarch64_cpu_features(void) {

__init_cpu_features();
}

__attribute__((target("sve"))) long
__arm_get_current_vg(void) __arm_streaming_compatible {
struct SME_STATE State = __arm_sme_state();
unsigned long long features =
__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED);
bool HasSVE = features & (1ULL << FEAT_SVE);

if (!HasSVE && !__aarch64_has_sme_and_tpidr2_el0)
return 0;

if (HasSVE || (State.PSTATE & 1)) {
long vl;
__asm__ __volatile__("cntd %0" : "=r"(vl));
return vl;
}

return 0;
}
44 changes: 44 additions & 0 deletions compiler-rt/lib/builtins/aarch64/sme-abi.S
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@
#if !defined(__APPLE__)
#define TPIDR2_SYMBOL SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)
#define TPIDR2_SYMBOL_OFFSET :lo12:SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)
#define CPU_FEATS_SYMBOL SYMBOL_NAME(__aarch64_cpu_features)
#define CPU_FEATS_SYMBOL_OFFSET :lo12:SYMBOL_NAME(__aarch64_cpu_features)
#else
// MachO requires @page/@pageoff directives because the global is defined
// in a different file. Otherwise this file may fail to build.
#define TPIDR2_SYMBOL SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)@page
#define TPIDR2_SYMBOL_OFFSET SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)@pageoff
#define CPU_FEATS_SYMBOL SYMBOL_NAME(__aarch64_cpu_features)@page
#define CPU_FEATS_SYMBOL_OFFSET SYMBOL_NAME(__aarch64_cpu_features)@pageoff
#endif

.arch armv9-a+sme
Expand Down Expand Up @@ -180,6 +184,46 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_za_disable)
ret
END_COMPILERRT_OUTLINE_FUNCTION(__arm_za_disable)

DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_get_current_vg)
.variant_pcs __arm_get_current_vg
BTI_C

stp x29, x30, [sp, #-16]!
.cfi_def_cfa_offset 16
mov x29, sp
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
adrp x17, CPU_FEATS_SYMBOL
ldr w17, [x17, CPU_FEATS_SYMBOL_OFFSET]
tbnz w17, #30, 0f
adrp x16, TPIDR2_SYMBOL
ldrb w16, [x16, TPIDR2_SYMBOL_OFFSET]
cbz w16, 1f
0:
mov x18, x1
bl __arm_sme_state
mov x1, x18
and x17, x17, #0x40000000
bfxil x17, x0, #0, #1
cbz x17, 1f
cntd x0
.cfi_def_cfa wsp, 16
ldp x29, x30, [sp], #16
.cfi_def_cfa_offset 0
.cfi_restore w30
.cfi_restore w29
ret
1:
mov x0, xzr
.cfi_def_cfa wsp, 16
ldp x29, x30, [sp], #16
.cfi_def_cfa_offset 0
.cfi_restore w30
.cfi_restore w29
ret
END_COMPILERRT_OUTLINE_FUNCTION(__arm_get_current_vg)

NO_EXEC_STACK_DIRECTIVE

// GNU property note for BTI and PAC
Expand Down
42 changes: 42 additions & 0 deletions compiler-rt/lib/builtins/trampoline_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,45 @@ COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack,
__clear_cache(trampOnStack, &trampOnStack[10]);
}
#endif // __powerpc__ && !defined(__powerpc64__)

// The AArch64 compiler generates calls to __trampoline_setup() when creating
// trampoline functions on the stack for use with nested functions.
// This function creates a custom 36-byte trampoline function on the stack
// which loads x18 with a pointer to the outer function's locals
// and then jumps to the target nested function.
// Note: x18 is a reserved platform register on Windows and macOS.

#if defined(__aarch64__) && defined(__ELF__)
COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack,
int trampSizeAllocated,
const void *realFunc, void *localsPtr) {
// This should never happen, but if compiler did not allocate
// enough space on stack for the trampoline, abort.
if (trampSizeAllocated < 36)
compilerrt_abort();

// create trampoline
// Load realFunc into x17. mov/movk 16 bits at a time.
trampOnStack[0] =
0xd2800000u | ((((uint64_t)realFunc >> 0) & 0xffffu) << 5) | 0x11;
trampOnStack[1] =
0xf2a00000u | ((((uint64_t)realFunc >> 16) & 0xffffu) << 5) | 0x11;
trampOnStack[2] =
0xf2c00000u | ((((uint64_t)realFunc >> 32) & 0xffffu) << 5) | 0x11;
trampOnStack[3] =
0xf2e00000u | ((((uint64_t)realFunc >> 48) & 0xffffu) << 5) | 0x11;
// Load localsPtr into x18
trampOnStack[4] =
0xd2800000u | ((((uint64_t)localsPtr >> 0) & 0xffffu) << 5) | 0x12;
trampOnStack[5] =
0xf2a00000u | ((((uint64_t)localsPtr >> 16) & 0xffffu) << 5) | 0x12;
trampOnStack[6] =
0xf2c00000u | ((((uint64_t)localsPtr >> 32) & 0xffffu) << 5) | 0x12;
trampOnStack[7] =
0xf2e00000u | ((((uint64_t)localsPtr >> 48) & 0xffffu) << 5) | 0x12;
trampOnStack[8] = 0xd61f0220; // br x17

// Clear instruction cache.
__clear_cache(trampOnStack, &trampOnStack[9]);
}
#endif // defined(__aarch64__) && !defined(__APPLE__) && !defined(_WIN64)
142 changes: 2 additions & 140 deletions compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2172,118 +2172,15 @@ static const char *RegNumToRegName(int reg) {
return "ebp";
case REG_ESP:
return "esp";
# elif defined(__arm__)
# define REG_STR(reg) #reg
# define MAKE_CASE(N) \
case REG_R##N: \
return REG_STR(r##N)
MAKE_CASE(0);
MAKE_CASE(1);
MAKE_CASE(2);
MAKE_CASE(3);
MAKE_CASE(4);
MAKE_CASE(5);
MAKE_CASE(6);
MAKE_CASE(7);
MAKE_CASE(8);
MAKE_CASE(9);
MAKE_CASE(10);
MAKE_CASE(11);
MAKE_CASE(12);
case REG_R13:
return "sp";
case REG_R14:
return "lr";
case REG_R15:
return "pc";
# elif defined(__aarch64__)
# define REG_STR(reg) #reg
# define MAKE_CASE(N) \
case N: \
return REG_STR(x##N)
MAKE_CASE(0);
MAKE_CASE(1);
MAKE_CASE(2);
MAKE_CASE(3);
MAKE_CASE(4);
MAKE_CASE(5);
MAKE_CASE(6);
MAKE_CASE(7);
MAKE_CASE(8);
MAKE_CASE(9);
MAKE_CASE(10);
MAKE_CASE(11);
MAKE_CASE(12);
MAKE_CASE(13);
MAKE_CASE(14);
MAKE_CASE(15);
MAKE_CASE(16);
MAKE_CASE(17);
MAKE_CASE(18);
MAKE_CASE(19);
MAKE_CASE(20);
MAKE_CASE(21);
MAKE_CASE(22);
MAKE_CASE(23);
MAKE_CASE(24);
MAKE_CASE(25);
MAKE_CASE(26);
MAKE_CASE(27);
MAKE_CASE(28);
case 29:
return "fp";
case 30:
return "lr";
case 31:
return "sp";
# endif
# endif
default:
return NULL;
}
return NULL;
}

# if SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__))
static uptr GetArmRegister(ucontext_t *ctx, int RegNum) {
switch (RegNum) {
# if defined(__arm__)
# define MAKE_CASE(N) \
case REG_R##N: \
return ctx->uc_mcontext.arm_r##N
MAKE_CASE(0);
MAKE_CASE(1);
MAKE_CASE(2);
MAKE_CASE(3);
MAKE_CASE(4);
MAKE_CASE(5);
MAKE_CASE(6);
MAKE_CASE(7);
MAKE_CASE(8);
MAKE_CASE(9);
MAKE_CASE(10);
case REG_R11:
return ctx->uc_mcontext.arm_fp;
case REG_R12:
return ctx->uc_mcontext.arm_ip;
case REG_R13:
return ctx->uc_mcontext.arm_sp;
case REG_R14:
return ctx->uc_mcontext.arm_lr;
case REG_R15:
return ctx->uc_mcontext.arm_pc;
# elif defined(__aarch64__)
case 0 ... 30:
return ctx->uc_mcontext.regs[RegNum];
case 31:
return ctx->uc_mcontext.sp;
# endif
default:
return 0;
}
return 0;
}
# endif // SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__))

# if SANITIZER_LINUX
UNUSED
static void DumpSingleReg(ucontext_t *ctx, int RegNum) {
const char *RegName = RegNumToRegName(RegNum);
Expand All @@ -2292,12 +2189,6 @@ static void DumpSingleReg(ucontext_t *ctx, int RegNum) {
RegName, ctx->uc_mcontext.gregs[RegNum]);
# elif defined(__i386__)
Printf("%s = 0x%08x ", RegName, ctx->uc_mcontext.gregs[RegNum]);
# elif defined(__arm__)
Printf("%s%s = 0x%08zx ", internal_strlen(RegName) == 2 ? " " : "", RegName,
GetArmRegister(ctx, RegNum));
# elif defined(__aarch64__)
Printf("%s%s = 0x%016zx ", internal_strlen(RegName) == 2 ? " " : "", RegName,
GetArmRegister(ctx, RegNum));
# else
(void)RegName;
# endif
Expand Down Expand Up @@ -2345,35 +2236,6 @@ void SignalContext::DumpAllRegisters(void *context) {
DumpSingleReg(ucontext, REG_EBP);
DumpSingleReg(ucontext, REG_ESP);
Printf("\n");
# elif defined(__arm__)
Report("Register values:\n");
DumpSingleReg(ucontext, REG_R0);
DumpSingleReg(ucontext, REG_R1);
DumpSingleReg(ucontext, REG_R2);
DumpSingleReg(ucontext, REG_R3);
Printf("\n");
DumpSingleReg(ucontext, REG_R4);
DumpSingleReg(ucontext, REG_R5);
DumpSingleReg(ucontext, REG_R6);
DumpSingleReg(ucontext, REG_R7);
Printf("\n");
DumpSingleReg(ucontext, REG_R8);
DumpSingleReg(ucontext, REG_R9);
DumpSingleReg(ucontext, REG_R10);
DumpSingleReg(ucontext, REG_R11);
Printf("\n");
DumpSingleReg(ucontext, REG_R12);
DumpSingleReg(ucontext, REG_R13);
DumpSingleReg(ucontext, REG_R14);
DumpSingleReg(ucontext, REG_R15);
Printf("\n");
# elif defined(__aarch64__)
Report("Register values:\n");
for (int i = 0; i <= 31; ++i) {
DumpSingleReg(ucontext, i);
if (i % 4 == 3)
Printf("\n");
}
# else
(void)ucontext;
# endif
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/test/builtins/Unit/trampoline_setup_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/*
* Tests nested functions
* The ppc compiler generates a call to __trampoline_setup
* The ppc and aarch64 compilers generates a call to __trampoline_setup
* The i386 and x86_64 compilers generate a call to ___enable_execute_stack
*/

Expand Down

This file was deleted.

This file was deleted.

3 changes: 3 additions & 0 deletions compiler-rt/test/tsan/debug_alloc_stack.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// RUN: %clangxx_tsan -O0 %s -o %t
// RUN: env %env_tsan_opts=stack_trace_format=DEFAULT %deflake %run %t 2>&1 | FileCheck %s

// Until I figure out how to make this test work on Linux
// REQUIRES: system-darwin

#include "test.h"
#include <pthread.h>
#include <stdint.h>
Expand Down
27 changes: 20 additions & 7 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1494,13 +1494,26 @@ genParallelOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
allSymbols.append(dsp.getAllSymbolsToPrivatize().begin(),
dsp.getAllSymbolsToPrivatize().end());

for (auto [arg, prv] : llvm::zip_equal(allSymbols, region.getArguments())) {
converter.bindSymbol(*arg, hlfir::translateToExtendedValue(
loc, firOpBuilder, hlfir::Entity{prv},
/*contiguousHint=*/
evaluate::IsSimplyContiguous(
*arg, converter.getFoldingContext()))
.first);
unsigned argIdx = 0;
for (const semantics::Symbol *arg : allSymbols) {
auto bind = [&](const semantics::Symbol *sym) {
mlir::BlockArgument blockArg = region.getArgument(argIdx);
++argIdx;
converter.bindSymbol(*sym,
hlfir::translateToExtendedValue(
loc, firOpBuilder, hlfir::Entity{blockArg},
/*contiguousHint=*/
evaluate::IsSimplyContiguous(
*sym, converter.getFoldingContext()))
.first);
};

if (const auto *commonDet =
arg->detailsIf<semantics::CommonBlockDetails>()) {
for (const auto &mem : commonDet->objects())
bind(&*mem);
} else
bind(arg);
}

return allSymbols;
Expand Down
1 change: 1 addition & 0 deletions flang/test/Driver/Inputs/config-1.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-flto
1 change: 1 addition & 0 deletions flang/test/Driver/Inputs/config-2.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-fno-signed-zeros
1 change: 1 addition & 0 deletions flang/test/Driver/Inputs/config-2a.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-fopenmp
1 change: 1 addition & 0 deletions flang/test/Driver/Inputs/config-6.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-fstack-arrays
1 change: 1 addition & 0 deletions flang/test/Driver/Inputs/config/config-4.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-O3
1 change: 1 addition & 0 deletions flang/test/Driver/Inputs/config2/config-4.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-ffp-contract=fast
63 changes: 63 additions & 0 deletions flang/test/Driver/config-file.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
!--- Config file (full path) in output of -###
!
! RUN: %flang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-DIRS
! CHECK-DIRS: System configuration file directory: {{.*}}/Inputs/config
! CHECK-DIRS: User configuration file directory: {{.*}}/Inputs/config2
!
!--- Config file (full path) in output of -###
!
! RUN: %flang --config %S/Inputs/config-1.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-HHH
! RUN: %flang --config=%S/Inputs/config-1.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-HHH
! CHECK-HHH: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
! CHECK-HHH: -flto
!
!
!--- Config file (full path) in output of -v
!
! RUN: %flang --config %S/Inputs/config-1.cfg -S %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-V
! CHECK-V: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
! CHECK-V: -flto
!
!--- Config file in output of -###
!
! RUN: %flang --config-system-dir=%S/Inputs --config-user-dir= --config config-1.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-HHH2
! CHECK-HHH2: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
! CHECK-HHH2: -flto
!
!--- Config file in output of -v
!
! RUN: %flang --config-system-dir=%S/Inputs --config-user-dir= --config config-1.cfg -S %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-V2
! CHECK-V2: Configuration file: {{.*}}Inputs{{.}}config-1.cfg
! CHECK-V2: -flto
!
!--- Nested config files
!
! RUN: %flang --config-system-dir=%S/Inputs --config-user-dir= --config config-2.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED
! CHECK-NESTED: Configuration file: {{.*}}Inputs{{.}}config-2.cfg
! CHECK-NESTED: -fno-signed-zeros
!
! RUN: %flang --config-system-dir=%S/Inputs --config-user-dir=%S/Inputs/config --config config-6.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED2
! CHECK-NESTED2: Configuration file: {{.*}}Inputs{{.}}config-6.cfg
! CHECK-NESTED2: -fstack-arrays
!
!
! RUN: %flang --config %S/Inputs/config-2a.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTEDa
! CHECK-NESTEDa: Configuration file: {{.*}}Inputs{{.}}config-2a.cfg
! CHECK-NESTEDa: -fopenmp
!
! RUN: %flang --config-system-dir=%S/Inputs --config-user-dir= --config config-2a.cfg -S %s -### 2>&1 | FileCheck %s -check-prefix CHECK-NESTED2a
! CHECK-NESTED2a: Configuration file: {{.*}}Inputs{{.}}config-2a.cfg
! CHECK-NESTED2a: -fopenmp
!
!--- User directory is searched first.
!
! RUN: %flang --config-system-dir=%S/Inputs/config --config-user-dir=%S/Inputs/config2 --config config-4.cfg -S %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-PRECEDENCE
! CHECK-PRECEDENCE: Configuration file: {{.*}}Inputs{{.}}config2{{.}}config-4.cfg
! CHECK-PRECEDENCE: -ffp-contract=fast
!
!--- Multiple configuration files can be specified.
! RUN: %flang --config-system-dir=%S/Inputs/config --config-user-dir= --config config-4.cfg --config %S/Inputs/config2/config-4.cfg -S %s -o /dev/null -v 2>&1 | FileCheck %s -check-prefix CHECK-TWO-CONFIGS
! CHECK-TWO-CONFIGS: Configuration file: {{.*}}Inputs{{.}}config{{.}}config-4.cfg
! CHECK-TWO-CONFIGS-NEXT: Configuration file: {{.*}}Inputs{{.}}config2{{.}}config-4.cfg
! CHECK-TWO-CONFIGS: -ffp-contract=fast
! CHECK-TWO-CONFIGS: -O3
12 changes: 4 additions & 8 deletions flang/test/Lower/OpenMP/firstprivate-commonblock.f90
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
! RUN: %flang_fc1 -emit-hlfir -fopenmp \
! RUN: -mmlir --openmp-enable-delayed-privatization=true -o - %s 2>&1 \
! RUN: | FileCheck %s

!CHECK: func.func @_QPfirstprivate_common() {
!CHECK: %[[val_0:.*]] = fir.address_of(@c_) : !fir.ref<!fir.array<8xi8>>
Expand All @@ -12,15 +14,9 @@
!CHECK: %[[val_5:.*]] = fir.coordinate_of %[[val_4]], %[[val_c4]] : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
!CHECK: %[[val_6:.*]] = fir.convert %[[val_5]] : (!fir.ref<i8>) -> !fir.ref<f32>
!CHECK: %[[VAL_6_DECL:.*]]:2 = hlfir.declare %[[val_6]] {uniq_name = "_QFfirstprivate_commonEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
!CHECK: omp.parallel {
!CHECK: %[[val_7:.*]] = fir.alloca f32 {bindc_name = "x", pinned, uniq_name = "_QFfirstprivate_commonEx"}
!CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %[[val_7:.*]] : {{.*}}, @{{.*}} %{{.*}}#0 -> %[[val_9:.*]] : {{.*}}) {
!CHECK: %[[VAL_7_DECL:.*]]:2 = hlfir.declare %[[val_7]] {uniq_name = "_QFfirstprivate_commonEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
!CHECK: %[[val_8:.*]] = fir.load %[[VAL_3_DECL]]#0 : !fir.ref<f32>
!CHECK: hlfir.assign %[[val_8]] to %[[VAL_7_DECL]]#0 temporary_lhs : f32, !fir.ref<f32>
!CHECK: %[[val_9:.*]] = fir.alloca f32 {bindc_name = "y", pinned, uniq_name = "_QFfirstprivate_commonEy"}
!CHECK: %[[VAL_9_DECL:.*]]:2 = hlfir.declare %[[val_9]] {uniq_name = "_QFfirstprivate_commonEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
!CHECK: %[[val_10:.*]] = fir.load %[[VAL_6_DECL]]#0 : !fir.ref<f32>
!CHECK: hlfir.assign %[[val_10]] to %[[VAL_9_DECL]]#0 temporary_lhs : f32, !fir.ref<f32>
!CHECK: omp.terminator
!CHECK: }
!CHECK: return
Expand Down
24 changes: 9 additions & 15 deletions flang/test/Lower/OpenMP/private-commonblock.f90
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
! RUN: %flang_fc1 -emit-hlfir -fopenmp \
! RUN: -mmlir --openmp-enable-delayed-privatization=true -o - %s 2>&1 \
! RUN: | FileCheck %s

!CHECK: func.func @_QPprivate_common() {
!CHECK: omp.parallel {
!CHECK: %[[X:.*]] = fir.alloca f32 {bindc_name = "x", pinned, uniq_name = "_QFprivate_commonEx"}
!CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %[[X:.*]] : {{.*}}, @{{.*}} %{{.*}}#0 -> %[[Y:.*]] : {{.*}}) {
!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFprivate_commonEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
!CHECK: %[[Y:.*]] = fir.alloca f32 {bindc_name = "y", pinned, uniq_name = "_QFprivate_commonEy"}
!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFprivate_commonEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
!CHECK: omp.terminator
!CHECK: }
Expand Down Expand Up @@ -48,17 +48,13 @@ subroutine private_common
!CHECK: %[[D_REF:.*]] = fir.convert %[[D_DECL]]#1 : (!fir.ref<!fir.array<5x!fir.char<1,5>>>) -> !fir.ref<!fir.char<1,5>>
!CHECK: %[[D_BOX:.*]] = fir.emboxchar %[[D_REF]], %[[TP5]] : (!fir.ref<!fir.char<1,5>>, index) -> !fir.boxchar<1>
!CHECK: fir.call @_QPsub1(%[[A_DECL]]#1, %[[B_DECL]]#1, %[[C_BOX]], %[[D_BOX]]) fastmath<contract> : (!fir.ref<i32>, !fir.ref<!fir.array<10xf32>>, !fir.boxchar<1>, !fir.boxchar<1>) -> ()
!CHECK: omp.parallel {
!CHECK: %[[A_PVT_REF:.*]] = fir.alloca i32 {bindc_name = "a", pinned, uniq_name = "_QFprivate_clause_commonblockEa"}
!CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %[[A_PVT_REF:.*]] : {{.*}}, @{{.*}} %{{.*}}#0 -> %[[B_PVT_REF:.*]] : {{.*}}, @{{.*}} %{{.*}}#0 -> %[[C_PVT_REF:.*]] : {{.*}}, @{{.*}} %{{.*}}#0 -> %[[D_PVT_REF:.*]] : {{.*}}) {
!CHECK: %[[A_PVT_DECL:.*]]:2 = hlfir.declare %[[A_PVT_REF]] {uniq_name = "_QFprivate_clause_commonblockEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[B_PVT_REF:.*]] = fir.alloca !fir.array<10xf32> {bindc_name = "b", pinned, uniq_name = "_QFprivate_clause_commonblockEb"}
!CHECK: %[[SH10:.*]] = fir.shape %c10 : (index) -> !fir.shape<1>
!CHECK: %[[SH10:.*]] = fir.shape %c10{{.*}} : (index) -> !fir.shape<1>
!CHECK: %[[B_PVT_DECL:.*]]:2 = hlfir.declare %[[B_PVT_REF]](%[[SH10]]) {uniq_name = "_QFprivate_clause_commonblockEb"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>)
!CHECK: %[[C_PVT_REF:.*]] = fir.alloca !fir.char<1,5> {bindc_name = "c", pinned, uniq_name = "_QFprivate_clause_commonblockEc"}
!CHECK: %[[C_PVT_DECL:.*]]:2 = hlfir.declare %[[C_PVT_REF]] typeparams %{{.*}} {uniq_name = "_QFprivate_clause_commonblockEc"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>)
!CHECK: %[[D_PVT_REF:.*]] = fir.alloca !fir.array<5x!fir.char<1,5>> {bindc_name = "d", pinned, uniq_name = "_QFprivate_clause_commonblockEd"}
!CHECK: %[[SH5:.*]] = fir.shape %c5_1 : (index) -> !fir.shape<1>
!CHECK: %[[D_PVT_DECL:.*]]:2 = hlfir.declare %[[D_PVT_REF]](%[[SH5]]) typeparams %[[TP5]] {uniq_name = "_QFprivate_clause_commonblockEd"} : (!fir.ref<!fir.array<5x!fir.char<1,5>>>, !fir.shape<1>, index) -> (!fir.ref<!fir.array<5x!fir.char<1,5>>>, !fir.ref<!fir.array<5x!fir.char<1,5>>>)
!CHECK: %[[SH5:.*]] = fir.shape %c5{{.*}} : (index) -> !fir.shape<1>
!CHECK: %[[D_PVT_DECL:.*]]:2 = hlfir.declare %[[D_PVT_REF]](%[[SH5]]) typeparams %c5{{.*}} {uniq_name = "_QFprivate_clause_commonblockEd"} : (!fir.ref<!fir.array<5x!fir.char<1,5>>>, !fir.shape<1>, index) -> (!fir.ref<!fir.array<5x!fir.char<1,5>>>, !fir.ref<!fir.array<5x!fir.char<1,5>>>)
!CHECK: %[[C_PVT_BOX:.*]] = fir.emboxchar %[[C_PVT_DECL]]#1, %{{.*}} : (!fir.ref<!fir.char<1,5>>, index) -> !fir.boxchar<1>
!CHECK: %[[D_PVT_REF:.*]] = fir.convert %[[D_PVT_DECL]]#1 : (!fir.ref<!fir.array<5x!fir.char<1,5>>>) -> !fir.ref<!fir.char<1,5>>
!CHECK: %[[D_PVT_BOX:.*]] = fir.emboxchar %[[D_PVT_REF]], %{{.*}} : (!fir.ref<!fir.char<1,5>>, index) -> !fir.boxchar<1>
Expand Down Expand Up @@ -98,10 +94,8 @@ subroutine private_clause_commonblock()
!CHECK: %[[C_ADDR:.*]] = fir.box_addr %[[C_BOX]] : (!fir.box<!fir.ptr<!fir.complex<4>>>) -> !fir.ptr<!fir.complex<4>>
!CHECK: %[[C_REF:.*]] = fir.convert %[[C_ADDR]] : (!fir.ptr<!fir.complex<4>>) -> !fir.ref<!fir.complex<4>>
!CHECK: fir.call @_QPsub4(%[[C_REF]], %[[A_DECL]]#1) fastmath<contract> : (!fir.ref<!fir.complex<4>>, !fir.ref<i32>) -> ()
!CHECK: omp.parallel {
!CHECK: %[[C_PVT_REF:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.complex<4>>> {bindc_name = "c", pinned, uniq_name = "_QFprivate_clause_commonblock_pointerEc"}
!CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %[[C_PVT_REF:.*]] : {{.*}}, @{{.*}} %{{.*}}#0 -> %[[A_PVT_REF:.*]] : {{.*}}) {
!CHECK: %[[C_PVT_DECL:.*]]:2 = hlfir.declare %[[C_PVT_REF]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFprivate_clause_commonblock_pointerEc"} : (!fir.ref<!fir.box<!fir.ptr<!fir.complex<4>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.complex<4>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.complex<4>>>>)
!CHECK: %[[A_PVT_REF:.*]] = fir.alloca i32 {bindc_name = "a", pinned, uniq_name = "_QFprivate_clause_commonblock_pointerEa"}
!CHECK: %[[A_PVT_DECL:.*]]:2 = hlfir.declare %[[A_PVT_REF]] {uniq_name = "_QFprivate_clause_commonblock_pointerEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[C_PVT_BOX:.*]] = fir.load %[[C_PVT_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.complex<4>>>>
!CHECK: %[[C_PVT_ADDR:.*]] = fir.box_addr %[[C_PVT_BOX]] : (!fir.box<!fir.ptr<!fir.complex<4>>>) -> !fir.ptr<!fir.complex<4>>
Expand Down
6 changes: 2 additions & 4 deletions libc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ foreach(config_path IN LISTS LIBC_CONFIG_JSON_FILE_LIST)
load_libc_config(${config_path}/config.json ${cmd_line_conf})
endforeach()

if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND LIBC_ENABLE_USE_BY_CLANG)
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND (LIBC_ENABLE_USE_BY_CLANG OR LIBC_TARGET_OS_IS_GPU))
set(LIBC_INCLUDE_DIR ${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE})
set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
set(LIBC_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
Expand All @@ -244,9 +244,7 @@ else()
set(LIBC_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX})
endif()
if(LIBC_TARGET_OS_IS_GPU)
if(LLVM_RUNTIMES_TARGET)
set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_RUNTIMES_TARGET})
elseif(LIBC_TARGET_TRIPLE)
if(LIBC_TARGET_TRIPLE)
set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LIBC_TARGET_TRIPLE})
else()
set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
Expand Down
91 changes: 0 additions & 91 deletions libc/cmake/modules/LLVMLibCLibraryRules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -83,97 +83,6 @@ function(get_all_object_file_deps result fq_deps_list)
set(${result} ${all_deps} PARENT_SCOPE)
endfunction()

# A rule to build a library from a collection of entrypoint objects and bundle
# it into a GPU fatbinary. Usage is the same as 'add_entrypoint_library'.
# Usage:
# add_gpu_entrypoint_library(
# DEPENDS <list of add_entrypoint_object targets>
# )
function(add_gpu_entrypoint_library target_name base_target_name)
cmake_parse_arguments(
"ENTRYPOINT_LIBRARY"
"" # No optional arguments
"" # No single value arguments
"DEPENDS" # Multi-value arguments
${ARGN}
)
if(NOT ENTRYPOINT_LIBRARY_DEPENDS)
message(FATAL_ERROR "'add_entrypoint_library' target requires a DEPENDS list "
"of 'add_entrypoint_object' targets.")
endif()

get_fq_deps_list(fq_deps_list ${ENTRYPOINT_LIBRARY_DEPENDS})
get_all_object_file_deps(all_deps "${fq_deps_list}")

# The GPU 'libc' needs to be exported in a format that can be linked with
# offloading langauges like OpenMP or CUDA. This wraps every GPU object into a
# fat binary and adds them to a static library.
set(objects "")
foreach(dep IN LISTS all_deps)
set(object $<$<STREQUAL:$<TARGET_NAME_IF_EXISTS:${dep}>,${dep}>:$<TARGET_OBJECTS:${dep}>>)
string(FIND ${dep} "." last_dot_loc REVERSE)
math(EXPR name_loc "${last_dot_loc} + 1")
string(SUBSTRING ${dep} ${name_loc} -1 name)
if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
set(prefix --image=arch=generic,triple=nvptx64-nvidia-cuda,feature=+ptx63)
elseif(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU)
set(prefix --image=arch=generic,triple=amdgcn-amd-amdhsa)
endif()

# Use the 'clang-offload-packager' to merge these files into a binary blob.
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/binary/${name}.gpubin"
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/binary
COMMAND ${LIBC_CLANG_OFFLOAD_PACKAGER}
"${prefix},file=$<JOIN:${object},,file=>" -o
${CMAKE_CURRENT_BINARY_DIR}/binary/${name}.gpubin
DEPENDS ${dep} ${base_target_name}
COMMENT "Packaging LLVM offloading binary for '${object}'"
)
add_custom_target(${dep}.__gpubin__ DEPENDS ${dep}
"${CMAKE_CURRENT_BINARY_DIR}/binary/${name}.gpubin")
if(TARGET clang-offload-packager)
add_dependencies(${dep}.__gpubin__ clang-offload-packager)
endif()

# CMake does not permit setting the name on object files. In order to have
# human readable names we create an empty stub file with the entrypoint
# name. This empty file will then have the created binary blob embedded.
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/stubs/${name}.cpp"
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/stubs
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/stubs/${name}.cpp
DEPENDS ${dep} ${dep}.__gpubin__ ${base_target_name}
)
add_custom_target(${dep}.__stub__
DEPENDS ${dep}.__gpubin__ "${CMAKE_CURRENT_BINARY_DIR}/stubs/${name}.cpp")

add_library(${dep}.__fatbin__
EXCLUDE_FROM_ALL OBJECT
"${CMAKE_CURRENT_BINARY_DIR}/stubs/${name}.cpp"
)

# This is always compiled for the LLVM host triple instead of the native GPU
# triple that is used by default in the build.
target_compile_options(${dep}.__fatbin__ BEFORE PRIVATE -nostdlib)
target_compile_options(${dep}.__fatbin__ PRIVATE
--target=${LLVM_HOST_TRIPLE}
"SHELL:-Xclang -fembed-offload-object=${CMAKE_CURRENT_BINARY_DIR}/binary/${name}.gpubin")
add_dependencies(${dep}.__fatbin__
${dep} ${dep}.__stub__ ${dep}.__gpubin__ ${base_target_name})

# Set the list of newly create fat binaries containing embedded device code.
list(APPEND objects $<TARGET_OBJECTS:${dep}.__fatbin__>)
endforeach()

add_library(
${target_name}
STATIC
${objects}
)
set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${LIBC_LIBRARY_DIR})
endfunction(add_gpu_entrypoint_library)

# A rule to build a library from a collection of entrypoint objects and bundle
# it in a single LLVM-IR bitcode file.
# Usage:
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.sys.select.select

# sys/socket.h entrypoints
libc.src.sys.socket.bind
libc.src.sys.socket.socket
)
endif()
Expand Down
19 changes: 0 additions & 19 deletions libc/docs/gpu/building.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,25 +151,6 @@ Build overview
Once installed, the GPU build will create several files used for different
targets. This section will briefly describe their purpose.

**lib/<host-triple>/libcgpu-amdgpu.a or lib/libcgpu-amdgpu.a**
A static library containing fat binaries supporting AMD GPUs. These are built
using the support described in the `clang documentation
<https://clang.llvm.org/docs/OffloadingDesign.html>`_. These are intended to
be static libraries included natively for offloading languages like CUDA, HIP,
or OpenMP. This implements the standard C library.

**lib/<host-triple>/libmgpu-amdgpu.a or lib/libmgpu-amdgpu.a**
A static library containing fat binaries that implements the standard math
library for AMD GPUs.

**lib/<host-triple>/libcgpu-nvptx.a or lib/libcgpu-nvptx.a**
A static library containing fat binaries that implement the standard C library
for NVIDIA GPUs.

**lib/<host-triple>/libmgpu-nvptx.a or lib/libmgpu-nvptx.a**
A static library containing fat binaries that implement the standard math
library for NVIDIA GPUs.

**include/<target-triple>**
The include directory where all of the generated headers for the target will
go. These definitions are strictly for the GPU when being targeted directly.
Expand Down
15 changes: 8 additions & 7 deletions libc/docs/gpu/using.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@ described in the `clang documentation
by the OpenMP toolchain, but is currently opt-in for the CUDA and HIP toolchains
through the ``--offload-new-driver``` and ``-fgpu-rdc`` flags.

The installation should contain a static library called ``libcgpu-amdgpu.a`` or
``libcgpu-nvptx.a`` depending on which GPU architectures your build targeted.
These contain fat binaries compatible with the offloading toolchain such that
they can be used directly.
In order or link the GPU runtime, we simply pass this library to the embedded
device linker job. This can be done using the ``-Xoffload-linker`` option, which
forwards an argument to a ``clang`` job used to create the final GPU executable.
The toolchain should pick up the C libraries automatically in most cases, so
this shouldn't be necessary.

.. code-block:: sh

$> clang openmp.c -fopenmp --offload-arch=gfx90a -lcgpu-amdgpu
$> clang cuda.cu --offload-arch=sm_80 --offload-new-driver -fgpu-rdc -lcgpu-nvptx
$> clang hip.hip --offload-arch=gfx940 --offload-new-driver -fgpu-rdc -lcgpu-amdgpu
$> clang openmp.c -fopenmp --offload-arch=gfx90a -Xoffload-linker -lc
$> clang cuda.cu --offload-arch=sm_80 --offload-new-driver -fgpu-rdc -Xoffload-linker -lc
$> clang hip.hip --offload-arch=gfx940 --offload-new-driver -fgpu-rdc -Xoffload-linker -lc

This will automatically link in the needed function definitions if they were
required by the user's application. Normally using the ``-fgpu-rdc`` option
Expand Down
15 changes: 0 additions & 15 deletions libc/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,6 @@ foreach(archive IN ZIP_LISTS
# Add the offloading version of the library for offloading languages. These
# are installed in the standard search path separate from the other libraries.
if(LIBC_TARGET_OS_IS_GPU)
add_gpu_entrypoint_library(
${archive_1}gpu
${archive_1}
DEPENDS
${${archive_2}}
)
set_target_properties(
${archive_1}gpu
PROPERTIES
ARCHIVE_OUTPUT_NAME ${archive_0}gpu-${LIBC_TARGET_ARCHITECTURE}
ARCHIVE_OUTPUT_DIRECTORY ${LLVM_LIBRARY_OUTPUT_INTDIR}
)
list(APPEND added_gpu_archive_targets ${archive_1}gpu)

add_bitcode_entrypoint_library(
${archive_1}bitcode
${archive_1}
Expand All @@ -65,7 +51,6 @@ foreach(archive IN ZIP_LISTS
PROPERTIES
OUTPUT_NAME ${archive_1}.bc
)
add_dependencies(${archive_1}gpu ${archive_1}bitcode)
list(APPEND added_gpu_bitcode_targets ${archive_1}bitcode)
endif()
endforeach()
Expand Down
24 changes: 12 additions & 12 deletions libc/test/src/math/smoke/TotalOrderMagTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,24 +104,24 @@ class TotalOrderMagTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}

void testNaNPayloads(TotalOrderMagFunc func) {
T qnan_123 = FPBits::quiet_nan(Sign::POS, 0x123).get_val();
T neg_qnan_123 = FPBits::quiet_nan(Sign::NEG, 0x123).get_val();
T snan_123 = FPBits::signaling_nan(Sign::POS, 0x123).get_val();
T neg_snan_123 = FPBits::signaling_nan(Sign::NEG, 0x123).get_val();
T qnan_0x42 = FPBits::quiet_nan(Sign::POS, 0x42).get_val();
T neg_qnan_0x42 = FPBits::quiet_nan(Sign::NEG, 0x42).get_val();
T snan_0x42 = FPBits::signaling_nan(Sign::POS, 0x42).get_val();
T neg_snan_0x42 = FPBits::signaling_nan(Sign::NEG, 0x42).get_val();

EXPECT_TRUE(funcWrapper(func, aNaN, aNaN));
EXPECT_TRUE(funcWrapper(func, sNaN, sNaN));
EXPECT_TRUE(funcWrapper(func, aNaN, qnan_123));
EXPECT_TRUE(funcWrapper(func, sNaN, snan_123));
EXPECT_FALSE(funcWrapper(func, qnan_123, aNaN));
EXPECT_FALSE(funcWrapper(func, snan_123, sNaN));
EXPECT_TRUE(funcWrapper(func, aNaN, qnan_0x42));
EXPECT_FALSE(funcWrapper(func, sNaN, snan_0x42));
EXPECT_FALSE(funcWrapper(func, qnan_0x42, aNaN));
EXPECT_TRUE(funcWrapper(func, snan_0x42, sNaN));

EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_aNaN));
EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_sNaN));
EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_qnan_123));
EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_snan_123));
EXPECT_FALSE(funcWrapper(func, neg_qnan_123, neg_aNaN));
EXPECT_FALSE(funcWrapper(func, neg_snan_123, neg_sNaN));
EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_qnan_0x42));
EXPECT_FALSE(funcWrapper(func, neg_sNaN, neg_snan_0x42));
EXPECT_FALSE(funcWrapper(func, neg_qnan_0x42, neg_aNaN));
EXPECT_TRUE(funcWrapper(func, neg_snan_0x42, neg_sNaN));
}
};

Expand Down
24 changes: 12 additions & 12 deletions libc/test/src/math/smoke/TotalOrderTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,24 +102,24 @@ class TotalOrderTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest {
}

void testNaNPayloads(TotalOrderFunc func) {
T qnan_123 = FPBits::quiet_nan(Sign::POS, 0x123).get_val();
T neg_qnan_123 = FPBits::quiet_nan(Sign::NEG, 0x123).get_val();
T snan_123 = FPBits::signaling_nan(Sign::POS, 0x123).get_val();
T neg_snan_123 = FPBits::signaling_nan(Sign::NEG, 0x123).get_val();
T qnan_0x42 = FPBits::quiet_nan(Sign::POS, 0x42).get_val();
T neg_qnan_0x42 = FPBits::quiet_nan(Sign::NEG, 0x42).get_val();
T snan_0x42 = FPBits::signaling_nan(Sign::POS, 0x42).get_val();
T neg_snan_0x42 = FPBits::signaling_nan(Sign::NEG, 0x42).get_val();

EXPECT_TRUE(funcWrapper(func, aNaN, aNaN));
EXPECT_TRUE(funcWrapper(func, sNaN, sNaN));
EXPECT_TRUE(funcWrapper(func, aNaN, qnan_123));
EXPECT_TRUE(funcWrapper(func, sNaN, snan_123));
EXPECT_FALSE(funcWrapper(func, qnan_123, aNaN));
EXPECT_FALSE(funcWrapper(func, snan_123, sNaN));
EXPECT_TRUE(funcWrapper(func, aNaN, qnan_0x42));
EXPECT_FALSE(funcWrapper(func, sNaN, snan_0x42));
EXPECT_FALSE(funcWrapper(func, qnan_0x42, aNaN));
EXPECT_TRUE(funcWrapper(func, snan_0x42, sNaN));

EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_aNaN));
EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_sNaN));
EXPECT_FALSE(funcWrapper(func, neg_aNaN, neg_qnan_123));
EXPECT_FALSE(funcWrapper(func, neg_sNaN, neg_snan_123));
EXPECT_TRUE(funcWrapper(func, neg_qnan_123, neg_aNaN));
EXPECT_TRUE(funcWrapper(func, neg_snan_123, neg_sNaN));
EXPECT_FALSE(funcWrapper(func, neg_aNaN, neg_qnan_0x42));
EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_snan_0x42));
EXPECT_TRUE(funcWrapper(func, neg_qnan_0x42, neg_aNaN));
EXPECT_FALSE(funcWrapper(func, neg_snan_0x42, neg_sNaN));
}
};

Expand Down
8 changes: 6 additions & 2 deletions libcxx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,16 @@ if (NOT "${LIBCXX_HARDENING_MODE}" IN_LIST LIBCXX_SUPPORTED_HARDENING_MODES)
"Unsupported hardening mode: '${LIBCXX_HARDENING_MODE}'. Supported values are ${LIBCXX_SUPPORTED_HARDENING_MODES}.")
endif()
set(LIBCXX_ASSERTION_HANDLER_FILE
"${CMAKE_CURRENT_SOURCE_DIR}/vendor/llvm/default_assertion_handler.in"
"vendor/llvm/default_assertion_handler.in"
CACHE STRING
"Specify the path to a header that contains a custom implementation of the
assertion handler that gets invoked when a hardening assertion fails. If
provided, this header will be included by the library, replacing the
default assertion handler.")
default assertion handler. If this is specified as a relative path, it
is assumed to be relative to '<monorepo>/libcxx'.")
if (NOT IS_ABSOLUTE "${LIBCXX_ASSERTION_HANDLER_FILE}")
set(LIBCXX_ASSERTION_HANDLER_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${LIBCXX_ASSERTION_HANDLER_FILE}")
endif()
option(LIBCXX_ENABLE_RANDOM_DEVICE
"Whether to include support for std::random_device in the library. Disabling
this can be useful when building the library for platforms that don't have
Expand Down
3 changes: 2 additions & 1 deletion libcxx/docs/BuildingLibcxx.rst
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,8 @@ libc++ Feature Options
Specify the path to a header that contains a custom implementation of the
assertion handler that gets invoked when a hardening assertion fails. If
provided, this header will be included by the library, replacing the
default assertion handler.
default assertion handler. If this is specified as a relative path, it
is assumed to be relative to ``<monorepo>/libcxx``.


libc++ ABI Feature Options
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx20Issues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@
"`3349 <https://wg21.link/LWG3349>`__","Missing ``__cpp_lib_constexpr_complex``\ for P0415R1","Prague","|Complete|","16.0"
"`3350 <https://wg21.link/LWG3350>`__","Simplify return type of ``lexicographical_compare_three_way``\ ","Prague","|Complete|","17.0","|spaceship|"
"`3351 <https://wg21.link/LWG3351>`__","``ranges::enable_safe_range``\ should not be constrained","Prague","|Complete|","15.0","|ranges|"
"`3352 <https://wg21.link/LWG3352>`__","``strong_equality``\ isn't a thing","Prague","|Nothing To Do|","","|spaceship|"
"`3352 <https://wg21.link/LWG3352>`__","``strong_equality``\ isn't a thing","Prague","|Complete|","19.0","|spaceship|"
"`3354 <https://wg21.link/LWG3354>`__","``has_strong_structural_equality``\ has a meaningless definition","Prague","|Nothing To Do|","","|spaceship|"
"`3355 <https://wg21.link/LWG3355>`__","The memory algorithms should support move-only input iterators introduced by P1207","Prague","|Complete|","15.0","|ranges|"
"`3356 <https://wg21.link/LWG3356>`__","``__cpp_lib_nothrow_convertible``\ should be ``__cpp_lib_is_nothrow_convertible``\ ","Prague","|Complete|","12.0"
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/SpaceshipProjects.csv
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Section,Description,Dependencies,Assignee,Complete
"| `[string.view.synop] <https://wg21.link/string.view.synop>`_
| `[string.view.comparison] <https://wg21.link/string.view.comparison>`_",| `basic_string_view <https://reviews.llvm.org/D130295>`_,None,Mark de Wever,|Complete|
- `5.7 Clause 22: Containers library <https://wg21.link/p1614r2#clause-22-containers-library>`_,,,,
| `[container.requirements.general] <https://wg21.link/container.requirements.general>`_,|,None,Unassigned,|Not Started|
| `[container.requirements.general] <https://wg21.link/container.requirements.general>`_,|,None,Mark de Wever,|Complete|
| `[array.syn] <https://wg21.link/array.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `array <https://reviews.llvm.org/D132265>`_,[expos.only.func],"| Adrian Vogelsgesang
| Hristo Hristov",|Complete|
| `[deque.syn] <https://wg21.link/deque.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `deque <https://reviews.llvm.org/D144821>`_,[expos.only.func],Hristo Hristov,|Complete|
Expand Down
14 changes: 14 additions & 0 deletions libcxx/include/__bit_reference
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <__bit/countr.h>
#include <__bit/invert_if.h>
#include <__bit/popcount.h>
#include <__compare/ordering.h>
#include <__config>
#include <__fwd/bit_reference.h>
#include <__iterator/iterator_traits.h>
Expand Down Expand Up @@ -913,6 +914,7 @@ public:
return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_;
}

#if _LIBCPP_STD_VER <= 17
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
operator!=(const __bit_iterator& __x, const __bit_iterator& __y) {
return !(__x == __y);
Expand All @@ -937,6 +939,18 @@ public:
operator>=(const __bit_iterator& __x, const __bit_iterator& __y) {
return !(__x < __y);
}
#else // _LIBCPP_STD_VER <= 17
_LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering
operator<=>(const __bit_iterator& __x, const __bit_iterator& __y) {
if (__x.__seg_ < __y.__seg_)
return strong_ordering::less;

if (__x.__seg_ == __y.__seg_)
return __x.__ctz_ <=> __y.__ctz_;

return strong_ordering::greater;
}
#endif // _LIBCPP_STD_VER <= 17

private:
_LIBCPP_HIDE_FROM_ABI
Expand Down
24 changes: 24 additions & 0 deletions libcxx/include/__iterator/bounded_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#define _LIBCPP___ITERATOR_BOUNDED_ITER_H

#include <__assert>
#include <__compare/ordering.h>
#include <__compare/three_way_comparable.h>
#include <__config>
#include <__iterator/iterator_traits.h>
#include <__memory/pointer_traits.h>
Expand Down Expand Up @@ -201,10 +203,15 @@ struct __bounded_iter {
operator==(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ == __y.__current_;
}

#if _LIBCPP_STD_VER <= 17
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
operator!=(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ != __y.__current_;
}
#endif

// TODO(mordante) disable these overloads in the LLVM 20 release.
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
operator<(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ < __y.__current_;
Expand All @@ -222,6 +229,23 @@ struct __bounded_iter {
return __x.__current_ >= __y.__current_;
}

#if _LIBCPP_STD_VER >= 20
_LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering
operator<=>(__bounded_iter const& __x, __bounded_iter const& __y) noexcept {
if constexpr (three_way_comparable<_Iterator, strong_ordering>) {
return __x.__current_ <=> __y.__current_;
} else {
if (__x.__current_ < __y.__current_)
return strong_ordering::less;

if (__x.__current_ == __y.__current_)
return strong_ordering::equal;

return strong_ordering::greater;
}
}
#endif // _LIBCPP_STD_VER >= 20

private:
template <class>
friend struct pointer_traits;
Expand Down
23 changes: 23 additions & 0 deletions libcxx/include/__iterator/wrap_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#ifndef _LIBCPP___ITERATOR_WRAP_ITER_H
#define _LIBCPP___ITERATOR_WRAP_ITER_H

#include <__compare/ordering.h>
#include <__compare/three_way_comparable.h>
#include <__config>
#include <__iterator/iterator_traits.h>
#include <__memory/addressof.h>
Expand Down Expand Up @@ -131,6 +133,7 @@ operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXC
return __x.base() < __y.base();
}

#if _LIBCPP_STD_VER <= 17
template <class _Iter1>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
Expand All @@ -142,7 +145,9 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
return !(__x == __y);
}
#endif

// TODO(mordante) disable these overloads in the LLVM 20 release.
template <class _Iter1>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
Expand Down Expand Up @@ -179,6 +184,24 @@ operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX
return !(__y < __x);
}

#if _LIBCPP_STD_VER >= 20
template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering
operator<=>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) noexcept {
if constexpr (three_way_comparable_with<_Iter1, _Iter2, strong_ordering>) {
return __x.base() <=> __y.base();
} else {
if (__x.base() < __y.base())
return strong_ordering::less;

if (__x.base() == __y.base())
return strong_ordering::equal;

return strong_ordering::greater;
}
}
#endif // _LIBCPP_STD_VER >= 20

template <class _Iter1, class _Iter2>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
#ifndef _LIBCPP_CXX03_LANG
Expand Down
29 changes: 27 additions & 2 deletions libcxx/include/deque
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,13 @@ public:
return __x.__ptr_ == __y.__ptr_;
}

#if _LIBCPP_STD_VER <= 17
_LIBCPP_HIDE_FROM_ABI friend bool operator!=(const __deque_iterator& __x, const __deque_iterator& __y) {
return !(__x == __y);
}
#endif

// TODO(mordante) disable these overloads in the LLVM 20 release.
_LIBCPP_HIDE_FROM_ABI friend bool operator<(const __deque_iterator& __x, const __deque_iterator& __y) {
return __x.__m_iter_ < __y.__m_iter_ || (__x.__m_iter_ == __y.__m_iter_ && __x.__ptr_ < __y.__ptr_);
}
Expand All @@ -396,6 +399,29 @@ public:
return !(__x < __y);
}

#if _LIBCPP_STD_VER >= 20
_LIBCPP_HIDE_FROM_ABI friend strong_ordering operator<=>(const __deque_iterator& __x, const __deque_iterator& __y) {
if (__x.__m_iter_ < __y.__m_iter_)
return strong_ordering::less;

if (__x.__m_iter_ == __y.__m_iter_) {
if constexpr (three_way_comparable<pointer, strong_ordering>) {
return __x.__ptr_ <=> __y.__ptr_;
} else {
if (__x.__ptr_ < __y.__ptr_)
return strong_ordering::less;

if (__x.__ptr_ == __y.__ptr_)
return strong_ordering::equal;

return strong_ordering::greater;
}
}

return strong_ordering::greater;
}
#endif // _LIBCPP_STD_VER >= 20

private:
_LIBCPP_HIDE_FROM_ABI explicit __deque_iterator(__map_iterator __m, pointer __p) _NOEXCEPT
: __m_iter_(__m),
Expand Down Expand Up @@ -2530,8 +2556,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const deque<_Tp, _Allocator>& __x,
template <class _Tp, class _Allocator>
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp>
operator<=>(const deque<_Tp, _Allocator>& __x, const deque<_Tp, _Allocator>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
}

#endif // _LIBCPP_STD_VER <= 17
Expand Down
14 changes: 12 additions & 2 deletions libcxx/test/libcxx/iterators/bounded_iter/comparison.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//
// Comparison operators

#include <concepts>
#include <__iterator/bounded_iter.h>

#include "test_iterators.h"
Expand Down Expand Up @@ -59,6 +60,12 @@ TEST_CONSTEXPR_CXX14 bool tests() {
assert(iter1 >= iter1);
}

#if TEST_STD_VER >= 20
// P1614
std::same_as<std::strong_ordering> decltype(auto) r1 = iter1 <=> iter2;
assert(r1 == std::strong_ordering::less);
#endif

return true;
}

Expand All @@ -69,8 +76,11 @@ int main(int, char**) {
#endif

#if TEST_STD_VER > 17
tests<contiguous_iterator<int*> >();
static_assert(tests<contiguous_iterator<int*> >(), "");
tests<contiguous_iterator<int*>>();
static_assert(tests<contiguous_iterator<int*>>());

tests<three_way_contiguous_iterator<int*>>();
static_assert(tests<three_way_contiguous_iterator<int*>>());
#endif

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
//
//===----------------------------------------------------------------------===//

// This test appears to hang with picolibc & qemu.
// This test did pass but is very slow when run using qemu. ~7 minutes on a
// Neoverse N1 (AArch64) server core.
// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME

// <algorithm>
Expand Down
18 changes: 18 additions & 0 deletions libcxx/test/std/containers/sequences/array/iterators.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ TEST_CONSTEXPR_CXX17 bool tests()
assert(std::rbegin(c) != std::rend(c));
assert(std::cbegin(c) != std::cend(c));
assert(std::crbegin(c) != std::crend(c));

# if TEST_STD_VER >= 20
// P1614 + LWG3352
std::same_as<std::strong_ordering> decltype(auto) r1 = ii1 <=> ii2;
assert(r1 == std::strong_ordering::equal);

std::same_as<std::strong_ordering> decltype(auto) r2 = cii <=> ii2;
assert(r2 == std::strong_ordering::equal);
# endif
}
{
typedef std::array<int, 0> C;
Expand Down Expand Up @@ -189,6 +198,15 @@ TEST_CONSTEXPR_CXX17 bool tests()
assert(std::rbegin(c) == std::rend(c));
assert(std::cbegin(c) == std::cend(c));
assert(std::crbegin(c) == std::crend(c));

# if TEST_STD_VER >= 20
// P1614 + LWG3352
std::same_as<std::strong_ordering> decltype(auto) r1 = ii1 <=> ii2;
assert(r1 == std::strong_ordering::equal);

std::same_as<std::strong_ordering> decltype(auto) r2 = cii <=> ii2;
assert(r2 == std::strong_ordering::equal);
# endif
}
}
#endif
Expand Down
29 changes: 29 additions & 0 deletions libcxx/test/std/containers/sequences/deque/iterators.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,27 @@ int main(int, char**)
i = c.begin();
C::const_iterator j;
j = c.cbegin();

assert(i == j);
assert(!(i != j));

assert(!(i < j));
assert((i <= j));

assert(!(i > j));
assert((i >= j));

# if TEST_STD_VER >= 20
// P1614 + LWG3352
// When the allocator does not have operator<=> then the iterator uses a
// fallback to provide operator<=>.
// Make sure to test with an allocator that does not have operator<=>.
static_assert(!std::three_way_comparable<min_allocator<int>, std::strong_ordering>);
static_assert(std::three_way_comparable<typename C::iterator, std::strong_ordering>);

std::same_as<std::strong_ordering> decltype(auto) r1 = i <=> j;
assert(r1 == std::strong_ordering::equal);
# endif
}
#endif
#if TEST_STD_VER > 11
Expand Down Expand Up @@ -74,6 +94,15 @@ int main(int, char**)
// assert ( cii != c.begin());
// assert ( cii != c.cend());
// assert ( ii1 != c.end());

# if TEST_STD_VER >= 20
// P1614 + LWG3352
std::same_as<std::strong_ordering> decltype(auto) r1 = ii1 <=> ii2;
assert(r1 == std::strong_ordering::equal);

std::same_as<std::strong_ordering> decltype(auto) r2 = cii <=> ii2;
assert(r2 == std::strong_ordering::equal);
# endif // TEST_STD_VER > 20
}
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,21 @@ TEST_CONSTEXPR_CXX20 bool tests()
C::iterator i = c.begin();
C::iterator j = c.end();
assert(std::distance(i, j) == 0);

assert(i == j);
assert(!(i != j));

assert(!(i < j));
assert((i <= j));

assert(!(i > j));
assert((i >= j));

# if TEST_STD_VER >= 20
// P1614 + LWG3352
std::same_as<std::strong_ordering> decltype(auto) r = i <=> j;
assert(r == std::strong_ordering::equal);
# endif
}
{
typedef bool T;
Expand All @@ -86,7 +100,21 @@ TEST_CONSTEXPR_CXX20 bool tests()
C::const_iterator i = c.begin();
C::const_iterator j = c.end();
assert(std::distance(i, j) == 0);

assert(i == j);
assert(!(i != j));

assert(!(i < j));
assert((i <= j));

assert(!(i > j));
assert((i >= j));

# if TEST_STD_VER >= 20
// P1614 + LWG3352
std::same_as<std::strong_ordering> decltype(auto) r = i <=> j;
assert(r == std::strong_ordering::equal);
# endif
}
{
typedef bool T;
Expand Down Expand Up @@ -131,6 +159,15 @@ TEST_CONSTEXPR_CXX20 bool tests()
assert ( (cii >= ii1 ));
assert (cii - ii1 == 0);
assert (ii1 - cii == 0);

# if TEST_STD_VER >= 20
// P1614 + LWG3352
std::same_as<std::strong_ordering> decltype(auto) r1 = ii1 <=> ii2;
assert(r1 == std::strong_ordering::equal);

std::same_as<std::strong_ordering> decltype(auto) r2 = cii <=> ii2;
assert(r2 == std::strong_ordering::equal);
# endif // TEST_STD_VER > 20
}
#endif

Expand Down
49 changes: 48 additions & 1 deletion libcxx/test/std/containers/sequences/vector/iterators.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,27 @@ TEST_CONSTEXPR_CXX20 bool tests()
C::iterator i = c.begin();
C::iterator j = c.end();
assert(std::distance(i, j) == 0);

assert(i == j);
assert(!(i != j));

assert(!(i < j));
assert((i <= j));

assert(!(i > j));
assert((i >= j));

# if TEST_STD_VER >= 20
// P1614 + LWG3352
// When the allocator does not have operator<=> then the iterator uses a
// fallback to provide operator<=>.
// Make sure to test with an allocator that does not have operator<=>.
static_assert(!std::three_way_comparable<min_allocator<int>, std::strong_ordering>);
static_assert(std::three_way_comparable<typename C::iterator, std::strong_ordering>);

std::same_as<std::strong_ordering> decltype(auto) r1 = i <=> j;
assert(r1 == std::strong_ordering::equal);
# endif
}
{
typedef int T;
Expand All @@ -96,7 +116,26 @@ TEST_CONSTEXPR_CXX20 bool tests()
C::const_iterator i = c.begin();
C::const_iterator j = c.end();
assert(std::distance(i, j) == 0);

assert(i == j);
assert(!(i != j));

assert(!(i < j));
assert((i <= j));

assert(!(i > j));
assert((i >= j));

# if TEST_STD_VER >= 20
// When the allocator does not have operator<=> then the iterator uses a
// fallback to provide operator<=>.
// Make sure to test with an allocator that does not have operator<=>.
static_assert(!std::three_way_comparable<min_allocator<int>, std::strong_ordering>);
static_assert(std::three_way_comparable<typename C::iterator, std::strong_ordering>);

std::same_as<std::strong_ordering> decltype(auto) r1 = i <=> j;
assert(r1 == std::strong_ordering::equal);
# endif
}
{
typedef int T;
Expand Down Expand Up @@ -164,8 +203,16 @@ TEST_CONSTEXPR_CXX20 bool tests()
assert ( (cii >= ii1 ));
assert (cii - ii1 == 0);
assert (ii1 - cii == 0);
# if TEST_STD_VER >= 20
// P1614 + LWG3352
std::same_as<std::strong_ordering> decltype(auto) r1 = ii1 <=> ii2;
assert(r1 == std::strong_ordering::equal);

std::same_as<std::strong_ordering> decltype(auto) r2 = cii <=> ii2;
assert(r2 == std::strong_ordering::equal);
# endif // TEST_STD_VER > 20
}
#endif
#endif // TEST_STD_VER > 11

return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17

// <span>

// class iterator

#include <cassert>
#include <concepts>
#include <iterator>
#include <span>
#include <string>
#include <version> // __cpp_lib_ranges_as_const is not defined in span.

#include "test_macros.h"

template <class T>
constexpr void test_type() {
using C = std::span<T>;
typename C::iterator ii1{}, ii2{};
typename C::iterator ii4 = ii1;
// TODO Test against C++23 after implementing
// P2278R4 cbegin should always return a constant iterator
// The means adjusting the #ifdef to guard against C++23.
#ifdef __cpp_lib_ranges_as_const
typename C::const_iterator cii{};
#endif
assert(ii1 == ii2);
assert(ii1 == ii4);
#ifdef __cpp_lib_ranges_as_const
assert(ii1 == cii);
#endif

assert(!(ii1 != ii2));
#ifdef __cpp_lib_ranges_as_const
assert(!(ii1 != cii));
#endif

T v;
C c{&v, 1};
assert(c.begin() == std::begin(c));
assert(c.rbegin() == std::rbegin(c));
#ifdef __cpp_lib_ranges_as_const
assert(c.cbegin() == std::cbegin(c));
assert(c.crbegin() == std::crbegin(c));
#endif

assert(c.end() == std::end(c));
assert(c.rend() == std::rend(c));
#ifdef __cpp_lib_ranges_as_const
assert(c.cend() == std::cend(c));
assert(c.crend() == std::crend(c));
#endif

assert(std::begin(c) != std::end(c));
assert(std::rbegin(c) != std::rend(c));
#ifdef __cpp_lib_ranges_as_const
assert(std::cbegin(c) != std::cend(c));
assert(std::crbegin(c) != std::crend(c));
#endif

// P1614 + LWG3352
std::same_as<std::strong_ordering> decltype(auto) r1 = ii1 <=> ii2;
assert(r1 == std::strong_ordering::equal);

#ifdef __cpp_lib_ranges_as_const
std::same_as<std::strong_ordering> decltype(auto) r2 = cii <=> ii2;
assert(r2 == std::strong_ordering::equal);
#endif
}

constexpr bool test() {
test_type<char>();
test_type<int>();
test_type<std::string>();

return true;
}

int main(int, char**) {
test();
static_assert(test(), "");

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: !stdlib=libc++ && (c++03 || c++11 || c++14)

// <string_view>

// class iterator

#include <cassert>
#include <concepts>
#include <iterator>
#include <string_view>

#include "test_macros.h"
#include "make_string.h"

template <class CharT>
TEST_CONSTEXPR_CXX14 void test_type() {
using C = std::basic_string_view<CharT>;
typename C::iterator ii1 = typename C::iterator(), ii2 = typename C::iterator();
typename C::iterator ii4 = ii1;
typename C::const_iterator cii = typename C::const_iterator();
assert(ii1 == ii2);
assert(ii1 == ii4);
assert(ii1 == cii);

assert(!(ii1 != ii2));
assert(!(ii1 != cii));

#if TEST_STD_VER >= 17
C c = MAKE_STRING_VIEW(CharT, "abc");
assert(c.begin() == std::begin(c));
assert(c.rbegin() == std::rbegin(c));
assert(c.cbegin() == std::cbegin(c));
assert(c.crbegin() == std::crbegin(c));

assert(c.end() == std::end(c));
assert(c.rend() == std::rend(c));
assert(c.cend() == std::cend(c));
assert(c.crend() == std::crend(c));

assert(std::begin(c) != std::end(c));
assert(std::rbegin(c) != std::rend(c));
assert(std::cbegin(c) != std::cend(c));
assert(std::crbegin(c) != std::crend(c));
#endif

#if TEST_STD_VER >= 20
// P1614 + LWG3352
std::same_as<std::strong_ordering> decltype(auto) r1 = ii1 <=> ii2;
assert(r1 == std::strong_ordering::equal);

std::same_as<std::strong_ordering> decltype(auto) r2 = ii1 <=> ii2;
assert(r2 == std::strong_ordering::equal);
#endif
}

TEST_CONSTEXPR_CXX14 bool test() {
test_type<char>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test_type<wchar_t>();
#endif
#ifndef TEST_HAS_NO_CHAR8_T
test_type<char8_t>();
#endif
test_type<char16_t>();
test_type<char32_t>();

return true;
}

int main(int, char**) {
test();
#if TEST_STD_VER >= 14
static_assert(test(), "");
#endif

return 0;
}
2 changes: 2 additions & 0 deletions libcxx/test/support/test_iterators.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ class contiguous_iterator
friend TEST_CONSTEXPR bool operator> (const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ > y.it_;}
friend TEST_CONSTEXPR bool operator>=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ >= y.it_;}

// Note no operator<=>, use three_way_contiguous_iterator for testing operator<=>

friend TEST_CONSTEXPR It base(const contiguous_iterator& i) { return i.it_; }

template <class T>
Expand Down
2 changes: 1 addition & 1 deletion lld/test/COFF/lto-cpu-string.ll
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ target triple = "x86_64-pc-windows-msvc19.14.26433"

define dllexport void @foo() #0 {
entry:
call void asm sideeffect ".p2align 4, 0x90", "~{dirflag},~{fpsr},~{flags}"()
call void asm sideeffect ".p2align 4", "~{dirflag},~{fpsr},~{flags}"()
ret void
}

Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/lto/cpu-string.ll
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ target triple = "x86_64-unknown-linux-gnu"

define void @foo() #0 {
entry:
call void asm sideeffect ".p2align 4, 0x90", "~{dirflag},~{fpsr},~{flags}"()
call void asm sideeffect ".p2align 4", "~{dirflag},~{fpsr},~{flags}"()
ret void
}

Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/lto/mllvm.ll
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16

define void @_start() #0 {
entry:
call void asm sideeffect ".p2align 4, 0x90", "~{dirflag},~{fpsr},~{flags}"()
call void asm sideeffect ".p2align 4", "~{dirflag},~{fpsr},~{flags}"()
ret void
}

Expand Down
2 changes: 1 addition & 1 deletion lld/test/MachO/lto-cpu-string.ll
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16

define void @foo() #0 {
entry:
call void asm sideeffect ".p2align 4, 0x90", "~{dirflag},~{fpsr},~{flags}"()
call void asm sideeffect ".p2align 4", "~{dirflag},~{fpsr},~{flags}"()
ret void
}

Expand Down
Loading