93 changes: 46 additions & 47 deletions clang/lib/APINotes/APINotesReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,9 @@ class IdentifierTableInfo {
}
};

/// Used to deserialize the on-disk Objective-C class table.
class ObjCContextIDTableInfo {
/// Used to deserialize the on-disk table of Objective-C classes and C++
/// namespaces.
class ContextIDTableInfo {
public:
using internal_key_type = ContextTableKey;
using external_key_type = internal_key_type;
Expand Down Expand Up @@ -221,9 +222,8 @@ class ObjCContextIDTableInfo {
};

/// Used to deserialize the on-disk Objective-C property table.
class ObjCContextInfoTableInfo
: public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
ObjCContextInfo> {
class ContextInfoTableInfo
: public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
public:
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
return endian::readNext<uint32_t, llvm::endianness::little>(Data);
Expand All @@ -233,9 +233,9 @@ class ObjCContextInfoTableInfo
return static_cast<size_t>(llvm::hash_value(Key));
}

static ObjCContextInfo readUnversioned(internal_key_type Key,
const uint8_t *&Data) {
ObjCContextInfo Info;
static ContextInfo readUnversioned(internal_key_type Key,
const uint8_t *&Data) {
ContextInfo Info;
ReadCommonTypeInfo(Data, Info);
uint8_t Payload = *Data++;

Expand Down Expand Up @@ -614,17 +614,17 @@ class APINotesReader::Implementation {
/// The identifier table.
std::unique_ptr<SerializedIdentifierTable> IdentifierTable;

using SerializedObjCContextIDTable =
llvm::OnDiskIterableChainedHashTable<ObjCContextIDTableInfo>;
using SerializedContextIDTable =
llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;

/// The Objective-C context ID table.
std::unique_ptr<SerializedObjCContextIDTable> ObjCContextIDTable;
/// The Objective-C / C++ context ID table.
std::unique_ptr<SerializedContextIDTable> ContextIDTable;

using SerializedObjCContextInfoTable =
llvm::OnDiskIterableChainedHashTable<ObjCContextInfoTableInfo>;
using SerializedContextInfoTable =
llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;

/// The Objective-C context info table.
std::unique_ptr<SerializedObjCContextInfoTable> ObjCContextInfoTable;
std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;

using SerializedObjCPropertyTable =
llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
Expand Down Expand Up @@ -685,8 +685,8 @@ class APINotesReader::Implementation {
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readIdentifierBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readObjCContextBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readContextBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
llvm::SmallVectorImpl<uint64_t> &Scratch);
bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
Expand Down Expand Up @@ -906,7 +906,7 @@ bool APINotesReader::Implementation::readIdentifierBlock(
return false;
}

bool APINotesReader::Implementation::readObjCContextBlock(
bool APINotesReader::Implementation::readContextBlock(
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
return true;
Expand Down Expand Up @@ -950,31 +950,30 @@ bool APINotesReader::Implementation::readObjCContextBlock(
}
unsigned Kind = MaybeKind.get();
switch (Kind) {
case objc_context_block::OBJC_CONTEXT_ID_DATA: {
// Already saw Objective-C context ID table.
if (ObjCContextIDTable)
case context_block::CONTEXT_ID_DATA: {
// Already saw Objective-C / C++ context ID table.
if (ContextIDTable)
return true;

uint32_t tableOffset;
objc_context_block::ObjCContextIDLayout::readRecord(Scratch, tableOffset);
context_block::ContextIDLayout::readRecord(Scratch, tableOffset);
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

ObjCContextIDTable.reset(SerializedObjCContextIDTable::Create(
ContextIDTable.reset(SerializedContextIDTable::Create(
base + tableOffset, base + sizeof(uint32_t), base));
break;
}

case objc_context_block::OBJC_CONTEXT_INFO_DATA: {
// Already saw Objective-C context info table.
if (ObjCContextInfoTable)
case context_block::CONTEXT_INFO_DATA: {
// Already saw Objective-C / C++ context info table.
if (ContextInfoTable)
return true;

uint32_t tableOffset;
objc_context_block::ObjCContextInfoLayout::readRecord(Scratch,
tableOffset);
context_block::ContextInfoLayout::readRecord(Scratch, tableOffset);
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());

ObjCContextInfoTable.reset(SerializedObjCContextInfoTable::Create(
ContextInfoTable.reset(SerializedContextInfoTable::Create(
base + tableOffset, base + sizeof(uint32_t), base));
break;
}
Expand Down Expand Up @@ -1678,7 +1677,7 @@ APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,

case OBJC_CONTEXT_BLOCK_ID:
if (!HasValidControlBlock ||
Implementation->readObjCContextBlock(Cursor, Scratch)) {
Implementation->readContextBlock(Cursor, Scratch)) {
Failed = true;
return;
}
Expand Down Expand Up @@ -1815,7 +1814,7 @@ APINotesReader::VersionedInfo<T>::VersionedInfo(

auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
-> std::optional<ContextID> {
if (!Implementation->ObjCContextIDTable)
if (!Implementation->ContextIDTable)
return std::nullopt;

std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
Expand All @@ -1824,33 +1823,33 @@ auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)

// ObjC classes can't be declared in C++ namespaces, so use -1 as the global
// context.
auto KnownID = Implementation->ObjCContextIDTable->find(
auto KnownID = Implementation->ContextIDTable->find(
ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
if (KnownID == Implementation->ObjCContextIDTable->end())
if (KnownID == Implementation->ContextIDTable->end())
return std::nullopt;

return ContextID(*KnownID);
}

auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
-> VersionedInfo<ObjCContextInfo> {
if (!Implementation->ObjCContextInfoTable)
-> VersionedInfo<ContextInfo> {
if (!Implementation->ContextInfoTable)
return std::nullopt;

std::optional<ContextID> CtxID = lookupObjCClassID(Name);
if (!CtxID)
return std::nullopt;

auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ObjCContextInfoTable->end())
auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ContextInfoTable->end())
return std::nullopt;

return {Implementation->SwiftVersion, *KnownInfo};
}

auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)
-> std::optional<ContextID> {
if (!Implementation->ObjCContextIDTable)
if (!Implementation->ContextIDTable)
return std::nullopt;

std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
Expand All @@ -1859,25 +1858,25 @@ auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)

// ObjC classes can't be declared in C++ namespaces, so use -1 as the global
// context.
auto KnownID = Implementation->ObjCContextIDTable->find(
auto KnownID = Implementation->ContextIDTable->find(
ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
if (KnownID == Implementation->ObjCContextIDTable->end())
if (KnownID == Implementation->ContextIDTable->end())
return std::nullopt;

return ContextID(*KnownID);
}

auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name)
-> VersionedInfo<ObjCContextInfo> {
if (!Implementation->ObjCContextInfoTable)
-> VersionedInfo<ContextInfo> {
if (!Implementation->ContextInfoTable)
return std::nullopt;

std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
if (!CtxID)
return std::nullopt;

auto KnownInfo = Implementation->ObjCContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ObjCContextInfoTable->end())
auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
if (KnownInfo == Implementation->ContextInfoTable->end())
return std::nullopt;

return {Implementation->SwiftVersion, *KnownInfo};
Expand Down Expand Up @@ -2014,7 +2013,7 @@ auto APINotesReader::lookupTypedef(llvm::StringRef Name,
auto APINotesReader::lookupNamespaceID(
llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
-> std::optional<ContextID> {
if (!Implementation->ObjCContextIDTable)
if (!Implementation->ContextIDTable)
return std::nullopt;

std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
Expand All @@ -2023,9 +2022,9 @@ auto APINotesReader::lookupNamespaceID(

uint32_t RawParentNamespaceID =
ParentNamespaceID ? ParentNamespaceID->Value : -1;
auto KnownID = Implementation->ObjCContextIDTable->find(
auto KnownID = Implementation->ContextIDTable->find(
{RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
if (KnownID == Implementation->ObjCContextIDTable->end())
if (KnownID == Implementation->ContextIDTable->end())
return std::nullopt;

return ContextID(*KnownID);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/APINotes/APINotesTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ LLVM_DUMP_METHOD void CommonTypeInfo::dump(llvm::raw_ostream &OS) const {
OS << '\n';
}

LLVM_DUMP_METHOD void ObjCContextInfo::dump(llvm::raw_ostream &OS) {
LLVM_DUMP_METHOD void ContextInfo::dump(llvm::raw_ostream &OS) {
static_cast<CommonTypeInfo &>(*this).dump(OS);
if (HasDefaultNullability)
OS << "DefaultNullability: " << DefaultNullability << ' ';
Expand Down
71 changes: 35 additions & 36 deletions clang/lib/APINotes/APINotesWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ class APINotesWriter::Implementation {
/// this context and provides both the context ID and information describing
/// the context within that module.
llvm::DenseMap<ContextTableKey,
std::pair<unsigned, VersionedSmallVector<ObjCContextInfo>>>
ObjCContexts;
std::pair<unsigned, VersionedSmallVector<ContextInfo>>>
Contexts;

/// Information about parent contexts for each context.
///
/// Indexed by context ID, provides the parent context ID.
llvm::DenseMap<uint32_t, uint32_t> ParentContexts;

/// Mapping from context IDs to the identifier ID holding the name.
llvm::DenseMap<unsigned, unsigned> ObjCContextNames;
llvm::DenseMap<unsigned, unsigned> ContextNames;

/// Information about Objective-C properties.
///
Expand Down Expand Up @@ -147,7 +147,7 @@ class APINotesWriter::Implementation {
void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
void writeControlBlock(llvm::BitstreamWriter &Stream);
void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
void writeObjCContextBlock(llvm::BitstreamWriter &Stream);
void writeContextBlock(llvm::BitstreamWriter &Stream);
void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
Expand Down Expand Up @@ -178,7 +178,7 @@ void APINotesWriter::Implementation::writeToStream(llvm::raw_ostream &OS) {
writeBlockInfoBlock(Stream);
writeControlBlock(Stream);
writeIdentifierBlock(Stream);
writeObjCContextBlock(Stream);
writeContextBlock(Stream);
writeObjCPropertyBlock(Stream);
writeObjCMethodBlock(Stream);
writeObjCSelectorBlock(Stream);
Expand Down Expand Up @@ -240,7 +240,7 @@ void APINotesWriter::Implementation::writeBlockInfoBlock(
BLOCK_RECORD(identifier_block, IDENTIFIER_DATA);

BLOCK(OBJC_CONTEXT_BLOCK);
BLOCK_RECORD(objc_context_block, OBJC_CONTEXT_ID_DATA);
BLOCK_RECORD(context_block, CONTEXT_ID_DATA);

BLOCK(OBJC_PROPERTY_BLOCK);
BLOCK_RECORD(objc_property_block, OBJC_PROPERTY_DATA);
Expand Down Expand Up @@ -337,7 +337,7 @@ void APINotesWriter::Implementation::writeIdentifierBlock(

namespace {
/// Used to serialize the on-disk Objective-C context table.
class ObjCContextIDTableInfo {
class ContextIDTableInfo {
public:
using key_type = ContextTableKey;
using key_type_ref = key_type;
Expand Down Expand Up @@ -552,9 +552,8 @@ void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) {
}

/// Used to serialize the on-disk Objective-C property table.
class ObjCContextInfoTableInfo
: public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
ObjCContextInfo> {
class ContextInfoTableInfo
: public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
public:
unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); }

Expand All @@ -567,11 +566,11 @@ class ObjCContextInfoTableInfo
return static_cast<size_t>(llvm::hash_value(Key));
}

unsigned getUnversionedInfoSize(const ObjCContextInfo &OCI) {
unsigned getUnversionedInfoSize(const ContextInfo &OCI) {
return getCommonTypeInfoSize(OCI) + 1;
}

void emitUnversionedInfo(raw_ostream &OS, const ObjCContextInfo &OCI) {
void emitUnversionedInfo(raw_ostream &OS, const ContextInfo &OCI) {
emitCommonTypeInfo(OS, OCI);

uint8_t payload = 0;
Expand All @@ -590,19 +589,19 @@ class ObjCContextInfoTableInfo
};
} // namespace

void APINotesWriter::Implementation::writeObjCContextBlock(
void APINotesWriter::Implementation::writeContextBlock(
llvm::BitstreamWriter &Stream) {
llvm::BCBlockRAII restoreBlock(Stream, OBJC_CONTEXT_BLOCK_ID, 3);

if (ObjCContexts.empty())
if (Contexts.empty())
return;

{
llvm::SmallString<4096> HashTableBlob;
uint32_t Offset;
{
llvm::OnDiskChainedHashTableGenerator<ObjCContextIDTableInfo> Generator;
for (auto &OC : ObjCContexts)
llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo> Generator;
for (auto &OC : Contexts)
Generator.insert(OC.first, OC.second.first);

llvm::raw_svector_ostream BlobStream(HashTableBlob);
Expand All @@ -612,16 +611,16 @@ void APINotesWriter::Implementation::writeObjCContextBlock(
Offset = Generator.Emit(BlobStream);
}

objc_context_block::ObjCContextIDLayout ObjCContextID(Stream);
ObjCContextID.emit(Scratch, Offset, HashTableBlob);
context_block::ContextIDLayout ContextID(Stream);
ContextID.emit(Scratch, Offset, HashTableBlob);
}

{
llvm::SmallString<4096> HashTableBlob;
uint32_t Offset;
{
llvm::OnDiskChainedHashTableGenerator<ObjCContextInfoTableInfo> Generator;
for (auto &OC : ObjCContexts)
llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo> Generator;
for (auto &OC : Contexts)
Generator.insert(OC.second.first, OC.second.second);

llvm::raw_svector_ostream BlobStream(HashTableBlob);
Expand All @@ -631,8 +630,8 @@ void APINotesWriter::Implementation::writeObjCContextBlock(
Offset = Generator.Emit(BlobStream);
}

objc_context_block::ObjCContextInfoLayout ObjCContextInfo(Stream);
ObjCContextInfo.emit(Scratch, Offset, HashTableBlob);
context_block::ContextInfoLayout ContextInfo(Stream);
ContextInfo.emit(Scratch, Offset, HashTableBlob);
}
}

Expand Down Expand Up @@ -1263,25 +1262,25 @@ void APINotesWriter::writeToStream(llvm::raw_ostream &OS) {
Implementation->writeToStream(OS);
}

ContextID APINotesWriter::addObjCContext(std::optional<ContextID> ParentCtxID,
StringRef Name, ContextKind Kind,
const ObjCContextInfo &Info,
VersionTuple SwiftVersion) {
ContextID APINotesWriter::addContext(std::optional<ContextID> ParentCtxID,
llvm::StringRef Name, ContextKind Kind,
const ContextInfo &Info,
llvm::VersionTuple SwiftVersion) {
IdentifierID NameID = Implementation->getIdentifier(Name);

uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
ContextTableKey Key(RawParentCtxID, static_cast<uint8_t>(Kind), NameID);
auto Known = Implementation->ObjCContexts.find(Key);
if (Known == Implementation->ObjCContexts.end()) {
unsigned NextID = Implementation->ObjCContexts.size() + 1;
auto Known = Implementation->Contexts.find(Key);
if (Known == Implementation->Contexts.end()) {
unsigned NextID = Implementation->Contexts.size() + 1;

Implementation::VersionedSmallVector<ObjCContextInfo> EmptyVersionedInfo;
Known = Implementation->ObjCContexts
Implementation::VersionedSmallVector<ContextInfo> EmptyVersionedInfo;
Known = Implementation->Contexts
.insert(std::make_pair(
Key, std::make_pair(NextID, EmptyVersionedInfo)))
.first;

Implementation->ObjCContextNames[NextID] = NameID;
Implementation->ContextNames[NextID] = NameID;
Implementation->ParentContexts[NextID] = RawParentCtxID;
}

Expand Down Expand Up @@ -1328,9 +1327,9 @@ void APINotesWriter::addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
uint32_t ParentCtxID = Implementation->ParentContexts[CtxID.Value];
ContextTableKey CtxKey(ParentCtxID,
static_cast<uint8_t>(ContextKind::ObjCClass),
Implementation->ObjCContextNames[CtxID.Value]);
assert(Implementation->ObjCContexts.contains(CtxKey));
auto &VersionedVec = Implementation->ObjCContexts[CtxKey].second;
Implementation->ContextNames[CtxID.Value]);
assert(Implementation->Contexts.contains(CtxKey));
auto &VersionedVec = Implementation->Contexts[CtxKey].second;
bool Found = false;
for (auto &Versioned : VersionedVec) {
if (Versioned.first == SwiftVersion) {
Expand All @@ -1341,7 +1340,7 @@ void APINotesWriter::addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
}

if (!Found) {
VersionedVec.push_back({SwiftVersion, ObjCContextInfo()});
VersionedVec.push_back({SwiftVersion, ContextInfo()});
VersionedVec.back().second.setHasDesignatedInits(true);
}
}
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/APINotes/APINotesYAMLCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ class YAMLConverter {
void convertContext(std::optional<ContextID> ParentContextID, const Class &C,
ContextKind Kind, VersionTuple SwiftVersion) {
// Write the class.
ObjCContextInfo CI;
ContextInfo CI;
convertCommonType(C, CI, C.Name);

if (C.AuditedForNullability)
Expand All @@ -797,7 +797,7 @@ class YAMLConverter {
CI.setSwiftObjCMembers(*C.SwiftObjCMembers);

ContextID CtxID =
Writer.addObjCContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);
Writer.addContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);

// Write all methods.
llvm::StringMap<std::pair<bool, bool>> KnownMethods;
Expand Down Expand Up @@ -863,12 +863,12 @@ class YAMLConverter {
const Namespace &TheNamespace,
VersionTuple SwiftVersion) {
// Write the namespace.
ObjCContextInfo CI;
ContextInfo CI;
convertCommonEntity(TheNamespace, CI, TheNamespace.Name);

ContextID CtxID =
Writer.addObjCContext(ParentContextID, TheNamespace.Name,
ContextKind::Namespace, CI, SwiftVersion);
Writer.addContext(ParentContextID, TheNamespace.Name,
ContextKind::Namespace, CI, SwiftVersion);

convertTopLevelItems(Context(CtxID, ContextKind::Namespace),
TheNamespace.Items, SwiftVersion);
Expand Down
281 changes: 280 additions & 1 deletion clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3140,6 +3140,285 @@ ASTContext::getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD) {
return llvm::getPointerAuthStableSipHash(Str);
}

/// Encode a function type for use in the discriminator of a function pointer
/// type. We can't use the itanium scheme for this since C has quite permissive
/// rules for type compatibility that we need to be compatible with.
///
/// Formally, this function associates every function pointer type T with an
/// encoded string E(T). Let the equivalence relation T1 ~ T2 be defined as
/// E(T1) == E(T2). E(T) is part of the ABI of values of type T. C type
/// compatibility requires equivalent treatment under the ABI, so
/// CCompatible(T1, T2) must imply E(T1) == E(T2), that is, CCompatible must be
/// a subset of ~. Crucially, however, it must be a proper subset because
/// CCompatible is not an equivalence relation: for example, int[] is compatible
/// with both int[1] and int[2], but the latter are not compatible with each
/// other. Therefore this encoding function must be careful to only distinguish
/// types if there is no third type with which they are both required to be
/// compatible.
static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
raw_ostream &OS, QualType QT) {
// FIXME: Consider address space qualifiers.
const Type *T = QT.getCanonicalType().getTypePtr();

// FIXME: Consider using the C++ type mangling when we encounter a construct
// that is incompatible with C.

switch (T->getTypeClass()) {
case Type::Atomic:
return encodeTypeForFunctionPointerAuth(
Ctx, OS, cast<AtomicType>(T)->getValueType());

case Type::LValueReference:
OS << "R";
encodeTypeForFunctionPointerAuth(Ctx, OS,
cast<ReferenceType>(T)->getPointeeType());
return;
case Type::RValueReference:
OS << "O";
encodeTypeForFunctionPointerAuth(Ctx, OS,
cast<ReferenceType>(T)->getPointeeType());
return;

case Type::Pointer:
// C11 6.7.6.1p2:
// For two pointer types to be compatible, both shall be identically
// qualified and both shall be pointers to compatible types.
// FIXME: we should also consider pointee types.
OS << "P";
return;

case Type::ObjCObjectPointer:
case Type::BlockPointer:
OS << "P";
return;

case Type::Complex:
OS << "C";
return encodeTypeForFunctionPointerAuth(
Ctx, OS, cast<ComplexType>(T)->getElementType());

case Type::VariableArray:
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::ArrayParameter:
// C11 6.7.6.2p6:
// For two array types to be compatible, both shall have compatible
// element types, and if both size specifiers are present, and are integer
// constant expressions, then both size specifiers shall have the same
// constant value [...]
//
// So since ElemType[N] has to be compatible ElemType[], we can't encode the
// width of the array.
OS << "A";
return encodeTypeForFunctionPointerAuth(
Ctx, OS, cast<ArrayType>(T)->getElementType());

case Type::ObjCInterface:
case Type::ObjCObject:
OS << "<objc_object>";
return;

case Type::Enum:
// C11 6.7.2.2p4:
// Each enumerated type shall be compatible with char, a signed integer
// type, or an unsigned integer type.
//
// So we have to treat enum types as integers.
return encodeTypeForFunctionPointerAuth(
Ctx, OS, cast<EnumType>(T)->getDecl()->getIntegerType());

case Type::FunctionNoProto:
case Type::FunctionProto: {
// C11 6.7.6.3p15:
// For two function types to be compatible, both shall specify compatible
// return types. Moreover, the parameter type lists, if both are present,
// shall agree in the number of parameters and in the use of the ellipsis
// terminator; corresponding parameters shall have compatible types.
//
// That paragraph goes on to describe how unprototyped functions are to be
// handled, which we ignore here. Unprototyped function pointers are hashed
// as though they were prototyped nullary functions since thats probably
// what the user meant. This behavior is non-conforming.
// FIXME: If we add a "custom discriminator" function type attribute we
// should encode functions as their discriminators.
OS << "F";
const auto *FuncType = cast<FunctionType>(T);
encodeTypeForFunctionPointerAuth(Ctx, OS, FuncType->getReturnType());
if (const auto *FPT = dyn_cast<FunctionProtoType>(FuncType)) {
for (QualType Param : FPT->param_types()) {
Param = Ctx.getSignatureParameterType(Param);
encodeTypeForFunctionPointerAuth(Ctx, OS, Param);
}
if (FPT->isVariadic())
OS << "z";
}
OS << "E";
return;
}

case Type::MemberPointer: {
OS << "M";
const auto *MPT = T->getAs<MemberPointerType>();
encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0));
encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
return;
}
case Type::ExtVector:
case Type::Vector:
OS << "Dv" << Ctx.getTypeSizeInChars(T).getQuantity();
break;

// Don't bother discriminating based on these types.
case Type::Pipe:
case Type::BitInt:
case Type::ConstantMatrix:
OS << "?";
return;

case Type::Builtin: {
const auto *BTy = T->getAs<BuiltinType>();
switch (BTy->getKind()) {
#define SIGNED_TYPE(Id, SingletonId) \
case BuiltinType::Id: \
OS << "i"; \
return;
#define UNSIGNED_TYPE(Id, SingletonId) \
case BuiltinType::Id: \
OS << "i"; \
return;
#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
#define BUILTIN_TYPE(Id, SingletonId)
#include "clang/AST/BuiltinTypes.def"
llvm_unreachable("placeholder types should not appear here.");

case BuiltinType::Half:
OS << "Dh";
return;
case BuiltinType::Float:
OS << "f";
return;
case BuiltinType::Double:
OS << "d";
return;
case BuiltinType::LongDouble:
OS << "e";
return;
case BuiltinType::Float16:
OS << "DF16_";
return;
case BuiltinType::Float128:
OS << "g";
return;

case BuiltinType::Void:
OS << "v";
return;

case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
case BuiltinType::NullPtr:
OS << "P";
return;

// Don't bother discriminating based on OpenCL types.
case BuiltinType::OCLSampler:
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
case BuiltinType::OCLReserveID:
case BuiltinType::BFloat16:
case BuiltinType::VectorQuad:
case BuiltinType::VectorPair:
OS << "?";
return;

// Don't bother discriminating based on these seldom-used types.
case BuiltinType::Ibm128:
return;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id: \
return;
#include "clang/Basic/OpenCLImageTypes.def"
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
case BuiltinType::Id: \
return;
#include "clang/Basic/OpenCLExtensionTypes.def"
#define SVE_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id: \
return;
#include "clang/Basic/AArch64SVEACLETypes.def"
case BuiltinType::Dependent:
llvm_unreachable("should never get here");
case BuiltinType::AMDGPUBufferRsrc:
case BuiltinType::WasmExternRef:
#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/RISCVVTypes.def"
llvm_unreachable("not yet implemented");
}
}
case Type::Record: {
const RecordDecl *RD = T->getAs<RecordType>()->getDecl();
const IdentifierInfo *II = RD->getIdentifier();

// In C++, an immediate typedef of an anonymous struct or union
// is considered to name it for ODR purposes, but C's specification
// of type compatibility does not have a similar rule. Using the typedef
// name in function type discriminators anyway, as we do here,
// therefore technically violates the C standard: two function pointer
// types defined in terms of two typedef'd anonymous structs with
// different names are formally still compatible, but we are assigning
// them different discriminators and therefore incompatible ABIs.
//
// This is a relatively minor violation that significantly improves
// discrimination in some cases and has not caused problems in
// practice. Regardless, it is now part of the ABI in places where
// function type discrimination is used, and it can no longer be
// changed except on new platforms.

if (!II)
if (const TypedefNameDecl *Typedef = RD->getTypedefNameForAnonDecl())
II = Typedef->getDeclName().getAsIdentifierInfo();

if (!II) {
OS << "<anonymous_record>";
return;
}
OS << II->getLength() << II->getName();
return;
}
case Type::DeducedTemplateSpecialization:
case Type::Auto:
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
#define ABSTRACT_TYPE(Class, Base)
#define TYPE(Class, Base)
#include "clang/AST/TypeNodes.inc"
llvm_unreachable("unexpected non-canonical or dependent type!");
return;
}
}

uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) const {
assert(!T->isDependentType() &&
"cannot compute type discriminator of a dependent type");

SmallString<256> Str;
llvm::raw_svector_ostream Out(Str);

if (T->isFunctionPointerType() || T->isFunctionReferenceType())
T = T->getPointeeType();

if (T->isFunctionType())
encodeTypeForFunctionPointerAuth(*this, Out, T);
else
llvm_unreachable(
"type discrimination of non-function type not implemented yet");

return llvm::getPointerAuthStableSipHash(Str);
}

QualType ASTContext::getObjCGCQualType(QualType T,
Qualifiers::GC GCAttr) const {
QualType CanT = getCanonicalType(T);
Expand Down Expand Up @@ -12116,7 +12395,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return false;

// Variables in other module units shouldn't be forced to be emitted.
if (VD->shouldEmitInExternalSource())
if (VD->isInAnotherModuleUnit())
return false;

// Variables that can be needed in other TUs are required.
Expand Down
12 changes: 9 additions & 3 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8439,8 +8439,14 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
auto ToFirstQualifierFoundInScope =
importChecked(Err, E->getFirstQualifierFoundInScope());

UnresolvedSet<8> ToUnqualifiedLookups;
for (auto D : E->unqualified_lookups())
if (auto ToDOrErr = import(D.getDecl()))
ToUnqualifiedLookups.addDecl(*ToDOrErr);
else
return ToDOrErr.takeError();

if (Err)
return std::move(Err);

Expand Down Expand Up @@ -8474,7 +8480,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(

return CXXDependentScopeMemberExpr::Create(
Importer.getToContext(), ToBase, ToType, E->isArrow(), ToOperatorLoc,
ToQualifierLoc, ToTemplateKeywordLoc, ToFirstQualifierFoundInScope,
ToQualifierLoc, ToTemplateKeywordLoc, ToUnqualifiedLookups.pairs(),
ToMemberNameInfo, ResInfo);
}

Expand Down
11 changes: 9 additions & 2 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,13 @@ Linkage NamedDecl::getLinkageInternal() const {
.getLinkage();
}

/// Determine whether D is attached to a named module.
static bool isInNamedModule(const NamedDecl *D) {
if (auto *M = D->getOwningModule())
return M->isNamedModule();
return false;
}

static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
// FIXME: Handle isModulePrivate.
switch (D->getModuleOwnershipKind()) {
Expand All @@ -1190,7 +1197,7 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
return false;
case Decl::ModuleOwnershipKind::Visible:
case Decl::ModuleOwnershipKind::VisibleWhenImported:
return D->isInNamedModule();
return isInNamedModule(D);
}
llvm_unreachable("unexpected module ownership kind");
}
Expand All @@ -1208,7 +1215,7 @@ Linkage NamedDecl::getFormalLinkage() const {
// [basic.namespace.general]/p2
// A namespace is never attached to a named module and never has a name with
// module linkage.
if (isInNamedModule() && InternalLinkage == Linkage::External &&
if (isInNamedModule(this) && InternalLinkage == Linkage::External &&
!isExportedFromModuleInterfaceUnit(
cast<NamedDecl>(this->getCanonicalDecl())) &&
!isa<NamespaceDecl>(this))
Expand Down
30 changes: 11 additions & 19 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1122,31 +1122,23 @@ bool Decl::isInExportDeclContext() const {
bool Decl::isInAnotherModuleUnit() const {
auto *M = getOwningModule();

if (!M || !M->isNamedModule())
if (!M)
return false;

return M != getASTContext().getCurrentNamedModule();
}

bool Decl::isInCurrentModuleUnit() const {
auto *M = getOwningModule();

if (!M || !M->isNamedModule())
M = M->getTopLevelModule();
// FIXME: It is problematic if the header module lives in another module
// unit. Consider to fix this by techniques like
// ExternalASTSource::hasExternalDefinitions.
if (M->isHeaderLikeModule())
return false;

return M == getASTContext().getCurrentNamedModule();
}

bool Decl::shouldEmitInExternalSource() const {
ExternalASTSource *Source = getASTContext().getExternalSource();
if (!Source)
// A global module without parent implies that we're parsing the global
// module. So it can't be in another module unit.
if (M->isGlobalModule())
return false;

return Source->hasExternalDefinitions(this) == ExternalASTSource::EK_Always;
}

bool Decl::isInNamedModule() const {
return getOwningModule() && getOwningModule()->isNamedModule();
assert(M->isNamedModule() && "New module kind?");
return M != getASTContext().getCurrentNamedModule();
}

bool Decl::isFromExplicitGlobalModule() const {
Expand Down
67 changes: 40 additions & 27 deletions clang/lib/AST/ExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1489,19 +1489,27 @@ SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const {
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
SourceLocation TemplateKWLoc, ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue,
OK_Ordinary),
Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc),
MemberNameInfo(MemberNameInfo) {
Base(Base), BaseType(BaseType), MemberNameInfo(MemberNameInfo),
OperatorLoc(OperatorLoc) {
CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
CXXDependentScopeMemberExprBits.HasQualifier = QualifierLoc.hasQualifier();
CXXDependentScopeMemberExprBits.NumUnqualifiedLookups =
UnqualifiedLookups.size();
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
FirstQualifierFoundInScope != nullptr;
CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;

if (hasQualifier())
new (getTrailingObjects<NestedNameSpecifierLoc>())
NestedNameSpecifierLoc(QualifierLoc);

std::uninitialized_copy_n(UnqualifiedLookups.data(),
UnqualifiedLookups.size(),
getTrailingObjects<DeclAccessPair>());

if (TemplateArgs) {
auto Deps = TemplateArgumentDependence::None;
Expand All @@ -1513,54 +1521,59 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
TemplateKWLoc);
}

if (hasFirstQualifierFoundInScope())
*getTrailingObjects<NamedDecl *>() = FirstQualifierFoundInScope;
setDependence(computeDependence(this));
}

CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
bool HasFirstQualifierFoundInScope)
EmptyShell Empty, bool HasQualifier, unsigned NumUnqualifiedLookups,
bool HasTemplateKWAndArgsInfo)
: Expr(CXXDependentScopeMemberExprClass, Empty) {
CXXDependentScopeMemberExprBits.HasQualifier = HasQualifier;
CXXDependentScopeMemberExprBits.NumUnqualifiedLookups = NumUnqualifiedLookups;
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
HasTemplateKWAndArgsInfo;
CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
HasFirstQualifierFoundInScope;
}

CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::Create(
const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
SourceLocation TemplateKWLoc, ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
bool HasQualifier = QualifierLoc.hasQualifier();
unsigned NumUnqualifiedLookups = UnqualifiedLookups.size();
assert(!NumUnqualifiedLookups || HasQualifier);
bool HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
bool HasFirstQualifierFoundInScope = FirstQualifierFoundInScope != nullptr;

unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc, NamedDecl *>(
HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
unsigned Size =
totalSizeToAlloc<NestedNameSpecifierLoc, DeclAccessPair,
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasQualifier, NumUnqualifiedLookups, HasTemplateKWAndArgsInfo,
NumTemplateArgs);

void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(
Ctx, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc,
FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs);
UnqualifiedLookups, MemberNameInfo, TemplateArgs);
}

CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty(
const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope) {
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
const ASTContext &Ctx, bool HasQualifier, unsigned NumUnqualifiedLookups,
bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) {
assert(!NumTemplateArgs || HasTemplateKWAndArgsInfo);
assert(!NumUnqualifiedLookups || HasQualifier);

unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc, NamedDecl *>(
HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
unsigned Size =
totalSizeToAlloc<NestedNameSpecifierLoc, DeclAccessPair,
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasQualifier, NumUnqualifiedLookups, HasTemplateKWAndArgsInfo,
NumTemplateArgs);

void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(
EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope);
return new (Mem) CXXDependentScopeMemberExpr(EmptyShell(), HasQualifier,
NumUnqualifiedLookups,
HasTemplateKWAndArgsInfo);
}

CXXThisExpr *CXXThisExpr::Create(const ASTContext &Ctx, SourceLocation L,
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2859,6 +2859,9 @@ static bool handleIntIntBinOp(EvalInfo &Info, const BinaryOperator *E,
else if (LHS.countl_zero() < SA)
Info.CCEDiag(E, diag::note_constexpr_lshift_discards);
}
if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
Info.getLangOpts().CPlusPlus11)
return false;
Result = LHS << SA;
return true;
}
Expand All @@ -2882,6 +2885,10 @@ static bool handleIntIntBinOp(EvalInfo &Info, const BinaryOperator *E,
if (SA != RHS)
Info.CCEDiag(E, diag::note_constexpr_large_shift)
<< RHS << E->getType() << LHS.getBitWidth();

if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
Info.getLangOpts().CPlusPlus11)
return false;
Result = LHS >> SA;
return true;
}
Expand Down
39 changes: 15 additions & 24 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -594,11 +594,10 @@ class CXXNameMangler {
void mangleMemberExprBase(const Expr *base, bool isArrow);
void mangleMemberExpr(const Expr *base, bool isArrow,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationName name,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
unsigned knownArity);
unsigned NumTemplateArgs, unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
void mangleInitListElements(const InitListExpr *InitList);
void mangleRequirement(SourceLocation RequiresExprLoc,
Expand Down Expand Up @@ -4496,14 +4495,11 @@ void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
}

/// Mangles a member expression.
void CXXNameMangler::mangleMemberExpr(const Expr *base,
bool isArrow,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName member,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
unsigned arity) {
void CXXNameMangler::mangleMemberExpr(
const Expr *base, bool isArrow, NestedNameSpecifier *qualifier,
ArrayRef<DeclAccessPair> UnqualifiedLookups, DeclarationName member,
const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs,
unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
if (base)
Expand Down Expand Up @@ -4985,22 +4981,19 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::MemberExprClass: {
NotPrimaryExpr();
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), nullptr,
ME->getMemberDecl()->getDeclName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
mangleMemberExpr(ME->getBase(), ME->isArrow(), ME->getQualifier(),
std::nullopt, ME->getMemberDecl()->getDeclName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(), Arity);
break;
}

case Expr::UnresolvedMemberExprClass: {
NotPrimaryExpr();
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(), nullptr,
ME->getMemberName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
ME->isArrow(), ME->getQualifier(), std::nullopt,
ME->getMemberName(), ME->getTemplateArgs(),
ME->getNumTemplateArgs(), Arity);
break;
}

Expand All @@ -5010,10 +5003,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
= cast<CXXDependentScopeMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(),
ME->getFirstQualifierFoundInScope(),
ME->getMember(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
ME->unqualified_lookups(), ME->getMember(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(), Arity);
break;
}

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1934,6 +1934,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
break;

case attr::CountedBy:
case attr::CountedByOrNull:
case attr::SizedBy:
case attr::SizedByOrNull:
case attr::LifetimeBound:
case attr::TypeNonNull:
case attr::TypeNullable:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/LangOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ void LangOptions::setLangDefaults(LangOptions &Opts, Language Lang,
Opts.HexFloats = Std.hasHexFloats();
Opts.WChar = Std.isCPlusPlus();
Opts.Digraphs = Std.hasDigraphs();
Opts.RawStringLiterals = Std.hasRawStringLiterals();

Opts.HLSL = Lang == Language::HLSL;
if (Opts.HLSL && Opts.IncludeDefaultHeader)
Expand Down
12 changes: 9 additions & 3 deletions clang/lib/Basic/Targets/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,15 @@ bool AMDGPUTargetInfo::initFeatureMap(
return false;

// TODO: Should move this logic into TargetParser
std::string ErrorMsg;
if (!insertWaveSizeFeature(CPU, getTriple(), Features, ErrorMsg)) {
Diags.Report(diag::err_invalid_feature_combination) << ErrorMsg;
auto HasError = insertWaveSizeFeature(CPU, getTriple(), Features);
switch (HasError.first) {
default:
break;
case llvm::AMDGPU::INVALID_FEATURE_COMBINATION:
Diags.Report(diag::err_invalid_feature_combination) << HasError.second;
return false;
case llvm::AMDGPU::UNSUPPORTED_TARGET_FEATURE:
Diags.Report(diag::err_opt_not_valid_on_target) << HasError.second;
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/Hexagon.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class LLVM_LIBRARY_VISIBILITY HexagonTargetInfo : public TargetInfo {
std::optional<unsigned> Rev = getHexagonCPURev(CPU);

// V73 and later have 64-byte cache lines.
unsigned CacheLineSizeBytes = Rev >= 73 ? 64 : 32;
unsigned CacheLineSizeBytes = Rev >= 73U ? 64 : 32;
return std::make_pair(CacheLineSizeBytes, CacheLineSizeBytes);
}
};
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/NVPTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {

ArrayRef<Builtin::Info> getTargetBuiltins() const override;

bool useFP16ConversionIntrinsics() const override { return false; }

bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
Expand Down
32 changes: 23 additions & 9 deletions clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1542,9 +1542,11 @@ ConstantEmitter::emitAbstract(const Expr *E, QualType destType) {

llvm::Constant *
ConstantEmitter::emitAbstract(SourceLocation loc, const APValue &value,
QualType destType) {
QualType destType,
bool EnablePtrAuthFunctionTypeDiscrimination) {
auto state = pushAbstract();
auto C = tryEmitPrivate(value, destType);
auto C =
tryEmitPrivate(value, destType, EnablePtrAuthFunctionTypeDiscrimination);
C = validateAndPopAbstract(C, state);
if (!C) {
CGM.Error(loc,
Expand Down Expand Up @@ -1938,14 +1940,18 @@ class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter,
ConstantEmitter &Emitter;
const APValue &Value;
QualType DestType;
bool EnablePtrAuthFunctionTypeDiscrimination;

// Befriend StmtVisitorBase so that we don't have to expose Visit*.
friend StmtVisitorBase;

public:
ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
QualType destType)
: CGM(emitter.CGM), Emitter(emitter), Value(value), DestType(destType) {}
QualType destType,
bool EnablePtrAuthFunctionTypeDiscrimination = true)
: CGM(emitter.CGM), Emitter(emitter), Value(value), DestType(destType),
EnablePtrAuthFunctionTypeDiscrimination(
EnablePtrAuthFunctionTypeDiscrimination) {}

llvm::Constant *tryEmit();

Expand Down Expand Up @@ -2069,7 +2075,10 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
return CGM.GetWeakRefReference(D).getPointer();

auto PtrAuthSign = [&](llvm::Constant *C) {
CGPointerAuthInfo AuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
CGPointerAuthInfo AuthInfo;

if (EnablePtrAuthFunctionTypeDiscrimination)
AuthInfo = CGM.getFunctionPointerAuthInfo(DestType);

if (AuthInfo) {
if (hasNonZeroOffset())
Expand Down Expand Up @@ -2220,8 +2229,10 @@ llvm::Constant *ConstantLValueEmitter::emitPointerAuthPointer(const Expr *E) {

// The assertions here are all checked by Sema.
assert(Result.Val.isLValue());
if (isa<FunctionDecl>(Result.Val.getLValueBase().get<const ValueDecl *>()))
assert(Result.Val.getLValueOffset().isZero());
return ConstantEmitter(CGM, Emitter.CGF)
.emitAbstract(E->getExprLoc(), Result.Val, E->getType());
.emitAbstract(E->getExprLoc(), Result.Val, E->getType(), false);
}

unsigned ConstantLValueEmitter::emitPointerAuthKey(const Expr *E) {
Expand Down Expand Up @@ -2278,15 +2289,18 @@ ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
return CGM.GetAddrOfGlobalTemporary(E, Inner);
}

llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value,
QualType DestType) {
llvm::Constant *
ConstantEmitter::tryEmitPrivate(const APValue &Value, QualType DestType,
bool EnablePtrAuthFunctionTypeDiscrimination) {
switch (Value.getKind()) {
case APValue::None:
case APValue::Indeterminate:
// Out-of-lifetime and indeterminate values can be modeled as 'undef'.
return llvm::UndefValue::get(CGM.getTypes().ConvertType(DestType));
case APValue::LValue:
return ConstantLValueEmitter(*this, Value, DestType).tryEmit();
return ConstantLValueEmitter(*this, Value, DestType,
EnablePtrAuthFunctionTypeDiscrimination)
.tryEmit();
case APValue::Int:
return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt());
case APValue::FixedPoint:
Expand Down
15 changes: 13 additions & 2 deletions clang/lib/CodeGen/CGLoopInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,9 +612,9 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
const OpenCLUnrollHintAttr *OpenCLHint =
dyn_cast<OpenCLUnrollHintAttr>(Attr);

const HLSLLoopHintAttr *HLSLLoopHint = dyn_cast<HLSLLoopHintAttr>(Attr);
// Skip non loop hint attributes
if (!LH && !OpenCLHint) {
if (!LH && !OpenCLHint && !HLSLLoopHint) {
continue;
}

Expand All @@ -635,6 +635,17 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
Option = LoopHintAttr::UnrollCount;
State = LoopHintAttr::Numeric;
}
} else if (HLSLLoopHint) {
ValueInt = HLSLLoopHint->getDirective();
if (HLSLLoopHint->getSemanticSpelling() ==
HLSLLoopHintAttr::Spelling::Microsoft_unroll) {
if (ValueInt == 0)
State = LoopHintAttr::Enable;
if (ValueInt > 0) {
Option = LoopHintAttr::UnrollCount;
State = LoopHintAttr::Numeric;
}
}
} else if (LH) {
auto *ValueExpr = LH->getValue();
if (ValueExpr) {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1952,7 +1952,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
Builder.CreateLoad(StateItemsPtr, "stateitems");

// Fetch the value at the current index from the buffer.
llvm::Value *CurrentItemPtr = Builder.CreateGEP(
llvm::Value *CurrentItemPtr = Builder.CreateInBoundsGEP(
ObjCIdType, EnumStateItems, index, "currentitem.ptr");
llvm::Value *CurrentItem =
Builder.CreateAlignedLoad(ObjCIdType, CurrentItemPtr, getPointerAlign());
Expand Down Expand Up @@ -2028,7 +2028,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){

// First we check in the local buffer.
llvm::Value *indexPlusOne =
Builder.CreateAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));
Builder.CreateNUWAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));

// If we haven't overrun the buffer yet, we can continue.
// Set the branch weights based on the simplifying assumption that this is
Expand Down
67 changes: 63 additions & 4 deletions clang/lib/CodeGen/CGPointerAuth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ llvm::ConstantInt *CodeGenModule::getPointerAuthOtherDiscriminator(
return nullptr;

case PointerAuthSchema::Discrimination::Type:
llvm_unreachable("type discrimination not implemented yet");
assert(!Type.isNull() && "type not provided for type-discriminated schema");
return llvm::ConstantInt::get(
IntPtrTy, getContext().getPointerAuthTypeDiscriminator(Type));

case PointerAuthSchema::Discrimination::Decl:
assert(Decl.getDecl() &&
Expand All @@ -43,6 +45,11 @@ llvm::ConstantInt *CodeGenModule::getPointerAuthOtherDiscriminator(
llvm_unreachable("bad discrimination kind");
}

uint16_t CodeGen::getPointerAuthTypeDiscriminator(CodeGenModule &CGM,
QualType FunctionType) {
return CGM.getContext().getPointerAuthTypeDiscriminator(FunctionType);
}

uint16_t CodeGen::getPointerAuthDeclDiscriminator(CodeGenModule &CGM,
GlobalDecl Declaration) {
return CGM.getPointerAuthDeclDiscriminator(Declaration);
Expand Down Expand Up @@ -71,12 +78,15 @@ CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) {
assert(!Schema.isAddressDiscriminated() &&
"function pointers cannot use address-specific discrimination");

assert(!Schema.hasOtherDiscrimination() &&
"function pointers don't support any discrimination yet");
llvm::Constant *Discriminator = nullptr;
if (T->isFunctionPointerType() || T->isFunctionReferenceType())
T = T->getPointeeType();
if (T->isFunctionType())
Discriminator = getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), T);

return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(),
/*IsaPointer=*/false, /*AuthenticatesNull=*/false,
/*Discriminator=*/nullptr);
Discriminator);
}

llvm::Value *
Expand Down Expand Up @@ -114,6 +124,47 @@ CGPointerAuthInfo CodeGenFunction::EmitPointerAuthInfo(
Schema.authenticatesNullValues(), Discriminator);
}

/// Return the natural pointer authentication for values of the given
/// pointee type.
static CGPointerAuthInfo
getPointerAuthInfoForPointeeType(CodeGenModule &CGM, QualType PointeeType) {
if (PointeeType.isNull())
return CGPointerAuthInfo();

// Function pointers use the function-pointer schema by default.
if (PointeeType->isFunctionType())
return CGM.getFunctionPointerAuthInfo(PointeeType);

// Normal data pointers never use direct pointer authentication by default.
return CGPointerAuthInfo();
}

CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForPointeeType(QualType T) {
return ::getPointerAuthInfoForPointeeType(*this, T);
}

/// Return the natural pointer authentication for values of the given
/// pointer type.
static CGPointerAuthInfo getPointerAuthInfoForType(CodeGenModule &CGM,
QualType PointerType) {
assert(PointerType->isSignableType());

// Block pointers are currently not signed.
if (PointerType->isBlockPointerType())
return CGPointerAuthInfo();

auto PointeeType = PointerType->getPointeeType();

if (PointeeType.isNull())
return CGPointerAuthInfo();

return ::getPointerAuthInfoForPointeeType(CGM, PointeeType);
}

CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) {
return ::getPointerAuthInfoForType(*this, T);
}

llvm::Constant *
CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key,
llvm::Constant *StorageAddress,
Expand Down Expand Up @@ -180,6 +231,14 @@ llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD,
llvm::Type *Ty) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
QualType FuncType = FD->getType();

// Annoyingly, K&R functions have prototypes in the clang AST, but
// expressions referring to them are unprototyped.
if (!FD->hasPrototype())
if (const auto *Proto = FuncType->getAs<FunctionProtoType>())
FuncType = Context.getFunctionNoProtoType(Proto->getReturnType(),
Proto->getExtInfo());

return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType);
}

Expand Down
61 changes: 21 additions & 40 deletions clang/lib/CodeGen/CGVTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1079,38 +1079,28 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
if (!RD->isExternallyVisible())
return llvm::GlobalVariable::InternalLinkage;

bool IsInNamedModule = RD->isInNamedModule();
// If the CXXRecordDecl are not in a module unit, we need to get
// its key function. We're at the end of the translation unit, so the current
// key function is fully correct.
const CXXMethodDecl *keyFunction =
IsInNamedModule ? nullptr : Context.getCurrentKeyFunction(RD);
if (IsInNamedModule || (keyFunction && !RD->hasAttr<DLLImportAttr>())) {
// We're at the end of the translation unit, so the current key
// function is fully correct.
const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD);
if (keyFunction && !RD->hasAttr<DLLImportAttr>()) {
// If this class has a key function, use that to determine the
// linkage of the vtable.
const FunctionDecl *def = nullptr;
if (keyFunction && keyFunction->hasBody(def))
if (keyFunction->hasBody(def))
keyFunction = cast<CXXMethodDecl>(def);

bool IsExternalDefinition =
IsInNamedModule ? RD->shouldEmitInExternalSource() : !def;

TemplateSpecializationKind Kind =
IsInNamedModule ? RD->getTemplateSpecializationKind()
: keyFunction->getTemplateSpecializationKind();

switch (Kind) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
switch (keyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
assert(
(IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
(def || CodeGenOpts.OptimizationLevel > 0 ||
CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) &&
"Shouldn't query vtable linkage without the class in module units, "
"key function, optimizations, or debug info");
if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
"Shouldn't query vtable linkage without key function, "
"optimizations, or debug info");
if (!def && CodeGenOpts.OptimizationLevel > 0)
return llvm::GlobalVariable::AvailableExternallyLinkage;

if (keyFunction && keyFunction->isInlined())
if (keyFunction->isInlined())
return !Context.getLangOpts().AppleKext
? llvm::GlobalVariable::LinkOnceODRLinkage
: llvm::Function::InternalLinkage;
Expand All @@ -1129,7 +1119,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {

case TSK_ExplicitInstantiationDeclaration:
llvm_unreachable("Should not have been asked to emit this");
}
}
}

// -fapple-kext mode does not support weak linkage, so we must use
Expand Down Expand Up @@ -1223,21 +1213,6 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
TSK == TSK_ExplicitInstantiationDefinition)
return false;

// Itanium C++ ABI [5.2.3]:
// Virtual tables for dynamic classes are emitted as follows:
//
// - If the class is templated, the tables are emitted in every object that
// references any of them.
// - Otherwise, if the class is attached to a module, the tables are uniquely
// emitted in the object for the module unit in which it is defined.
// - Otherwise, if the class has a key function (see below), the tables are
// emitted in the object for the translation unit containing the definition of
// the key function. This is unique if the key function is not inline.
// - Otherwise, the tables are emitted in every object that references any of
// them.
if (RD->isInNamedModule())
return RD->shouldEmitInExternalSource();

// Otherwise, if the class doesn't have a key function (possibly
// anymore), the vtable must be defined here.
const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
Expand All @@ -1247,7 +1222,13 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
const FunctionDecl *Def;
// Otherwise, if we don't have a definition of the key function, the
// vtable must be defined somewhere else.
return !keyFunction->hasBody(Def);
if (!keyFunction->hasBody(Def))
return true;

assert(Def && "The body of the key function is not assigned to Def?");
// If the non-inline key function comes from another module unit, the vtable
// must be defined there.
return Def->isInAnotherModuleUnit() && !Def->isInlineSpecified();
}

/// Given that we're currently at the end of the translation unit, and
Expand Down
47 changes: 27 additions & 20 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3702,6 +3702,19 @@ template <typename AttrT> static bool hasImplicitAttr(const ValueDecl *D) {
return D->isImplicit();
}

bool CodeGenModule::shouldEmitCUDAGlobalVar(const VarDecl *Global) const {
assert(LangOpts.CUDA && "Should not be called by non-CUDA languages");
// We need to emit host-side 'shadows' for all global
// device-side variables because the CUDA runtime needs their
// size and host-side address in order to provide access to
// their device-side incarnations.
return !LangOpts.CUDAIsDevice || Global->hasAttr<CUDADeviceAttr>() ||
Global->hasAttr<CUDAConstantAttr>() ||
Global->hasAttr<CUDASharedAttr>() ||
Global->getType()->isCUDADeviceBuiltinSurfaceType() ||
Global->getType()->isCUDADeviceBuiltinTextureType();
}

void CodeGenModule::EmitGlobal(GlobalDecl GD) {
const auto *Global = cast<ValueDecl>(GD.getDecl());

Expand All @@ -3726,36 +3739,27 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// Non-constexpr non-lambda implicit host device functions are not emitted
// unless they are used on device side.
if (LangOpts.CUDA) {
if (LangOpts.CUDAIsDevice) {
assert((isa<FunctionDecl>(Global) || isa<VarDecl>(Global)) &&
"Expected Variable or Function");
if (const auto *VD = dyn_cast<VarDecl>(Global)) {
if (!shouldEmitCUDAGlobalVar(VD))
return;
} else if (LangOpts.CUDAIsDevice) {
const auto *FD = dyn_cast<FunctionDecl>(Global);
if ((!Global->hasAttr<CUDADeviceAttr>() ||
(LangOpts.OffloadImplicitHostDeviceTemplates && FD &&
(LangOpts.OffloadImplicitHostDeviceTemplates &&
hasImplicitAttr<CUDAHostAttr>(FD) &&
hasImplicitAttr<CUDADeviceAttr>(FD) && !FD->isConstexpr() &&
!isLambdaCallOperator(FD) &&
!getContext().CUDAImplicitHostDeviceFunUsedByDevice.count(FD))) &&
!Global->hasAttr<CUDAGlobalAttr>() &&
!Global->hasAttr<CUDAConstantAttr>() &&
!Global->hasAttr<CUDASharedAttr>() &&
!Global->getType()->isCUDADeviceBuiltinSurfaceType() &&
!Global->getType()->isCUDADeviceBuiltinTextureType() &&
!(LangOpts.HIPStdPar && isa<FunctionDecl>(Global) &&
!Global->hasAttr<CUDAHostAttr>()))
return;
} else {
// We need to emit host-side 'shadows' for all global
// device-side variables because the CUDA runtime needs their
// size and host-side address in order to provide access to
// their device-side incarnations.

// So device-only functions are the only things we skip.
if (isa<FunctionDecl>(Global) && !Global->hasAttr<CUDAHostAttr>() &&
Global->hasAttr<CUDADeviceAttr>())
return;

assert((isa<FunctionDecl>(Global) || isa<VarDecl>(Global)) &&
"Expected Variable or Function");
}
// Device-only functions are the only things we skip.
} else if (!Global->hasAttr<CUDAHostAttr>() &&
Global->hasAttr<CUDADeviceAttr>())
return;
}

if (LangOpts.OpenMP) {
Expand Down Expand Up @@ -7165,6 +7169,9 @@ void CodeGenModule::AddDeferredUnusedCoverageMapping(Decl *D) {
SourceManager &SM = getContext().getSourceManager();
if (LimitedCoverage && SM.getMainFileID() != SM.getFileID(D->getBeginLoc()))
break;
if (!llvm::coverage::SystemHeadersCoverage &&
SM.isInSystemHeader(D->getBeginLoc()))
break;
DeferredEmptyCoverageMappingDecls.try_emplace(D, true);
break;
}
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,9 @@ class CodeGenModule : public CodeGenTypeCache {

bool isTriviallyRecursive(const FunctionDecl *F);
bool shouldEmitFunction(GlobalDecl GD);
// Whether a global variable should be emitted by CUDA/HIP host/device
// related attributes.
bool shouldEmitCUDAGlobalVar(const VarDecl *VD) const;
bool shouldOpportunisticallyEmitVTables();
/// Map used to be sure we don't emit the same CompoundLiteral twice.
llvm::DenseMap<const CompoundLiteralExpr *, llvm::GlobalVariable *>
Expand Down Expand Up @@ -972,6 +975,10 @@ class CodeGenModule : public CodeGenTypeCache {

CGPointerAuthInfo getFunctionPointerAuthInfo(QualType T);

CGPointerAuthInfo getPointerAuthInfoForPointeeType(QualType type);

CGPointerAuthInfo getPointerAuthInfoForType(QualType type);

bool shouldSignPointer(const PointerAuthSchema &Schema);
llvm::Constant *getConstantSignedPointer(llvm::Constant *Pointer,
const PointerAuthSchema &Schema,
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/CodeGen/CodeGenPGO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1044,13 +1044,17 @@ void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile))
return;

SourceManager &SM = CGM.getContext().getSourceManager();
if (!llvm::coverage::SystemHeadersCoverage &&
SM.isInSystemHeader(D->getLocation()))
return;

setFuncName(Fn);

mapRegionCounters(D);
if (CGM.getCodeGenOpts().CoverageMapping)
emitCounterRegionMapping(D);
if (PGOReader) {
SourceManager &SM = CGM.getContext().getSourceManager();
loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
computeRegionCounts(D);
applyFunctionAttributes(PGOReader, Fn);
Expand Down
9 changes: 6 additions & 3 deletions clang/lib/CodeGen/ConstantEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@ class ConstantEmitter {
/// expression is known to be a constant expression with either a fairly
/// simple type or a known simple form.
llvm::Constant *emitAbstract(const Expr *E, QualType T);
llvm::Constant *emitAbstract(SourceLocation loc, const APValue &value,
QualType T);
llvm::Constant *
emitAbstract(SourceLocation loc, const APValue &value, QualType T,
bool EnablePtrAuthFunctionTypeDiscrimination = true);

/// Try to emit the result of the given expression as an abstract constant.
llvm::Constant *tryEmitAbstract(const Expr *E, QualType T);
Expand Down Expand Up @@ -138,7 +139,9 @@ class ConstantEmitter {
llvm::Constant *tryEmitPrivate(const Expr *E, QualType T);
llvm::Constant *tryEmitPrivateForMemory(const Expr *E, QualType T);

llvm::Constant *tryEmitPrivate(const APValue &value, QualType T);
llvm::Constant *
tryEmitPrivate(const APValue &value, QualType T,
bool EnablePtrAuthFunctionTypeDiscrimination = true);
llvm::Constant *tryEmitPrivateForMemory(const APValue &value, QualType T);

/// Get the address of the current location. This is a constant
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2161,9 +2161,6 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
if (!canSpeculativelyEmitVTableAsBaseClass(RD))
return false;

if (RD->shouldEmitInExternalSource())
return false;

// For a complete-object vtable (or more specifically, for the VTT), we need
// to be able to speculatively emit the vtables of all dynamic virtual bases.
for (const auto &B : RD->vbases()) {
Expand Down
43 changes: 13 additions & 30 deletions clang/lib/CodeGen/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,37 +120,20 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
if (!FD)
return;

const auto *TA = FD->getAttr<TargetAttr>();
if (TA == nullptr)
return;

ParsedTargetAttr Attr =
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
if (Attr.BranchProtection.empty())
return;

TargetInfo::BranchProtectionInfo BPI;
StringRef Error;
(void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
Attr.CPU, BPI, Error);
assert(Error.empty());

auto *Fn = cast<llvm::Function>(GV);
Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());

if (BPI.SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None) {
Fn->addFnAttr("sign-return-address-key",
BPI.SignKey == LangOptions::SignReturnAddressKeyKind::AKey
? "a_key"
: "b_key");
TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());

if (const auto *TA = FD->getAttr<TargetAttr>()) {
ParsedTargetAttr Attr =
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
if (!Attr.BranchProtection.empty()) {
StringRef Error;
(void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
Attr.CPU, BPI, Error);
assert(Error.empty());
}
}

Fn->addFnAttr("branch-target-enforcement",
BPI.BranchTargetEnforcement ? "true" : "false");
Fn->addFnAttr("branch-protection-pauth-lr",
BPI.BranchProtectionPAuthLR ? "true" : "false");
Fn->addFnAttr("guarded-control-stack",
BPI.GuardedControlStack ? "true" : "false");
auto *Fn = cast<llvm::Function>(GV);
BPI.setFnAttributes(*Fn);
}

bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/CodeGen/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
ParsedTargetAttr Attr =
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
if (!Attr.BranchProtection.empty()) {
TargetInfo::BranchProtectionInfo BPI;
TargetInfo::BranchProtectionInfo BPI{};
StringRef DiagMsg;
StringRef Arch =
Attr.CPU.empty() ? CGM.getTarget().getTargetOpts().CPU : Attr.CPU;
Expand All @@ -152,9 +152,7 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
diag::warn_target_unsupported_branch_protection_attribute)
<< Arch;
} else {
Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
Fn->addFnAttr("branch-target-enforcement",
BPI.BranchTargetEnforcement ? "true" : "false");
BPI.setFnAttributes(*Fn);
}
} else if (CGM.getLangOpts().BranchTargetEnforcement ||
CGM.getLangOpts().hasSignReturnAddress()) {
Expand All @@ -167,6 +165,10 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
diag::warn_target_unsupported_branch_protection_attribute)
<< Attr.CPU;
}
} else if (CGM.getTarget().isBranchProtectionSupportedArch(
CGM.getTarget().getTargetOpts().CPU)) {
TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());
BPI.setFnAttributes(*Fn);
}

const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4367,6 +4367,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
return;
}
if (Opt == options::OPT_print_enabled_extensions &&
!C.getDefaultToolChain().getTriple().isRISCV() &&
!C.getDefaultToolChain().getTriple().isAArch64()) {
C.getDriver().Diag(diag::err_opt_not_valid_on_target)
<< "--print-enabled-extensions";
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ bool SanitizerArgs::needsFuzzerInterceptors() const {

bool SanitizerArgs::needsUbsanRt() const {
// All of these include ubsan.
if (needsAsanRt() || needsMsanRt() || needsHwasanRt() || needsTsanRt() ||
needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
if (needsAsanRt() || needsMsanRt() || needsNsanRt() || needsHwasanRt() ||
needsTsanRt() || needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||
(needsScudoRt() && !requiresMinimalRuntime()))
return false;

Expand Down
20 changes: 12 additions & 8 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,13 @@ static void getAArch64MultilibFlags(const Driver &D,
UnifiedFeatures.end());
std::vector<std::string> MArch;
for (const auto &Ext : AArch64::Extensions)
if (FeatureSet.contains(Ext.PosTargetFeature))
MArch.push_back(Ext.UserVisibleName.str());
if (!Ext.UserVisibleName.empty())
if (FeatureSet.contains(Ext.PosTargetFeature))
MArch.push_back(Ext.UserVisibleName.str());
for (const auto &Ext : AArch64::Extensions)
if (FeatureSet.contains(Ext.NegTargetFeature))
MArch.push_back(("no" + Ext.UserVisibleName).str());
if (!Ext.UserVisibleName.empty())
if (FeatureSet.contains(Ext.NegTargetFeature))
MArch.push_back(("no" + Ext.UserVisibleName).str());
StringRef ArchName;
for (const auto &ArchInfo : AArch64::ArchInfos)
if (FeatureSet.contains(ArchInfo->ArchFeature))
Expand All @@ -221,11 +223,13 @@ static void getARMMultilibFlags(const Driver &D,
UnifiedFeatures.end());
std::vector<std::string> MArch;
for (const auto &Ext : ARM::ARCHExtNames)
if (FeatureSet.contains(Ext.Feature))
MArch.push_back(Ext.Name.str());
if (!Ext.Name.empty())
if (FeatureSet.contains(Ext.Feature))
MArch.push_back(Ext.Name.str());
for (const auto &Ext : ARM::ARCHExtNames)
if (FeatureSet.contains(Ext.NegFeature))
MArch.push_back(("no" + Ext.Name).str());
if (!Ext.Name.empty())
if (FeatureSet.contains(Ext.NegFeature))
MArch.push_back(("no" + Ext.Name).str());
MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
Result.push_back(llvm::join(MArch, "+"));

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
if (Args.hasArg(options::OPT_ffixed_x28))
Features.push_back("+reserve-x28");

if (Args.hasArg(options::OPT_mlr_for_calls_only))
Features.push_back("+reserve-lr-for-ra");

if (Args.hasArg(options::OPT_fcall_saved_x8))
Features.push_back("+call-saved-x8");

Expand Down
8 changes: 3 additions & 5 deletions clang/lib/Driver/ToolChains/Arch/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,11 +591,9 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,

// Add CPU features for generic CPUs
if (CPUName == "native") {
llvm::StringMap<bool> HostFeatures;
if (llvm::sys::getHostCPUFeatures(HostFeatures))
for (auto &F : HostFeatures)
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
for (auto &F : llvm::sys::getHostCPUFeatures())
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
} else if (!CPUName.empty()) {
// This sets the default features for the specified CPU. We certainly don't
// want to override the features that have been explicitly specified on the
Expand Down
8 changes: 3 additions & 5 deletions clang/lib/Driver/ToolChains/Arch/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,9 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
// If -march=native, autodetect the feature list.
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
if (StringRef(A->getValue()) == "native") {
llvm::StringMap<bool> HostFeatures;
if (llvm::sys::getHostCPUFeatures(HostFeatures))
for (auto &F : HostFeatures)
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
for (auto &F : llvm::sys::getHostCPUFeatures())
Features.push_back(
Args.MakeArgString((F.second ? "+" : "-") + F.first()));
}
}

Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1789,6 +1789,9 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
options::OPT_fno_ptrauth_vtable_pointer_type_discrimination);
Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_init_fini,
options::OPT_fno_ptrauth_init_fini);
Args.addOptInFlag(
CmdArgs, options::OPT_fptrauth_function_pointer_type_discrimination,
options::OPT_fno_ptrauth_function_pointer_type_discrimination);
}

void Clang::AddLoongArchTargetArgs(const ArgList &Args,
Expand Down Expand Up @@ -6519,6 +6522,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs);
Args.AddLastArg(CmdArgs, options::OPT_fzero_call_used_regs_EQ);
Args.AddLastArg(CmdArgs, options::OPT_fraw_string_literals,
options::OPT_fno_raw_string_literals);

if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls,
Triple.hasDefaultEmulatedTLS()))
Expand Down
14 changes: 9 additions & 5 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
HelperStaticRuntimes.push_back("memprof-preinit");
}
if (SanArgs.needsNsanRt())
SharedRuntimes.push_back("nsan");
if (SanArgs.needsUbsanRt()) {
if (SanArgs.requiresMinimalRuntime())
SharedRuntimes.push_back("ubsan_minimal");
Expand Down Expand Up @@ -1479,7 +1481,7 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("msan_cxx");
}
if (SanArgs.needsNsanRt())
if (!SanArgs.needsSharedRt() && SanArgs.needsNsanRt())
StaticRuntimes.push_back("nsan");
if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt()) {
StaticRuntimes.push_back("tsan");
Expand Down Expand Up @@ -1532,6 +1534,12 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
RequiredSymbols);
}

// -u options must be added before the runtime libs that resolve them.
for (auto S : RequiredSymbols) {
CmdArgs.push_back("-u");
CmdArgs.push_back(Args.MakeArgString(S));
}

// Inject libfuzzer dependencies.
if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() &&
!Args.hasArg(options::OPT_shared)) {
Expand Down Expand Up @@ -1564,10 +1572,6 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
addSanitizerRuntime(TC, Args, CmdArgs, RT, false, false);
AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
}
for (auto S : RequiredSymbols) {
CmdArgs.push_back("-u");
CmdArgs.push_back(Args.MakeArgString(S));
}
// If there is a static runtime with no dynamic list, force all the symbols
// to be dynamic to be sure we export sanitizer interface functions.
if (AddExportDynamic)
Expand Down
32 changes: 20 additions & 12 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,26 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input,

void Flang::addFortranDialectOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
Args.addAllArgs(
CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
options::OPT_ffixed_line_length_EQ, options::OPT_fopenacc,
options::OPT_finput_charset_EQ, options::OPT_fimplicit_none,
options::OPT_fno_implicit_none, options::OPT_fbackslash,
options::OPT_fno_backslash, options::OPT_flogical_abbreviations,
options::OPT_fno_logical_abbreviations,
options::OPT_fxor_operator, options::OPT_fno_xor_operator,
options::OPT_falternative_parameter_statement,
options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8, options::OPT_flarge_sizes,
options::OPT_fno_automatic});
Args.addAllArgs(CmdArgs, {options::OPT_ffixed_form,
options::OPT_ffree_form,
options::OPT_ffixed_line_length_EQ,
options::OPT_fopenacc,
options::OPT_finput_charset_EQ,
options::OPT_fimplicit_none,
options::OPT_fno_implicit_none,
options::OPT_fbackslash,
options::OPT_fno_backslash,
options::OPT_flogical_abbreviations,
options::OPT_fno_logical_abbreviations,
options::OPT_fxor_operator,
options::OPT_fno_xor_operator,
options::OPT_falternative_parameter_statement,
options::OPT_fdefault_real_8,
options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8,
options::OPT_flarge_sizes,
options::OPT_fno_automatic,
options::OPT_fhermetic_module_files});
}

void Flang::addPreprocessingOptions(const ArgList &Args,
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2564,9 +2564,11 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"riscv64-unknown-elf"};

static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
static const char *const SPARCv8Triples[] = {"sparcv8-linux-gnu"};
static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
"sparcv8-linux-gnu"};
static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib"};
static const char *const SPARCv9Triples[] = {"sparcv9-linux-gnu"};
static const char *const SPARCv9Triples[] = {"sparc64-linux-gnu",
"sparcv9-linux-gnu"};

static const char *const SystemZLibDirs[] = {"/lib64", "/lib"};
static const char *const SystemZTriples[] = {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/HLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain {
static std::optional<std::string> parseTargetProfile(StringRef TargetProfile);
bool requiresValidation(llvm::opt::DerivedArgList &Args) const;

// Set default DWARF version to 4 for DXIL uses version 4.
unsigned GetDefaultDwarfVersion() const override { return 4; }

private:
mutable std::unique_ptr<tools::hlsl::Validator> Validator;
};
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ namespace format {
TYPE(ForEachMacro) \
TYPE(FunctionAnnotationRParen) \
TYPE(FunctionDeclarationName) \
TYPE(FunctionDeclarationLParen) \
TYPE(FunctionLBrace) \
TYPE(FunctionLikeOrFreestandingMacro) \
TYPE(FunctionTypeLParen) \
Expand Down
24 changes: 18 additions & 6 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3539,7 +3539,8 @@ static unsigned maxNestingDepth(const AnnotatedLine &Line) {

// Returns the name of a function with no return type, e.g. a constructor or
// destructor.
static FormatToken *getFunctionName(const AnnotatedLine &Line) {
static FormatToken *getFunctionName(const AnnotatedLine &Line,
FormatToken *&OpeningParen) {
for (FormatToken *Tok = Line.getFirstNonComment(), *Name = nullptr; Tok;
Tok = Tok->getNextNonComment()) {
// Skip C++11 attributes both before and after the function name.
Expand All @@ -3552,10 +3553,12 @@ static FormatToken *getFunctionName(const AnnotatedLine &Line) {

// Make sure the name is followed by a pair of parentheses.
if (Name) {
return Tok->is(tok::l_paren) && Tok->isNot(TT_FunctionTypeLParen) &&
Tok->MatchingParen
? Name
: nullptr;
if (Tok->is(tok::l_paren) && Tok->isNot(TT_FunctionTypeLParen) &&
Tok->MatchingParen) {
OpeningParen = Tok;
return Name;
}
return nullptr;
}

// Skip keywords that may precede the constructor/destructor name.
Expand Down Expand Up @@ -3632,10 +3635,13 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
ExprParser.parse();

if (IsCpp) {
auto *Tok = getFunctionName(Line);
FormatToken *OpeningParen = nullptr;
auto *Tok = getFunctionName(Line, OpeningParen);
if (Tok && ((!Scopes.empty() && Scopes.back() == ST_Class) ||
Line.endsWith(TT_FunctionLBrace) || isCtorOrDtorName(Tok))) {
Tok->setFinalizedType(TT_CtorDtorDeclName);
assert(OpeningParen);
OpeningParen->setFinalizedType(TT_FunctionDeclarationLParen);
}
}

Expand Down Expand Up @@ -3864,6 +3870,12 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
Tok->setFinalizedType(TT_FunctionDeclarationName);
LineIsFunctionDeclaration = true;
SeenName = true;
if (ClosingParen) {
auto *OpeningParen = ClosingParen->MatchingParen;
assert(OpeningParen);
if (OpeningParen->is(TT_Unknown))
OpeningParen->setType(TT_FunctionDeclarationLParen);
}
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/WhitespaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ void WhitespaceManager::alignTrailingComments() {
// leave the comments.
if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
break;
C.Spaces = OriginalSpaces;
C.Spaces = C.NewlinesBefore > 0 ? C.Tok->OriginalColumn : OriginalSpaces;
continue;
}

Expand Down
23 changes: 21 additions & 2 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,19 @@ static bool FixupInvocation(CompilerInvocation &Invocation,
LangOpts.NewAlignOverride = 0;
}

// The -f[no-]raw-string-literals option is only valid in C and in C++
// standards before C++11.
if (LangOpts.CPlusPlus11) {
if (Args.hasArg(OPT_fraw_string_literals, OPT_fno_raw_string_literals)) {
Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals);
Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11)
<< bool(LangOpts.RawStringLiterals);
}

// Do not allow disabling raw string literals in C++11 or later.
LangOpts.RawStringLiterals = true;
}

// Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.
if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)
Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"
Expand Down Expand Up @@ -1466,8 +1479,10 @@ void CompilerInvocation::setDefaultPointerAuthOptions(
using Key = PointerAuthSchema::ARM8_3Key;
using Discrimination = PointerAuthSchema::Discrimination;
// If you change anything here, be sure to update <ptrauth.h>.
Opts.FunctionPointers =
PointerAuthSchema(Key::ASIA, false, Discrimination::None);
Opts.FunctionPointers = PointerAuthSchema(
Key::ASIA, false,
LangOpts.PointerAuthFunctionTypeDiscrimination ? Discrimination::Type
: Discrimination::None);

Opts.CXXVTablePointers = PointerAuthSchema(
Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,
Expand Down Expand Up @@ -3398,6 +3413,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
if (Opts.PointerAuthInitFini)
GenerateArg(Consumer, OPT_fptrauth_init_fini);
if (Opts.PointerAuthFunctionTypeDiscrimination)
GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);
}

static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Expand All @@ -3411,6 +3428,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Opts.PointerAuthVTPtrTypeDiscrimination =
Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);
Opts.PointerAuthFunctionTypeDiscrimination =
Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination);
}

/// Check if input file kind and language standard are compatible.
Expand Down
11 changes: 9 additions & 2 deletions clang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -841,9 +841,16 @@ static StringRef ModuleKindName(Module::ModuleKind MK) {
}

void DumpModuleInfoAction::ExecuteAction() {
assert(isCurrentFileAST() && "dumping non-AST?");
// Set up the output file.
CompilerInstance &CI = getCompilerInstance();

// Don't process files of type other than module to avoid crash
if (!isCurrentFileAST()) {
CI.getDiagnostics().Report(diag::err_file_is_not_module)
<< getCurrentFile();
return;
}

// Set up the output file.
StringRef OutputFileName = CI.getFrontendOpts().OutputFile;
if (!OutputFileName.empty() && OutputFileName != "-") {
std::error_code EC;
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ static T PickFP(const llvm::fltSemantics *Sem, T IEEEHalfVal, T IEEESingleVal,

static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix,
const llvm::fltSemantics *Sem, StringRef Ext) {
const char *DenormMin, *Epsilon, *Max, *Min;
const char *DenormMin, *NormMax, *Epsilon, *Max, *Min;
NormMax = PickFP(Sem, "6.5504e+4", "3.40282347e+38",
"1.7976931348623157e+308", "1.18973149535723176502e+4932",
"8.98846567431157953864652595394501e+307",
"1.18973149535723176508575932662800702e+4932");
DenormMin = PickFP(Sem, "5.9604644775390625e-8", "1.40129846e-45",
"4.9406564584124654e-324", "3.64519953188247460253e-4951",
"4.94065645841246544176568792868221e-324",
Expand Down Expand Up @@ -144,6 +148,7 @@ static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix,
DefPrefix += "_";

Builder.defineMacro(DefPrefix + "DENORM_MIN__", Twine(DenormMin)+Ext);
Builder.defineMacro(DefPrefix + "NORM_MAX__", Twine(NormMax)+Ext);
Builder.defineMacro(DefPrefix + "HAS_DENORM__");
Builder.defineMacro(DefPrefix + "DIG__", Twine(Digits));
Builder.defineMacro(DefPrefix + "DECIMAL_DIG__", Twine(DecimalDigits));
Expand Down
26 changes: 26 additions & 0 deletions clang/lib/Headers/arm_acle.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ static __inline__ void __attribute__((__always_inline__, __nodebug__)) __yield(v
#define __dbg(t) __builtin_arm_dbg(t)
#endif

#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE
#define _CHKFEAT_GCS 1
static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__chkfeat(uint64_t __features) {
return __builtin_arm_chkfeat(__features) ^ __features;
}
#endif

/* 7.5 Swap */
static __inline__ uint32_t __attribute__((__always_inline__, __nodebug__))
__swp(uint32_t __x, volatile uint32_t *__p) {
Expand Down Expand Up @@ -855,6 +863,24 @@ __rndrrs(uint64_t *__p) {
}
#endif

/* 11.2 Guarded Control Stack intrinsics */
#if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE
static __inline__ void * __attribute__((__always_inline__, __nodebug__))
__gcspr() {
return (void *)__builtin_arm_rsr64("gcspr_el0");
}

static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__, target("gcs")))
__gcspopm() {
return __builtin_arm_gcspopm(0);
}

static __inline__ const void * __attribute__((__always_inline__, __nodebug__, target("gcs")))
__gcsss(const void *__stack) {
return __builtin_arm_gcsss(__stack);
}
#endif

#if defined(__cplusplus)
}
#endif
Expand Down
76 changes: 38 additions & 38 deletions clang/lib/Headers/avx512fp16intrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ _mm512_set_ph(_Float16 __h1, _Float16 __h2, _Float16 __h3, _Float16 __h4,
(h5), (h4), (h3), (h2), (h1))

static __inline __m512h __DEFAULT_FN_ATTRS512
_mm512_set1_pch(_Float16 _Complex h) {
return (__m512h)_mm512_set1_ps(__builtin_bit_cast(float, h));
_mm512_set1_pch(_Float16 _Complex __h) {
return (__m512h)_mm512_set1_ps(__builtin_bit_cast(float, __h));
}

static __inline__ __m128 __DEFAULT_FN_ATTRS128 _mm_castph_ps(__m128h __a) {
Expand Down Expand Up @@ -282,75 +282,75 @@ _mm512_zextph256_ph512(__m256h __a) {
#define _mm_comi_sh(A, B, pred) \
_mm_comi_round_sh((A), (B), (pred), _MM_FROUND_CUR_DIRECTION)

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_EQ_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_EQ_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_LT_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_LT_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_LE_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_LE_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_GT_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_GT_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_GE_OS,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_GE_OS,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_NEQ_US,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_NEQ_US,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomieq_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_EQ_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomieq_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_EQ_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomilt_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_LT_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomilt_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_LT_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomile_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_LE_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomile_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_LE_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomigt_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_GT_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomigt_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_GT_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomige_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_GE_OQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomige_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_GE_OQ,
_MM_FROUND_CUR_DIRECTION);
}

static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomineq_sh(__m128h A,
__m128h B) {
return __builtin_ia32_vcomish((__v8hf)A, (__v8hf)B, _CMP_NEQ_UQ,
static __inline__ int __DEFAULT_FN_ATTRS128 _mm_ucomineq_sh(__m128h __A,
__m128h __B) {
return __builtin_ia32_vcomish((__v8hf)__A, (__v8hf)__B, _CMP_NEQ_UQ,
_MM_FROUND_CUR_DIRECTION);
}

Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Headers/cpuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,4 +339,13 @@ static __inline int __get_cpuid_count (unsigned int __leaf,
return 1;
}

// In some configurations, __cpuidex is defined as a builtin (primarily
// -fms-extensions) which will conflict with the __cpuidex definition below.
#if !(__has_builtin(__cpuidex))
static __inline void __cpuidex(int __cpu_info[4], int __leaf, int __subleaf) {
__cpuid_count(__leaf, __subleaf, __cpu_info[0], __cpu_info[1], __cpu_info[2],
__cpu_info[3]);
}
#endif

#endif /* __CPUID_H */
10 changes: 10 additions & 0 deletions clang/lib/Headers/float.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@
# undef DBL_HAS_SUBNORM
# undef LDBL_HAS_SUBNORM
# endif
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
!defined(__STRICT_ANSI__)
# undef FLT_NORM_MAX
# undef DBL_NORM_MAX
# undef LDBL_NORM_MAX
#endif
#endif

#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
Expand Down Expand Up @@ -166,6 +172,10 @@
/* C23 5.2.5.3.3p29-30 */
# define INFINITY (__builtin_inff())
# define NAN (__builtin_nanf(""))
/* C23 5.2.5.3.3p32 */
# define FLT_NORM_MAX __FLT_NORM_MAX__
# define DBL_NORM_MAX __DBL_NORM_MAX__
# define LDBL_NORM_MAX __LDBL_NORM_MAX__
#endif

#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/InstallAPI/DylibVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,18 @@ bool DylibVerifier::shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx,

bool DylibVerifier::shouldIgnoreReexport(const Record *R,
SymbolContext &SymCtx) const {
StringRef SymName = SymCtx.SymbolName;
// Linker directive symbols can never be ignored.
if (SymName.starts_with("$ld$"))
return false;

if (Reexports.empty())
return false;

for (const InterfaceFile &Lib : Reexports) {
if (!Lib.hasTarget(Ctx.Target))
continue;
if (auto Sym =
Lib.getSymbol(SymCtx.Kind, SymCtx.SymbolName, SymCtx.ObjCIFKind))
if (auto Sym = Lib.getSymbol(SymCtx.Kind, SymName, SymCtx.ObjCIFKind))
if ((*Sym)->hasTarget(Ctx.Target))
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Lex/DependencyDirectivesScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ struct Scanner {
// Set the lexer to use 'tok::at' for '@', instead of 'tok::unknown'.
LangOpts.ObjC = true;
LangOpts.LineComment = true;
// FIXME: we do not enable C11 or C++11, so we are missing u/u8/U"" and
// R"()" literals.
LangOpts.RawStringLiterals = true;
// FIXME: we do not enable C11 or C++11, so we are missing u/u8/U"".
return LangOpts;
}

Expand Down
Loading