18 changes: 11 additions & 7 deletions clang/lib/Basic/IdentifierTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,14 @@ enum TokenKey : unsigned {
KEYMSCOMPAT = 0x400000,
KEYSYCL = 0x800000,
KEYCUDA = 0x1000000,
KEYHLSL = 0x2000000,
KEYFIXEDPOINT = 0x4000000,
KEYZOS = 0x2000000,
KEYNOZOS = 0x4000000,
KEYHLSL = 0x8000000,
KEYFIXEDPOINT = 0x10000000,
KEYMAX = KEYFIXEDPOINT, // The maximum key
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
KEYALL = (KEYMAX | (KEYMAX - 1)) & ~KEYNOMS18 &
~KEYNOOPENCL // KEYNOMS18 and KEYNOOPENCL are used to exclude.
KEYALL = (KEYMAX | (KEYMAX - 1)) & ~KEYNOMS18 & ~KEYNOOPENCL &
~KEYNOZOS // KEYNOMS18, KEYNOOPENCL, KEYNOZOS are excluded.
};

/// How a keyword is treated in the selected standard. This enum is ordered
Expand Down Expand Up @@ -199,16 +201,17 @@ static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
return LangOpts.isSYCL() ? KS_Enabled : KS_Unknown;
case KEYCUDA:
return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
case KEYZOS:
return LangOpts.ZOSExt ? KS_Enabled : KS_Unknown;
case KEYHLSL:
return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
case KEYNOCXX:
// This is enabled in all non-C++ modes, but might be enabled for other
// reasons as well.
return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
case KEYNOOPENCL:
// The disable behavior for this is handled in getKeywordStatus.
return KS_Unknown;
case KEYNOMS18:
case KEYNOZOS:
// The disable behavior for this is handled in getKeywordStatus.
return KS_Unknown;
case KEYFIXEDPOINT:
Expand All @@ -230,7 +233,8 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
!LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))
return KS_Disabled;

if (LangOpts.ZOSExt && (Flags & KEYNOZOS))
return KS_Disabled;
KeywordStatus CurStatus = KS_Unknown;

while (Flags != 0) {
Expand Down
40 changes: 39 additions & 1 deletion clang/lib/Basic/Targets/SystemZ.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,30 @@
namespace clang {
namespace targets {

static const unsigned ZOSAddressMap[] = {
0, // Default
0, // opencl_global
0, // opencl_local
0, // opencl_constant
0, // opencl_private
0, // opencl_generic
0, // opencl_global_device
0, // opencl_global_host
0, // cuda_device
0, // cuda_constant
0, // cuda_shared
0, // sycl_global
0, // sycl_global_device
0, // sycl_global_host
0, // sycl_local
0, // sycl_private
0, // ptr32_sptr
1, // ptr32_uptr
0, // ptr64
0, // hlsl_groupshared
0 // wasm_funcref
};

class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {

static const char *const GCCRegNames[];
Expand All @@ -30,6 +54,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
bool HasVector;
bool SoftFloat;
bool UnalignedSymbols;
enum AddrSpace { ptr32 = 1 };

public:
SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
Expand All @@ -49,14 +74,17 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
MinGlobalAlign = 16;
HasUnalignedAccess = true;
if (Triple.isOSzOS()) {
if (Triple.isArch64Bit()) {
AddrSpaceMap = &ZOSAddressMap;
}
TLSSupported = false;
// All vector types are default aligned on an 8-byte boundary, even if the
// vector facility is not available. That is different from Linux.
MaxVectorAlign = 64;
// Compared to Linux/ELF, the data layout differs only in some details:
// - name mangling is GOFF.
// - 32 bit pointers, either as default or special address space
resetDataLayout("E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-"
resetDataLayout("E-m:l-p1:32:32-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-"
"a:8:16-n32:64");
} else {
TLSSupported = true;
Expand Down Expand Up @@ -224,6 +252,16 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(256, 256);
}
uint64_t getPointerWidthV(LangAS AddrSpace) const override {
return (getTriple().isOSzOS() && getTriple().isArch64Bit() &&
getTargetAddressSpace(AddrSpace) == ptr32)
? 32
: PointerWidth;
}

uint64_t getPointerAlignV(LangAS AddrSpace) const override {
return getPointerWidthV(AddrSpace);
}
};
} // namespace targets
} // namespace clang
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7514,6 +7514,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
(C.isForDiagnostics() && !HaveModules))
CmdArgs.push_back("-frewrite-includes");

if (Args.hasFlag(options::OPT_fzos_extensions,
options::OPT_fno_zos_extensions, false))
CmdArgs.push_back("-fzos-extensions");
else if (Args.hasArg(options::OPT_fno_zos_extensions))
CmdArgs.push_back("-fno-zos-extensions");

// Only allow -traditional or -traditional-cpp outside in preprocessing modes.
if (Arg *A = Args.getLastArg(options::OPT_traditional,
options::OPT_traditional_cpp)) {
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/Frontend/ASTUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,8 @@ class ASTInfoCollector : public ASTReaderListener {
LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target),
Counter(Counter) {}

bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
bool ReadLanguageOptions(const LangOptions &LangOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override {
if (InitializedLanguage)
return false;
Expand All @@ -559,6 +560,7 @@ class ASTInfoCollector : public ASTReaderListener {
}

bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
StringRef ModuleFilename,
StringRef SpecificModuleCachePath,
bool Complain) override {
// llvm::SaveAndRestore doesn't support bit field.
Expand Down Expand Up @@ -597,13 +599,15 @@ class ASTInfoCollector : public ASTReaderListener {
}

bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
bool ReadMacros, bool Complain,
StringRef ModuleFilename, bool ReadMacros,
bool Complain,
std::string &SuggestedPredefines) override {
this->PPOpts = PPOpts;
return false;
}

bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
bool ReadTargetOptions(const TargetOptions &TargetOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override {
// If we've already initialized the target, don't do it again.
if (Target)
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3650,6 +3650,11 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_ftrigraphs);
}

if (T.isOSzOS() && !Opts.ZOSExt)
GenerateArg(Consumer, OPT_fno_zos_extensions);
else if (Opts.ZOSExt)
GenerateArg(Consumer, OPT_fzos_extensions);

if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
GenerateArg(Consumer, OPT_fblocks);

Expand Down Expand Up @@ -4051,6 +4056,9 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.Trigraphs =
Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);

Opts.ZOSExt =
Args.hasFlag(OPT_fzos_extensions, OPT_fno_zos_extensions, T.isOSzOS());

Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
&& Opts.OpenCLVersion == 200);

Expand Down
11 changes: 8 additions & 3 deletions clang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,8 @@ namespace {
Out.indent(2) << "Module map file: " << ModuleMapPath << "\n";
}

bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
bool ReadLanguageOptions(const LangOptions &LangOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override {
Out.indent(2) << "Language options:\n";
#define LANGOPT(Name, Bits, Default, Description) \
Expand All @@ -645,7 +646,8 @@ namespace {
return false;
}

bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
bool ReadTargetOptions(const TargetOptions &TargetOpts,
StringRef ModuleFilename, bool Complain,
bool AllowCompatibleDifferences) override {
Out.indent(2) << "Target options:\n";
Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n";
Expand All @@ -665,6 +667,7 @@ namespace {
}

bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
StringRef ModuleFilename,
bool Complain) override {
Out.indent(2) << "Diagnostic options:\n";
#define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name);
Expand All @@ -684,6 +687,7 @@ namespace {
}

bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
StringRef ModuleFilename,
StringRef SpecificModuleCachePath,
bool Complain) override {
Out.indent(2) << "Header search options:\n";
Expand Down Expand Up @@ -717,7 +721,8 @@ namespace {
}

bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
bool ReadMacros, bool Complain,
StringRef ModuleFilename, bool ReadMacros,
bool Complain,
std::string &SuggestedPredefines) override {
Out.indent(2) << "Preprocessor options:\n";
DUMP_BOOLEAN(PPOpts.UsePredefines,
Expand Down
56 changes: 46 additions & 10 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4340,7 +4340,7 @@ static OverloadingResult ResolveConstructorOverload(
/// \param IsListInit Is this list-initialization?
/// \param IsInitListCopy Is this non-list-initialization resulting from a
/// list-initialization from {x} where x is the same
/// type as the entity?
/// aggregate type as the entity?
static void TryConstructorInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Expand Down Expand Up @@ -4370,6 +4370,14 @@ static void TryConstructorInitialization(Sema &S,
Entity.getKind() !=
InitializedEntity::EK_LambdaToBlockConversionBlockElement);

bool CopyElisionPossible = false;
auto ElideConstructor = [&] {
// Convert qualifications if necessary.
Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
if (ILE)
Sequence.RewrapReferenceInitList(DestType, ILE);
};

// C++17 [dcl.init]p17:
// - If the initializer expression is a prvalue and the cv-unqualified
// version of the source type is the same class as the class of the
Expand All @@ -4382,11 +4390,33 @@ static void TryConstructorInitialization(Sema &S,
if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor &&
UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) {
// Convert qualifications if necessary.
Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
if (ILE)
Sequence.RewrapReferenceInitList(DestType, ILE);
return;
if (ILE && !DestType->isAggregateType()) {
// CWG2311: T{ prvalue_of_type_T } is not eligible for copy elision
// Make this an elision if this won't call an initializer-list
// constructor. (Always on an aggregate type or check constructors first.)

// This effectively makes our resolution as follows. The parts in angle
// brackets are additions.
// C++17 [over.match.list]p(1.2):
// - If no viable initializer-list constructor is found <and the
// initializer list does not consist of exactly a single element with
// the same cv-unqualified class type as T>, [...]
// C++17 [dcl.init.list]p(3.6):
// - Otherwise, if T is a class type, constructors are considered. The
// applicable constructors are enumerated and the best one is chosen
// through overload resolution. <If no constructor is found and the
// initializer list consists of exactly a single element with the same
// cv-unqualified class type as T, the object is initialized from that
// element (by copy-initialization for copy-list-initialization, or by
// direct-initialization for direct-list-initialization). Otherwise, >
// if a narrowing conversion [...]
assert(!IsInitListCopy &&
"IsInitListCopy only possible with aggregate types");
CopyElisionPossible = true;
} else {
ElideConstructor();
return;
}
}

const RecordType *DestRecordType = DestType->getAs<RecordType>();
Expand Down Expand Up @@ -4431,6 +4461,12 @@ static void TryConstructorInitialization(Sema &S,
S, Kind.getLocation(), Args, CandidateSet, DestType, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructors=*/true, IsListInit, RequireActualConstructor);

if (CopyElisionPossible && Result == OR_No_Viable_Function) {
// No initializer list candidate
ElideConstructor();
return;
}
}

// C++11 [over.match.list]p1:
Expand Down Expand Up @@ -4712,9 +4748,9 @@ static void TryListInitialization(Sema &S,
return;
}

// C++11 [dcl.init.list]p3, per DR1467:
// - If T is a class type and the initializer list has a single element of
// type cv U, where U is T or a class derived from T, the object is
// C++11 [dcl.init.list]p3, per DR1467 and DR2137:
// - If T is an aggregate class and the initializer list has a single element
// of type cv U, where U is T or a class derived from T, the object is
// initialized from that element (by copy-initialization for
// copy-list-initialization, or by direct-initialization for
// direct-list-initialization).
Expand All @@ -4725,7 +4761,7 @@ static void TryListInitialization(Sema &S,
// - Otherwise, if T is an aggregate, [...] (continue below).
if (S.getLangOpts().CPlusPlus11 && InitList->getNumInits() == 1 &&
!IsDesignatedInit) {
if (DestType->isRecordType()) {
if (DestType->isRecordType() && DestType->isAggregateType()) {
QualType InitType = InitList->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
S.IsDerivedFrom(InitList->getBeginLoc(), InitType, DestType)) {
Expand Down
41 changes: 29 additions & 12 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1619,19 +1619,36 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// called for those cases.
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
QualType FromCanon
= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
QualType FromType;
SourceLocation FromLoc;
// C++11 [over.ics.list]p6, per DR2137:
// C++17 [over.ics.list]p6:
// If C is not an initializer-list constructor and the initializer list
// has a single element of type cv U, where U is X or a class derived
// from X, the implicit conversion sequence has Exact Match rank if U is
// X, or Conversion rank if U is derived from X.
if (const auto *InitList = dyn_cast<InitListExpr>(From);
InitList && InitList->getNumInits() == 1 &&
!S.isInitListConstructor(Constructor)) {
const Expr *SingleInit = InitList->getInit(0);
FromType = SingleInit->getType();
FromLoc = SingleInit->getBeginLoc();
} else {
FromType = From->getType();
FromLoc = From->getBeginLoc();
}
QualType FromCanon =
S.Context.getCanonicalType(FromType.getUnqualifiedType());
QualType ToCanon
= S.Context.getCanonicalType(ToType).getUnqualifiedType();
if (Constructor->isCopyConstructor() &&
(FromCanon == ToCanon ||
S.IsDerivedFrom(From->getBeginLoc(), FromCanon, ToCanon))) {
if ((FromCanon == ToCanon ||
S.IsDerivedFrom(FromLoc, FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction;
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(From->getType());
ICS.Standard.setFromType(FromType);
ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = Constructor;
ICS.Standard.FoundCopyConstructor = Found;
Expand Down Expand Up @@ -5335,18 +5352,18 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
IsDesignatedInit)
return Result;

// Per DR1467:
// If the parameter type is a class X and the initializer list has a single
// element of type cv U, where U is X or a class derived from X, the
// implicit conversion sequence is the one required to convert the element
// to the parameter type.
// Per DR1467 and DR2137:
// If the parameter type is an aggregate class X and the initializer list
// has a single element of type cv U, where U is X or a class derived from
// X, the implicit conversion sequence is the one required to convert the
// element to the parameter type.
//
// Otherwise, if the parameter type is a character array [... ]
// and the initializer list has a single element that is an
// appropriately-typed string literal (8.5.2 [dcl.init.string]), the
// implicit conversion sequence is the identity conversion.
if (From->getNumInits() == 1 && !IsDesignatedInit) {
if (ToType->isRecordType()) {
if (ToType->isRecordType() && ToType->isAggregateType()) {
QualType InitType = From->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, ToType) ||
S.IsDerivedFrom(From->getBeginLoc(), InitType, ToType))
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7057,6 +7057,7 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,

// Add address space to type based on its attributes.
LangAS ASIdx = LangAS::Default;
llvm::Triple Triple = S.Context.getTargetInfo().getTriple();
uint64_t PtrWidth =
S.Context.getTargetInfo().getPointerWidth(LangAS::Default);
if (PtrWidth == 32) {
Expand All @@ -7065,7 +7066,7 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
else if (Attrs[attr::UPtr])
ASIdx = LangAS::ptr32_uptr;
} else if (PtrWidth == 64 && Attrs[attr::Ptr32]) {
if (Attrs[attr::UPtr])
if (Triple.isOSzOS() || Attrs[attr::UPtr])
ASIdx = LangAS::ptr32_uptr;
else
ASIdx = LangAS::ptr32_sptr;
Expand Down
332 changes: 183 additions & 149 deletions clang/lib/Serialization/ASTReader.cpp

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1196,13 +1196,15 @@ namespace incdecbool {
}

#if __cplusplus >= 201402L
/// NOTE: The diagnostics of the two interpreters are a little
/// different here, but they both make sense.
constexpr int externvar1() { // both-error {{never produces a constant expression}}
extern char arr[]; // ref-note {{declared here}}
return arr[0]; // ref-note {{read of non-constexpr variable 'arr'}} \
// expected-note {{indexing of array without known bound}}
extern char arr[]; // both-note {{declared here}}
return arr[0]; // both-note {{read of non-constexpr variable 'arr'}}
}
namespace externarr {
extern int arr[];
constexpr int *externarrindex = &arr[0]; /// No diagnostic.
}


namespace StmtExprs {
constexpr int foo() {
Expand Down
10 changes: 0 additions & 10 deletions clang/test/CXX/drs/cwg14xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,16 +505,6 @@ namespace cwg1467 { // cwg1467: 3.7 c++11
}
} // nonaggregate

namespace SelfInitIsNotListInit {
struct S {
S();
explicit S(S &);
S(const S &);
};
S s1;
S s2 = {s1}; // ok, not list-initialization so we pick the non-explicit constructor
}

struct NestedInit { int a, b, c; };
NestedInit ni[1] = {{NestedInit{1, 2, 3}}};

Expand Down
45 changes: 44 additions & 1 deletion clang/test/CXX/drs/cwg21xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@
#endif

namespace std {
struct type_info;
typedef __SIZE_TYPE__ size_t;

template<typename E> struct initializer_list {
const E *p; size_t n;
initializer_list(const E *p, size_t n);
initializer_list();
};

struct type_info;
}

namespace cwg2100 { // cwg2100: 12
Expand Down Expand Up @@ -136,6 +144,41 @@ namespace cwg2126 { // cwg2126: 12
#endif
}

namespace cwg2137 { // cwg2137: 20
#if __cplusplus >= 201103L
struct Q {
Q();
Q(Q&&);
Q(std::initializer_list<Q>) = delete; // #cwg2137-Qcons
};

Q x = Q { Q() };
// since-cxx11-error@-1 {{call to deleted constructor of 'Q'}}
// since-cxx11-note@#cwg2137-Qcons {{'Q' has been explicitly marked deleted here}}

int f(Q); // #cwg2137-f
int y = f({ Q() });
// since-cxx11-error@-1 {{call to deleted constructor of 'Q'}}
// since-cxx11-note@#cwg2137-Qcons {{'Q' has been explicitly marked deleted here}}
// since-cxx11-note@#cwg2137-f {{passing argument to parameter here}}

struct U {
U();
U(const U&);
};

struct Derived : U {
Derived();
Derived(const Derived&);
} d;

int g(Derived);
int g(U(&&)[1]) = delete;

int z = g({ d });
#endif
}

namespace cwg2140 { // cwg2140: 9
#if __cplusplus >= 201103L
union U { int a; decltype(nullptr) b; };
Expand Down
99 changes: 99 additions & 0 deletions clang/test/CXX/drs/cwg23xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s

namespace std {
__extension__ typedef __SIZE_TYPE__ size_t;

template<typename E> struct initializer_list {
const E *p; size_t n;
initializer_list(const E *p, size_t n);
initializer_list();
};
}

#if __cplusplus >= 201103L
namespace cwg2303 { // cwg2303: 12
template <typename... T>
Expand Down Expand Up @@ -94,6 +104,95 @@ struct Z : W,
// cwg2331: na
// cwg2335 is in cwg2335.cxx

namespace cwg2311 { // cwg2311 is open with no proposed resolution
#if __cplusplus >= 201707L
template<typename T>
void test() {
// Ensure none of these try to call a move constructor.
T a = T{T(0)};
T b{T(0)};
auto c{T(0)};
T d = {T(0)};
auto e = {T(0)};
#if __cplusplus >= 202302L
auto f = auto{T(0)};
#endif
void(*fn)(T);
fn({T(0)});
}

struct NonMovable {
NonMovable(int);
NonMovable(NonMovable&&) = delete;
};
struct NonMovableNonApplicableIList {
NonMovableNonApplicableIList(int);
NonMovableNonApplicableIList(NonMovableNonApplicableIList&&) = delete;
NonMovableNonApplicableIList(std::initializer_list<int>);
};
struct ExplicitMovable {
ExplicitMovable(int);
explicit ExplicitMovable(ExplicitMovable&&);
};
struct ExplicitNonMovable {
ExplicitNonMovable(int);
explicit ExplicitNonMovable(ExplicitNonMovable&&) = delete;
};
struct ExplicitNonMovableNonApplicableIList {
ExplicitNonMovableNonApplicableIList(int);
explicit ExplicitNonMovableNonApplicableIList(ExplicitNonMovableNonApplicableIList&&) = delete;
ExplicitNonMovableNonApplicableIList(std::initializer_list<int>);
};
struct CopyOnly {
CopyOnly(int);
CopyOnly(const CopyOnly&);
CopyOnly(CopyOnly&&) = delete;
};
struct ExplicitCopyOnly {
ExplicitCopyOnly(int);
explicit ExplicitCopyOnly(const ExplicitCopyOnly&);
explicit ExplicitCopyOnly(ExplicitCopyOnly&&) = delete;
};

template void test<NonMovable>();
template void test<NonMovableNonApplicableIList>();
template void test<ExplicitMovable>();
template void test<ExplicitNonMovable>();
template void test<ExplicitNonMovableNonApplicableIList>();
template void test<CopyOnly>();
template void test<ExplicitCopyOnly>();

struct any {
template<typename T>
any(T&&);
};

template<typename T>
struct X {
X();
X(T) = delete; // #cwg2311-X
};

X<std::initializer_list<any>> x{ X<std::initializer_list<any>>() };
// since-cxx17-error@-1 {{call to deleted constructor of 'X<std::initializer_list<any>>'}}
// since-cxx17-note@#cwg2311-X {{'X' has been explicitly marked deleted here}}

// Per the currently implemented resolution, this does not apply to std::initializer_list.
// An initializer list initialized from `{ e }` always has exactly one element constructed
// from `e`, where previously that could have been a copy of an init list or `e.operator std::initializer_list()`
struct InitListCtor {
InitListCtor(int);
InitListCtor(InitListCtor&&) = delete;
InitListCtor(std::initializer_list<InitListCtor>) = delete; // #cwg2311-InitListCtor
};

std::initializer_list<InitListCtor> i;
auto j = std::initializer_list<InitListCtor>{ i };
// since-cxx17-error@-1 {{conversion function from 'std::initializer_list<InitListCtor>' to 'const cwg2311::InitListCtor' invokes a deleted function}}
// since-cxx17-note@#cwg2311-InitListCtor {{'InitListCtor' has been explicitly marked deleted here}}
#endif
}

#if __cplusplus >= 201103L
namespace cwg2338 { // cwg2338: 12
namespace B {
Expand Down
53 changes: 53 additions & 0 deletions clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-definitions.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// RUN: %clang_cc1 -triple s390x-ibm-zos -emit-llvm < %s | FileCheck %s --check-prefix=PTR32-ZOS
// RUN: %clang_cc1 -triple s390x-ibm-linux -fzos-extensions -emit-llvm < %s | FileCheck %s --check-prefix=PTR32-LINUX
// RUN: %clang_cc1 -triple s390x-linux-gnu -fzos-extensions -emit-llvm < %s | FileCheck %s --check-prefix=PTR32-LINUX

void ptr32_declarations() {
// PTR32-ZOS-LABEL: @ptr32_declarations()
// PTR32-LINUX-LABEL: @ptr32_declarations()

// PTR32-ZOS: %p1 = alloca ptr addrspace(1), align 4
// PTR32-LINUX-NOT: %p1 = alloca i8 addrspace(1)*, align 4
// PTR32-LINUX: %p1 = alloca ptr, align 8
char * __ptr32 p1;

// PTR32-ZOS: %p2 = alloca ptr, align 8
// PTR32-LINUX-NOT: %p2 = alloca ptr addrspace(1), align 8
// PTR32-LINUX: %p2 = alloca ptr, align 8
char * __ptr32 *p2;

// PTR32-ZOS: %p3 = alloca ptr addrspace(1), align 4
// PTR32-LINUX-NOT: %p3 = alloca i8* addrspace(1)*, align 4
// PTR32-LINUX: %p3 = alloca ptr, align 8
char ** __ptr32 p3;

// PTR32-ZOS: %p4 = alloca ptr, align 8
// PTR32-LINUX-NOT: %p4 = alloca ptr addrspace(1), align 8
// PTR32-LINUX: %p4 = alloca ptr, align 8
char ** __ptr32 *p4;

// PTR32-ZOS: %p5 = alloca ptr, align 8
// PTR32-LINUX-NOT: %p5 = alloca ptr addrspace(1), align 8
// PTR32-LINUX: %p5 = alloca ptr, align 8
char *** __ptr32 *p5;

// PTR32-ZOS: %p6 = alloca ptr, align 8
// PTR32-LINUX: %p6 = alloca ptr, align 8
char **p6;

// PTR32-ZOS: %p7 = alloca ptr addrspace(1), align 4
// PTR32-LINUX-NOT: %p7 = alloca i8 addrspace(1)* addrspace(1)*, align 4
// PTR32-LINUX: %p7 = alloca ptr, align 8
char * __ptr32 * __ptr32 p7;

// PTR32-ZOS: %p8 = alloca ptr addrspace(1), align 4
// PTR32-LINUX-NOT: %p8 = alloca i8* addrspace(1)* addrspace(1)*, align 4
// PTR32-LINUX: %p8 = alloca ptr, align 8
char ** __ptr32 * __ptr32 p8;

// PTR32-ZOS: %p9 = alloca ptr, align 8
// PTR32-LINUX-NOT: %p9 = alloca i8* addrspace(1)* addrspace(1)**, align 8
// PTR32-LINUX: %p9 = alloca ptr, align 8
char ** __ptr32 * __ptr32 *p9;

}
84 changes: 84 additions & 0 deletions clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-malloc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// RUN: %clang -target s390x-ibm-zos -emit-llvm -S -O2 %s -o - | FileCheck %s --check-prefix=X64
#include <stddef.h>
void *__malloc31(size_t);

int test_1() {
// X64-LABEL: define {{.*}} i32 @test_1()
// X64: ret i32 135
int *__ptr32 a;
int *b;
int i;
int sum1, sum2, sum3;

a = (int *__ptr32)__malloc31(sizeof(int) * 10);

b = a;
sum1 = 0;
for (i = 0; i < 10; ++i) {
a[i] = i;
sum1 += i;
}

sum2 = 0;
for (i = 0; i < 10; ++i) {
sum2 += a[i];
}
sum3 = 0;
for (i = 0; i < 10; ++i) {
sum3 += b[i];
}

return (sum1 + sum2 + sum3);
}

int test_2() {
// X64-LABEL: define {{.*}} i32 @test_2()
// X64: ret i32 4
int *a = (int *)__malloc31(sizeof(int));
int *__ptr32 b;

*a = 99;
b = a;
*b = 44;

// Test should return 4
return (*b - 40);
}

int test_3() {
// X64-LABEL: define {{.*}} i32 @test_3()
// X64: ret i32 4
int *a = (int *)__malloc31(sizeof(int));
int *__ptr32 b;

*a = 99;
b = a;

// Test should return 4
return (*b - 95);
}

int test_4() {
// X64-LABEL: define {{.*}} i32 @test_4()
// X64: ret i32 1
int *a = (int *)__malloc31(sizeof(int));
float *d = (float *)__malloc31(sizeof(float));

int *__ptr32 b;
int *c;

float *__ptr32 e;
float *f;

*a = 0;
*d = 0.0;

b = a;
c = a;
e = d;
f = d;

// Test should return 1
return (b == c && e == f);
}

94 changes: 94 additions & 0 deletions clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-sizeof.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// RUN: %clang_cc1 -emit-llvm -triple s390x-ibm-zos -fzos-extensions -fdump-record-layouts < %s | FileCheck %s --check-prefix=PTR32-ZOS
// RUN: %clang_cc1 -emit-llvm -triple s390x-ibm-linux -fzos-extensions -fdump-record-layouts < %s | FileCheck %s --check-prefix=PTR32-LINUX
// RUN: %clang_cc1 -emit-llvm -triple s390x-linux-gnu -fzos-extensions -fdump-record-layouts < %s | FileCheck %s --check-prefix=PTR32-LINUX

// PTR32-ZOS: 0 | struct s1
// PTR32-ZOS-NEXT: 0 | long a
// PTR32-ZOS-NEXT: 8 | int b
// PTR32-ZOS-NEXT: 12 | int * __ptr32 c
// PTR32-ZOS-NEXT: 16 | int d
// PTR32-ZOS-NEXT: | [sizeof=24, align=8]

// PTR32-LINUX: 0 | struct s1
// PTR32-LINUX-NEXT: 0 | long a
// PTR32-LINUX-NEXT: 8 | int b
// PTR32-LINUX-NEXT: 16 | int * __ptr32 c
// PTR32-LINUX-NEXT: 24 | int d
// PTR32-LINUX-NEXT: | [sizeof=32, align=8]
struct s1 {
long a;
int b;
int * __ptr32 c;
int d;
} S1;

// PTR32-ZOS: 0 | struct s2
// PTR32-ZOS-NEXT: 0 | long a
// PTR32-ZOS-NEXT: 8 | int b
// PTR32-ZOS-NEXT: 16 | int * c
// PTR32-ZOS-NEXT: 24 | int d
// PTR32-ZOS-NEXT: | [sizeof=32, align=8]

// PTR32-LINUX: 0 | struct s2
// PTR32-LINUX-NEXT: 0 | long a
// PTR32-LINUX-NEXT: 8 | int b
// PTR32-LINUX-NEXT: 16 | int * c
// PTR32-LINUX-NEXT: 24 | int d
// PTR32-LINUX-NEXT: | [sizeof=32, align=8]
struct s2 {
long a;
int b;
int *c;
int d;
} S2;

// PTR32-ZOS: 0 | struct s3
// PTR32-ZOS-NEXT: 0 | int a
// PTR32-ZOS-NEXT: 4 | int * __ptr32 b
// PTR32-ZOS-NEXT: 8 | int * __ptr32 c
// PTR32-ZOS-NEXT: 12 | int * d
// PTR32-ZOS-NEXT: | [sizeof=20, align=1]

struct __attribute__((packed)) s3 {
int a;
int *__ptr32 b;
int *__ptr32 c;
int *d;
};
struct s3 S3;

// PTR32-ZOS: 0 | union u1
// PTR32-ZOS-NEXT: 0 | int * __ptr32 a
// PTR32-ZOS-NEXT: 0 | int * b
// PTR32-ZOS-NEXT: | [sizeof=8, align=8]

// PTR32-LINUX: 0 | union u1
// PTR32-LINUX-NEXT: 0 | int * __ptr32 a
// PTR32-LINUX-NEXT: 0 | int * b
// PTR32-LINUX-NEXT: | [sizeof=8, align=8]
union u1 {
int *__ptr32 a;
int *b;
} U1;

// PTR32-ZOS: 0 | union u2
// PTR32-ZOS-NEXT: 0 | int * __ptr32 a
// PTR32-ZOS-NEXT: 0 | int * b
// PTR32-ZOS-NEXT: | [sizeof=8, align=1]

union __attribute__((packed)) u2 {
int *__ptr32 a;
int *b;
};
union u2 U2;

// PTR32-ZOS: 0 | union u3
// PTR32-ZOS-NEXT: 0 | int * __ptr32 a
// PTR32-ZOS-NEXT: 0 | short b
// PTR32-ZOS-NEXT: | [sizeof=4, align=1]

union __attribute__((packed)) u3 {
int *__ptr32 a;
short b;
};
union u3 U3;
298 changes: 298 additions & 0 deletions clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
// RUN: %clang_cc1 -triple s390x-ibm-zos -emit-llvm -O2 < %s | FileCheck %s --check-prefix=X64

#define PSA_PTR 0x00
#define PSAAOLD 0x224

struct Foo {
int * __ptr32 p32;
int *p64;
char *cp64;
};

void use_foo(struct Foo *f);

void ptr32_to_ptr(struct Foo *f, int * __ptr32 i) {
// X64-LABEL: define void @ptr32_to_ptr(ptr noundef %f, ptr addrspace(1) noundef %i)
// X64: %{{.+}} = addrspacecast ptr addrspace(1) %i to ptr
f->p64= i;
use_foo(f);
}

void ptr_to_ptr32(struct Foo *f, int *i) {
// X64-LABEL: define void @ptr_to_ptr32(ptr noundef %f, ptr noundef %i)
// X64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(1)
f->p32 = i;
use_foo(f);
}

void ptr32_to_ptr32(struct Foo *f, int * __ptr32 i) {
// X64-LABEL: define void @ptr32_to_ptr32(ptr noundef %f, ptr addrspace(1) noundef %i)
// X64-NOT: addrspacecast
f->p32 = i;
use_foo(f);
}

void ptr_to_ptr32_explicit_cast(struct Foo *f, int *i) {
// X64-LABEL: define void @ptr_to_ptr32_explicit_cast(ptr noundef %f, ptr noundef %i)
// X64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(1)
f->p32 = (int * __ptr32)i;
use_foo(f);
}

void test_indexing(struct Foo *f) {
// X64-LABEL: define void @test_indexing(ptr noundef %f)
// X64: addrspacecast ptr addrspace(1) {{%[0-9]}} to ptr
f->cp64 = ((char * __ptr32 *)1028)[1];
use_foo(f);
}

void test_indexing_2(struct Foo *f) {
// X64-LABEL: define void @test_indexing_2(ptr noundef %f)
// X64: getelementptr inbounds i8, ptr addrspace(1) {{%[0-9]}}, i32 16
// X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 24
f->cp64 = ((char *** __ptr32 *)1028)[1][2][3];
use_foo(f);
}

unsigned long* test_misc() {
// X64-LABEL: define ptr @test_misc()
// X64: %arrayidx = getelementptr inbounds i8, ptr addrspace(1) %0, i32 88
// X64-NEXT: %1 = load ptr, ptr addrspace(1) %arrayidx
// X64-NEXT: %arrayidx1 = getelementptr inbounds i8, ptr %1, i64 8
// X64-NEXT: %2 = load ptr, ptr %arrayidx1
// X64-NEXT: %arrayidx2 = getelementptr inbounds i8, ptr %2, i64 904
// X64-NEXT: %3 = load ptr, ptr %arrayidx2
// X64-NEXT: %arrayidx3 = getelementptr inbounds i8, ptr %3, i64 1192
unsigned long* x = (unsigned long*)((char***** __ptr32*)1208)[0][11][1][113][149];
return x;
}

char* __ptr32* __ptr32 test_misc_2() {
// X64-LABEL: define ptr addrspace(1) @test_misc_2()
// X64: br i1 %cmp, label %if.then, label %if.end
// X64: %1 = load ptr addrspace(1), ptr inttoptr (i64 16 to ptr)
// X64-NEXT: %arrayidx = getelementptr inbounds i8, ptr addrspace(1) %1, i32 544
// X64-NEXT: %2 = load ptr addrspace(1), ptr addrspace(1) %arrayidx
// X64-NEXT: %arrayidx1 = getelementptr inbounds i8, ptr addrspace(1) %2, i32 24
// X64-NEXT: %3 = load ptr addrspace(1), ptr addrspace(1) %arrayidx1
// X64-NEXT: store ptr addrspace(1) %3, ptr @test_misc_2.res
// X64: ret ptr addrspace(1)
static char* __ptr32* __ptr32 res = 0;
if (res == 0) {
res = ((char* __ptr32* __ptr32* __ptr32* __ptr32*)0)[4][136][6];
}
return res;
}

unsigned short test_misc_3() {
// X64-LABEL: define zeroext i16 @test_misc_3()
// X64: %0 = load ptr addrspace(1), ptr inttoptr (i64 548 to ptr)
// X64-NEXT: %1 = addrspacecast ptr addrspace(1) %0 to ptr
// X64-NEXT: %arrayidx = getelementptr inbounds i8, ptr %1, i64 36
// X64-NEXT: %2 = load i16, ptr %arrayidx, align 2
// X64-NEXT: ret i16 %2
unsigned short this_asid = ((unsigned short*)(*(char* __ptr32*)(0x224)))[18];
return this_asid;
}

int test_misc_4() {
// X64-LABEL: define signext range(i32 0, 2) i32 @test_misc_4()
// X64: getelementptr inbounds i8, ptr addrspace(1) {{%[0-9]}}, i32 88
// X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 8
// X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 984
// X64: getelementptr inbounds i8, ptr %3, i64 80
// X64: icmp sgt i32 {{.*[0-9]}}, 67240703
// X64: ret i32
int a = (*(int*)(80 + ((char**** __ptr32*)1208)[0][11][1][123]) > 0x040202FF);
return a;
}

void test_misc_5(struct Foo *f) {
// X64-LABEL: define void @test_misc_5(ptr noundef %f)
// X64: addrspacecast ptr addrspace(1) %0 to ptr
f->cp64 = *(char* __ptr32 *)(PSA_PTR + PSAAOLD);
use_foo(f);
}

int test_misc_6() {
// X64-LABEL: define {{.*}} i32 @test_misc_6()
// X64: ret i32 8
int * __ptr32 ip32;
int *ip64;
ip64 = ip32;
return sizeof(ip64);
}

int test_misc_7() {
// X64-LABEL: define {{.*}} i32 @test_misc_7()
// X64: ret i32 12
int foo = 12;

int *ip64;
int * __ptr32 ip32;

ip64 = &foo;
ip32 = (int * __ptr32) ip64;

return *ip32;
}

int test_misc_8() {
// X64-LABEL: define {{.*}} i32 @test_misc_8()
// X64: ret i32 97
char foo = 'a';

char *cp64;
char * __ptr32 cp32;

cp64 = &foo;
cp32 = (char * __ptr32) cp64;

return *cp32;
}

int test_misc_9() {
// X64-LABEL: define {{.*}} i32 @test_misc_9()
// X64: ret i32 15
int foo = 15;

int *ip64;
int * __ptr32 ip32;

ip32 = &foo;
ip64 = (int *)ip32;

return *ip64;
}

int test_misc_10() {
// X64-LABEL: define {{.*}} i32 @test_misc_10()
// X64: ret i32 97
char foo = 'a';

char *cp64;
char * __ptr32 cp32;

cp32 = &foo;
cp64= (char *)cp32;

return *cp64;
}

int test_function_ptr32_is_32bit() {
// X64-LABEL: define {{.*}} i32 @test_function_ptr32_is_32bit()
// X64: ret i32 4
int (* __ptr32 a)(int a);
return sizeof(a);
}

int get_processor_count() {
// X64-LABEL: define signext range(i32 -128, 128) i32 @get_processor_count()
// X64: load ptr addrspace(1), ptr inttoptr (i64 16 to ptr)
// X64-NEXT: [[ARR_IDX1:%[a-z].*]] = getelementptr inbounds i8, ptr addrspace(1) %0, i32 660
// X64: load ptr addrspace(1), ptr addrspace(1) [[ARR_IDX1]]
// X64: load i8, ptr addrspace(1) {{%[a-z].*}}
// X64: sext i8 {{%[0-9]}} to i32
// X64-NEXT: ret i32
return ((char * __ptr32 * __ptr32 *)0)[4][165][53];
}

int get_sizes_ptr32() {
// X64-LABEL: define {{.*}} i32 @get_sizes_ptr32()
// X64: ret i32 72
char * __ptr32 a;
signed char * __ptr32 b;
unsigned char *__ptr32 c;
int * __ptr32 d;
signed int * __ptr32 e;
unsigned int *__ptr32 f;
short * __ptr32 g;
signed short * __ptr32 h;
unsigned short * __ptr32 i;
long * __ptr32 j;
signed * __ptr32 k;
unsigned * __ptr32 l;
long long * __ptr32 m;
signed long long * __ptr32 n;
unsigned long long * __ptr32 o;
float * __ptr32 p;
double * __ptr32 q;
long double * __ptr32 r;

int sum = 0;
sum += sizeof(a);
sum += sizeof(b);
sum += sizeof(c);
sum += sizeof(d);
sum += sizeof(e);
sum += sizeof(f);
sum += sizeof(g);
sum += sizeof(h);
sum += sizeof(i);
sum += sizeof(j);
sum += sizeof(k);
sum += sizeof(l);
sum += sizeof(m);
sum += sizeof(n);
sum += sizeof(o);
sum += sizeof(p);
sum += sizeof(q);
sum += sizeof(r);

return sum;
}

int get_sizes_p64() {
// X64-LABEL: define {{.*}} i32 @get_sizes_p64()
// X64: ret i32 144
char *a;
signed char *b;
unsigned char *c;
int *d;
signed int *e;
unsigned int *f;
short *g;
signed short *h;
unsigned short *i;
long *j;
signed *k;
unsigned *l;
long long *m;
signed long long *n;
unsigned long long *o;
float *p;
double *q;
long double *r;

int sum = 0;
sum += sizeof(a);
sum += sizeof(b);
sum += sizeof(c);
sum += sizeof(d);
sum += sizeof(e);
sum += sizeof(f);
sum += sizeof(g);
sum += sizeof(h);
sum += sizeof(i);
sum += sizeof(j);
sum += sizeof(k);
sum += sizeof(l);
sum += sizeof(m);
sum += sizeof(n);
sum += sizeof(o);
sum += sizeof(p);
sum += sizeof(q);
sum += sizeof(r);

return sum;

}

int host_cpu() {
char *__ptr32 CVT = *(char * __ptr32 *__ptr32) 16;
unsigned short Id = *(unsigned short *)&CVT[-6];
Id = ((((Id >> 12) & 0x0f) * 10 + ((Id >> 8) & 0x0f)) * 10 + ((Id >> 4) & 0x0f)) * 10 + (Id & 0x0f);
int HaveVectorSupport = CVT[244] & 0x80;
int z13 = (Id >= 2964 && HaveVectorSupport);
return z13;
}
2 changes: 1 addition & 1 deletion clang/test/CodeGen/target-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@
// RUN: FileCheck %s -check-prefix=ZOS
// RUN: %clang_cc1 -triple s390x-none-zos -target-cpu z13 -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=ZOS
// ZOS: target datalayout = "E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
// ZOS: target datalayout = "E-m:l-p1:32:32-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"

// RUN: %clang_cc1 -triple msp430-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=MSP430
Expand Down
17 changes: 17 additions & 0 deletions clang/test/CodeGenCXX/zos-mangle-ptr-size-address-space.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang_cc1 -fzos-extensions -emit-llvm -triple s390x-ibm-zos -x c++ -o - %s | FileCheck %s --check-prefixes=CHECK

// CHECK-LABEL: define void @_Z2f1v()
void f1() {}

// CHECK-LABEL: define void @_Z2f2Pi(ptr addrspace(1) noundef %p32)
void f2(int * __ptr32 p32) {}

// CHECK-LABEL: define noundef ptr addrspace(1) @_Z2f3Pi(ptr addrspace(1) noundef %p32)
int * __ptr32 f3(int * __ptr32 p32) {
return p32;
}

// CHECK-LABEL: define noundef ptr @_Z2f4PPi(ptr noundef %p32)
int * __ptr32 *f4(int * __ptr32 *p32) {
return p32;
}
2 changes: 1 addition & 1 deletion clang/test/Modules/check-for-sanitizer-feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
//
// Import the PCH without ASan enabled (we expect an error).
// RUN: not %clang_cc1 -x c -include-pch %t.asan_pch %s -verify 2>&1 | FileCheck %s --check-prefix=PCH_MISMATCH
// PCH_MISMATCH: AST file was compiled with the target feature '-fsanitize=address' but the current translation unit is not
// PCH_MISMATCH: AST file '{{.*}}.asan_pch' was compiled with the target feature '-fsanitize=address' but the current translation unit is not
//
// Emit a PCH with UBSan enabled.
// RUN: %clang_cc1 -x c -fsanitize=null %S/Inputs/check-for-sanitizer-feature/check.h -emit-pch -o %t.ubsan_pch
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Modules/ignored_macros.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// RUN: %clang_cc1 -fmodules-cache-path=%t.modules -fmodules -fimplicit-module-maps -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify
// RUN: not %clang_cc1 -fmodules-cache-path=%t.modules -DIGNORED=1 -fmodules -fimplicit-module-maps -I %S/Inputs -include-pch %t.pch %s > %t.err 2>&1
// RUN: FileCheck -check-prefix=CHECK-CONFLICT %s < %t.err
// CHECK-CONFLICT: PCH was compiled with module cache path
// CHECK-CONFLICT: AST file '{{.*}}' was compiled with module cache path

// Third trial: pass -DIGNORED=1 only to the second invocation, but
// make it ignored. There should be no failure, IGNORED is defined in
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Modules/load_failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// RUN: FileCheck -check-prefix=CHECK-FAILURE %s < %t.out

// FIXME: Clean up diagnostic text below and give it a location
// CHECK-FAILURE: error: C99 was disabled in PCH file but is currently enabled
// CHECK-FAILURE: error: C99 was disabled in AST file '{{.*}}load_failure.pcm' but is currently enabled
// FIXME: When we have a syntax for modules in C, use that.


6 changes: 3 additions & 3 deletions clang/test/Modules/merge-target-features.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// RUN: -target-cpu i386 \
// RUN: -fsyntax-only merge-target-features.cpp 2>&1 \
// RUN: | FileCheck --check-prefix=SUBSET --implicit-check-not=error: %s
// SUBSET: error: AST file was compiled with the target feature '+sse2' but the current translation unit is not
// SUBSET: error: AST file '{{.*}}foo.pcm' was compiled with the target feature '+sse2' but the current translation unit is not
// SUBSET: error: {{.*}} configuration mismatch
//
// RUN: %clang_cc1 -fmodules -x c++ -fmodules-cache-path=%t \
Expand Down Expand Up @@ -57,8 +57,8 @@
// RUN: -target-cpu i386 -target-feature +cx16 \
// RUN: -fsyntax-only merge-target-features.cpp 2>&1 \
// RUN: | FileCheck --check-prefix=MISMATCH --implicit-check-not=error: %s
// MISMATCH: error: AST file was compiled with the target feature '+sse2' but the current translation unit is not
// MISMATCH: error: current translation unit is compiled with the target feature '+cx16' but the AST file was not
// MISMATCH: error: AST file '{{.*}}foo.pcm' was compiled with the target feature '+sse2' but the current translation unit is not
// MISMATCH: error: current translation unit is compiled with the target feature '+cx16' but the AST file '{{.*}}foo.pcm' was not
// MISMATCH: error: {{.*}} configuration mismatch

#include "foo.h"
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Modules/mismatch-diagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ export module mismatching_module;

//--- use.cpp
import mismatching_module;
// CHECK: error: POSIX thread support was enabled in PCH file but is currently disabled
// CHECK: error: POSIX thread support was enabled in AST file '{{.*[/|\\\\]}}mismatching_module.pcm' but is currently disabled
// CHECK-NEXT: module file {{.*[/|\\\\]}}mismatching_module.pcm cannot be loaded due to a configuration mismatch with the current compilation
4 changes: 2 additions & 2 deletions clang/test/Modules/module-pch-different-cache-path.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@

pch_int x = 0;

// CHECK-ERROR: PCH was compiled with module cache path '{{.*}}', but the path is currently '{{.*}}'
// CHECK-SUCCESS-NOT: PCH was compiled with module cache path '{{.*}}', but the path is currently '{{.*}}'
// CHECK-ERROR: AST file '{{.*}}' was compiled with module cache path '{{.*}}', but the path is currently '{{.*}}'
// CHECK-SUCCESS-NOT: AST file '{{.*}}' was compiled with module cache path '{{.*}}', but the path is currently '{{.*}}'
4 changes: 2 additions & 2 deletions clang/test/Modules/pr62359.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ int use() {
return 0;
}

// CHECK: OpenMP{{.*}}differs in PCH file vs. current file
// CHECK: OpenMP{{.*}}differs in AST file '{{.*}}Hello.pcm' vs. current file

//--- use2.cpp
// expected-no-diagnostics
Expand All @@ -55,5 +55,5 @@ int use2() {
return 0;
}

// CHECK: OpenMP{{.*}}differs in PCH file vs. current file
// CHECK: OpenMP{{.*}}differs in AST file '{{.*}}Hello.pcm' vs. current file
// CHECK: use of undeclared identifier 'pragma'
4 changes: 2 additions & 2 deletions clang/test/PCH/arc.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
array0 a0;
array1 a1;

// CHECK-ERR1: Objective-C automated reference counting was enabled in PCH file but is currently disabled
// CHECK-ERR2: Objective-C automated reference counting was disabled in PCH file but is currently enabled
// CHECK-ERR1: Objective-C automated reference counting was enabled in AST file '{{.*}}' but is currently disabled
// CHECK-ERR2: Objective-C automated reference counting was disabled in AST file '{{.*}}' but is currently enabled
6 changes: 3 additions & 3 deletions clang/test/PCH/fuzzy-pch.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ BAR bar = 17;
# error BAR was not defined
#endif

// CHECK-FOO: definition of macro 'FOO' differs between the precompiled header ('1') and the command line ('blah')
// CHECK-NOFOO: macro 'FOO' was defined in the precompiled header but undef'd on the command line
// CHECK-FOO: definition of macro 'FOO' differs between the AST file '{{.*}}' ('1') and the command line ('blah')
// CHECK-NOFOO: macro 'FOO' was defined in the AST file '{{.*}}' but undef'd on the command line

// CHECK-UNDEF: command line contains '-undef' but precompiled header was not built with it
// CHECK-UNDEF: command line contains '-undef' but AST file '{{.*}}' was not built with it

2 changes: 1 addition & 1 deletion clang/test/PCH/module-hash-difference.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
// RUN: not %clang_cc1 -fsyntax-only -include-pch %t.pch %s -I %S/Inputs/modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash 2> %t.err
// RUN: FileCheck -input-file=%t.err %s

// CHECK: error: PCH was compiled with module cache path {{.*}}, but the path is currently {{.*}}
// CHECK: error: AST file '{{.*}}' was compiled with module cache path {{.*}}, but the path is currently {{.*}}
@import Foo;
4 changes: 2 additions & 2 deletions clang/test/PCH/ms-pch-macro.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ BAR bar = 17;
# error BAR was not defined
#endif

// CHECK-FOO: definition of macro 'FOO' differs between the precompiled header ('1') and the command line ('blah')
// CHECK-NOFOO: macro 'FOO' was defined in the precompiled header but undef'd on the command line
// CHECK-FOO: definition of macro 'FOO' differs between the AST file '{{.*}}1.pch' ('1') and the command line ('blah')
// CHECK-NOFOO: macro 'FOO' was defined in the AST file '{{.*}}1.pch' but undef'd on the command line

// expected-warning@2 {{definition of macro 'BAR' does not match definition in precompiled header}}
4 changes: 2 additions & 2 deletions clang/test/PCH/no-validate-pch.cl
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
// CHECK: note: previous definition is here
// CHECK: #define X 4

// CHECK-VAL: error: __OPTIMIZE__ predefined macro was enabled in PCH file but is currently disabled
// CHECK-VAL: error: definition of macro 'X' differs between the precompiled header ('4') and the command line ('5')
// CHECK-VAL: error: __OPTIMIZE__ predefined macro was enabled in AST file '{{.*}}' but is currently disabled
// CHECK-VAL: error: definition of macro 'X' differs between the AST file '{{.*}}' ('4') and the command line ('5')

void test(void) {
int a = ONE;
Expand Down
120 changes: 120 additions & 0 deletions clang/test/Sema/ZOSExtensions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// RUN: %clang_cc1 -triple s390x-ibm-zos %s -fsyntax-only -fzos-extensions -verify
// RUN: %clang_cc1 -triple s390x-ibm-zos %s -fsyntax-only -verify

struct A {
int a;
short b;
float q;
double z;
};

union B {
int a;
short b;
float q;
double z;
};

class C {
int a;
short b;
float q;
double z;
};

// ************************
// INCORRECT DECLARATION
// ************************
int * __ptr64 p64; // expected-error {{expected ';' after top level declarator}}
int *wrong_var3 __ptr32; // expected-error {{expected ';' after top level declarator}} expected-warning {{declaration does not declare anything}}

// **************************
// INCORRECT USAGES OF PTR32
// **************************
struct D {
int __ptr32 *a; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
};

union E {
int __ptr32 *b; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
};

char __ptr32 *a; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
signed char __ptr32 *b; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
unsigned char __ptr32 *c; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
int __ptr32 *d; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
signed int __ptr32 *e; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
unsigned int __ptr32 *f; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
short int __ptr32 *g; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
signed short int __ptr32 *h; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
unsigned short int __ptr32 *i; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
long int __ptr32 *j; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
signed long int __ptr32 *k; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
unsigned long int __ptr32 *l; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
long long int __ptr32 *m; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
signed long long int __ptr32 *n; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
unsigned long long int __ptr32 *o; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
float __ptr32 *p; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
double __ptr32 *q; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
int __ptr32 **r; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
int __ptr32 *__ptr32 *s; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
int __ptr32 *__ptr32 *__ptr32 t; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
int __ptr32 *__ptr32 *__ptr32 *__ptr32 u; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
int __ptr32 __ptr32 **v_i; // expected-error {{'__ptr32' attribute only applies to pointer arguments}} expected-error {{'__ptr32' attribute only applies to pointer arguments}}
int __ptr32 __ptr32 __ptr32 w_i; // expected-error {{'__ptr32' attribute only applies to pointer arguments}} expected-error {{'__ptr32' attribute only applies to pointer arguments}} expected-error {{'__ptr32' attribute only applies to pointer arguments}}

__ptr32 int wrong_var; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}

struct A __ptr32 *c1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
struct A __ptr32 **e1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
struct A __ptr32 *__ptr32 *f1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
struct A __ptr32 *__ptr32 *__ptr32 g1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
union B __ptr32 *d1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
union B __ptr32 **h1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
union B __ptr32 * __ptr32 *i1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
union B __ptr32 * __ptr32 * __ptr32 j1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}

C __ptr32 **k1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
C __ptr32 * __ptr32 *l1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
C __ptr32 * __ptr32 * __ptr32 m1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}

struct D n1;
union E o1;

int incorrect_func() {
int __ptr32 = 1; // expected-error {{expected unqualified-id}}
return __ptr32; // expected-error {{expected expression}}
}

typedef int __ptr32; // expected-warning {{typedef requires a name}}
int incorrect_func2() {
return 1;
}

typedef int __ptr32 *v; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
int incorrect_func3() {
v v1;
return 0;
}

int *__ptr32 a_ptr; //expected-note {{previous definition is here}}
int *a_ptr; // expected-error {{redefinition of 'a_ptr' with a different type: 'int *' vs 'int * __ptr32'}}

// *******************************************************
// FUNCTION OVERLOADING BETWEEN PTR32 AND REGULAR POINTERS
// *******************************************************
void func(int * __ptr32 p32) {} // expected-note {{previous definition is here}}
void func(int *p64) {} // expected-error {{redefinition of 'func'}}

// Overloads between ptr32 and other non-pointer types are permissible
void func1(int *__ptr32 p32) {}
void func1(int p64) {}

// ******
// MISC
// ******
void func2() {
char * __ptr32 v = ((char * __ptr32 *)1028)[0];
char *v1 = ((char ** __ptr32 *)1028)[0][1];
}

31 changes: 31 additions & 0 deletions clang/test/Sema/attr-print-zos.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// RUN: %clang_cc1 %s -triple s390x-ibm-zos -ast-print -fzos-extensions | FileCheck %s

// CHECK: int * __ptr32 p32;
int * __ptr32 p32;

// CHECK: char * __ptr32 c32;
char * __ptr32 c32;

// CHECK: void * __ptr32 v32;
void * __ptr32 v32;

// CHECK: int * __ptr32 *q;
int * __ptr32 *q;

// CHECK: void *func(int * __ptr32 p);
void *func(int * __ptr32 p);

// CHECK: int * __ptr32 func1(int * __ptr32 p);
int * __ptr32 func1(int * __ptr32 p);

// CHECK: int *func2(void * __ptr32 p);
int *func2(void * __ptr32 p);

// CHECK: int *const __ptr32 r;
int * __ptr32 const r;

// CHECK: int ** __ptr32 *v;
int * *__ptr32* v;

// CHECK: int *** __ptr32 *z;
int ** * __ptr32 * z;
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ template<typename T> constexpr bool has_type(T&) { return true; }

std::initializer_list il1 = {1, 2, 3, 4, 5};
auto il2 = std::initializer_list{1, 2, 3, 4};
auto il3 = std::initializer_list{il1};
auto il3 = std::initializer_list(il1);
auto il4 = std::initializer_list{il1, il1, il1};
static_assert(has_type<std::initializer_list<int>>(il1));
static_assert(has_type<std::initializer_list<int>>(il2));
static_assert(has_type<std::initializer_list<int>>(il3));
static_assert(has_type<std::initializer_list<std::initializer_list<int>>>(il4));

auto il5 = std::initializer_list{il1};
// expected-error@-1 {{no viable conversion from 'std::initializer_list<int>' to 'const int'}}

template<typename T> struct vector {
template<typename Iter> vector(Iter, Iter);
vector(std::initializer_list<T>);
Expand Down
82 changes: 82 additions & 0 deletions clang/test/SemaCXX/single-element-init-list.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s

// This is heavily affected by the speculative resolution applied to CWG2311
// So behaviour shown here is subject to change.

// expected-no-diagnostics

namespace std {
typedef decltype(sizeof(int)) size_t;

// libc++'s implementation
template <class _E>
class initializer_list
{
const _E* __begin_;
size_t __size_;

initializer_list(const _E* __b, size_t __s)
: __begin_(__b),
__size_(__s)
{}

public:
typedef _E value_type;
typedef const _E& reference;
typedef const _E& const_reference;
typedef size_t size_type;

typedef const _E* iterator;
typedef const _E* const_iterator;

constexpr initializer_list() : __begin_(nullptr), __size_(0) {}

constexpr size_t size() const {return __size_;}
const _E* begin() const {return __begin_;}
const _E* end() const {return __begin_ + __size_;}
};

template<typename T>
struct vector {
size_t sz;
constexpr vector() : sz(0) {}
constexpr vector(initializer_list<T> ilist) : sz(ilist.size()) {}
constexpr vector(const vector& other) : sz(other.sz) {}
constexpr std::size_t size() const { return sz; }
};
}

// https://github.com/llvm/llvm-project/pull/77768#issuecomment-1908062472
namespace Issue1 {
struct A {
constexpr A() {}
};

struct B {
int called_ctor;
constexpr explicit B(A) : called_ctor(0) {}
constexpr explicit B(std::vector<A>) : called_ctor(1) {}
};

struct C {
B b;
constexpr C() : b({A()}) {}
};

static_assert(C().b.called_ctor == 0);
}

// https://github.com/llvm/llvm-project/pull/77768#issuecomment-1957171805
namespace Issue2 {
struct A {
constexpr A(int x_) {}
constexpr A(const std::vector<A>& a) {}
};

void f() {
constexpr std::vector<A> a{1,2};
constexpr std::vector<A> b{a};
// -> constexpr std::vector<A> b(std::initializer_list<A>{ A(a) });
static_assert(b.size() == 1);
}
}
3 changes: 2 additions & 1 deletion clang/tools/clang-linker-wrapper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ add_clang_tool(clang-linker-wrapper

DEPENDS
${tablegen_deps}
EXPORT_SYMBOLS_FOR_PLUGINS
)

set(CLANG_LINKER_WRAPPER_LIB_DEPS
Expand All @@ -42,3 +41,5 @@ target_link_libraries(clang-linker-wrapper
PRIVATE
${CLANG_LINKER_WRAPPER_LIB_DEPS}
)

export_executable_symbols_for_plugins(clang-linker-wrapper)
4 changes: 2 additions & 2 deletions clang/tools/clang-repl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ set( LLVM_LINK_COMPONENTS

add_clang_tool(clang-repl
ClangRepl.cpp

EXPORT_SYMBOLS_FOR_PLUGINS
)

if(MSVC)
Expand Down Expand Up @@ -63,6 +61,8 @@ clang_target_link_libraries(clang-repl PRIVATE
clangInterpreter
)

export_executable_symbols_for_plugins(clang-repl)

# The clang-repl binary can get huge with static linking in debug mode.
# Some 32-bit targets use PLT slots with limited branch range by default and we
# start to exceed this limit, e.g. when linking for arm-linux-gnueabihf with
Expand Down
7 changes: 5 additions & 2 deletions clang/tools/driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ set( LLVM_LINK_COMPONENTS
# Support plugins.
if(CLANG_PLUGIN_SUPPORT)
set(support_plugins SUPPORT_PLUGINS)
set(export_symbols EXPORT_SYMBOLS_FOR_PLUGINS)
endif()

add_clang_tool(clang
Expand All @@ -36,7 +35,6 @@ add_clang_tool(clang
ARMTargetParserTableGen
AArch64TargetParserTableGen
${support_plugins}
${export_symbols}
GENERATE_DRIVER
)

Expand All @@ -56,6 +54,11 @@ else()
set_target_properties(clang PROPERTIES VERSION ${CLANG_EXECUTABLE_VERSION})
endif()

# Support plugins.
if(CLANG_PLUGIN_SUPPORT)
export_executable_symbols_for_plugins(clang)
endif()

add_dependencies(clang clang-resource-headers)

if(NOT CLANG_LINKS_TO_CREATE)
Expand Down
2 changes: 1 addition & 1 deletion clang/www/cxx_dr_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -12637,7 +12637,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2137.html">2137</a></td>
<td>CD4</td>
<td>List-initialization from object of same type</td>
<td class="unknown" align="center">Unknown</td>
<td class="unreleased" align="center">Clang 20</td>
</tr>
<tr id="2138">
<td><a href="https://cplusplus.github.io/CWG/issues/2138.html">2138</a></td>
Expand Down
2 changes: 1 addition & 1 deletion flang/runtime/edit-input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static RT_API_ATTRS bool EditBOZInput(
std::memset(n, 0, bytes);
int increment{isHostLittleEndian ? -1 : 1};
auto *data{reinterpret_cast<unsigned char *>(n) +
(isHostLittleEndian ? significantBytes - 1 : 0)};
(isHostLittleEndian ? significantBytes - 1 : bytes - significantBytes)};
int shift{((digits - 1) * LOG2_BASE) & 7};
while (digits > 0) {
char32_t ch{*io.NextInField(remaining, edit)};
Expand Down
16 changes: 7 additions & 9 deletions flang/tools/flang-driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,9 @@ set( LLVM_LINK_COMPONENTS
TargetParser
)

option(FLANG_PLUGIN_SUPPORT "Build Flang with plugin support." ON)

# Enable support for plugins, which need access to symbols from flang-new
if(FLANG_PLUGIN_SUPPORT)
set(export_symbols EXPORT_SYMBOLS_FOR_PLUGINS)
endif()

add_flang_tool(flang-new
driver.cpp
fc1_main.cpp

${export_symbols}
)

target_link_libraries(flang-new
Expand All @@ -37,4 +28,11 @@ clang_target_link_libraries(flang-new
clangBasic
)

option(FLANG_PLUGIN_SUPPORT "Build Flang with plugin support." ON)

# Enable support for plugins, which need access to symbols from flang-new
if(FLANG_PLUGIN_SUPPORT)
export_executable_symbols_for_plugins(flang-new)
endif()

install(TARGETS flang-new DESTINATION "${CMAKE_INSTALL_BINDIR}")
2 changes: 1 addition & 1 deletion lld/cmake/modules/AddLLD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ macro(add_lld_tool name)
AND (NOT LLVM_DISTRIBUTION_COMPONENTS OR ${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS)
)
set(get_obj_args ${ARGN})
list(FILTER get_obj_args EXCLUDE REGEX "^(SUPPORT_PLUGINS|EXPORT_SYMBOLS_FOR_PLUGINS)$")
list(FILTER get_obj_args EXCLUDE REGEX "^SUPPORT_PLUGINS$")
generate_llvm_objects(${name} ${get_obj_args})
add_custom_target(${name} DEPENDS llvm-driver)
else()
Expand Down
2 changes: 1 addition & 1 deletion lld/tools/lld/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ add_lld_tool(lld

SUPPORT_PLUGINS
GENERATE_DRIVER
EXPORT_SYMBOLS_FOR_PLUGINS
)
export_executable_symbols_for_plugins(lld)

function(lld_target_link_libraries target type)
if (TARGET obj.${target})
Expand Down
12 changes: 5 additions & 7 deletions llvm/cmake/modules/AddLLVM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@ endmacro()

macro(add_llvm_executable name)
cmake_parse_arguments(ARG
"DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH;SUPPORT_PLUGINS;EXPORT_SYMBOLS;EXPORT_SYMBOLS_FOR_PLUGINS"
"DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH;SUPPORT_PLUGINS;EXPORT_SYMBOLS"
"ENTITLEMENTS;BUNDLE_PATH"
""
${ARGN})
Expand Down Expand Up @@ -1081,12 +1081,6 @@ macro(add_llvm_executable name)
endif()
endif()

if (ARG_EXPORT_SYMBOLS)
export_executable_symbols(${name})
elseif(ARG_EXPORT_SYMBOLS_FOR_PLUGINS)
export_executable_symbols_for_plugins(${name})
endif()

if (LLVM_LINK_LLVM_DYLIB AND NOT ARG_DISABLE_LLVM_LINK_LLVM_DYLIB)
set(USE_SHARED USE_SHARED)
endif()
Expand Down Expand Up @@ -1118,6 +1112,10 @@ macro(add_llvm_executable name)
endif()

llvm_codesign(${name} ENTITLEMENTS ${ARG_ENTITLEMENTS} BUNDLE_PATH ${ARG_BUNDLE_PATH})

if (ARG_EXPORT_SYMBOLS)
export_executable_symbols(${name})
endif()
endmacro(add_llvm_executable name)

# add_llvm_pass_plugin(name [NO_MODULE] ...)
Expand Down
4 changes: 4 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2309,6 +2309,10 @@ example:
This attribute indicates that MemTagSanitizer checks
(dynamic address safety analysis based on Armv8 MTE) are enabled for
this function.
``sanitize_realtime``
This attribute indicates that RealtimeSanitizer checks
(realtime safety analysis - no allocations, syscalls or exceptions) are enabled
for this function.
``speculative_load_hardening``
This attribute indicates that
`Speculative Load Hardening <https://llvm.org/docs/SpeculativeLoadHardening.html>`_
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/ADT/GraphTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ struct GraphTraits {

namespace detail {
template <typename T>
using has_number_t = decltype(GraphTraits<T>::getNumber(std::declval<T>()));
using has_number_t = decltype(GraphTraits<T>::getNumber(
std::declval<typename GraphTraits<T>::NodeRef>()));
} // namespace detail

/// Indicate whether a GraphTraits<NodeT>::getNumber() is supported.
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Bitcode/LLVMBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ enum AttributeKindCodes {
ATTR_KIND_SANITIZE_NUMERICAL_STABILITY = 93,
ATTR_KIND_INITIALIZES = 94,
ATTR_KIND_HYBRID_PATCHABLE = 95,
ATTR_KIND_SANITIZE_REALTIME = 96,
};

enum ComdatSelectionKindCodes {
Expand Down
38 changes: 25 additions & 13 deletions llvm/include/llvm/CodeGen/BasicTTIImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2135,21 +2135,17 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return Cost;
}
case Intrinsic::smax:
ISD = ISD::SMAX;
break;
case Intrinsic::smin:
ISD = ISD::SMIN;
break;
case Intrinsic::umax:
case Intrinsic::umin: {
// minmax(X,Y) = select(icmp(X,Y),X,Y)
Type *CondTy = RetTy->getWithNewBitWidth(1);
bool IsUnsigned = IID == Intrinsic::umax || IID == Intrinsic::umin;
CmpInst::Predicate Pred =
IsUnsigned ? CmpInst::ICMP_UGT : CmpInst::ICMP_SGT;
InstructionCost Cost = 0;
Cost += thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy,
Pred, CostKind);
Cost += thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy,
Pred, CostKind);
return Cost;
}
ISD = ISD::UMAX;
break;
case Intrinsic::umin:
ISD = ISD::UMIN;
break;
case Intrinsic::sadd_sat:
ISD = ISD::SADDSAT;
break;
Expand Down Expand Up @@ -2345,6 +2341,22 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
return thisT()->getIntrinsicInstrCost(FMulAttrs, CostKind) +
thisT()->getIntrinsicInstrCost(FAddAttrs, CostKind);
}
case Intrinsic::smin:
case Intrinsic::smax:
case Intrinsic::umin:
case Intrinsic::umax: {
// minmax(X,Y) = select(icmp(X,Y),X,Y)
Type *CondTy = RetTy->getWithNewBitWidth(1);
bool IsUnsigned = IID == Intrinsic::umax || IID == Intrinsic::umin;
CmpInst::Predicate Pred =
IsUnsigned ? CmpInst::ICMP_UGT : CmpInst::ICMP_SGT;
InstructionCost Cost = 0;
Cost += thisT()->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, CondTy,
Pred, CostKind);
Cost += thisT()->getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy,
Pred, CostKind);
return Cost;
}
case Intrinsic::sadd_sat:
case Intrinsic::ssub_sat: {
// Assume a default expansion.
Expand Down
12 changes: 12 additions & 0 deletions llvm/include/llvm/CodeGen/MachineBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,9 @@ template <> struct GraphTraits<MachineBasicBlock *> {
}
};

static_assert(GraphHasNodeNumbers<MachineBasicBlock *>,
"GraphTraits getNumber() not detected");

template <> struct GraphTraits<const MachineBasicBlock *> {
using NodeRef = const MachineBasicBlock *;
using ChildIteratorType = MachineBasicBlock::const_succ_iterator;
Expand All @@ -1318,6 +1321,9 @@ template <> struct GraphTraits<const MachineBasicBlock *> {
}
};

static_assert(GraphHasNodeNumbers<const MachineBasicBlock *>,
"GraphTraits getNumber() not detected");

// Provide specializations of GraphTraits to be able to treat a
// MachineFunction as a graph of MachineBasicBlocks and to walk it
// in inverse order. Inverse order for a function is considered
Expand All @@ -1341,6 +1347,9 @@ template <> struct GraphTraits<Inverse<MachineBasicBlock*>> {
}
};

static_assert(GraphHasNodeNumbers<Inverse<MachineBasicBlock *>>,
"GraphTraits getNumber() not detected");

template <> struct GraphTraits<Inverse<const MachineBasicBlock*>> {
using NodeRef = const MachineBasicBlock *;
using ChildIteratorType = MachineBasicBlock::const_pred_iterator;
Expand All @@ -1358,6 +1367,9 @@ template <> struct GraphTraits<Inverse<const MachineBasicBlock*>> {
}
};

static_assert(GraphHasNodeNumbers<Inverse<const MachineBasicBlock *>>,
"GraphTraits getNumber() not detected");

// These accessors are handy for sharing templated code between IR and MIR.
inline auto successors(const MachineBasicBlock *BB) { return BB->successors(); }
inline auto predecessors(const MachineBasicBlock *BB) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/FuzzMutate/OpDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class SourcePred {
struct OpDescriptor {
unsigned Weight;
SmallVector<SourcePred, 2> SourcePreds;
std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
std::function<Value *(ArrayRef<Value *>, BasicBlock::iterator)> BuilderFunc;
};

static inline SourcePred onlyType(Type *Only) {
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/Attributes.td
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ def SanitizeMemTag : EnumAttr<"sanitize_memtag", [FnAttr]>;
/// NumericalStabilitySanitizer is on.
def SanitizeNumericalStability : EnumAttr<"sanitize_numerical_stability", [FnAttr]>;

/// RealtimeSanitizer is on.
def SanitizeRealtime : EnumAttr<"sanitize_realtime", [FnAttr]>;

/// Speculative Load Hardening is enabled.
///
/// Note that this uses the default compatibility (always compatible during
Expand Down Expand Up @@ -385,6 +388,7 @@ def : CompatRule<"isEqual<SanitizeMemoryAttr>">;
def : CompatRule<"isEqual<SanitizeHWAddressAttr>">;
def : CompatRule<"isEqual<SanitizeMemTagAttr>">;
def : CompatRule<"isEqual<SanitizeNumericalStabilityAttr>">;
def : CompatRule<"isEqual<SanitizeRealtimeAttr>">;
def : CompatRule<"isEqual<SafeStackAttr>">;
def : CompatRule<"isEqual<ShadowCallStackAttr>">;
def : CompatRule<"isEqual<UseSampleProfileAttr>">;
Expand Down
29 changes: 15 additions & 14 deletions llvm/include/llvm/Support/GenericDomTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,10 @@ class DominatorTreeBase {
SmallVector<std::unique_ptr<DomTreeNodeBase<NodeT>>>;
DomTreeNodeStorageTy DomTreeNodes;
// For graphs where blocks don't have numbers, create a numbering here.
DenseMap<const NodeT *, unsigned> NodeNumberMap;
// TODO: use an empty struct with [[no_unique_address]] in C++20.
std::conditional_t<!GraphHasNodeNumbers<NodeT *>,
DenseMap<const NodeT *, unsigned>, std::tuple<>>
NodeNumberMap;
DomTreeNodeBase<NodeT> *RootNode = nullptr;
ParentPtr Parent = nullptr;

Expand Down Expand Up @@ -355,12 +358,8 @@ class DominatorTreeBase {
}

private:
template <typename T>
using has_number_t =
decltype(GraphTraits<T *>::getNumber(std::declval<T *>()));

std::optional<unsigned> getNodeIndex(const NodeT *BB) const {
if constexpr (is_detected<has_number_t, NodeT>::value) {
if constexpr (GraphHasNodeNumbers<NodeT *>) {
// BB can be nullptr, map nullptr to index 0.
assert(BlockNumberEpoch ==
GraphTraits<ParentPtr>::getNumberEpoch(Parent) &&
Expand All @@ -374,7 +373,7 @@ class DominatorTreeBase {
}

unsigned getNodeIndexForInsert(const NodeT *BB) {
if constexpr (is_detected<has_number_t, NodeT>::value) {
if constexpr (GraphHasNodeNumbers<NodeT *>) {
// getNodeIndex will never fail if nodes have getNumber().
unsigned Idx = *getNodeIndex(BB);
if (Idx >= DomTreeNodes.size()) {
Expand Down Expand Up @@ -736,7 +735,8 @@ class DominatorTreeBase {
}

DomTreeNodes[*IdxOpt] = nullptr;
NodeNumberMap.erase(BB);
if constexpr (!GraphHasNodeNumbers<NodeT *>)
NodeNumberMap.erase(BB);

if (!IsPostDom) return;

Expand Down Expand Up @@ -830,7 +830,7 @@ class DominatorTreeBase {
private:
void updateBlockNumberEpoch() {
// Nothing to do for graphs that don't number their blocks.
if constexpr (is_detected<has_number_t, NodeT>::value)
if constexpr (GraphHasNodeNumbers<NodeT *>)
BlockNumberEpoch = GraphTraits<ParentPtr>::getNumberEpoch(Parent);
}

Expand All @@ -849,9 +849,8 @@ class DominatorTreeBase {
}

/// Update dominator tree after renumbering blocks.
template <class T_ = NodeT>
std::enable_if_t<is_detected<has_number_t, T_>::value, void>
updateBlockNumbers() {
template <typename T = NodeT>
std::enable_if_t<GraphHasNodeNumbers<T *>, void> updateBlockNumbers() {
updateBlockNumberEpoch();

unsigned MaxNumber = GraphTraits<ParentPtr>::getMaxNumber(Parent);
Expand Down Expand Up @@ -889,7 +888,8 @@ class DominatorTreeBase {

void reset() {
DomTreeNodes.clear();
NodeNumberMap.clear();
if constexpr (!GraphHasNodeNumbers<NodeT *>)
NodeNumberMap.clear();
Roots.clear();
RootNode = nullptr;
Parent = nullptr;
Expand Down Expand Up @@ -989,7 +989,8 @@ class DominatorTreeBase {
/// assignable and destroyable state, but otherwise invalid.
void wipe() {
DomTreeNodes.clear();
NodeNumberMap.clear();
if constexpr (!GraphHasNodeNumbers<NodeT *>)
NodeNumberMap.clear();
RootNode = nullptr;
Parent = nullptr;
}
Expand Down
19 changes: 12 additions & 7 deletions llvm/lib/Analysis/MustExecute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,21 @@ static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock,
// todo: this would be a lot more powerful if we used scev, but all the
// plumbing is currently missing to pass a pointer in from the pass
// Check for cmp (phi [x, preheader] ...), y where (pred x, y is known
ICmpInst::Predicate Pred = Cond->getPredicate();
auto *LHS = dyn_cast<PHINode>(Cond->getOperand(0));
auto *RHS = Cond->getOperand(1);
if (!LHS || LHS->getParent() != CurLoop->getHeader())
return false;
auto DL = ExitBlock->getDataLayout();
if (!LHS || LHS->getParent() != CurLoop->getHeader()) {
Pred = Cond->getSwappedPredicate();
LHS = dyn_cast<PHINode>(Cond->getOperand(1));
RHS = Cond->getOperand(0);
if (!LHS || LHS->getParent() != CurLoop->getHeader())
return false;
}

auto DL = ExitBlock->getModule()->getDataLayout();
auto *IVStart = LHS->getIncomingValueForBlock(CurLoop->getLoopPreheader());
auto *SimpleValOrNull = simplifyCmpInst(Cond->getPredicate(),
IVStart, RHS,
{DL, /*TLI*/ nullptr,
DT, /*AC*/ nullptr, BI});
auto *SimpleValOrNull = simplifyCmpInst(
Pred, IVStart, RHS, {DL, /*TLI*/ nullptr, DT, /*AC*/ nullptr, BI});
auto *SimpleCst = dyn_cast_or_null<Constant>(SimpleValOrNull);
if (!SimpleCst)
return false;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2141,6 +2141,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::SanitizeMemory;
case bitc::ATTR_KIND_SANITIZE_NUMERICAL_STABILITY:
return Attribute::SanitizeNumericalStability;
case bitc::ATTR_KIND_SANITIZE_REALTIME:
return Attribute::SanitizeRealtime;
case bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING:
return Attribute::SpeculativeLoadHardening;
case bitc::ATTR_KIND_SWIFT_ERROR:
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
return bitc::ATTR_KIND_SANITIZE_MEMORY;
case Attribute::SanitizeNumericalStability:
return bitc::ATTR_KIND_SANITIZE_NUMERICAL_STABILITY;
case Attribute::SanitizeRealtime:
return bitc::ATTR_KIND_SANITIZE_REALTIME;
case Attribute::SpeculativeLoadHardening:
return bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING;
case Attribute::SwiftError:
Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/FuzzMutate/IRMutator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ void InjectorIRStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
for (const auto &Pred : ArrayRef(OpDesc->SourcePreds).slice(1))
Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));

if (Value *Op = OpDesc->BuilderFunc(Srcs, Insts[IP])) {
if (Value *Op = OpDesc->BuilderFunc(Srcs, Insts[IP]->getIterator())) {
// Find a sink and wire up the results of the operation.
IB.connectToSink(BB, InstsAfter, Op);
}
Expand Down Expand Up @@ -388,9 +388,9 @@ void InsertFunctionStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
}
bool isRetVoid = (F->getReturnType() == Type::getVoidTy(M->getContext()));
auto BuilderFunc = [FTy, F, isRetVoid](ArrayRef<Value *> Srcs,
Instruction *Inst) {
BasicBlock::iterator InsertPt) {
StringRef Name = isRetVoid ? nullptr : "C";
CallInst *Call = CallInst::Create(FTy, F, Srcs, Name, Inst);
CallInst *Call = CallInst::Create(FTy, F, Srcs, Name, InsertPt);
// Don't return this call inst if it return void as it can't be sinked.
return isRetVoid ? nullptr : Call;
};
Expand All @@ -414,7 +414,7 @@ void InsertFunctionStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));
}

if (Value *Op = BuilderFunc(Srcs, Insts[IP])) {
if (Value *Op = BuilderFunc(Srcs, Insts[IP]->getIterator())) {
// Find a sink and wire up the results of the operation.
IB.connectToSink(BB, InstsAfter, Op);
}
Expand Down Expand Up @@ -543,7 +543,7 @@ void InsertPHIStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
if (&BB == &BB.getParent()->getEntryBlock())
return;
Type *Ty = IB.randomType();
PHINode *PHI = PHINode::Create(Ty, llvm::pred_size(&BB), "", &BB.front());
PHINode *PHI = PHINode::Create(Ty, llvm::pred_size(&BB), "", BB.begin());

// Use a map to make sure the same incoming basic block has the same value.
DenseMap<BasicBlock *, Value *> IncomingValues;
Expand Down
54 changes: 30 additions & 24 deletions llvm/lib/FuzzMutate/Operations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,25 @@ void llvm::describeFuzzerVectorOps(std::vector<fuzzerop::OpDescriptor> &Ops) {
}

OpDescriptor llvm::fuzzerop::selectDescriptor(unsigned Weight) {
auto buildOp = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
return SelectInst::Create(Srcs[0], Srcs[1], Srcs[2], "S", Inst);
auto buildOp = [](ArrayRef<Value *> Srcs, BasicBlock::iterator InsertPt) {
return SelectInst::Create(Srcs[0], Srcs[1], Srcs[2], "S", InsertPt);
};
return {Weight,
{boolOrVecBoolType(), matchFirstLengthWAnyType(), matchSecondType()},
buildOp};
}

OpDescriptor llvm::fuzzerop::fnegDescriptor(unsigned Weight) {
auto buildOp = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
return UnaryOperator::Create(Instruction::FNeg, Srcs[0], "F", Inst);
auto buildOp = [](ArrayRef<Value *> Srcs, BasicBlock::iterator InsertPt) {
return UnaryOperator::Create(Instruction::FNeg, Srcs[0], "F", InsertPt);
};
return {Weight, {anyFloatOrVecFloatType()}, buildOp};
}

OpDescriptor llvm::fuzzerop::binOpDescriptor(unsigned Weight,
Instruction::BinaryOps Op) {
auto buildOp = [Op](ArrayRef<Value *> Srcs, Instruction *Inst) {
return BinaryOperator::Create(Op, Srcs[0], Srcs[1], "B", Inst);
auto buildOp = [Op](ArrayRef<Value *> Srcs, BasicBlock::iterator InsertPt) {
return BinaryOperator::Create(Op, Srcs[0], Srcs[1], "B", InsertPt);
};
switch (Op) {
case Instruction::Add:
Expand Down Expand Up @@ -148,8 +148,9 @@ OpDescriptor llvm::fuzzerop::binOpDescriptor(unsigned Weight,
OpDescriptor llvm::fuzzerop::cmpOpDescriptor(unsigned Weight,
Instruction::OtherOps CmpOp,
CmpInst::Predicate Pred) {
auto buildOp = [CmpOp, Pred](ArrayRef<Value *> Srcs, Instruction *Inst) {
return CmpInst::Create(CmpOp, Pred, Srcs[0], Srcs[1], "C", Inst);
auto buildOp = [CmpOp, Pred](ArrayRef<Value *> Srcs,
BasicBlock::iterator InsertPt) {
return CmpInst::Create(CmpOp, Pred, Srcs[0], Srcs[1], "C", InsertPt);
};

switch (CmpOp) {
Expand All @@ -163,9 +164,10 @@ OpDescriptor llvm::fuzzerop::cmpOpDescriptor(unsigned Weight,
}

OpDescriptor llvm::fuzzerop::splitBlockDescriptor(unsigned Weight) {
auto buildSplitBlock = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
BasicBlock *Block = Inst->getParent();
BasicBlock *Next = Block->splitBasicBlock(Inst, "BB");
auto buildSplitBlock = [](ArrayRef<Value *> Srcs,
BasicBlock::iterator InsertPt) {
BasicBlock *Block = InsertPt->getParent();
BasicBlock *Next = Block->splitBasicBlock(InsertPt, "BB");

// If it was an exception handling block, we are done.
if (Block->isEHPad())
Expand All @@ -174,7 +176,8 @@ OpDescriptor llvm::fuzzerop::splitBlockDescriptor(unsigned Weight) {
// Loop back on this block by replacing the unconditional forward branch
// with a conditional with a backedge.
if (Block != &Block->getParent()->getEntryBlock()) {
BranchInst::Create(Block, Next, Srcs[0], Block->getTerminator());
BranchInst::Create(Block, Next, Srcs[0],
Block->getTerminator()->getIterator());
Block->getTerminator()->eraseFromParent();

// We need values for each phi in the block. Since there isn't a good way
Expand All @@ -193,12 +196,12 @@ OpDescriptor llvm::fuzzerop::splitBlockDescriptor(unsigned Weight) {
}

OpDescriptor llvm::fuzzerop::gepDescriptor(unsigned Weight) {
auto buildGEP = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
auto buildGEP = [](ArrayRef<Value *> Srcs, BasicBlock::iterator InsertPt) {
// TODO: It would be better to generate a random type here, rather than
// generating a random value and picking its type.
Type *Ty = Srcs[1]->getType();
auto Indices = ArrayRef(Srcs).drop_front(2);
return GetElementPtrInst::Create(Ty, Srcs[0], Indices, "G", Inst);
return GetElementPtrInst::Create(Ty, Srcs[0], Indices, "G", InsertPt);
};
// TODO: Handle aggregates and vectors
// TODO: Support multiple indices.
Expand Down Expand Up @@ -239,10 +242,11 @@ static SourcePred validExtractValueIndex() {
}

OpDescriptor llvm::fuzzerop::extractValueDescriptor(unsigned Weight) {
auto buildExtract = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
auto buildExtract = [](ArrayRef<Value *> Srcs,
BasicBlock::iterator InsertPt) {
// TODO: It's pretty inefficient to shuffle this all through constants.
unsigned Idx = cast<ConstantInt>(Srcs[1])->getZExtValue();
return ExtractValueInst::Create(Srcs[0], {Idx}, "E", Inst);
return ExtractValueInst::Create(Srcs[0], {Idx}, "E", InsertPt);
};
// TODO: Should we handle multiple indices?
return {Weight, {anyAggregateType(), validExtractValueIndex()}, buildExtract};
Expand Down Expand Up @@ -298,10 +302,10 @@ static SourcePred validInsertValueIndex() {
}

OpDescriptor llvm::fuzzerop::insertValueDescriptor(unsigned Weight) {
auto buildInsert = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
auto buildInsert = [](ArrayRef<Value *> Srcs, BasicBlock::iterator InsertPt) {
// TODO: It's pretty inefficient to shuffle this all through constants.
unsigned Idx = cast<ConstantInt>(Srcs[2])->getZExtValue();
return InsertValueInst::Create(Srcs[0], Srcs[1], {Idx}, "I", Inst);
return InsertValueInst::Create(Srcs[0], Srcs[1], {Idx}, "I", InsertPt);
};
return {
Weight,
Expand All @@ -310,16 +314,17 @@ OpDescriptor llvm::fuzzerop::insertValueDescriptor(unsigned Weight) {
}

OpDescriptor llvm::fuzzerop::extractElementDescriptor(unsigned Weight) {
auto buildExtract = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
return ExtractElementInst::Create(Srcs[0], Srcs[1], "E", Inst);
auto buildExtract = [](ArrayRef<Value *> Srcs,
BasicBlock::iterator InsertPt) {
return ExtractElementInst::Create(Srcs[0], Srcs[1], "E", InsertPt);
};
// TODO: Try to avoid undefined accesses.
return {Weight, {anyVectorType(), anyIntType()}, buildExtract};
}

OpDescriptor llvm::fuzzerop::insertElementDescriptor(unsigned Weight) {
auto buildInsert = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
return InsertElementInst::Create(Srcs[0], Srcs[1], Srcs[2], "I", Inst);
auto buildInsert = [](ArrayRef<Value *> Srcs, BasicBlock::iterator InsertPt) {
return InsertElementInst::Create(Srcs[0], Srcs[1], Srcs[2], "I", InsertPt);
};
// TODO: Try to avoid undefined accesses.
return {Weight,
Expand All @@ -343,8 +348,9 @@ static SourcePred validShuffleVectorIndex() {
}

OpDescriptor llvm::fuzzerop::shuffleVectorDescriptor(unsigned Weight) {
auto buildShuffle = [](ArrayRef<Value *> Srcs, Instruction *Inst) {
return new ShuffleVectorInst(Srcs[0], Srcs[1], Srcs[2], "S", Inst);
auto buildShuffle = [](ArrayRef<Value *> Srcs,
BasicBlock::iterator InsertPt) {
return new ShuffleVectorInst(Srcs[0], Srcs[1], Srcs[2], "S", InsertPt);
};
return {Weight,
{anyVectorType(), matchFirstType(), validShuffleVectorIndex()},
Expand Down
17 changes: 9 additions & 8 deletions llvm/lib/FuzzMutate/RandomIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ AllocaInst *RandomIRBuilder::createStackMemory(Function *F, Type *Ty,
BasicBlock *EntryBB = &F->getEntryBlock();
DataLayout DL(F->getParent());
AllocaInst *Alloca = new AllocaInst(Ty, DL.getAllocaAddrSpace(), "A",
&*EntryBB->getFirstInsertionPt());
EntryBB->getFirstInsertionPt());
if (Init)
new StoreInst(Init, Alloca, Alloca->getNextNode());
new StoreInst(Init, Alloca, std::next(Alloca->getIterator()));
return Alloca;
}

Expand Down Expand Up @@ -165,7 +165,7 @@ Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
Type *Ty = GV->getValueType();
LoadInst *LoadGV = nullptr;
if (BB.getTerminator()) {
LoadGV = new LoadInst(Ty, GV, "LGV", &*BB.getFirstInsertionPt());
LoadGV = new LoadInst(Ty, GV, "LGV", BB.getFirstInsertionPt());
} else {
LoadGV = new LoadInst(Ty, GV, "LGV", &BB);
}
Expand Down Expand Up @@ -213,7 +213,7 @@ Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts,
}
// Pick the type independently.
Type *AccessTy = RS.getSelection()->getType();
auto *NewLoad = new LoadInst(AccessTy, Ptr, "L", &*IP);
auto *NewLoad = new LoadInst(AccessTy, Ptr, "L", IP);

// Only sample this load if it really matches the descriptor
if (Pred.matches(Srcs, NewLoad))
Expand All @@ -231,7 +231,8 @@ Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts,
Function *F = BB.getParent();
AllocaInst *Alloca = createStackMemory(F, Ty, newSrc);
if (BB.getTerminator()) {
newSrc = new LoadInst(Ty, Alloca, /*ArrLen,*/ "L", BB.getTerminator());
newSrc = new LoadInst(Ty, Alloca, /*ArrLen,*/ "L",
BB.getTerminator()->getIterator());
} else {
newSrc = new LoadInst(Ty, Alloca, /*ArrLen,*/ "L", &BB);
}
Expand Down Expand Up @@ -325,7 +326,7 @@ Instruction *RandomIRBuilder::connectToSink(BasicBlock &BB,
for (BasicBlock *Dom : Dominators) {
for (Instruction &I : *Dom) {
if (isa<PointerType>(I.getType()))
return new StoreInst(V, &I, Insts.back());
return new StoreInst(V, &I, Insts.back()->getIterator());
}
}
break;
Expand All @@ -351,7 +352,7 @@ Instruction *RandomIRBuilder::connectToSink(BasicBlock &BB,
Module *M = BB.getParent()->getParent();
auto [GV, DidCreate] =
findOrCreateGlobalVariable(M, {}, fuzzerop::onlyType(V->getType()));
return new StoreInst(V, GV, Insts.back());
return new StoreInst(V, GV, Insts.back()->getIterator());
}
case EndOfValueSink:
default:
Expand All @@ -373,7 +374,7 @@ Instruction *RandomIRBuilder::newSink(BasicBlock &BB,
}
}

return new StoreInst(V, Ptr, Insts.back());
return new StoreInst(V, Ptr, Insts.back()->getIterator());
}

Value *RandomIRBuilder::findPointer(BasicBlock &BB,
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/IR/Instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2484,8 +2484,9 @@ void ExtractValueInst::init(ArrayRef<unsigned> Idxs, const Twine &Name) {
}

ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
: UnaryInstruction(EVI.getType(), ExtractValue, EVI.getOperand(0)),
Indices(EVI.Indices) {
: UnaryInstruction(EVI.getType(), ExtractValue, EVI.getOperand(0),
(BasicBlock *)nullptr),
Indices(EVI.Indices) {
SubclassOptionalData = EVI.SubclassOptionalData;
}

Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/IR/Metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,12 @@ void ReplaceableMetadataImpl::SalvageDebugInfo(const Constant &C) {
MetadataTracking::OwnerTy Owner = Pair.second.first;
if (!Owner)
continue;
// Check for MetadataAsValue.
if (isa<MetadataAsValue *>(Owner)) {
cast<MetadataAsValue *>(Owner)->handleChangedMetadata(
ValueAsMetadata::get(UndefValue::get(C.getType())));
continue;
}
if (!isa<Metadata *>(Owner))
continue;
auto *OwnerMD = dyn_cast_if_present<MDNode>(cast<Metadata *>(Owner));
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Support/regcomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ static char nuls[10]; /* place to point scanner in event of error */
#else
#define DUPMAX 255
#endif
#define INFINITY (DUPMAX + 1)
#define REGINFINITY (DUPMAX + 1)

#ifndef NDEBUG
static int never = 0; /* for use in asserts; shuts lint up */
Expand Down Expand Up @@ -582,7 +582,7 @@ p_ere_exp(struct parse *p)
count2 = p_count(p);
REQUIRE(count <= count2, REG_BADBR);
} else /* single number with comma */
count2 = INFINITY;
count2 = REGINFINITY;
} else /* just a single number */
count2 = count;
repeat(p, pos, count, count2);
Expand Down Expand Up @@ -753,7 +753,7 @@ p_simp_re(struct parse *p,
count2 = p_count(p);
REQUIRE(count <= count2, REG_BADBR);
} else /* single number with comma */
count2 = INFINITY;
count2 = REGINFINITY;
} else /* just a single number */
count2 = count;
repeat(p, pos, count, count2);
Expand Down Expand Up @@ -1115,7 +1115,7 @@ repeat(struct parse *p,
# define N 2
# define INF 3
# define REP(f, t) ((f)*8 + (t))
# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
# define MAP(n) (((n) <= 1) ? (n) : ((n) == REGINFINITY) ? INF : N)
sopno copy;

if (p->error != 0) /* head off possible runaway recursion */
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "AMDKernelCodeT.h"
#include "MCTargetDesc/AMDGPUInstPrinter.h"
#include "MCTargetDesc/AMDGPUMCExpr.h"
#include "MCTargetDesc/AMDGPUMCKernelDescriptor.h"
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
Expand Down Expand Up @@ -1133,7 +1134,8 @@ class AMDGPUOperand : public MCParsedAsmOperand {
void print(raw_ostream &OS) const override {
switch (Kind) {
case Register:
OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
OS << "<register " << AMDGPUInstPrinter::getRegisterName(getReg())
<< " mods: " << Reg.Mods << '>';
break;
case Immediate:
OS << '<' << getImm();
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/LoongArch/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ add_llvm_target(LoongArchCodeGen
LoongArchISelDAGToDAG.cpp
LoongArchISelLowering.cpp
LoongArchMCInstLower.cpp
LoongArchMergeBaseOffset.cpp
LoongArchOptWInstrs.cpp
LoongArchRegisterInfo.cpp
LoongArchSubtarget.cpp
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArch.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
FunctionPass *createLoongArchDeadRegisterDefinitionsPass();
FunctionPass *createLoongArchExpandAtomicPseudoPass();
FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM);
FunctionPass *createLoongArchMergeBaseOffsetOptPass();
FunctionPass *createLoongArchOptWInstrsPass();
FunctionPass *createLoongArchPreRAExpandPseudoPass();
FunctionPass *createLoongArchExpandPseudoPass();
void initializeLoongArchDAGToDAGISelLegacyPass(PassRegistry &);
void initializeLoongArchDeadRegisterDefinitionsPass(PassRegistry &);
void initializeLoongArchExpandAtomicPseudoPass(PassRegistry &);
void initializeLoongArchMergeBaseOffsetOptPass(PassRegistry &);
void initializeLoongArchOptWInstrsPass(PassRegistry &);
void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &);
void initializeLoongArchExpandPseudoPass(PassRegistry &);
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,16 @@ bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
OS << "$" << LoongArchInstPrinter::getRegisterName(BaseMO.getReg());
// Print the offset operand.
const MachineOperand &OffsetMO = MI->getOperand(OpNo + 1);
MCOperand MCO;
if (!lowerOperand(OffsetMO, MCO))
return true;
if (OffsetMO.isReg())
OS << ", $" << LoongArchInstPrinter::getRegisterName(OffsetMO.getReg());
else if (OffsetMO.isImm())
OS << ", " << OffsetMO.getImm();
else if (OffsetMO.isGlobal() || OffsetMO.isBlockAddress() ||
OffsetMO.isMCSymbol())
OS << ", " << *MCO.getExpr();
else
return true;

Expand Down
Loading