44 changes: 22 additions & 22 deletions clang/include/clang/Basic/riscv_vector.td
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ multiclass RVVIndexedLoad<string op> {
defvar eew = eew_list[0];
defvar eew_type = eew_list[1];
let Name = op # eew # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>) in {
def: RVVOutOp1Builtin<"v", "vPCe" # eew_type # "Uv", type>;
if !not(IsFloat<type>.val) then {
Expand All @@ -128,7 +128,7 @@ multiclass RVVIndexedLoad<string op> {
defvar eew64 = "64";
defvar eew64_type = "(Log2EEW:6)";
let Name = op # eew64 # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh", "RV64"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin", "RV64"],
["RV64"]) in {
def: RVVOutOp1Builtin<"v", "vPCe" # eew64_type # "Uv", type>;
if !not(IsFloat<type>.val) then {
Expand Down Expand Up @@ -222,7 +222,7 @@ multiclass RVVIndexedStore<string op> {
defvar eew = eew_list[0];
defvar eew_type = eew_list[1];
let Name = op # eew # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>) in {
def : RVVBuiltin<"v", "0Pe" # eew_type # "Uvv", type>;
if !not(IsFloat<type>.val) then {
Expand All @@ -233,7 +233,7 @@ multiclass RVVIndexedStore<string op> {
defvar eew64 = "64";
defvar eew64_type = "(Log2EEW:6)";
let Name = op # eew64 # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh", "RV64"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin", "RV64"],
["RV64"]) in {
def : RVVBuiltin<"v", "0Pe" # eew64_type # "Uvv", type>;
if !not(IsFloat<type>.val) then {
Expand Down Expand Up @@ -681,30 +681,30 @@ let HasBuiltinAlias = false,
def vlm: RVVVLEMaskBuiltin;
defm vle8: RVVVLEBuiltin<["c"]>;
defm vle16: RVVVLEBuiltin<["s"]>;
let Name = "vle16_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vle16_v", RequiredFeatures = ["Zvfhmin"] in
defm vle16_h: RVVVLEBuiltin<["x"]>;
defm vle32: RVVVLEBuiltin<["i","f"]>;
defm vle64: RVVVLEBuiltin<["l","d"]>;

def vsm : RVVVSEMaskBuiltin;
defm vse8 : RVVVSEBuiltin<["c"]>;
defm vse16: RVVVSEBuiltin<["s"]>;
let Name = "vse16_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vse16_v", RequiredFeatures = ["Zvfhmin"] in
defm vse16_h: RVVVSEBuiltin<["x"]>;
defm vse32: RVVVSEBuiltin<["i","f"]>;
defm vse64: RVVVSEBuiltin<["l","d"]>;

// 7.5. Vector Strided Instructions
defm vlse8: RVVVLSEBuiltin<["c"]>;
defm vlse16: RVVVLSEBuiltin<["s"]>;
let Name = "vlse16_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vlse16_v", RequiredFeatures = ["Zvfhmin"] in
defm vlse16_h: RVVVLSEBuiltin<["x"]>;
defm vlse32: RVVVLSEBuiltin<["i","f"]>;
defm vlse64: RVVVLSEBuiltin<["l","d"]>;

defm vsse8 : RVVVSSEBuiltin<["c"]>;
defm vsse16: RVVVSSEBuiltin<["s"]>;
let Name = "vsse16_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vsse16_v", RequiredFeatures = ["Zvfhmin"] in
defm vsse16_h: RVVVSSEBuiltin<["x"]>;
defm vsse32: RVVVSSEBuiltin<["i","f"]>;
defm vsse64: RVVVSSEBuiltin<["l","d"]>;
Expand All @@ -719,7 +719,7 @@ defm : RVVIndexedStore<"vsoxei">;
// 7.7. Unit-stride Fault-Only-First Loads
defm vle8ff: RVVVLEFFBuiltin<["c"]>;
defm vle16ff: RVVVLEFFBuiltin<["s"]>;
let Name = "vle16ff_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vle16ff_v", RequiredFeatures = ["Zvfhmin"] in
defm vle16ff: RVVVLEFFBuiltin<["x"]>;
defm vle32ff: RVVVLEFFBuiltin<["i", "f"]>;
defm vle64ff: RVVVLEFFBuiltin<["l", "d"]>;
Expand All @@ -738,7 +738,7 @@ multiclass RVVUnitStridedSegLoadTuple<string op> {
IRName = op # nf,
MaskedIRName = op # nf # "_mask",
NF = nf,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
Expand Down Expand Up @@ -800,7 +800,7 @@ multiclass RVVUnitStridedSegStoreTuple<string op> {
MaskedIRName = op # nf # "_mask",
NF = nf,
HasMaskedOffOperand = false,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
Expand Down Expand Up @@ -852,7 +852,7 @@ multiclass RVVUnitStridedSegLoadFFTuple<string op> {
IRName = op # nf # "ff",
MaskedIRName = op # nf # "ff_mask",
NF = nf,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
Expand Down Expand Up @@ -927,7 +927,7 @@ multiclass RVVStridedSegLoadTuple<string op> {
IRName = op # nf,
MaskedIRName = op # nf # "_mask",
NF = nf,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
Expand Down Expand Up @@ -991,7 +991,7 @@ multiclass RVVStridedSegStoreTuple<string op> {
NF = nf,
HasMaskedOffOperand = false,
MaskedPolicyScheme = NonePolicy,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
Expand Down Expand Up @@ -1040,7 +1040,7 @@ multiclass RVVIndexedSegLoadTuple<string op> {
IRName = op # nf,
MaskedIRName = op # nf # "_mask",
NF = nf,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
Expand Down Expand Up @@ -1103,7 +1103,7 @@ multiclass RVVIndexedSegStoreTuple<string op> {
NF = nf,
HasMaskedOffOperand = false,
MaskedPolicyScheme = NonePolicy,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
Expand Down Expand Up @@ -1345,7 +1345,7 @@ let HasMasked = false,
[["v", "Uv", "UvUv"]]>;
defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csilfd",
[["v", "v", "vv"]]>;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "x",
[["v", "v", "vv"]]>;
let SupportOverloading = false in
Expand Down Expand Up @@ -1841,7 +1841,7 @@ let HasMasked = false,
}] in {
defm vmerge : RVVOutOp1BuiltinSet<"vmerge", "fd",
[["vvm", "v", "vvvm"]]>;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
defm vmerge : RVVOutOp1BuiltinSet<"vmerge", "x",
[["vvm", "v", "vvvm"]]>;
defm vfmerge : RVVOutOp1BuiltinSet<"vfmerge", "xfd",
Expand Down Expand Up @@ -1869,7 +1869,7 @@ let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
def vfwcvt_f_xu_v : RVVConvBuiltin<"Fw", "FwUv", "csi", "vfwcvt_f">;
def vfwcvt_f_x_v : RVVConvBuiltin<"Fw", "Fwv", "csi", "vfwcvt_f">;
def vfwcvt_f_f_v : RVVConvBuiltin<"w", "wv", "f", "vfwcvt_f">;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
def vfwcvt_f_f_v_fp16 : RVVConvBuiltin<"w", "wv", "x", "vfwcvt_f"> {
let Name = "vfwcvt_f_f_v";
let IRName = "vfwcvt_f_f_v";
Expand Down Expand Up @@ -1966,7 +1966,7 @@ let ManualCodegen = [{
}
let OverloadedName = "vfncvt_f" in {
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "f", [["v", "vwu"]]>;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "x", [["v", "vwu"]]>;
}
}
Expand Down Expand Up @@ -2011,7 +2011,7 @@ let ManualCodegen = [{
}
let OverloadedName = "vfncvt_f" in {
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "f", [["v", "vw"]]>;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "x", [["v", "vw"]]>;
}
}
Expand Down Expand Up @@ -2271,7 +2271,7 @@ let HasMasked = false, HasVL = false, IRName = "" in {
def vreinterpret_u_f : RVVBuiltin<"FvUv", "UvFv", "il", "Uv">;
def vreinterpret_f_i : RVVBuiltin<"vFv", "Fvv", "il", "Fv">;
def vreinterpret_f_u : RVVBuiltin<"UvFv", "FvUv", "il", "Fv">;
let RequiredFeatures = ["ZvfhminOrZvfh"] in {
let RequiredFeatures = ["Zvfhmin"] in {
def vreinterpret_i_h : RVVBuiltin<"Fvv", "vFv", "s", "v">;
def vreinterpret_u_h : RVVBuiltin<"FvUv", "UvFv", "s", "Uv">;
def vreinterpret_h_i : RVVBuiltin<"vFv", "Fvv", "s", "Fv">;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -5172,7 +5172,7 @@ def module_file_info : Flag<["-"], "module-file-info">, Flags<[]>,
HelpText<"Provide information about a particular module file">;
def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>,
HelpText<"Only supported on AArch64, PowerPC, RISC-V, SystemZ, and X86">;
HelpText<"Only supported on AArch64, PowerPC, RISC-V, SPARC, SystemZ, and X86">;
def multi__module : Flag<["-"], "multi_module">;
def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">;
def multiply__defined : Separate<["-"], "multiply_defined">;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Support/RISCVVIntrinsicUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ class RVVIntrinsic {
enum RVVRequire : uint32_t {
RVV_REQ_None = 0,
RVV_REQ_RV64 = 1 << 0,
RVV_REQ_ZvfhminOrZvfh = 1 << 1,
RVV_REQ_Zvfhmin = 1 << 1,
RVV_REQ_Xsfvcp = 1 << 2,
RVV_REQ_Xsfvfnrclipxfqf = 1 << 3,
RVV_REQ_Xsfvfwmaccqqq = 1 << 4,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2337,7 +2337,7 @@ bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
auto GlobalIndex = P.getGlobal(VD);
assert(GlobalIndex); // visitVarDecl() didn't return false.
if (VarT) {
if (!this->emitGetGlobal(*VarT, *GlobalIndex, VD))
if (!this->emitGetGlobalUnchecked(*VarT, *GlobalIndex, VD))
return false;
} else {
if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
Expand Down
48 changes: 38 additions & 10 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
return true;
}

static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
const ValueDecl *VD) {
if (!S.getLangOpts().CPlusPlus)
return;

const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc,
VD->getType()->isIntegralOrEnumerationType()
? diag::note_constexpr_ltor_non_const_int
: diag::note_constexpr_ltor_non_constexpr,
1)
<< VD;
S.Note(VD->getLocation(), diag::note_declared_at);
}

static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK) {
if (Ptr.isActive())
Expand Down Expand Up @@ -171,9 +186,7 @@ bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {

if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
const auto *VD = Ptr.getDeclDesc()->asValueDecl();
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
S.Note(VD->getLocation(), diag::note_declared_at);
diagnoseNonConstVariable(S, OpPC, VD);
}
return false;
}
Expand Down Expand Up @@ -216,6 +229,24 @@ bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return true;
}

bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
assert(Desc);
if (const auto *D = Desc->asValueDecl()) {
if (const auto *VD = dyn_cast<VarDecl>(D);
VD && VD->hasGlobalStorage() &&
!(VD->isConstexpr() || VD->getType().isConstQualified())) {
diagnoseNonConstVariable(S, OpPC, VD);
return false;
}
}

return true;
}

static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return CheckConstant(S, OpPC, Ptr.getDeclDesc());
}

bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return !Ptr.isZero() && !Ptr.isDummy();
}
Expand Down Expand Up @@ -304,6 +335,9 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!CheckLive(S, OpPC, Ptr, AK_Read))
return false;
if (!CheckConstant(S, OpPC, Ptr))
return false;

if (!CheckDummy(S, OpPC, Ptr))
return false;
if (!CheckExtern(S, OpPC, Ptr))
Expand Down Expand Up @@ -605,13 +639,7 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
}
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (!VD->getType().isConstQualified()) {
S.FFDiag(E,
VD->getType()->isIntegralOrEnumerationType()
? diag::note_constexpr_ltor_non_const_int
: diag::note_constexpr_ltor_non_constexpr,
1)
<< VD;
S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
diagnoseNonConstVariable(S, OpPC, VD);
return false;
}

Expand Down
14 changes: 14 additions & 0 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
/// Checks if a pointer points to const storage.
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

/// Checks if the Descriptor is of a constexpr or const global variable.
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc);

/// Checks if a pointer points to a mutable field.
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

Expand Down Expand Up @@ -1004,12 +1007,23 @@ bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
const Block *B = S.P.getGlobal(I);

if (!CheckConstant(S, OpPC, B->getDescriptor()))
return false;
if (B->isExtern())
return false;
S.Stk.push<T>(B->deref<T>());
return true;
}

/// Same as GetGlobal, but without the checks.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) {
auto *B = S.P.getGlobal(I);
S.Stk.push<T>(B->deref<T>());
return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
// TODO: emit warning.
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ def CheckGlobalCtor : Opcode {}

// [] -> [Value]
def GetGlobal : AccessOpcode;
def GetGlobalUnchecked : AccessOpcode;
// [Value] -> []
def InitGlobal : AccessOpcode;
// [Value] -> []
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,8 +730,8 @@ struct MCDCCoverageBuilder {
return;

// If binary expression is disqualified, don't do mapping.
if (NestLevel.empty() && MCDCBitmapMap.find(CodeGenFunction::stripCond(
E)) == MCDCBitmapMap.end())
if (NestLevel.empty() &&
!MCDCBitmapMap.contains(CodeGenFunction::stripCond(E)))
NotMapped = true;

// Push Stmt on 'NestLevel' stack to keep track of nest location.
Expand All @@ -744,7 +744,7 @@ struct MCDCCoverageBuilder {
// If the operator itself has an assigned ID, this means it represents a
// larger subtree. In this case, pop its ID out of the RHS stack and
// assign that ID to its LHS node. Its RHS will receive a new ID.
if (CondIDs.find(CodeGenFunction::stripCond(E)) != CondIDs.end()) {
if (CondIDs.contains(CodeGenFunction::stripCond(E))) {
// If Stmt has an ID, assign its ID to LHS
CondIDs[CodeGenFunction::stripCond(E->getLHS())] = CondIDs[E];

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Frontend/CompilerInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2204,7 +2204,7 @@ void CompilerInstance::createModuleFromSource(SourceLocation ImportLoc,
// Build the module, inheriting any modules that we've built locally.
if (compileModuleImpl(*this, ImportLoc, ModuleName, Input, StringRef(),
ModuleFileName, PreBuildStep, PostBuildStep)) {
BuiltModules[std::string(ModuleName)] = std::string(ModuleFileName.str());
BuiltModules[std::string(ModuleName)] = std::string(ModuleFileName);
llvm::sys::RemoveFileOnSignal(ModuleFileName);
}
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Frontend/Rewrite/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class FixItActionSuffixInserter : public FixItOptions {
SmallString<128> Path(Filename);
llvm::sys::path::replace_extension(Path,
NewSuffix + llvm::sys::path::extension(Path));
return std::string(Path.str());
return std::string(Path);
}
};

Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Sema/SemaRISCVVectorLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,8 @@ void RISCVIntrinsicManagerImpl::ConstructRVVIntrinsics(
continue;

if (BaseType == BasicType::Float16) {
if ((Record.RequiredExtensions & RVV_REQ_ZvfhminOrZvfh) ==
RVV_REQ_ZvfhminOrZvfh) {
if (!TI.hasFeature("zvfh") && !TI.hasFeature("zvfhmin"))
if ((Record.RequiredExtensions & RVV_REQ_Zvfhmin) == RVV_REQ_Zvfhmin) {
if (!TI.hasFeature("zvfhmin"))
continue;
} else if (!TI.hasFeature("zvfh")) {
continue;
Expand Down
32 changes: 32 additions & 0 deletions clang/test/AST/Interp/arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,3 +566,35 @@ namespace GH69115 {
static_assert(foo2() == 0, "");
#endif
}

namespace NonConstReads {
#if __cplusplus >= 202002L
void *p = nullptr; // ref-note {{declared here}} \
// expected-note {{declared here}}

int arr[!p]; // ref-error {{not allowed at file scope}} \
// expected-error {{not allowed at file scope}} \
// ref-warning {{variable length arrays}} \
// ref-note {{read of non-constexpr variable 'p'}} \
// expected-warning {{variable length arrays}} \
// expected-note {{read of non-constexpr variable 'p'}}
int z; // ref-note {{declared here}} \
// expected-note {{declared here}}
int a[z]; // ref-error {{not allowed at file scope}} \
// expected-error {{not allowed at file scope}} \
// ref-warning {{variable length arrays}} \
// ref-note {{read of non-const variable 'z'}} \
// expected-warning {{variable length arrays}} \
// expected-note {{read of non-const variable 'z'}}
#else
void *p = nullptr;
int arr[!p]; // ref-error {{not allowed at file scope}} \
// expected-error {{not allowed at file scope}}
int z;
int a[z]; // ref-error {{not allowed at file scope}} \
// expected-error {{not allowed at file scope}}
#endif

const int y = 0;
int yy[y];
}
22 changes: 16 additions & 6 deletions clang/test/AST/Interp/cxx23.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,32 @@ constexpr int g(int n) { // ref20-error {{constexpr function never produc
}

constexpr int c_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
// ref23-error {{constexpr function never produces a constant expression}}
// ref23-error {{constexpr function never produces a constant expression}} \
// expected20-error {{constexpr function never produces a constant expression}} \
// expected23-error {{constexpr function never produces a constant expression}}
static _Thread_local int m = 0; // ref20-note {{control flows through the definition of a thread_local variable}} \
// ref20-warning {{is a C++23 extension}} \
// ref23-note {{control flows through the definition of a thread_local variable}} \
// expected20-warning {{is a C++23 extension}}
return m;
// expected20-warning {{is a C++23 extension}} \
// expected20-note {{declared here}} \
// expected23-note {{declared here}}
return m; // expected20-note {{read of non-const variable}} \
// expected23-note {{read of non-const variable}}
}


constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
// ref23-error {{constexpr function never produces a constant expression}}
// ref23-error {{constexpr function never produces a constant expression}} \
// expected20-error {{constexpr function never produces a constant expression}} \
// expected23-error {{constexpr function never produces a constant expression}}
static __thread int m = 0; // ref20-note {{control flows through the definition of a thread_local variable}} \
// ref20-warning {{is a C++23 extension}} \
// ref23-note {{control flows through the definition of a thread_local variable}} \
// expected20-warning {{is a C++23 extension}}
return m;
// expected20-warning {{is a C++23 extension}} \
// expected20-note {{declared here}} \
// expected23-note {{declared here}}
return m; // expected20-note {{read of non-const variable}} \
// expected23-note {{read of non-const variable}}
}

constexpr int h(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
Expand Down
27 changes: 24 additions & 3 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1181,8 +1181,29 @@ namespace InvalidDeclRefs {
// expected-error {{not an integral constant expression}} \
// expected-note {{initializer of 'b02' is unknown}}

/// FIXME: This should also be diagnosed in the new interpreter.
int b03 = 3; // ref-note {{declared here}}
int b03 = 3; // ref-note {{declared here}} \
// expected-note {{declared here}}
static_assert(b03, ""); // ref-error {{not an integral constant expression}} \
// ref-note {{read of non-const variable}}
// ref-note {{read of non-const variable}} \
// expected-error {{not an integral constant expression}} \
// expected-note {{read of non-const variable}}
}

namespace NonConstReads {
void *p = nullptr; // ref-note {{declared here}} \
// expected-note {{declared here}}
static_assert(!p, ""); // ref-error {{not an integral constant expression}} \
// ref-note {{read of non-constexpr variable 'p'}} \
// expected-error {{not an integral constant expression}} \
// expected-note {{read of non-constexpr variable 'p'}}

int arr[!p]; // ref-error {{variable length array}} \
// expected-error {{variable length array}}

int z; // ref-note {{declared here}} \
// expected-note {{declared here}}
static_assert(z == 0, ""); // ref-error {{not an integral constant expression}} \
// ref-note {{read of non-const variable 'z'}} \
// expected-error {{not an integral constant expression}} \
// expected-note {{read of non-const variable 'z'}}
}
202 changes: 101 additions & 101 deletions clang/test/CXX/drs/dr0xx.cpp

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions clang/test/CXX/drs/dr13xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ void caller() {
#endif // __cplusplus >= 201103L
} // namespace dr1307

// dr1308: sup 1330

namespace dr1310 { // dr1310: 5
struct S {} * sp = new S::S;
// expected-error@-1 {{qualified reference to 'S' is a constructor name rather than a type in this context}}
Expand Down Expand Up @@ -379,6 +381,77 @@ namespace dr1347 { // dr1347: 3.1
#endif
}

namespace dr1350 { // dr1350: 3.5
#if __cplusplus >= 201103L
struct NoexceptCtor {
NoexceptCtor(int) noexcept {}
};

struct ThrowingNSDMI : NoexceptCtor {
int a = []() noexcept(false) { return 0; }();
using NoexceptCtor::NoexceptCtor;
};

static_assert(!__is_nothrow_constructible(ThrowingNSDMI, int), "");

struct ThrowingCtor {
ThrowingCtor() noexcept(false) {}
};

struct ThrowingNSDM : NoexceptCtor {
ThrowingCtor c;
using NoexceptCtor::NoexceptCtor;
};

static_assert(!__is_nothrow_constructible(ThrowingNSDM, int), "");

struct ThrowingCtorTemplate {
template <typename = int>
ThrowingCtorTemplate() noexcept(false) {}
};

struct ThrowingNSDM2 : NoexceptCtor {
ThrowingCtorTemplate c;
using NoexceptCtor::NoexceptCtor;
};

static_assert(!__is_nothrow_constructible(ThrowingNSDM2, int), "");

struct D1 : NoexceptCtor, ThrowingCtor {
using NoexceptCtor::NoexceptCtor;
};

static_assert(!__is_nothrow_constructible(D1, int), "");

struct D2 : NoexceptCtor, ThrowingCtorTemplate {
using NoexceptCtor::NoexceptCtor;
};

static_assert(!__is_nothrow_constructible(D2, int), "");

struct ThrowingDefaultArg {
ThrowingDefaultArg(ThrowingCtor = {}) {}
};

struct D3 : NoexceptCtor, ThrowingDefaultArg {
using NoexceptCtor::NoexceptCtor;
};

static_assert(!__is_nothrow_constructible(D3, int), "");

struct ThrowingDefaultArgTemplate {
template <typename = int>
ThrowingDefaultArgTemplate(ThrowingCtor = {}) {}
};

struct D4 : NoexceptCtor, ThrowingDefaultArgTemplate {
using NoexceptCtor::NoexceptCtor;
};

static_assert(!__is_nothrow_constructible(D4, int), "");
#endif
} // namespace dr1350

namespace dr1358 { // dr1358: 3.1
#if __cplusplus >= 201103L
struct Lit { constexpr operator int() const { return 0; } };
Expand Down
7 changes: 7 additions & 0 deletions clang/test/CXX/drs/dr15xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,13 @@ namespace dr1573 { // dr1573: 3.9
H h(0);
// since-cxx11-error@-1 {{constructor inherited by 'H' from base class 'G' is implicitly deleted}}
// since-cxx11-note@#dr1573-H {{constructor inherited by 'H' is implicitly deleted because field 'g' has no default constructor}}

// deleted definition of constructor is inherited
struct I { I(int) = delete; }; // #dr1573-I
struct J : I { using I::I; };
J j(0);
// since-cxx11-error@-1 {{call to deleted constructor of 'J'}}
// since-cxx11-note@#dr1573-I {{'I' has been explicitly marked deleted here}}
#endif
}

Expand Down
28 changes: 28 additions & 0 deletions clang/test/CXX/drs/dr18xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,34 @@ namespace dr1881 { // dr1881: 7
static_assert(!__is_standard_layout(D), "");
}

namespace dr1890 { // dr1890: no drafting
// FIXME: current consensus for CWG2335 is that the examples are well-formed.
namespace ex1 {
#if __cplusplus >= 201402L
struct A {
struct B {
auto foo() { return 0; } // #dr1890-foo
};
decltype(B().foo()) x;
// since-cxx14-error@-1 {{function 'foo' with deduced return type cannot be used before it is defined}}
// since-cxx14-note@#dr1890-foo {{'foo' declared here}}
};
#endif
} // namespace ex1

namespace ex2 {
#if __cplusplus >= 201103L
struct Bar {
struct Baz {
int a = 0;
};
static_assert(__is_constructible(Baz), "");
// since-cxx11-error@-1 {{static assertion failed due to requirement '__is_constructible(dr1890::ex2::Bar::Baz)'}}
};
#endif
} // namespace ex2
} // namespace dr1890

void dr1891() { // dr1891: 4
#if __cplusplus >= 201103L
int n;
Expand Down
134 changes: 67 additions & 67 deletions clang/test/CXX/drs/dr1xx.cpp

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions clang/test/CXX/drs/dr2335.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors

#if __cplusplus <= 201103L
// expected-no-diagnostics
#endif

namespace dr2335 { // dr2335: no drafting
// FIXME: current consensus is that the examples are well-formed.
#if __cplusplus >= 201402L
namespace ex1 {
template <class...> struct partition_indices {
static auto compute_right() {}
static constexpr auto right = compute_right;
};
template struct partition_indices<int>;
} // namespace ex1

namespace ex2 {
template <int> struct X {};
template <class T> struct partition_indices {
static auto compute_right() { return X<I>(); }
// since-cxx14-error@-1 {{no member 'I' in 'dr2335::ex2::partition_indices<int>'; it has not yet been instantiated}}
// since-cxx14-note@#dr2335-ex2-right {{in instantiation of member function 'dr2335::ex2::partition_indices<int>::compute_right' requested here}}
// since-cxx14-note@#dr2335-ex2-inst {{in instantiation of template class 'dr2335::ex2::partition_indices<int>' requested here}}
// since-cxx14-note@#dr2335-ex2-I {{not-yet-instantiated member is declared here}}
static constexpr auto right = compute_right; // #dr2335-ex2-right
static constexpr int I = sizeof(T); // #dr2335-ex2-I
};
template struct partition_indices<int>; // #dr2335-ex2-inst
} // namespace ex2

namespace ex3 {
struct partition_indices {
static auto compute_right() {} // #dr2335-compute_right
static constexpr auto right = compute_right; // #dr2335-ex3-right
// since-cxx14-error@-1 {{function 'compute_right' with deduced return type cannot be used before it is defined}}
// since-cxx14-note@#dr2335-compute_right {{'compute_right' declared here}}
// since-cxx14-error@#dr2335-ex3-right {{declaration of variable 'right' with deduced type 'const auto' requires an initializer}}
};
} // namespace ex3
#endif
} // namespace dr2335
1 change: 1 addition & 0 deletions clang/test/CXX/drs/dr23xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ void g() {
#endif

// dr2331: na
// dr2335 is in dr2335.cxx

#if __cplusplus >= 201103L
namespace dr2338 { // dr2338: 12
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CXX/drs/dr26xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ int \N{Λ} = 0;
// expected-error@-2 {{expected unqualified-id}}
const char* emoji = "\N{🤡}";
// expected-error@-1 {{'🤡' is not a valid Unicode character name}}
// expected-note@-2 {{did you mean OX ('🐂' U+1F402)?}}
// expected-note@-3 {{did you mean ANT ('🐜' U+1F41C)?}}
// expected-note@-4 {{did you mean ARC ('⌒' U+2312)?}}
// expected-note@-5 {{did you mean AXE ('🪓' U+1FA93)?}}
// expected-note@-6 {{did you mean BAT ('🦇' U+1F987)?}}
// expected-note@-2 {{did you mean OX ('🐂' U+1F402)?}}
// expected-note@-3 {{did you mean ANT ('🐜' U+1F41C)?}}
// expected-note@-4 {{did you mean ARC ('⌒' U+2312)?}}
// expected-note@-5 {{did you mean AXE ('🪓' U+1FA93)?}}
// expected-note@-6 {{did you mean BAT ('🦇' U+1F987)?}}

#define z(x) 0
#define dr2640_a z(
Expand Down
158 changes: 79 additions & 79 deletions clang/test/CXX/drs/dr2xx.cpp

Large diffs are not rendered by default.

172 changes: 86 additions & 86 deletions clang/test/CXX/drs/dr3xx.cpp

Large diffs are not rendered by default.

134 changes: 67 additions & 67 deletions clang/test/CXX/drs/dr4xx.cpp

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions clang/test/CXX/drs/dr6xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ namespace dr657 { // dr657: partial

struct C { C(Abs) {} };
// expected-error@-1 {{parameter type 'Abs' is an abstract class}}
// expected-note@#dr657-Abs {{unimplemented pure virtual method 'x' in 'Abs'}}
// expected-note@#dr657-Abs {{unimplemented pure virtual method 'x' in 'Abs'}}
struct Q { operator Abs() { __builtin_unreachable(); } } q;
// expected-error@-1 {{return type 'Abs' is an abstract class}}
#if __cplusplus >= 201703L
Expand Down Expand Up @@ -809,7 +809,7 @@ namespace dr659 { // dr659: 3.0
struct A; // #dr659-A
int m = alignof(A&);
// since-cxx11-error@-1 {{invalid application of 'alignof' to an incomplete type 'A'}}
// since-cxx11-note@#dr659-A {{forward declaration of 'dr659::A'}}
// since-cxx11-note@#dr659-A {{forward declaration of 'dr659::A'}}
}
#endif

Expand All @@ -836,7 +836,7 @@ namespace dr662 { // dr662: yes
T &tr = t;
T *tp = &t;
// expected-error@-1 {{'tp' declared as a pointer to a reference of type 'int &'}}
// expected-note@#dr662-f-call {{in instantiation of function template specialization 'dr662::f<int &>' requested here}}
// expected-note@#dr662-f-call {{in instantiation of function template specialization 'dr662::f<int &>' requested here}}
#if __cplusplus >= 201103L
auto *ap = &t;
#endif
Expand Down Expand Up @@ -1302,12 +1302,12 @@ namespace dr692 { // dr692: 16
e2(b2);
f<int>(42);
// expected-error@-1 {{call to 'f' is ambiguous}}
// expected-note@#dr692-f-deleted {{candidate function [with T = int, U = int] has been explicitly deleted}}
// expected-note@#dr692-f {{candidate function [with U = int]}}
// expected-note@#dr692-f-deleted {{candidate function [with T = int, U = int] has been explicitly deleted}}
// expected-note@#dr692-f {{candidate function [with U = int]}}
g(42);
// expected-error@-1 {{ambiguous}}
// expected-note@#dr692-g {{candidate function [with T = int]}}
// expected-note@#dr692-g-variadic {{candidate function [with T = int, U = <>]}}
// expected-note@#dr692-g {{candidate function [with T = int]}}
// expected-note@#dr692-g-variadic {{candidate function [with T = int, U = <>]}}
}
}

Expand Down Expand Up @@ -1371,7 +1371,7 @@ namespace dr696 { // dr696: 3.1
int arr[N]; (void)arr;
f(&N);
// expected-error@-1 {{reference to local variable 'N' declared in enclosing function 'dr696::g'}}
// expected-note@#dr696-N {{'N' declared here}}
// expected-note@#dr696-N {{'N' declared here}}
}
};
#if __cplusplus >= 201103L
Expand Down
3 changes: 3 additions & 0 deletions clang/test/CodeGen/X86/inline-asm-constraints.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,12 @@ __m512 testZMM0(void) {
}

extern int var, arr[4];
struct Pair { int a, b; } pair;

// CHECK-LABEL: test_Ws(
// CHECK: call void asm sideeffect "// ${0:p} ${1:p} ${2:p}", "^Ws,^Ws,^Ws,~{dirflag},~{fpsr},~{flags}"(ptr @var, ptr getelementptr inbounds ([4 x i32], ptr @arr, i64 0, i64 3), ptr @test_Ws)
// CHECK: call void asm sideeffect "// $0", "^Ws,~{dirflag},~{fpsr},~{flags}"(ptr getelementptr inbounds (%struct.Pair, ptr @pair, i32 0, i32 1))
void test_Ws(void) {
asm("// %p0 %p1 %p2" :: "Ws"(&var), "Ws"(&arr[3]), "Ws"(test_Ws));
asm("// %0" :: "Ws"(&pair.b));
}
6 changes: 5 additions & 1 deletion clang/test/Sema/inline-asm-validate-x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,9 @@ void pr40890(void) {
}

void test_W(int i) {
asm("" : : "Wd"(test_W)); // expected-error{{invalid input constraint 'Wd' in asm}}
__asm__("" : : "Wd"(test_W)); // expected-error{{invalid input constraint 'Wd' in asm}}

__asm__("" : : "Ws"(test_W(0))); // expected-error{{invalid type 'void' in asm input for constraint 'Ws'}}
// Codegen error
__asm__("" : : "Ws"(i));
}
2 changes: 1 addition & 1 deletion clang/tools/driver/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
if (llvm::ErrorOr<std::string> P =
llvm::sys::findProgramByName(ExecutablePath))
ExecutablePath = *P;
return std::string(ExecutablePath.str());
return std::string(ExecutablePath);
}

// This just needs to be some symbol in the binary; C++ doesn't
Expand Down
2 changes: 1 addition & 1 deletion clang/utils/TableGen/RISCVVEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ void RVVEmitter::createRVVIntrinsics(
RVVRequire RequireExt =
StringSwitch<RVVRequire>(RequiredFeature)
.Case("RV64", RVV_REQ_RV64)
.Case("ZvfhminOrZvfh", RVV_REQ_ZvfhminOrZvfh)
.Case("Zvfhmin", RVV_REQ_Zvfhmin)
.Case("Xsfvcp", RVV_REQ_Xsfvcp)
.Case("Xsfvfnrclipxfqf", RVV_REQ_Xsfvfnrclipxfqf)
.Case("Xsfvfwmaccqqq", RVV_REQ_Xsfvfwmaccqqq)
Expand Down
10 changes: 5 additions & 5 deletions clang/www/cxx_dr_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -2662,7 +2662,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/437.html">437</a></td>
<td>CD1</td>
<td>Is type of class allowed in member function exception specification?</td>
<td class="unknown" align="center">Superseded by <a href="#1308">1308</a></td>
<td class="full" align="center">Superseded by <a href="#1308">1308</a></td>
</tr>
<tr id="438">
<td><a href="https://cplusplus.github.io/CWG/issues/438.html">438</a></td>
Expand Down Expand Up @@ -7656,7 +7656,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/1308.html">1308</a></td>
<td>CD3</td>
<td>Completeness of class type within an <I>exception-specification</I></td>
<td class="unknown" align="center">Unknown</td>
<td class="full" align="center">Superseded by <a href="#1330">1330</a></td>
</tr>
<tr id="1309">
<td><a href="https://cplusplus.github.io/CWG/issues/1309.html">1309</a></td>
Expand Down Expand Up @@ -7908,7 +7908,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/1350.html">1350</a></td>
<td>CD3</td>
<td>Incorrect exception specification for inherited constructors</td>
<td class="unknown" align="center">Unknown</td>
<td class="full" align="center">Clang 3.5</td>
</tr>
<tr id="1351">
<td><a href="https://cplusplus.github.io/CWG/issues/1351.html">1351</a></td>
Expand Down Expand Up @@ -11148,7 +11148,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/1890.html">1890</a></td>
<td>drafting</td>
<td>Member type depending on definition of member function</td>
<td align="center">Not resolved</td>
<td class="none" align="center">No</td>
</tr>
<tr id="1891">
<td><a href="https://cplusplus.github.io/CWG/issues/1891.html">1891</a></td>
Expand Down Expand Up @@ -13818,7 +13818,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2335.html">2335</a></td>
<td>drafting</td>
<td>Deduced return types vs member types</td>
<td align="center">Not resolved</td>
<td class="none" align="center">No</td>
</tr>
<tr id="2336">
<td><a href="https://cplusplus.github.io/CWG/issues/2336.html">2336</a></td>
Expand Down
26 changes: 17 additions & 9 deletions compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,19 +160,24 @@ static zx_status_t GetSanitizerHeapVmar(zx_handle_t *vmar) {

static zx_status_t TryVmoMapSanitizerVmar(zx_vm_option_t options,
size_t vmar_offset, zx_handle_t vmo,
size_t size, uintptr_t *addr) {
size_t size, uintptr_t *addr,
zx_handle_t *vmar_used = nullptr) {
zx_handle_t vmar;
zx_status_t status = GetSanitizerHeapVmar(&vmar);
if (status != ZX_OK)
return status;

status = _zx_vmar_map(gSanitizerHeapVmar, options, vmar_offset, vmo,
/*vmo_offset=*/0, size, addr);
if (status == ZX_ERR_NO_RESOURCES) {
if (vmar_used)
*vmar_used = gSanitizerHeapVmar;
if (status == ZX_ERR_NO_RESOURCES || status == ZX_ERR_INVALID_ARGS) {
// This means there's no space in the heap VMAR, so fallback to the root
// VMAR.
status = _zx_vmar_map(_zx_vmar_root_self(), options, vmar_offset, vmo,
/*vmo_offset=*/0, size, addr);
if (vmar_used)
*vmar_used = _zx_vmar_root_self();
}

return status;
Expand Down Expand Up @@ -367,30 +372,33 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
// beginning of the VMO, and unmap the excess before and after.
size_t map_size = size + alignment;
uintptr_t addr;
zx_handle_t vmar_used;
status = TryVmoMapSanitizerVmar(ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
/*vmar_offset=*/0, vmo, map_size, &addr);
/*vmar_offset=*/0, vmo, map_size, &addr,
&vmar_used);
if (status == ZX_OK) {
uintptr_t map_addr = addr;
uintptr_t map_end = map_addr + map_size;
addr = RoundUpTo(map_addr, alignment);
uintptr_t end = addr + size;
if (addr != map_addr) {
zx_info_vmar_t info;
status = _zx_object_get_info(gSanitizerHeapVmar, ZX_INFO_VMAR, &info,
sizeof(info), NULL, NULL);
status = _zx_object_get_info(vmar_used, ZX_INFO_VMAR, &info, sizeof(info),
NULL, NULL);
if (status == ZX_OK) {
uintptr_t new_addr;
status = TryVmoMapSanitizerVmar(
status = _zx_vmar_map(
vmar_used,
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC_OVERWRITE,
addr - info.base, vmo, size, &new_addr);
addr - info.base, vmo, 0, size, &new_addr);
if (status == ZX_OK)
CHECK_EQ(new_addr, addr);
}
}
if (status == ZX_OK && addr != map_addr)
status = _zx_vmar_unmap(_zx_vmar_root_self(), map_addr, addr - map_addr);
status = _zx_vmar_unmap(vmar_used, map_addr, addr - map_addr);
if (status == ZX_OK && end != map_end)
status = _zx_vmar_unmap(_zx_vmar_root_self(), end, map_end - end);
status = _zx_vmar_unmap(vmar_used, end, map_end - end);
}
_zx_handle_close(vmo);

Expand Down
58 changes: 40 additions & 18 deletions flang/docs/Intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ used in constant expressions have currently no folding support at all.

#### Usage and Info

- **Standard:** Fortran 2008 and later, specified in 16.9.73
- **Standard:** Fortran 2008 and later, specified in subclause 16.9.73
- **Class:** Subroutine
- **Syntax:** `CALL EXECUTE_COMMAND_LINE(COMMAND [, WAIT, EXITSTAT, CMDSTAT, CMDMSG ])`
- **Arguments:**
Expand All @@ -862,28 +862,50 @@ used in constant expressions have currently no folding support at all.

#### Implementation Specifics

- **`COMMAND`:**
- Must be preset.
##### `COMMAND`:

- **`WAIT`:**
- If set to `false`, the command is executed asynchronously. If not preset or set to `false`, it is executed synchronously.
- Sync: achieved by passing command into `std::system` on all systems.
- Async: achieved by calling a `fork()` on POSIX-compatible systems, or `CreateProcess()` on Windows.
- Must be preset.

- **`CMDSTAT`:**
##### `WAIT`:

- If set to `false`, the command is executed asynchronously.
- If not preset or set to `true`, it is executed synchronously.
- Synchronous execution is achieved by passing the command into `std::system` on all systems.
- Asynchronous execution is achieved by calling `fork()` on POSIX-compatible systems or `CreateProcess()` on Windows.

##### `EXITSTAT`:

- Synchronous execution:
- Inferred by the return value of `std::system(cmd)`.
- On POSIX-compatible systems: return value is first passed into `WEXITSTATUS(status)`, then assigned to `EXITSTAT`.
- On Windows, the value is directly assigned as the return value of `std::system()`.
- Asynchronous execution:
- Value is not modified.

##### `CMDSTAT`:

- Synchronous execution:
- -2: No error condition occurs, but `WAIT` is present with the value `false`, and the processor does not support asynchronous execution.
- -1: The processor does not support command line execution.
- \+ (positive value): An error condition occurs.
- 1: Fork Error, where `pid_t < 0`, would only occur on POSIX-compatible systems.
- 2: Execution Error, a command exits with status -1.
- 3: Invalid Command Error, determined by the exit code depending on the system.
- On Windows, if the exit code is 1.
- On POSIX-compatible systems, if the exit code is 127 or 126.
- 4: Signal error, either it is stopped or killed by signal, would only occur on POSIX-compatible systems.
- 1: Fork Error (occurs only on POSIX-compatible systems).
- 2: Execution Error (command exits with status -1).
- 3: Invalid Command Error (determined by the exit code depending on the system).
- On Windows: exit code is 1.
- On POSIX-compatible systems: exit code is 127 or 126.
- 4: Signal error (either stopped or killed by signal, occurs only on POSIX-compatible systems).
- 0: Otherwise.
- Asynchronous execution:
- 0 will always be assigned.

##### `CMDMSG`:

- **`CMDMSG`:**
- If an error condition occurs, it is assigned an explanatory message. Otherwise, it remains unchanged.
- Synchronous execution:
- If an error condition occurs, it is assigned an explanatory message; otherwise, it remains unchanged.
- If a condition occurs that would assign a nonzero value to `CMDSTAT` but the `CMDSTAT` variable is not present, error termination is initiated (applies to both POSIX-compatible systems and Windows).
- Asynchronous execution:
- The value is unchanged.
- If a condition occurs that would assign a nonzero value to `CMDSTAT` but the `CMDSTAT` variable is not present, error termination is initiated.
- On POSIX-compatible systems, this applies to both synchronous and asynchronous error termination. When the execution mode is set to async with error termination, the child process (async process) will be terminated with no effect on the parent process (continues).
- On Windows, this only applies to synchronous error termination.
- On POSIX-compatible systems, the child process (async process) will be terminated with no effect on the parent process (continues).
- On Windows, error termination is not initiated.

2 changes: 1 addition & 1 deletion flang/runtime/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void RTNAME(ExecuteCommandLine)(const Descriptor &command, bool wait,
const Descriptor *exitstat, const Descriptor *cmdstat,
const Descriptor *cmdmsg, const char *sourceFile, int line) {
Terminator terminator{sourceFile, line};
const char *newCmd{EnsureNullTerminated(
char *newCmd{EnsureNullTerminated(
command.OffsetElement(), command.ElementBytes(), terminator)};

if (exitstat) {
Expand Down
4 changes: 2 additions & 2 deletions flang/runtime/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ RT_API_ATTRS void ShallowCopy(const Descriptor &to, const Descriptor &from) {
ShallowCopy(to, from, to.IsContiguous(), from.IsContiguous());
}

RT_API_ATTRS const char *EnsureNullTerminated(
const char *str, std::size_t length, Terminator &terminator) {
RT_API_ATTRS char *EnsureNullTerminated(
char *str, std::size_t length, Terminator &terminator) {
if (std::memchr(str, '\0', length) == nullptr) {
char *newCmd{(char *)AllocateMemoryOrCrash(terminator, length + 1)};
std::memcpy(newCmd, str, length);
Expand Down
4 changes: 2 additions & 2 deletions flang/runtime/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@ RT_API_ATTRS void ShallowCopy(const Descriptor &to, const Descriptor &from);
// size memory for null-terminator if necessary. Returns the original or a newly
// allocated null-terminated string (responsibility for deallocation is on the
// caller).
RT_API_ATTRS const char *EnsureNullTerminated(
const char *str, std::size_t length, Terminator &terminator);
RT_API_ATTRS char *EnsureNullTerminated(
char *str, std::size_t length, Terminator &terminator);

RT_API_ATTRS bool IsValidCharDescriptor(const Descriptor *value);

Expand Down
2 changes: 1 addition & 1 deletion flang/test/Driver/isysroot.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
! RUN: %flang -### --target=aarch64-linux-gnu -isysroot /path/to/sysroot \
! RUN: %s 2>&1 | FileCheck %s --check-prefix=CHECK-LINUX

! CHECK-DARWIN: "{{.*[\/]}}ld" {{.*}}"-syslibroot" "/path/to/sysroot"
! CHECK-DARWIN: "{{.*}}ld{{(64)?(\.lld)?}}" {{.*}}"-syslibroot" "/path/to/sysroot"
! Unused on Linux.
! CHECK-LINUX: warning: argument unused during compilation: '-isysroot /path/to/sysroot'
! CHECK-LINUX-NOT: /path/to/sysroot
6 changes: 3 additions & 3 deletions libcxx/docs/ReleaseNotes/18.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ Implemented Papers
- P2905R2 - Runtime format strings
- P2918R2 - Runtime format strings II
- P2871R3 - Remove Deprecated Unicode Conversion Facets from C++26
- P2870R3 - Remove basic_string::reserve()
- P2870R3 - Remove ``basic_string::reserve()``
- P2909R4 - Fix formatting of code units as integers (Dude, where’s my ``char``?)
- P2821R5 - span.at()
- P0521R0 - Proposed Resolution for CA 14 (shared_ptr use_count/unique)
- P2821R5 - ``span.at()``
- P0521R0 - Proposed Resolution for CA 14 (``shared_ptr`` ``use_count/unique``)
- P1759R6 - Native handles and file streams
- P2517R1 - Add a conditional ``noexcept`` specification to ``std::apply``

Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Compiler Versions Restrictions Support policy
Clang 16, 17, 18-git latest two stable releases per `LLVM's release page <https://releases.llvm.org>`_ and the development version
AppleClang 15 latest stable release per `Xcode's release page <https://developer.apple.com/documentation/xcode-release-notes>`_
Open XL 17.1 (AIX) latest stable release per `Open XL's documentation page <https://www.ibm.com/docs/en/openxl-c-and-cpp-aix>`_
GCC 12 In C++11 or later only latest stable release per `GCC's release page <https://gcc.gnu.org/releases.html>`_
GCC 13 In C++11 or later only latest stable release per `GCC's release page <https://gcc.gnu.org/releases.html>`_
============ =============== ========================== =====================

Libc++ also supports common platforms and architectures:
Expand Down
3 changes: 1 addition & 2 deletions libcxx/include/string
Original file line number Diff line number Diff line change
Expand Up @@ -1891,8 +1891,7 @@ private:
#if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
const void* __begin = data();
const void* __end = data() + capacity() + 1;
if (!__libcpp_is_constant_evaluated() && __begin != nullptr &&
is_same<allocator_type, __default_allocator_type>::value)
if (__asan_annotate_container_with_allocator<allocator_type>::value && !__libcpp_is_constant_evaluated())
__sanitizer_annotate_contiguous_container(__begin, __end, __old_mid, __new_mid);
#endif
}
Expand Down
56 changes: 56 additions & 0 deletions libcxx/test/libcxx/containers/strings/basic.string/asan.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// REQUIRES: asan
// UNSUPPORTED: c++03

// Basic test if ASan annotations work for basic_string.

#include <string>
#include <cassert>
#include <cstdlib>

#include "asan_testing.h"
#include "min_allocator.h"
#include "test_iterators.h"
#include "test_macros.h"

extern "C" void __sanitizer_set_death_callback(void (*callback)(void));

void do_exit() { exit(0); }

int main(int, char**) {
{
typedef cpp17_input_iterator<char*> MyInputIter;
// Should not trigger ASan.
std::basic_string<char, std::char_traits<char>, safe_allocator<char>> v;
char i[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};

v.insert(v.begin(), MyInputIter(i), MyInputIter(i + 29));
assert(v[0] == 'a');
assert(is_string_asan_correct(v));
}

__sanitizer_set_death_callback(do_exit);
{
using T = char;
using C = std::basic_string<T, std::char_traits<T>, safe_allocator<T>>;
const T t[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
C c(std::begin(t), std::end(t));
assert(is_string_asan_correct(c));
assert(__sanitizer_verify_contiguous_container(c.data(), c.data() + c.size() + 1, c.data() + c.capacity() + 1) !=
0);
T foo = c[c.size() + 1]; // should trigger ASAN and call do_exit().
assert(false); // if we got here, ASAN didn't trigger
((void)foo);

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

// REQUIRES: asan
// UNSUPPORTED: c++03

// Test based on: https://bugs.chromium.org/p/chromium/issues/detail?id=1419798#c5
// Some allocators during deallocation may not call destructors and just reuse memory.
// In those situations, one may want to deactivate annotations for a specific allocator.
// It's possible with __asan_annotate_container_with_allocator template class.
// This test confirms that those allocators work after turning off annotations.
//
// A context to this test is a situations when memory is repurposed and destructors are not called.
// Related issue: https://github.com/llvm/llvm-project/issues/60384
//
// That issue appeared in the past and was addressed here: https://reviews.llvm.org/D145628
//
// There was also a discussion, if it's UB.
// Related discussion: https://reviews.llvm.org/D136765#4155262
// Related notes: https://eel.is/c++draft/basic.life#6
// Probably it's no longer UB due a change in CWG2523.
// https://cplusplus.github.io/CWG/issues/2523.html
//
// Therefore we make sure that it works that way, also because people rely on this behavior.
// Annotations are turned off only, if a user explicitly turns off annotations for a specific allocator.

#include <assert.h>
#include <stdlib.h>
#include <string>
#include <new>

// Allocator with pre-allocated (with malloc in constructor) buffers.
// Memory may be freed without calling destructors.
struct reuse_allocator {
static size_t const N = 100;
reuse_allocator() {
for (size_t i = 0; i < N; ++i)
__buffers[i] = malloc(8 * 1024);
}
~reuse_allocator() {
for (size_t i = 0; i < N; ++i)
free(__buffers[i]);
}
void* alloc() {
assert(__next_id < N);
return __buffers[__next_id++];
}
void reset() { __next_id = 0; }
void* __buffers[N];
size_t __next_id = 0;
} reuse_buffers;

template <typename T>
struct user_allocator {
using value_type = T;
user_allocator() = default;
template <class U>
user_allocator(user_allocator<U>) {}
friend bool operator==(user_allocator, user_allocator) { return true; }
friend bool operator!=(user_allocator x, user_allocator y) { return !(x == y); }

T* allocate(size_t n) {
if (n * sizeof(T) > 8 * 1024)
throw std::bad_array_new_length();
return (T*)reuse_buffers.alloc();
}
void deallocate(T*, size_t) noexcept {}
};

// Turn off annotations for user_allocator:
template <class T>
struct std::__asan_annotate_container_with_allocator<user_allocator<T>> {
static bool const value = false;
};

int main(int, char**) {
using S = std::basic_string<char, std::char_traits<char>, user_allocator<char>>;

{
// Create a string with a buffer from reuse allocator object:
S* s = new (reuse_buffers.alloc()) S();
// Use string, so it's poisoned, if container annotations for that allocator are not turned off:
for (int i = 0; i < 40; i++)
s->push_back('a');
}
// Reset the state of the allocator, don't call destructors, allow memory to be reused:
reuse_buffers.reset();
{
// Create a next string with the same allocator, so the same buffer due to the reset:
S s;
// Use memory inside the string again, if it's poisoned, an error will be raised:
for (int i = 0; i < 60; i++)
s.push_back('a');
}

return 0;
}
2 changes: 1 addition & 1 deletion libcxx/test/support/asan_testing.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ TEST_CONSTEXPR bool is_string_asan_correct(const std::basic_string<ChrT, TraitsT
return true;

if (!is_string_short(c) || _LIBCPP_SHORT_STRING_ANNOTATIONS_ALLOWED) {
if (std::is_same<Alloc, std::allocator<ChrT>>::value)
if (std::__asan_annotate_container_with_allocator<Alloc>::value)
return __sanitizer_verify_contiguous_container(c.data(), c.data() + c.size() + 1, c.data() + c.capacity() + 1) !=
0;
else
Expand Down
6 changes: 2 additions & 4 deletions lld/COFF/DriverUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,11 @@ void LinkerDriver::parseManifestUAC(StringRef arg) {
arg = arg.ltrim();
if (arg.empty())
return;
if (arg.starts_with_insensitive("level=")) {
arg = arg.substr(strlen("level="));
if (arg.consume_front_insensitive("level=")) {
std::tie(ctx.config.manifestLevel, arg) = arg.split(" ");
continue;
}
if (arg.starts_with_insensitive("uiaccess=")) {
arg = arg.substr(strlen("uiaccess="));
if (arg.consume_front_insensitive("uiaccess=")) {
std::tie(ctx.config.manifestUIAccess, arg) = arg.split(" ");
continue;
}
Expand Down
4 changes: 2 additions & 2 deletions lld/Common/Args.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ static int64_t getInteger(opt::InputArgList &args, unsigned key,

int64_t v;
StringRef s = a->getValue();
if (base == 16 && (s.starts_with("0x") || s.starts_with("0X")))
s = s.drop_front(2);
if (base == 16)
s.consume_front_insensitive("0x");
if (to_integer(s, v, base))
return v;

Expand Down
3 changes: 1 addition & 2 deletions lld/MachO/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -952,8 +952,7 @@ static std::vector<SectionAlign> parseSectAlign(const opt::InputArgList &args) {
StringRef segName = arg->getValue(0);
StringRef sectName = arg->getValue(1);
StringRef alignStr = arg->getValue(2);
if (alignStr.starts_with("0x") || alignStr.starts_with("0X"))
alignStr = alignStr.drop_front(2);
alignStr.consume_front_insensitive("0x");
uint32_t align;
if (alignStr.getAsInteger(16, align)) {
error("-sectalign: failed to parse '" + StringRef(arg->getValue(2)) +
Expand Down
57 changes: 57 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"day=${var.__d_%u}")));

AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxChronoMonthSummaryProvider,
"libc++ std::chrono::month summary provider",
Expand All @@ -1050,6 +1051,23 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue, "year=${var.__y_}")));

AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxChronoWeekdaySummaryProvider,
"libc++ std::chrono::weekday summary provider",
"^std::__[[:alnum:]]+::chrono::weekday$",
eTypeOptionHideChildren | eTypeOptionHideValue, true);

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::weekday_indexed$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue,
"${var.__wd_} index=${var.__idx_%u}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::weekday_last$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__wd_} index=last")));
cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::month_day$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
Expand All @@ -1060,12 +1078,51 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__m_} day=last")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::month_weekday$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__m_} ${var.__wdi_}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::month_weekday_last$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__m_} ${var.__wdl_}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::year_month$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__y_} ${var.__m_}")));

AddCXXSummary(
cpp_category_sp,
lldb_private::formatters::LibcxxChronoYearMonthDaySummaryProvider,
"libc++ std::chrono::year_month_day summary provider",
"^std::__[[:alnum:]]+::chrono::year_month_day$",
eTypeOptionHideChildren | eTypeOptionHideValue, true);

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::year_month_day_last$",
eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(eTypeOptionHideChildren |
eTypeOptionHideValue,
"${var.__y_} ${var.__mdl_}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::year_month_weekday$", eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue,
"${var.__y_} ${var.__m_} ${var.__wdi_}")));

cpp_category_sp->AddTypeSummary(
"^std::__[[:alnum:]]+::chrono::year_month_weekday_last$",
eFormatterMatchRegex,
TypeSummaryImplSP(new StringSummaryFormat(
eTypeOptionHideChildren | eTypeOptionHideValue,
"${var.__y_} ${var.__m_} ${var.__wdl_}")));
}

static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
Expand Down
21 changes: 21 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,27 @@ bool lldb_private::formatters::LibcxxChronoMonthSummaryProvider(
return true;
}

bool lldb_private::formatters::LibcxxChronoWeekdaySummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
// FIXME: These are the names used in the C++20 ostream operator. Since LLVM
// uses C++17 it's not possible to use the ostream operator directly.
static const std::array<std::string_view, 7> weekdays = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};

ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__wd_");
if (!ptr_sp)
return false;

const unsigned weekday = ptr_sp->GetValueAsUnsigned(0);
if (weekday >= 0 && weekday < 7)
stream << "weekday=" << weekdays[weekday];
else
stream.Printf("weekday=%u", weekday);

return true;
}

bool lldb_private::formatters::LibcxxChronoYearMonthDaySummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__y_");
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ bool LibcxxChronoMonthSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options); // libc++ std::chrono::month

bool LibcxxChronoWeekdaySummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options); // libc++ std::chrono::weekday

bool LibcxxChronoYearMonthDaySummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options); // libc++ std::chrono::year_month_day
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,53 @@ def test_with_run_command(self):
self.expect("frame variable month_13", substrs=["month_13 = month=13"])
self.expect("frame variable month_255", substrs=["month_255 = month=255"])

self.expect("frame variable sun", substrs=["sun = weekday=Sunday"])
self.expect("frame variable mon", substrs=["mon = weekday=Monday"])
self.expect("frame variable tue", substrs=["tue = weekday=Tuesday"])
self.expect("frame variable wed", substrs=["wed = weekday=Wednesday"])
self.expect("frame variable thu", substrs=["thu = weekday=Thursday"])
self.expect("frame variable fri", substrs=["fri = weekday=Friday"])
self.expect("frame variable sat", substrs=["sat = weekday=Saturday"])

self.expect("frame variable weekday_0", substrs=["weekday_0 = weekday=Sunday"])
self.expect("frame variable weekday_1", substrs=["weekday_1 = weekday=Monday"])
self.expect("frame variable weekday_2", substrs=["weekday_2 = weekday=Tuesday"])
self.expect(
"frame variable weekday_3", substrs=["weekday_3 = weekday=Wednesday"]
)
self.expect(
"frame variable weekday_4", substrs=["weekday_4 = weekday=Thursday"]
)
self.expect("frame variable weekday_5", substrs=["weekday_5 = weekday=Friday"])
self.expect(
"frame variable weekday_6", substrs=["weekday_6 = weekday=Saturday"]
)
self.expect("frame variable weekday_7", substrs=["weekday_7 = weekday=Sunday"])
self.expect("frame variable weekday_8", substrs=["weekday_8 = weekday=8"])
self.expect("frame variable weekday_255", substrs=["weekday_255 = weekday=255"])

self.expect(
"frame variable wdi_saturday_0",
substrs=["wdi_saturday_0 = weekday=Saturday index=0"],
)
self.expect(
"frame variable wdi_monday_1",
substrs=["wdi_monday_1 = weekday=Monday index=1"],
)
self.expect(
"frame variable wdi_invalid",
substrs=["wdi_invalid = weekday=255 index=255"],
)

self.expect(
"frame variable wdl_monday",
substrs=["wdl_monday = weekday=Monday index=last"],
)
self.expect(
"frame variable wdl_invalid",
substrs=["wdl_invalid = weekday=255 index=last"],
)

self.expect("frame variable y_min", substrs=["y_min = year=-32767"])
self.expect("frame variable y_0", substrs=["y_0 = year=0"])
self.expect("frame variable y_1970", substrs=["y_1970 = year=1970"])
Expand All @@ -91,6 +138,21 @@ def test_with_run_command(self):
substrs=["mdl_new_years_eve = month=December day=last"],
)

self.expect(
"frame variable mwd_first_thursday",
substrs=["mwd_first_thursday = month=January weekday=Thursday index=1"],
)

self.expect(
"frame variable mwdl_last_saturday",
substrs=["mwdl_last_saturday = month=December weekday=Saturday index=last"],
)

self.expect(
"frame variable ym_year_zero",
substrs=["ym_year_zero = year=0 month=January"],
)

self.expect("frame variable ymd_bc", substrs=["ymd_bc = date=-0001-03-255"])
self.expect(
"frame variable ymd_year_zero", substrs=["ymd_year_zero = date=0000-255-25"]
Expand All @@ -99,3 +161,34 @@ def test_with_run_command(self):
"frame variable ymd_unix_epoch",
substrs=["ymd_unix_epoch = date=1970-01-01"],
)

self.expect(
"frame variable ymdl_bc",
substrs=["ymdl_bc = year=-1 month=December day=last"],
)
self.expect(
"frame variable ymdl_may_1970",
substrs=["ymdl_may_1970 = year=1970 month=May day=last"],
)

self.expect(
"frame variable ymwd_bc",
substrs=["ymwd_bc = year=-1 month=June weekday=Wednesday index=2"],
)
self.expect(
"frame variable ymwd_forth_tuesday_2024",
substrs=[
"ymwd_forth_tuesday_2024 = year=2024 month=January weekday=Tuesday index=4"
],
)

self.expect(
"frame variable ymwdl_bc",
substrs=["ymwdl_bc = year=-1 month=April weekday=Friday index=last"],
)
self.expect(
"frame variable ymwdl_2024_last_tuesday_january",
substrs=[
"ymwdl_2024_last_tuesday_january = year=2024 month=January weekday=Tuesday index=last"
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,75 @@ int main() {
std::chrono::year y_2038{2038};
std::chrono::year y_max{std::chrono::year::max()};

std::chrono::weekday sun = std::chrono::Sunday;
std::chrono::weekday mon = std::chrono::Monday;
std::chrono::weekday tue = std::chrono::Tuesday;
std::chrono::weekday wed = std::chrono::Wednesday;
std::chrono::weekday thu = std::chrono::Thursday;
std::chrono::weekday fri = std::chrono::Friday;
std::chrono::weekday sat = std::chrono::Saturday;

std::chrono::weekday weekday_0{0};
std::chrono::weekday weekday_1{1};
std::chrono::weekday weekday_2{2};
std::chrono::weekday weekday_3{3};
std::chrono::weekday weekday_4{4};
std::chrono::weekday weekday_5{5};
std::chrono::weekday weekday_6{6};
std::chrono::weekday weekday_7{7};
std::chrono::weekday weekday_8{8};
std::chrono::weekday weekday_255{255};

std::chrono::weekday_indexed wdi_saturday_0{std::chrono::Saturday, 0};
std::chrono::weekday_indexed wdi_monday_1{std::chrono::Monday, 1};
std::chrono::weekday_indexed wdi_invalid{std::chrono::weekday{255}, 255};

std::chrono::weekday_last wdl_monday{std::chrono::Monday};
std::chrono::weekday_last wdl_invalid{std::chrono::weekday{255}};

std::chrono::month_day md_new_years_eve{std::chrono::December / 31};
std::chrono::month_day md_new_year{std::chrono::January / 1};
std::chrono::month_day md_invalid{std::chrono::month{255} / 255};

std::chrono::month_day_last mdl_jan{std::chrono::January};
std::chrono::month_day_last mdl_new_years_eve{std::chrono::December};

std::chrono::month_weekday mwd_first_thursday{
std::chrono::January,
std::chrono::weekday_indexed{std::chrono::Thursday, 1}};

std::chrono::month_weekday_last mwdl_last_saturday{
std::chrono::December, std::chrono::weekday_last{std::chrono::Saturday}};

std::chrono::year_month ym_year_zero{std::chrono::year{0},
std::chrono::January};

std::chrono::year_month_day ymd_bc{std::chrono::year{-1}, std::chrono::March,
std::chrono::day{255}};
std::chrono::year_month_day ymd_year_zero{
std::chrono::year{0}, std::chrono::month{255}, std::chrono::day{25}};
std::chrono::year_month_day ymd_unix_epoch{
std::chrono::year{1970}, std::chrono::January, std::chrono::day{1}};

std::chrono::year_month_day_last ymdl_bc{
std::chrono::year{-1},
std::chrono::month_day_last{std::chrono::December}};
std::chrono::year_month_day_last ymdl_may_1970{
std::chrono::year{1970}, std::chrono::month_day_last{std::chrono::May}};

std::chrono::year_month_weekday ymwd_bc{
std::chrono::year{-1}, std::chrono::June,
std::chrono::weekday_indexed{std::chrono::Wednesday, 2}};
std::chrono::year_month_weekday ymwd_forth_tuesday_2024{
std::chrono::year{2024}, std::chrono::January,
std::chrono::weekday_indexed{std::chrono::Tuesday, 4}};

std::chrono::year_month_weekday_last ymwdl_bc{
std::chrono::year{-1}, std::chrono::April,
std::chrono::weekday_last{std::chrono::Friday}};
std::chrono::year_month_weekday_last ymwdl_2024_last_tuesday_january{
std::chrono::year{2024}, std::chrono::January,
std::chrono::weekday_last{std::chrono::Tuesday}};

std::cout << "break here\n";
}
7 changes: 2 additions & 5 deletions llvm/docs/tutorial/MyFirstLanguageFrontend/LangImpl02.rst
Original file line number Diff line number Diff line change
Expand Up @@ -716,15 +716,12 @@ Intermediate Representation (IR) from the AST.
Full Code Listing
=================

Here is the complete code listing for our running example. Because this
uses the LLVM libraries, we need to link them in. To do this, we use the
`llvm-config <https://llvm.org/cmds/llvm-config.html>`_ tool to inform
our makefile/command line about which options to use:
Here is the complete code listing for our running example.

.. code-block:: bash

# Compile
clang++ -g -O3 toy.cpp `llvm-config --cxxflags`
clang++ -g -O3 toy.cpp
# Run
./a.out

Expand Down
4 changes: 0 additions & 4 deletions llvm/examples/Kaleidoscope/Chapter2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
set(LLVM_LINK_COMPONENTS
Support
)

add_kaleidoscope_chapter(Kaleidoscope-Ch2
toy.cpp
)
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsNVVM.td
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,14 @@ let TargetPrefix = "nvvm" in {
def int_nvvm_barrier_cluster_wait :
Intrinsic<[], [], [IntrConvergent, IntrNoCallback]>;

// 'aligned' versions of the above barrier.cluster.* intrinsics
def int_nvvm_barrier_cluster_arrive_aligned :
Intrinsic<[], [], [IntrConvergent, IntrNoCallback]>;
def int_nvvm_barrier_cluster_arrive_relaxed_aligned :
Intrinsic<[], [], [IntrConvergent, IntrNoCallback]>;
def int_nvvm_barrier_cluster_wait_aligned :
Intrinsic<[], [], [IntrConvergent, IntrNoCallback]>;

// Membar
def int_nvvm_membar_cta : ClangBuiltin<"__nvvm_membar_cta">,
Intrinsic<[], [], [IntrNoCallback]>;
Expand Down
12 changes: 6 additions & 6 deletions llvm/include/llvm/IR/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,6 @@ using ValueName = StringMapEntry<Value *>;
/// objects that watch it and listen to RAUW and Destroy events. See
/// llvm/IR/ValueHandle.h for details.
class Value {
Type *VTy;
Use *UseList;

friend class ValueAsMetadata; // Allow access to IsUsedByMD.
friend class ValueHandleBase;

const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast)
unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this?

Expand Down Expand Up @@ -121,6 +115,12 @@ class Value {
unsigned HasDescriptor : 1;

private:
Type *VTy;
Use *UseList;

friend class ValueAsMetadata; // Allow access to IsUsedByMD.
friend class ValueHandleBase; // Allow access to HasValueHandle.

template <typename UseT> // UseT == 'Use' or 'const Use'
class use_iterator_impl {
friend class Value;
Expand Down
39 changes: 39 additions & 0 deletions llvm/include/llvm/Passes/PassBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define LLVM_PASSES_PASSBUILDER_H

#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Passes/OptimizationLevel.h"
#include "llvm/Support/Error.h"
Expand Down Expand Up @@ -165,6 +166,14 @@ class PassBuilder {
/// additional analyses.
void registerLoopAnalyses(LoopAnalysisManager &LAM);

/// Registers all available machine function analysis passes.
///
/// This is an interface that can be used to populate a \c
/// MachineFunctionAnalysisManager with all registered function analyses.
/// Callers can still manually register any additional analyses. Callers can
/// also pre-register analyses and this will not override those.
void registerMachineFunctionAnalyses(MachineFunctionAnalysisManager &MFAM);

/// Construct the core LLVM function canonicalization and simplification
/// pipeline.
///
Expand Down Expand Up @@ -352,6 +361,18 @@ class PassBuilder {
Error parsePassPipeline(LoopPassManager &LPM, StringRef PipelineText);
/// @}}

/// Parse a textual MIR pipeline into the provided \c MachineFunctionPass
/// manager.
/// The format of the textual machine pipeline is a comma separated list of
/// machine pass names:
///
/// machine-funciton-pass,machine-module-pass,...
///
/// There is no need to specify the pass nesting, and this function
/// currently cannot handle the pass nesting.
Error parsePassPipeline(MachineFunctionPassManager &MFPM,
StringRef PipelineText);

/// Parse a textual alias analysis pipeline into the provided AA manager.
///
/// The format of the textual AA pipeline is a comma separated list of AA
Expand Down Expand Up @@ -520,6 +541,10 @@ class PassBuilder {
const std::function<void(ModuleAnalysisManager &)> &C) {
ModuleAnalysisRegistrationCallbacks.push_back(C);
}
void registerAnalysisRegistrationCallback(
const std::function<void(MachineFunctionAnalysisManager &)> &C) {
MachineFunctionAnalysisRegistrationCallbacks.push_back(C);
}
/// @}}

/// {{@ Register pipeline parsing callbacks with this pass builder instance.
Expand All @@ -546,6 +571,11 @@ class PassBuilder {
ArrayRef<PipelineElement>)> &C) {
ModulePipelineParsingCallbacks.push_back(C);
}
void registerPipelineParsingCallback(
const std::function<bool(StringRef Name, MachineFunctionPassManager &)>
&C) {
MachinePipelineParsingCallbacks.push_back(C);
}
/// @}}

/// Register a callback for a top-level pipeline entry.
Expand Down Expand Up @@ -616,8 +646,12 @@ class PassBuilder {
Error parseCGSCCPass(CGSCCPassManager &CGPM, const PipelineElement &E);
Error parseFunctionPass(FunctionPassManager &FPM, const PipelineElement &E);
Error parseLoopPass(LoopPassManager &LPM, const PipelineElement &E);
Error parseMachinePass(MachineFunctionPassManager &MFPM,
const PipelineElement &E);
bool parseAAPassName(AAManager &AA, StringRef Name);

Error parseMachinePassPipeline(MachineFunctionPassManager &MFPM,
ArrayRef<PipelineElement> Pipeline);
Error parseLoopPassPipeline(LoopPassManager &LPM,
ArrayRef<PipelineElement> Pipeline);
Error parseFunctionPassPipeline(FunctionPassManager &FPM,
Expand Down Expand Up @@ -699,6 +733,11 @@ class PassBuilder {
// AA callbacks
SmallVector<std::function<bool(StringRef Name, AAManager &AA)>, 2>
AAParsingCallbacks;
// Machine pass callbackcs
SmallVector<std::function<void(MachineFunctionAnalysisManager &)>, 2>
MachineFunctionAnalysisRegistrationCallbacks;
SmallVector<std::function<bool(StringRef, MachineFunctionPassManager &)>, 2>
MachinePipelineParsingCallbacks;
};

/// This utility template takes care of adding require<> and invalidate<>
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1108,8 +1108,8 @@ void ValueEnumerator::purgeFunction() {
/// Remove purged values from the ValueMap.
for (unsigned i = NumModuleValues, e = Values.size(); i != e; ++i)
ValueMap.erase(Values[i].first);
for (unsigned i = NumModuleMDs, e = MDs.size(); i != e; ++i)
MetadataMap.erase(MDs[i]);
for (const Metadata *MD : llvm::drop_begin(MDs, NumModuleMDs))
MetadataMap.erase(MD);
for (const BasicBlock *BB : BasicBlocks)
ValueMap.erase(BB);

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/RDFGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1790,7 +1790,7 @@ bool DataFlowGraph::hasUntrackedRef(Stmt S, bool IgnoreReserved) const {
for (const MachineOperand &Op : S.Addr->getCode()->operands()) {
if (!Op.isReg() && !Op.isRegMask())
continue;
if (llvm::find(Ops, &Op) == Ops.end())
if (!llvm::is_contained(Ops, &Op))
return true;
}
return false;
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3534,8 +3534,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
Results.push_back(ExpandFABS(Node));
break;
case ISD::IS_FPCLASS: {
auto CNode = cast<ConstantSDNode>(Node->getOperand(1));
auto Test = static_cast<FPClassTest>(CNode->getZExtValue());
auto Test = static_cast<FPClassTest>(Node->getConstantOperandVal(1));
if (SDValue Expanded =
TLI.expandIS_FPCLASS(Node->getValueType(0), Node->getOperand(0),
Test, Node->getFlags(), SDLoc(Node), DAG))
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/IR/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ static inline Type *checkType(Type *Ty) {
}

Value::Value(Type *ty, unsigned scid)
: VTy(checkType(ty)), UseList(nullptr), SubclassID(scid), HasValueHandle(0),
SubclassOptionalData(0), SubclassData(0), NumUserOperands(0),
IsUsedByMD(false), HasName(false), HasMetadata(false) {
: SubclassID(scid), HasValueHandle(0), SubclassOptionalData(0),
SubclassData(0), NumUserOperands(0), IsUsedByMD(false), HasName(false),
HasMetadata(false), VTy(checkType(ty)), UseList(nullptr) {
static_assert(ConstantFirstVal == 0, "!(SubclassID < ConstantFirstVal)");
// FIXME: Why isn't this in the subclass gunk??
// Note, we cannot call isa<CallInst> before the CallInst has been
Expand Down
82 changes: 82 additions & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,12 @@ PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
#include "PassRegistry.def"

#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
PIC->addClassToPassName(PASS_NAME::name(), NAME);
#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
PIC->addClassToPassName(PASS_NAME::name(), NAME);
#include "llvm/CodeGen/MachinePassRegistry.def"
}
}

Expand Down Expand Up @@ -427,6 +433,17 @@ void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
C(FAM);
}

void PassBuilder::registerMachineFunctionAnalyses(
MachineFunctionAnalysisManager &MFAM) {

#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
MFAM.registerPass([&] { return PASS_NAME(); });
#include "llvm/CodeGen/MachinePassRegistry.def"

for (auto &C : MachineFunctionAnalysisRegistrationCallbacks)
C(MFAM);
}

void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) {
#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
LAM.registerPass([&] { return CREATE_PASS; });
Expand Down Expand Up @@ -1781,6 +1798,33 @@ Error PassBuilder::parseLoopPass(LoopPassManager &LPM,
inconvertibleErrorCode());
}

Error PassBuilder::parseMachinePass(MachineFunctionPassManager &MFPM,
const PipelineElement &E) {
StringRef Name = E.Name;
if (!E.InnerPipeline.empty())
return make_error<StringError>("invalid pipeline",
inconvertibleErrorCode());

#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) { \
MFPM.addPass(PASS_NAME()); \
return Error::success(); \
}
#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) { \
MFPM.addPass(PASS_NAME()); \
return Error::success(); \
}
#include "llvm/CodeGen/MachinePassRegistry.def"

for (auto &C : MachinePipelineParsingCallbacks)
if (C(Name, MFPM))
return Error::success();
return make_error<StringError>(
formatv("unknown machine pass '{0}'", Name).str(),
inconvertibleErrorCode());
}

bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {
#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
if (Name == NAME) { \
Expand All @@ -1802,6 +1846,15 @@ bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {
return false;
}

Error PassBuilder::parseMachinePassPipeline(
MachineFunctionPassManager &MFPM, ArrayRef<PipelineElement> Pipeline) {
for (const auto &Element : Pipeline) {
if (auto Err = parseMachinePass(MFPM, Element))
return Err;
}
return Error::success();
}

Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM,
ArrayRef<PipelineElement> Pipeline) {
for (const auto &Element : Pipeline) {
Expand Down Expand Up @@ -1961,6 +2014,20 @@ Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM,
return Error::success();
}

Error PassBuilder::parsePassPipeline(MachineFunctionPassManager &MFPM,
StringRef PipelineText) {
auto Pipeline = parsePipelineText(PipelineText);
if (!Pipeline || Pipeline->empty())
return make_error<StringError>(
formatv("invalid machine pass pipeline '{0}'", PipelineText).str(),
inconvertibleErrorCode());

if (auto Err = parseMachinePassPipeline(MFPM, *Pipeline))
return Err;

return Error::success();
}

Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {
// If the pipeline just consists of the word 'default' just replace the AA
// manager with our default one.
Expand Down Expand Up @@ -2055,6 +2122,21 @@ void PassBuilder::printPassNames(raw_ostream &OS) {
OS << "Loop analyses:\n";
#define LOOP_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
#include "PassRegistry.def"

OS << "Machine module passes (WIP):\n";
#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
printPassName(NAME, OS);
#include "llvm/CodeGen/MachinePassRegistry.def"

OS << "Machine function passes (WIP):\n";
#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
printPassName(NAME, OS);
#include "llvm/CodeGen/MachinePassRegistry.def"

OS << "Machine function analyses (WIP):\n";
#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
printPassName(NAME, OS);
#include "llvm/CodeGen/MachinePassRegistry.def"
}

void PassBuilder::registerParseTopLevelPipelineCallback(
Expand Down
8 changes: 2 additions & 6 deletions llvm/lib/Support/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1630,10 +1630,8 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
// otherwise feed it to the eating positional.
ArgName = StringRef(argv[i] + 1);
// Eat second dash.
if (!ArgName.empty() && ArgName[0] == '-') {
if (ArgName.consume_front("-"))
HaveDoubleDash = true;
ArgName = ArgName.substr(1);
}

Handler = LookupLongOption(*ChosenSubCommand, ArgName, Value,
LongOptionsUseDoubleDash, HaveDoubleDash);
Expand All @@ -1644,10 +1642,8 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
} else { // We start with a '-', must be an argument.
ArgName = StringRef(argv[i] + 1);
// Eat second dash.
if (!ArgName.empty() && ArgName[0] == '-') {
if (ArgName.consume_front("-"))
HaveDoubleDash = true;
ArgName = ArgName.substr(1);
}

Handler = LookupLongOption(*ChosenSubCommand, ArgName, Value,
LongOptionsUseDoubleDash, HaveDoubleDash);
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Support/FormatVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ formatv_object_base::parseReplacementItem(StringRef Spec) {
return ReplacementItem{};
}
RepString = RepString.trim();
if (!RepString.empty() && RepString.front() == ',') {
RepString = RepString.drop_front();
if (RepString.consume_front(",")) {
if (!consumeFieldLayout(RepString, Where, Align, Pad))
assert(false && "Invalid replacement field layout specification!");
}
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Support/StringRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,8 +517,7 @@ bool StringRef::consumeInteger(unsigned Radix, APInt &Result) {

// Skip leading zeroes. This can be a significant improvement if
// it means we don't need > 64 bits.
while (!Str.empty() && Str.front() == '0')
Str = Str.substr(1);
Str = Str.ltrim('0');

// If it was nothing but zeroes....
if (Str.empty()) {
Expand Down
6 changes: 2 additions & 4 deletions llvm/lib/Support/VersionTuple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,8 @@ bool VersionTuple::tryParse(StringRef input) {
}

// If we're not done, parse the micro version, \.[0-9]+
if (input[0] != '.')
if (!input.consume_front("."))
return true;
input = input.substr(1);
if (parseInt(input, micro))
return true;

Expand All @@ -97,9 +96,8 @@ bool VersionTuple::tryParse(StringRef input) {
}

// If we're not done, parse the micro version, \.[0-9]+
if (input[0] != '.')
if (!input.consume_front("."))
return true;
input = input.substr(1);
if (parseInt(input, build))
return true;

Expand Down
6 changes: 2 additions & 4 deletions llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
auto IndexedLoadBasicPred = [=](const LegalityQuery &Query) {
LLT LdTy = Query.Types[0];
LLT PtrTy = Query.Types[1];
if (llvm::find(PackedVectorAllTypesVec, LdTy) ==
PackedVectorAllTypesVec.end() &&
llvm::find(ScalarAndPtrTypesVec, LdTy) == ScalarAndPtrTypesVec.end() &&
LdTy != s128)
if (!llvm::is_contained(PackedVectorAllTypesVec, LdTy) &&
!llvm::is_contained(ScalarAndPtrTypesVec, LdTy) && LdTy != s128)
return false;
if (PtrTy != p0)
return false;
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Target/NVPTX/NVPTXIntrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def INT_BARRIER_SYNC_CNT_II : NVPTXInst<(outs), (ins i32imm:$id, i32imm:$cnt),
"barrier.sync \t$id, $cnt;",
[(int_nvvm_barrier_sync_cnt imm:$id, imm:$cnt)]>,
Requires<[hasPTX<60>, hasSM<30>]>;

class INT_BARRIER_CLUSTER<string variant, Intrinsic Intr,
list<Predicate> Preds = [hasPTX<78>, hasSM<90>]>:
NVPTXInst<(outs), (ins), "barrier.cluster."# variant #";", [(Intr)]>,
Expand All @@ -145,6 +146,15 @@ def barrier_cluster_arrive_relaxed:
def barrier_cluster_wait:
INT_BARRIER_CLUSTER<"wait", int_nvvm_barrier_cluster_wait>;

// 'aligned' versions of the cluster barrier intrinsics
def barrier_cluster_arrive_aligned:
INT_BARRIER_CLUSTER<"arrive.aligned", int_nvvm_barrier_cluster_arrive_aligned>;
def barrier_cluster_arrive_relaxed_aligned:
INT_BARRIER_CLUSTER<"arrive.relaxed.aligned",
int_nvvm_barrier_cluster_arrive_relaxed_aligned, [hasPTX<80>, hasSM<90>]>;
def barrier_cluster_wait_aligned:
INT_BARRIER_CLUSTER<"wait.aligned", int_nvvm_barrier_cluster_wait_aligned>;

class SHFL_INSTR<bit sync, string mode, string reg, bit return_pred,
bit offset_imm, bit mask_imm, bit threadmask_imm>
: NVPTXInst<(outs), (ins), "?", []> {
Expand Down
19 changes: 12 additions & 7 deletions llvm/lib/Target/Sparc/SparcSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "SparcSubtarget.h"
#include "Sparc.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/MathExtras.h"

Expand All @@ -25,15 +26,18 @@ using namespace llvm;

void SparcSubtarget::anchor() { }

SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU,
StringRef FS) {
SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(
StringRef CPU, StringRef TuneCPU, StringRef FS) {
// Determine default and user specified characteristics
std::string CPUName = std::string(CPU);
if (CPUName.empty())
CPUName = (Is64Bit) ? "v9" : "v8";

if (TuneCPU.empty())
TuneCPU = CPUName;

// Parse features string.
ParseSubtargetFeatures(CPUName, /*TuneCPU*/ CPUName, FS);
ParseSubtargetFeatures(CPUName, TuneCPU, FS);

// Popc is a v9-only instruction.
if (!IsV9)
Expand All @@ -42,11 +46,12 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU,
return *this;
}

SparcSubtarget::SparcSubtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, const TargetMachine &TM,
SparcSubtarget::SparcSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
const StringRef &FS, const TargetMachine &TM,
bool is64Bit)
: SparcGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), TargetTriple(TT),
Is64Bit(is64Bit), InstrInfo(initializeSubtargetDependencies(CPU, FS)),
: SparcGenSubtargetInfo(TM.getTargetTriple(), CPU, TuneCPU, FS),
TargetTriple(TM.getTargetTriple()), Is64Bit(is64Bit),
InstrInfo(initializeSubtargetDependencies(CPU, TuneCPU, FS)),
TLInfo(TM, *this), FrameLowering(*this) {}

int SparcSubtarget::getAdjustedFrameSize(int frameSize) const {
Expand Down
8 changes: 5 additions & 3 deletions llvm/lib/Target/Sparc/SparcSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ class SparcSubtarget : public SparcGenSubtargetInfo {
SparcFrameLowering FrameLowering;

public:
SparcSubtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, const TargetMachine &TM, bool is64bit);
SparcSubtarget(const StringRef &CPU, const StringRef &TuneCPU,
const StringRef &FS, const TargetMachine &TM, bool is64bit);

const SparcInstrInfo *getInstrInfo() const override { return &InstrInfo; }
const TargetFrameLowering *getFrameLowering() const override {
Expand All @@ -70,7 +70,9 @@ class SparcSubtarget : public SparcGenSubtargetInfo {
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
SparcSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
SparcSubtarget &initializeSubtargetDependencies(StringRef CPU,
StringRef TuneCPU,
StringRef FS);

bool is64Bit() const { return Is64Bit; }

Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/Target/Sparc/SparcTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,13 @@ SparcTargetMachine::~SparcTargetMachine() = default;
const SparcSubtarget *
SparcTargetMachine::getSubtargetImpl(const Function &F) const {
Attribute CPUAttr = F.getFnAttribute("target-cpu");
Attribute TuneAttr = F.getFnAttribute("tune-cpu");
Attribute FSAttr = F.getFnAttribute("target-features");

std::string CPU =
CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
std::string TuneCPU =
TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
std::string FS =
FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;

Expand All @@ -137,8 +140,8 @@ SparcTargetMachine::getSubtargetImpl(const Function &F) const {
// creation will depend on the TM and the code generation flags on the
// function that reside in TargetOptions.
resetTargetOptions(F);
I = std::make_unique<SparcSubtarget>(TargetTriple, CPU, FS, *this,
this->is64Bit);
I = std::make_unique<SparcSubtarget>(CPU, TuneCPU, FS, *this,
this->is64Bit);
}
return I.get();
}
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
#include "WebAssemblyMachineFunctionInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Function.h"

using namespace llvm;

WebAssemblyDebugValueManager::WebAssemblyDebugValueManager(MachineInstr *Def)
: Def(Def) {
if (!Def->getMF()->getFunction().getSubprogram())
return;

// This code differs from MachineInstr::collectDebugValues in that it scans
// the whole BB, not just contiguous DBG_VALUEs, until another definition to
// the same register is encountered.
Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/Target/X86/X86SpeculativeLoadHardening.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1840,7 +1840,7 @@ MachineInstr *X86SpeculativeLoadHardeningPass::sinkPostLoadHardenedInst(
// just bail. Also check that its register class is one of the ones we
// can harden.
Register UseDefReg = UseMI.getOperand(0).getReg();
if (!UseDefReg.isVirtual() || !canHardenRegister(UseDefReg))
if (!canHardenRegister(UseDefReg))
return {};

SingleUseMI = &UseMI;
Expand All @@ -1863,6 +1863,10 @@ MachineInstr *X86SpeculativeLoadHardeningPass::sinkPostLoadHardenedInst(
}

bool X86SpeculativeLoadHardeningPass::canHardenRegister(Register Reg) {
// We only support hardening virtual registers.
if (!Reg.isVirtual())
return false;

auto *RC = MRI->getRegClass(Reg);
int RegBytes = TRI->getRegSizeInBits(*RC) / 8;
if (RegBytes > 8)
Expand Down Expand Up @@ -1909,7 +1913,6 @@ unsigned X86SpeculativeLoadHardeningPass::hardenValueInRegister(
Register Reg, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertPt,
const DebugLoc &Loc) {
assert(canHardenRegister(Reg) && "Cannot harden this register!");
assert(Reg.isVirtual() && "Cannot harden a physical register!");

auto *RC = MRI->getRegClass(Reg);
int Bytes = TRI->getRegSizeInBits(*RC) / 8;
Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/TextAPI/RecordsSlice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,8 @@ llvm::MachO::convertToInterfaceFile(const Records &Slices) {
}

File = createInterfaceFile(Slices, *InstallNames.begin());
for (auto it = std::next(InstallNames.begin()); it != InstallNames.end();
++it)
File->addDocument(createInterfaceFile(Slices, *it));
for (StringRef IN : llvm::drop_begin(InstallNames))
File->addDocument(createInterfaceFile(Slices, IN));

return File;
}
9 changes: 0 additions & 9 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5703,15 +5703,6 @@ Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {
return new ICmpInst(ICmp.getPredicate(), Op0Src, NewOp1);
}

// Turn icmp pred (inttoptr x), (inttoptr y) into icmp pred x, y
if (CastOp0->getOpcode() == Instruction::IntToPtr &&
CompatibleSizes(DestTy, SrcTy)) {
Value *Op1Src;
if (match(ICmp.getOperand(1), m_IntToPtr(m_Value(Op1Src))) &&
Op1Src->getType() == SrcTy)
return new ICmpInst(ICmp.getPredicate(), Op0Src, Op1Src);
}

if (Instruction *R = foldICmpWithTrunc(ICmp))
return R;

Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/XRay/Trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ Error loadNaiveFormatLog(StringRef Data, bool IsLittleEndian,
return FileHeaderOrError.takeError();
FileHeader = std::move(FileHeaderOrError.get());

size_t NumReservations = llvm::divideCeil(Reader.size() - OffsetPtr, 32U);
Records.reserve(NumReservations);

// Each record after the header will be 32 bytes, in the following format:
//
// (2) uint16 : record type
Expand Down
13 changes: 13 additions & 0 deletions llvm/test/CodeGen/NVPTX/intrinsics-sm90.ll
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ define void @test_barrier_cluster() {
ret void
}

; CHECK-LABEL: test_barrier_cluster_aligned(
define void @test_barrier_cluster_aligned() {
; CHECK: barrier.cluster.arrive.aligned;
call void @llvm.nvvm.barrier.cluster.arrive.aligned()
; CHECK: barrier.cluster.arrive.relaxed.aligned;
call void @llvm.nvvm.barrier.cluster.arrive.relaxed.aligned()
; CHECK: barrier.cluster.wait.aligned;
call void @llvm.nvvm.barrier.cluster.wait.aligned()
ret void
}

declare i1 @llvm.nvvm.isspacep.shared.cluster(ptr %p);
declare ptr @llvm.nvvm.mapa(ptr %p, i32 %r);
Expand All @@ -153,4 +163,7 @@ declare i1 @llvm.nvvm.is_explicit_cluster()
declare void @llvm.nvvm.barrier.cluster.arrive()
declare void @llvm.nvvm.barrier.cluster.arrive.relaxed()
declare void @llvm.nvvm.barrier.cluster.wait()
declare void @llvm.nvvm.barrier.cluster.arrive.aligned()
declare void @llvm.nvvm.barrier.cluster.arrive.relaxed.aligned()
declare void @llvm.nvvm.barrier.cluster.wait.aligned()
declare void @llvm.nvvm.fence.sc.cluster()
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/WebAssembly/cfg-stackify-dbg-skip.ll
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

target triple = "wasm32-unknown-unknown"

define void @foo(i64 %arg) {
define void @foo(i64 %arg) !dbg !37 {
start:
%val = trunc i64 %arg to i32
%cmp = icmp eq i32 %val, 0
Expand All @@ -39,7 +39,7 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
!22 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "&str", file: !6, size: 64, align: 32, elements: !{}, identifier: "111094d970b097647de579f9c509ef08")
!33 = !{i32 2, !"Debug Info Version", i32 3}
!35 = distinct !DILexicalBlock(scope: !37, file: !6, line: 357, column: 8)
!37 = distinct !DISubprogram(name: "foobar", linkageName: "_fooba", scope: !38, file: !6, line: 353, type: !39, isLocal: true, isDefinition: true, scopeLine: 353, flags: DIFlagPrototyped, isOptimized: true, unit: !0, templateParams: !2, retainedNodes: !42)
!37 = distinct !DISubprogram(name: "foo", scope: !6, file: !6, line: 353, type: !39, isLocal: true, isDefinition: true, scopeLine: 353, flags: DIFlagPrototyped, isOptimized: true, unit: !0, templateParams: !2, retainedNodes: !42)
!38 = !DINamespace(name: "ptr", scope: null)
!39 = !DISubroutineType(types: !2)
!42 = !{!46}
Expand Down
31 changes: 31 additions & 0 deletions llvm/test/CodeGen/X86/speculative-load-hardening.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1161,3 +1161,34 @@ define void @idempotent_atomic(ptr %x) speculative_load_hardening {
%tmp = atomicrmw or ptr %x, i32 0 seq_cst
ret void
}

; Make sure we don't crash on longjmps (PR60081).
declare void @llvm.eh.sjlj.longjmp(ptr)
define void @test_longjmp(ptr %env) speculative_load_hardening {
; X64-LABEL: test_longjmp:
; X64: # %bb.0:
; X64-NEXT: pushq %rbp
; X64-NEXT: .cfi_def_cfa_offset 16
; X64-NEXT: .cfi_offset %rbp, -16
; X64-NEXT: movq %rsp, %rax
; X64-NEXT: movq $-1, %rcx
; X64-NEXT: sarq $63, %rax
; X64-NEXT: orq %rax, %rdi
; X64-NEXT: movq (%rdi), %rbp
; X64-NEXT: movq 8(%rdi), %rcx
; X64-NEXT: movq 16(%rdi), %rsp
; X64-NEXT: orq %rax, %rcx
; X64-NEXT: jmpq *%rcx
;
; X64-LFENCE-LABEL: test_longjmp:
; X64-LFENCE: # %bb.0:
; X64-LFENCE-NEXT: pushq %rbp
; X64-LFENCE-NEXT: .cfi_def_cfa_offset 16
; X64-LFENCE-NEXT: .cfi_offset %rbp, -16
; X64-LFENCE-NEXT: movq (%rdi), %rbp
; X64-LFENCE-NEXT: movq 8(%rdi), %rax
; X64-LFENCE-NEXT: movq 16(%rdi), %rsp
; X64-LFENCE-NEXT: jmpq *%rax
call void @llvm.eh.sjlj.longjmp(ptr %env)
unreachable
}
4 changes: 2 additions & 2 deletions llvm/test/DebugInfo/WebAssembly/dbg-value-move-clone.mir
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
declare void @foo(i32)
declare i32 @bar()

define void @test(i64 %arg) {
define void @test(i64 %arg) !dbg !6 {
unreachable
}

Expand All @@ -32,7 +32,7 @@
!3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "&str", file: !2, size: 64, align: 32, elements: !{}, identifier: "111094d970b097647de579f9c509ef08")
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = distinct !DILexicalBlock(scope: !6, file: !2, line: 357, column: 8)
!6 = distinct !DISubprogram(name: "testfoo", linkageName: "_testba", scope: !7, file: !2, line: 353, type: !8, isLocal: true, isDefinition: true, scopeLine: 353, flags: DIFlagPrototyped, isOptimized: true, unit: !0, templateParams: !1, retainedNodes: !9)
!6 = distinct !DISubprogram(name: "test", scope: !7, file: !2, line: 353, type: !8, isLocal: true, isDefinition: true, scopeLine: 353, flags: DIFlagPrototyped, isOptimized: true, unit: !0, templateParams: !1, retainedNodes: !9)
!7 = !DINamespace(name: "ptr", scope: null)
!8 = !DISubroutineType(types: !1)
!9 = !{!10}
Expand Down
Loading