27 changes: 27 additions & 0 deletions clang/include/clang/AST/ASTMutationListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace clang {
class FunctionTemplateDecl;
class Module;
class NamedDecl;
class NamespaceDecl;
class ObjCCategoryDecl;
class ObjCContainerDecl;
class ObjCInterfaceDecl;
Expand All @@ -35,6 +36,7 @@ namespace clang {
class QualType;
class RecordDecl;
class TagDecl;
class TranslationUnitDecl;
class ValueDecl;
class VarDecl;
class VarTemplateDecl;
Expand Down Expand Up @@ -147,6 +149,31 @@ class ASTMutationListener {
virtual void AddedAttributeToRecord(const Attr *Attr,
const RecordDecl *Record) {}

/// The parser find the named module declaration.
virtual void EnteringModulePurview() {}

/// An mangling number was added to a Decl
///
/// \param D The decl that got a mangling number
///
/// \param Number The mangling number that was added to the Decl
virtual void AddedManglingNumber(const Decl *D, unsigned Number) {}

/// An static local number was added to a Decl
///
/// \param D The decl that got a static local number
///
/// \param Number The static local number that was added to the Decl
virtual void AddedStaticLocalNumbers(const Decl *D, unsigned Number) {}

/// An anonymous namespace was added the translation unit decl
///
/// \param TU The translation unit decl that got a new anonymous namespace
///
/// \param AnonNamespace The anonymous namespace that was added
virtual void AddedAnonymousNamespace(const TranslationUnitDecl *TU,
NamespaceDecl *AnonNamespace) {}

// NOTE: If new methods are added they should also be added to
// MultiplexASTMutationListener.
};
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class TranslationUnitDecl : public Decl,
ASTContext &getASTContext() const { return Ctx; }

NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; }
void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; }
void setAnonymousNamespace(NamespaceDecl *D);

static TranslationUnitDecl *Create(ASTContext &C);

Expand Down Expand Up @@ -3149,7 +3149,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
bool isBitField() const { return BitField; }

/// Determines whether this is an unnamed bitfield.
bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); }
bool isUnnamedBitField() const { return isBitField() && !getDeclName(); }

/// Determines whether this field is a
/// representative for an anonymous struct or union. Such fields are
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def err_no_matching_target : Error<"no matching target found for target variant
def err_unsupported_vendor : Error<"vendor '%0' is not supported: '%1'">;
def err_unsupported_environment : Error<"environment '%0' is not supported: '%1'">;
def err_unsupported_os : Error<"os '%0' is not supported: '%1'">;
def err_cannot_read_alias_list : Error<"could not read alias list '%0': %1">;
} // end of command line category.

let CategoryName = "Verification" in {
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3669,6 +3669,9 @@ def warn_attribute_dllexport_explicit_instantiation_decl : Warning<
def warn_attribute_dllexport_explicit_instantiation_def : Warning<
"'dllexport' attribute ignored on explicit instantiation definition">,
InGroup<IgnoredAttributes>;
def warn_attribute_exclude_from_explicit_instantiation_local_class : Warning<
"%0 attribute ignored on local class%select{| member}1">,
InGroup<IgnoredAttributes>;
def warn_invalid_initializer_from_system_header : Warning<
"invalid constructor from class in system header, should not be explicit">,
InGroup<DiagGroup<"invalid-initializer-from-system-header">>;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,7 @@ def end_no_unused_arguments : Flag<["--"], "end-no-unused-arguments">,
def interface_stub_version_EQ : JoinedOrSeparate<["-"], "interface-stub-version=">,
Visibility<[ClangOption, CC1Option]>;
def exported__symbols__list : Separate<["-"], "exported_symbols_list">;
def alias_list : Separate<["-"], "alias_list">, Flags<[LinkerInput]>;
def extract_api : Flag<["-"], "extract-api">,
Visibility<[ClangOption, CC1Option]>, Group<Action_Group>,
HelpText<"Extract API information">;
Expand Down
15 changes: 10 additions & 5 deletions clang/include/clang/InstallAPI/DylibVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
DylibVerifier() = default;

DylibVerifier(llvm::MachO::Records &&Dylib, ReexportedInterfaces &&Reexports,
DiagnosticsEngine *Diag, VerificationMode Mode, bool Zippered,
bool Demangle, StringRef DSYMPath)
: Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), Mode(Mode),
Zippered(Zippered), Demangle(Demangle), DSYMPath(DSYMPath),
AliasMap Aliases, DiagnosticsEngine *Diag,
VerificationMode Mode, bool Zippered, bool Demangle,
StringRef DSYMPath)
: Dylib(std::move(Dylib)), Reexports(std::move(Reexports)),
Aliases(std::move(Aliases)), Mode(Mode), Zippered(Zippered),
Demangle(Demangle), DSYMPath(DSYMPath),
Exports(std::make_unique<SymbolSet>()), Ctx(VerifierContext{Diag}) {}

Result verify(GlobalRecord *R, const FrontendAttrs *FA);
Expand All @@ -104,7 +106,7 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
void setTarget(const Target &T);

/// Release ownership over exports.
std::unique_ptr<SymbolSet> getExports() { return std::move(Exports); }
std::unique_ptr<SymbolSet> takeExports();

/// Get result of verification.
Result getState() const { return Ctx.FrontendState; }
Expand Down Expand Up @@ -189,6 +191,9 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
// Reexported interfaces apart of the library.
ReexportedInterfaces Reexports;

// Symbol aliases.
AliasMap Aliases;

// Controls what class of violations to report.
VerificationMode Mode = VerificationMode::Invalid;

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/InstallAPI/MachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "llvm/TextAPI/TextAPIWriter.h"
#include "llvm/TextAPI/Utils.h"

using AliasMap = llvm::MachO::AliasMap;
using Architecture = llvm::MachO::Architecture;
using ArchitectureSet = llvm::MachO::ArchitectureSet;
using SymbolFlags = llvm::MachO::SymbolFlags;
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Sema/Scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ class Scope {
/// This is the scope of an OpenACC Compute Construct, which restricts
/// jumping into/out of it.
OpenACCComputeConstructScope = 0x10000000,

/// This is a scope of type alias declaration.
TypeAliasScope = 0x20000000,
};

private:
Expand Down Expand Up @@ -580,6 +583,9 @@ class Scope {
/// if/switch/while/for statement.
bool isControlScope() const { return getFlags() & Scope::ControlScope; }

/// Determine whether this scope is a type alias scope.
bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; }

/// Returns if rhs has a higher scope depth than this.
///
/// The caller is responsible for calling this only if one of the two scopes
Expand Down
14 changes: 14 additions & 0 deletions clang/include/clang/Serialization/ASTWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@ class ASTWriter : public ASTDeserializationListener,
/// record containing modifications to them.
DeclUpdateMap DeclUpdates;

/// DeclUpdates added during parsing the GMF. We split these from
/// DeclUpdates since we want to add these updates in GMF on need.
/// Only meaningful for reduced BMI.
DeclUpdateMap DeclUpdatesFromGMF;

using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>;

/// Map of first declarations from a chained PCH that point to the
Expand Down Expand Up @@ -554,6 +559,8 @@ class ASTWriter : public ASTDeserializationListener,
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
bool IsModule);
void WriteDeclAndTypes(ASTContext &Context);
void PrepareWritingSpecialDecls(Sema &SemaRef);
void WriteSpecialDeclRecords(Sema &SemaRef);
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
void WriteFPPragmaOptions(const FPOptionsOverride &Opts);
Expand Down Expand Up @@ -707,6 +714,8 @@ class ASTWriter : public ASTDeserializationListener,

/// Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordDataImpl &Record);
// Emit a reference to a declaration if the declaration was emitted.
void AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record);

/// Force a declaration to be emitted and get its ID.
serialization::DeclID GetDeclRef(const Decl *D);
Expand Down Expand Up @@ -866,6 +875,11 @@ class ASTWriter : public ASTDeserializationListener,
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
void AddedAttributeToRecord(const Attr *Attr,
const RecordDecl *Record) override;
void EnteringModulePurview() override;
void AddedManglingNumber(const Decl *D, unsigned) override;
void AddedStaticLocalNumbers(const Decl *D, unsigned) override;
void AddedAnonymousNamespace(const TranslationUnitDecl *,
NamespaceDecl *AnonNamespace) override;
};

/// AST and semantic-analysis consumer that generates a
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/APValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,8 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy,
for (const auto *FI : RD->fields()) {
if (!First)
Out << ", ";
if (FI->isUnnamedBitfield()) continue;
if (FI->isUnnamedBitField())
continue;
getStructField(FI->getFieldIndex()).
printPretty(Out, Policy, FI->getType(), Ctx);
First = false;
Expand Down
20 changes: 15 additions & 5 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2684,7 +2684,7 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context,
if (Field->isBitField()) {
// If we have explicit padding bits, they don't contribute bits
// to the actual object representation, so return 0.
if (Field->isUnnamedBitfield())
if (Field->isUnnamedBitField())
return 0;

int64_t BitfieldSize = Field->getBitWidthValue(Context);
Expand Down Expand Up @@ -12245,8 +12245,13 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth,
}

void ASTContext::setManglingNumber(const NamedDecl *ND, unsigned Number) {
if (Number > 1)
MangleNumbers[ND] = Number;
if (Number <= 1)
return;

MangleNumbers[ND] = Number;

if (Listener)
Listener->AddedManglingNumber(ND, Number);
}

unsigned ASTContext::getManglingNumber(const NamedDecl *ND,
Expand All @@ -12265,8 +12270,13 @@ unsigned ASTContext::getManglingNumber(const NamedDecl *ND,
}

void ASTContext::setStaticLocalNumber(const VarDecl *VD, unsigned Number) {
if (Number > 1)
StaticLocalNumbers[VD] = Number;
if (Number <= 1)
return;

StaticLocalNumbers[VD] = Number;

if (Listener)
Listener->AddedStaticLocalNumbers(VD, Number);
}

unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const {
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4597,7 +4597,7 @@ unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
}

bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const {
return isUnnamedBitfield() && !getBitWidth()->isValueDependent() &&
return isUnnamedBitField() && !getBitWidth()->isValueDependent() &&
getBitWidthValue(Ctx) == 0;
}

Expand Down Expand Up @@ -5274,6 +5274,13 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
}

void TranslationUnitDecl::setAnonymousNamespace(NamespaceDecl *D) {
AnonymousNamespace = D;

if (ASTMutationListener *Listener = Ctx.getASTMutationListener())
Listener->AddedAnonymousNamespace(this, D);
}

void PragmaCommentDecl::anchor() {}

PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C,
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType(
for (auto *FD : X->fields()) {
// FIXME: Should we really care about the type of the first non-static
// data member of a non-union if there are preceding unnamed bit-fields?
if (FD->isUnnamedBitfield())
if (FD->isUnnamedBitField())
continue;

if (!IsFirstField && !FD->isZeroSize(Ctx))
Expand Down Expand Up @@ -947,7 +947,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// A declaration for a bit-field that omits the identifier declares an
// unnamed bit-field. Unnamed bit-fields are not members and cannot be
// initialized.
if (Field->isUnnamedBitfield()) {
if (Field->isUnnamedBitField()) {
// C++ [meta.unary.prop]p4: [LWG2358]
// T is a class type [...] with [...] no unnamed bit-fields of non-zero
// length
Expand Down Expand Up @@ -3469,7 +3469,8 @@ static bool isValidStructGUID(ASTContext &Ctx, QualType T) {
return false;
auto MatcherIt = Fields.begin();
for (const FieldDecl *FD : RD->fields()) {
if (FD->isUnnamedBitfield()) continue;
if (FD->isUnnamedBitField())
continue;
if (FD->isBitField() || MatcherIt == Fields.end() ||
!(*MatcherIt)(FD->getType()))
return false;
Expand Down
36 changes: 21 additions & 15 deletions clang/lib/AST/DeclPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ namespace {
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
const TemplateParameterList *Params);
enum class AttrPosAsWritten { Default = 0, Left, Right };
void
bool
prettyPrintAttributes(const Decl *D,
AttrPosAsWritten Pos = AttrPosAsWritten::Default);
void prettyPrintPragmas(Decl *D);
Expand Down Expand Up @@ -252,16 +252,19 @@ static DeclPrinter::AttrPosAsWritten getPosAsWritten(const Attr *A,
return DeclPrinter::AttrPosAsWritten::Right;
}

void DeclPrinter::prettyPrintAttributes(const Decl *D,
// returns true if an attribute was printed.
bool DeclPrinter::prettyPrintAttributes(const Decl *D,
AttrPosAsWritten Pos /*=Default*/) {
if (Policy.PolishForDeclaration)
return;
bool hasPrinted = false;

if (D->hasAttrs()) {
const AttrVec &Attrs = D->getAttrs();
for (auto *A : Attrs) {
if (A->isInherited() || A->isImplicit())
continue;
// Print out the keyword attributes, they aren't regular attributes.
if (Policy.PolishForDeclaration && !A->isKeywordAttribute())
continue;
switch (A->getKind()) {
#define ATTR(X)
#define PRAGMA_SPELLING_ATTR(X) case attr::X:
Expand All @@ -275,13 +278,15 @@ void DeclPrinter::prettyPrintAttributes(const Decl *D,
if (Pos != AttrPosAsWritten::Left)
Out << ' ';
A->printPretty(Out, Policy);
hasPrinted = true;
if (Pos == AttrPosAsWritten::Left)
Out << ' ';
}
break;
}
}
}
return hasPrinted;
}

void DeclPrinter::prettyPrintPragmas(Decl *D) {
Expand Down Expand Up @@ -1065,12 +1070,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
// FIXME: add printing of pragma attributes if required.
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
Out << "__module_private__ ";
Out << D->getKindName();

prettyPrintAttributes(D);
Out << D->getKindName() << ' ';

if (D->getIdentifier()) {
// FIXME: Move before printing the decl kind to match the behavior of the
// attribute printing for variables and function where they are printed first.
if (prettyPrintAttributes(D, AttrPosAsWritten::Left))
Out << ' ';

if (D->getIdentifier()) {
if (auto *NNS = D->getQualifier())
NNS->print(Out, Policy);
Out << *D;
Expand All @@ -1087,16 +1095,13 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
}
}

if (D->hasDefinition()) {
if (D->hasAttr<FinalAttr>()) {
Out << " final";
}
}
prettyPrintAttributes(D, AttrPosAsWritten::Right);

if (D->isCompleteDefinition()) {
Out << ' ';
// Print the base classes
if (D->getNumBases()) {
Out << " : ";
Out << ": ";
for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
if (Base != D->bases_begin())
Expand All @@ -1115,14 +1120,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (Base->isPackExpansion())
Out << "...";
}
Out << ' ';
}

// Print the class definition
// FIXME: Doesn't print access specifiers, e.g., "public:"
if (Policy.TerseOutput) {
Out << " {}";
Out << "{}";
} else {
Out << " {\n";
Out << "{\n";
VisitDeclContext(D);
Indent() << "}";
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2044,7 +2044,7 @@ const FieldDecl *CastExpr::getTargetFieldForToUnionCast(const RecordDecl *RD,
for (Field = RD->field_begin(), FieldEnd = RD->field_end();
Field != FieldEnd; ++Field) {
if (Ctx.hasSameUnqualifiedType(Field->getType(), OpType) &&
!Field->isUnnamedBitfield()) {
!Field->isUnnamedBitField()) {
return *Field;
}
}
Expand Down Expand Up @@ -3393,7 +3393,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
continue;

// Don't emit anonymous bitfields, they just affect layout.
if (Field->isUnnamedBitfield())
if (Field->isUnnamedBitField())
continue;

if (ElementNo < ILE->getNumInits()) {
Expand Down
18 changes: 9 additions & 9 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2492,7 +2492,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
}
}
for (const auto *I : RD->fields()) {
if (I->isUnnamedBitfield())
if (I->isUnnamedBitField())
continue;

if (!CheckEvaluationResult(CERK, Info, DiagLoc, I->getType(),
Expand Down Expand Up @@ -3529,7 +3529,7 @@ static bool isReadByLvalueToRvalueConversion(const CXXRecordDecl *RD) {
return false;

for (auto *Field : RD->fields())
if (!Field->isUnnamedBitfield() &&
if (!Field->isUnnamedBitField() &&
isReadByLvalueToRvalueConversion(Field->getType()))
return true;

Expand Down Expand Up @@ -4898,7 +4898,7 @@ static bool handleDefaultInitValue(QualType T, APValue &Result) {
handleDefaultInitValue(I->getType(), Result.getStructBase(Index));

for (const auto *I : RD->fields()) {
if (I->isUnnamedBitfield())
if (I->isUnnamedBitField())
continue;
Success &= handleDefaultInitValue(
I->getType(), Result.getStructField(I->getFieldIndex()));
Expand Down Expand Up @@ -6436,7 +6436,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
// Default-initialize any fields with no explicit initializer.
for (; !declaresSameEntity(*FieldIt, FD); ++FieldIt) {
assert(FieldIt != RD->field_end() && "missing field?");
if (!FieldIt->isUnnamedBitfield())
if (!FieldIt->isUnnamedBitField())
Success &= handleDefaultInitValue(
FieldIt->getType(),
Result.getStructField(FieldIt->getFieldIndex()));
Expand Down Expand Up @@ -6546,7 +6546,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
// Default-initialize any remaining fields.
if (!RD->isUnion()) {
for (; FieldIt != RD->field_end(); ++FieldIt) {
if (!FieldIt->isUnnamedBitfield())
if (!FieldIt->isUnnamedBitField())
Success &= handleDefaultInitValue(
FieldIt->getType(),
Result.getStructField(FieldIt->getFieldIndex()));
Expand Down Expand Up @@ -6708,7 +6708,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceRange CallRange,
// fields first and then walk them backwards.
SmallVector<FieldDecl*, 16> Fields(RD->fields());
for (const FieldDecl *FD : llvm::reverse(Fields)) {
if (FD->isUnnamedBitfield())
if (FD->isUnnamedBitField())
continue;

LValue Subobject = This;
Expand Down Expand Up @@ -10220,7 +10220,7 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E,

for (const auto *I : RD->fields()) {
// -- if T is a reference type, no initialization is performed.
if (I->isUnnamedBitfield() || I->getType()->isReferenceType())
if (I->isUnnamedBitField() || I->getType()->isReferenceType())
continue;

LValue Subobject = This;
Expand All @@ -10243,7 +10243,7 @@ bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) {
// C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
// object's first non-static named data member is zero-initialized
RecordDecl::field_iterator I = RD->field_begin();
while (I != RD->field_end() && (*I)->isUnnamedBitfield())
while (I != RD->field_end() && (*I)->isUnnamedBitField())
++I;
if (I == RD->field_end()) {
Result = APValue((const FieldDecl*)nullptr);
Expand Down Expand Up @@ -10390,7 +10390,7 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
for (const auto *Field : RD->fields()) {
// Anonymous bit-fields are not considered members of the class for
// purposes of aggregate initialization.
if (Field->isUnnamedBitfield())
if (Field->isUnnamedBitField())
continue;

LValue Subobject = This;
Expand Down
53 changes: 34 additions & 19 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,11 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,

unsigned InitIndex = 0;
for (const Expr *Init : Inits) {
// Skip unnamed bitfields.
while (InitIndex < R->getNumFields() &&
R->getField(InitIndex)->Decl->isUnnamedBitField())
++InitIndex;

if (!this->emitDupPtr(E))
return false;

Expand Down Expand Up @@ -1838,7 +1843,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr(
const Expr *Init = E->getInitializer();
if (Initializing) {
// We already have a value, just initialize that.
return this->visitInitializer(Init);
return this->visitInitializer(Init) && this->emitFinishInit(E);
}

std::optional<PrimType> T = classify(E->getType());
Expand All @@ -1857,7 +1862,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr(
return this->emitInitGlobal(*T, *GlobalIndex, E);
}

return this->visitInitializer(Init);
return this->visitInitializer(Init) && this->emitFinishInit(E);
}

return false;
Expand Down Expand Up @@ -1886,7 +1891,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr(
}
return this->emitInit(*T, E);
} else {
if (!this->visitInitializer(Init))
if (!this->visitInitializer(Init) || !this->emitFinishInit(E))
return false;
}

Expand Down Expand Up @@ -3206,15 +3211,20 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return false;
if (!this->emitAddf(getRoundingMode(E), E))
return false;
return this->emitStoreFloat(E);
if (!this->emitStoreFloat(E))
return false;
} else {
assert(isIntegralType(*T));
if (!this->emitLoad(*T, E))
return false;
if (!this->emitConst(1, E))
return false;
if (!this->emitAdd(*T, E))
return false;
if (!this->emitStore(*T, E))
return false;
}
if (!this->emitLoad(*T, E))
return false;
if (!this->emitConst(1, E))
return false;
if (!this->emitAdd(*T, E))
return false;
return this->emitStore(*T, E);
return E->isGLValue() || this->emitLoadPop(*T, E);
}
case UO_PreDec: { // --x
if (!this->visit(SubExpr))
Expand Down Expand Up @@ -3245,15 +3255,20 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return false;
if (!this->emitSubf(getRoundingMode(E), E))
return false;
return this->emitStoreFloat(E);
if (!this->emitStoreFloat(E))
return false;
} else {
assert(isIntegralType(*T));
if (!this->emitLoad(*T, E))
return false;
if (!this->emitConst(1, E))
return false;
if (!this->emitSub(*T, E))
return false;
if (!this->emitStore(*T, E))
return false;
}
if (!this->emitLoad(*T, E))
return false;
if (!this->emitConst(1, E))
return false;
if (!this->emitSub(*T, E))
return false;
return this->emitStore(*T, E);
return E->isGLValue() || this->emitLoadPop(*T, E);
}
case UO_LNot: // !x
if (DiscardResult)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/EvaluationResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
Result &= CheckFieldsInitialized(S, Loc, FieldPtr, FieldPtr.getRecord());
} else if (FieldType->isIncompleteArrayType()) {
// Nothing to do here.
} else if (F.Decl->isUnnamedBitfield()) {
} else if (F.Decl->isUnnamedBitField()) {
// Nothing do do here.
} else if (FieldType->isArrayType()) {
const auto *CAT =
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,11 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
// Reserve space for fields.
Record::FieldList Fields;
for (const FieldDecl *FD : RD->fields()) {
// Note that we DO create fields and descriptors
// for unnamed bitfields here, even though we later ignore
// them everywhere. That's because so the FieldDecl's
// getFieldIndex() matches.

// Reserve space for the field's descriptor and the offset.
BaseSize += align(sizeof(InlineDescriptor));

Expand Down
8 changes: 4 additions & 4 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6176,7 +6176,7 @@ static bool isZeroInitialized(QualType T, const APValue &V) {
}
I = 0;
for (const FieldDecl *FD : RD->fields()) {
if (!FD->isUnnamedBitfield() &&
if (!FD->isUnnamedBitField() &&
!isZeroInitialized(FD->getType(), V.getStructField(I)))
return false;
++I;
Expand All @@ -6189,7 +6189,7 @@ static bool isZeroInitialized(QualType T, const APValue &V) {
assert(RD && "unexpected type for union value");
// Zero-initialization zeroes the first non-unnamed-bitfield field, if any.
for (const FieldDecl *FD : RD->fields()) {
if (!FD->isUnnamedBitfield())
if (!FD->isUnnamedBitField())
return V.getUnionField() && declaresSameEntity(FD, V.getUnionField()) &&
isZeroInitialized(FD->getType(), V.getUnionValue());
}
Expand Down Expand Up @@ -6331,7 +6331,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
llvm::SmallVector<const FieldDecl *, 16> Fields(RD->fields());
while (
!Fields.empty() &&
(Fields.back()->isUnnamedBitfield() ||
(Fields.back()->isUnnamedBitField() ||
isZeroInitialized(Fields.back()->getType(),
V.getStructField(Fields.back()->getFieldIndex())))) {
Fields.pop_back();
Expand All @@ -6351,7 +6351,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
for (unsigned I = 0, N = Bases.size(); I != N; ++I)
mangleValueInTemplateArg(Bases[I].getType(), V.getStructBase(I), false);
for (unsigned I = 0, N = Fields.size(); I != N; ++I) {
if (Fields[I]->isUnnamedBitfield())
if (Fields[I]->isUnnamedBitField())
continue;
mangleValueInTemplateArg(Fields[I]->getType(),
V.getStructField(Fields[I]->getFieldIndex()),
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1933,7 +1933,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
for (const CXXBaseSpecifier &B : RD->bases())
mangleTemplateArgValue(B.getType(), V.getStructBase(BaseIndex++), TAK);
for (const FieldDecl *FD : RD->fields())
if (!FD->isUnnamedBitfield())
if (!FD->isUnnamedBitField())
mangleTemplateArgValue(FD->getType(),
V.getStructField(FD->getFieldIndex()), TAK,
/*WithScalarType*/ true);
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/RecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2458,6 +2458,11 @@ static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) {
}

static bool isMsLayout(const ASTContext &Context) {
// Check if it's CUDA device compilation; ensure layout consistency with host.
if (Context.getLangOpts().CUDA && Context.getLangOpts().CUDAIsDevice &&
Context.getAuxTargetInfo())
return Context.getAuxTargetInfo()->getCXXABI().isMicrosoft();

return Context.getTargetInfo().getCXXABI().isMicrosoft();
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Analysis/FlowSensitive/ASTOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ getFieldsForInitListExpr(const InitListExpr *InitList) {
// fields to avoid mapping inits to the wrongs fields.
llvm::copy_if(
RD->fields(), std::back_inserter(Fields),
[](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); });
[](const FieldDecl *Field) { return !Field->isUnnamedBitField(); });
return Fields;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Analysis/UninitializedValues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ static bool recordIsNotEmpty(const RecordDecl *RD) {
// We consider a record decl to be empty if it contains only unnamed bit-
// fields, zero-width fields, and fields of empty record type.
for (const auto *FD : RD->fields()) {
if (FD->isUnnamedBitfield())
if (FD->isUnnamedBitField())
continue;
if (FD->isZeroSize(FD->getASTContext()))
continue;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/ABIInfoImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1,

bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD,
bool AllowArrays, bool AsIfNoUniqueAddr) {
if (FD->isUnnamedBitfield())
if (FD->isUnnamedBitField())
return true;

QualType FT = FD->getType();
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3665,7 +3665,7 @@ static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset,
for (auto I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++Idx) {
const FieldDecl *F = *I;

if (F->isUnnamedBitfield() || F->isZeroLengthBitField(Context) ||
if (F->isUnnamedBitField() || F->isZeroLengthBitField(Context) ||
F->getType()->isIncompleteArrayType())
continue;

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4704,7 +4704,7 @@ unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec,
for (auto *F : Rec->getDefinition()->fields()) {
if (I == FieldIndex)
break;
if (F->isUnnamedBitfield())
if (F->isUnnamedBitField())
Skipped++;
I++;
}
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1755,7 +1755,9 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
// Make sure that it's really an empty and not a failure of
// semantic analysis.
for (const auto *Field : record->fields())
assert((Field->isUnnamedBitfield() || Field->isAnonymousStructOrUnion()) && "Only unnamed bitfields or ananymous class allowed");
assert(
(Field->isUnnamedBitField() || Field->isAnonymousStructOrUnion()) &&
"Only unnamed bitfields or ananymous class allowed");
#endif
return;
}
Expand Down Expand Up @@ -1783,7 +1785,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
break;

// Always skip anonymous bitfields.
if (field->isUnnamedBitfield())
if (field->isUnnamedBitField())
continue;

// We're done if we reach the end of the explicit initializers, we
Expand Down Expand Up @@ -1988,7 +1990,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) {
if (Field->getType()->isIncompleteArrayType() ||
ILEElement == ILE->getNumInits())
break;
if (Field->isUnnamedBitfield())
if (Field->isUnnamedBitField())
continue;

const Expr *E = ILE->getInit(ILEElement++);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RType->getDecl()))
NumElements = CXXRD->getNumBases();
for (auto *Field : RType->getDecl()->fields())
if (!Field->isUnnamedBitfield())
if (!Field->isUnnamedBitField())
++NumElements;
// FIXME: Recurse into nested InitListExprs.
if (ILE->getNumInits() == NumElements)
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) {
continue;

// Don't emit anonymous bitfields.
if (Field->isUnnamedBitfield())
if (Field->isUnnamedBitField())
continue;

// Get the initializer. A struct can include fields without initializers,
Expand Down Expand Up @@ -840,7 +840,7 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
continue;

// Don't emit anonymous bitfields or zero-sized fields.
if (Field->isUnnamedBitfield() || Field->isZeroSize(CGM.getContext()))
if (Field->isUnnamedBitField() || Field->isZeroSize(CGM.getContext()))
continue;

// Emit the value of the initializer.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenTBAA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
});
}
for (FieldDecl *Field : RD->fields()) {
if (Field->isZeroSize(Context) || Field->isUnnamedBitfield())
if (Field->isZeroSize(Context) || Field->isUnnamedBitField())
continue;
QualType FieldQTy = Field->getType();
llvm::MDNode *TypeNode = isValidBaseType(FieldQTy)
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2087,7 +2087,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
bool BitField = i->isBitField();

// Ignore padding bit-fields.
if (BitField && i->isUnnamedBitfield())
if (BitField && i->isUnnamedBitField())
continue;

// AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger than
Expand Down Expand Up @@ -2128,7 +2128,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
// structure to be passed in memory even if unaligned, and
// therefore they can straddle an eightbyte.
if (BitField) {
assert(!i->isUnnamedBitfield());
assert(!i->isUnnamedBitField());
uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
uint64_t Size = i->getBitWidthValue(getContext());

Expand Down
29 changes: 29 additions & 0 deletions clang/lib/Driver/ToolChains/AIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,30 @@ AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const {
return "/";
}

void AIX::AddOpenMPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Add OpenMP include paths if -fopenmp is specified.
if (DriverArgs.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false)) {
SmallString<128> PathOpenMP;
switch (getDriver().getOpenMPRuntime(DriverArgs)) {
case Driver::OMPRT_OMP:
PathOpenMP = GetHeaderSysroot(DriverArgs);
llvm::sys::path::append(PathOpenMP, "opt/IBM/openxlCSDK", "include",
"openmp");
addSystemInclude(DriverArgs, CC1Args, PathOpenMP.str());
break;
case Driver::OMPRT_IOMP5:
LLVM_FALLTHROUGH;
case Driver::OMPRT_GOMP:
LLVM_FALLTHROUGH;
case Driver::OMPRT_Unknown:
// Unknown / unsupported include paths.
break;
}
}
}

void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Return if -nostdinc is specified as a driver option.
Expand All @@ -380,6 +404,11 @@ void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str()));
}

// Add the include directory containing omp.h. This needs to be before
// adding the system include directory because other compilers put their
// omp.h in /usr/include.
AddOpenMPIncludeArgs(DriverArgs, CC1Args);

// Return if -nostdlibinc is specified as a driver option.
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/AIX.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ class LLVM_LIBRARY_VISIBILITY AIX : public ToolChain {
private:
llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const;
bool ParseInlineAsmUsingAsmParser;
void AddOpenMPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
};

} // end namespace toolchains
Expand Down
10 changes: 4 additions & 6 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2912,6 +2912,8 @@ class AnnotatingParser {
return TT_UnaryOperator;
if (PrevToken->is(TT_TypeName))
return TT_PointerOrReference;
if (PrevToken->isOneOf(tok::kw_new, tok::kw_delete) && Tok.is(tok::ampamp))
return TT_BinaryOperator;

const FormatToken *NextToken = Tok.getNextNonComment();

Expand Down Expand Up @@ -5595,12 +5597,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return true;
if (Left.IsUnterminatedLiteral)
return true;
// FIXME: Breaking after newlines seems useful in general. Turn this into an
// option and recognize more cases like endl etc, and break independent of
// what comes after operator lessless.
if (Right.is(tok::lessless) && Right.Next &&
Right.Next->is(tok::string_literal) && Left.is(tok::string_literal) &&
Left.TokenText.ends_with("\\n\"")) {
if (Right.is(tok::lessless) && Right.Next && Left.is(tok::string_literal) &&
Right.Next->is(tok::string_literal)) {
return true;
}
if (Right.is(TT_RequiresClause)) {
Expand Down
29 changes: 29 additions & 0 deletions clang/lib/Frontend/MultiplexConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ using namespace clang;

namespace clang {

class NamespaceDecl;
class TranslationUnitDecl;

MultiplexASTDeserializationListener::MultiplexASTDeserializationListener(
const std::vector<ASTDeserializationListener*>& L)
: Listeners(L) {
Expand Down Expand Up @@ -115,6 +118,11 @@ class MultiplexASTMutationListener : public ASTMutationListener {
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
void AddedAttributeToRecord(const Attr *Attr,
const RecordDecl *Record) override;
void EnteringModulePurview() override;
void AddedManglingNumber(const Decl *D, unsigned) override;
void AddedStaticLocalNumbers(const Decl *D, unsigned) override;
void AddedAnonymousNamespace(const TranslationUnitDecl *,
NamespaceDecl *AnonNamespace) override;

private:
std::vector<ASTMutationListener*> Listeners;
Expand Down Expand Up @@ -238,6 +246,27 @@ void MultiplexASTMutationListener::AddedAttributeToRecord(
L->AddedAttributeToRecord(Attr, Record);
}

void MultiplexASTMutationListener::EnteringModulePurview() {
for (auto *L : Listeners)
L->EnteringModulePurview();
}

void MultiplexASTMutationListener::AddedManglingNumber(const Decl *D,
unsigned Number) {
for (auto *L : Listeners)
L->AddedManglingNumber(D, Number);
}
void MultiplexASTMutationListener::AddedStaticLocalNumbers(const Decl *D,
unsigned Number) {
for (auto *L : Listeners)
L->AddedStaticLocalNumbers(D, Number);
}
void MultiplexASTMutationListener::AddedAnonymousNamespace(
const TranslationUnitDecl *TU, NamespaceDecl *AnonNamespace) {
for (auto *L : Listeners)
L->AddedAnonymousNamespace(TU, AnonNamespace);
}

} // end namespace clang

MultiplexConsumer::MultiplexConsumer(
Expand Down
24 changes: 24 additions & 0 deletions clang/lib/InstallAPI/DylibVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,11 @@ void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) {
return;
}

if (Aliases.count({SymbolName.str(), SymCtx.Kind})) {
updateState(Result::Valid);
return;
}

// All checks at this point classify as some kind of violation.
// The different verification modes dictate whether they are reported to the
// user.
Expand Down Expand Up @@ -973,5 +978,24 @@ bool DylibVerifier::verifyBinaryAttrs(const ArrayRef<Target> ProvidedTargets,
return true;
}

std::unique_ptr<SymbolSet> DylibVerifier::takeExports() {
for (const auto &[Alias, Base] : Aliases) {
TargetList Targets;
SymbolFlags Flags = SymbolFlags::None;
if (const Symbol *Sym = Exports->findSymbol(Base.second, Base.first)) {
Flags = Sym->getFlags();
Targets = {Sym->targets().begin(), Sym->targets().end()};
}

Record R(Alias.first, RecordLinkage::Exported, Flags);
SymbolContext SymCtx;
SymCtx.SymbolName = Alias.first;
SymCtx.Kind = Alias.second;
addSymbol(&R, SymCtx, std::move(Targets));
}

return std::move(Exports);
}

} // namespace installapi
} // namespace clang
5 changes: 5 additions & 0 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,11 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration(
ProhibitAttributes(PrefixAttrs);

Decl *DeclFromDeclSpec = nullptr;
Scope *CurScope = getCurScope();
if (CurScope)
CurScope->setFlags(Scope::ScopeFlags::TypeAliasScope |
CurScope->getFlags());

Decl *AD = ParseAliasDeclarationAfterDeclarator(
TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, &DeclFromDeclSpec);
return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ struct BuiltinDumpStructGenerator {
for (auto *D : RD->decls()) {
auto *IFD = dyn_cast<IndirectFieldDecl>(D);
auto *FD = IFD ? IFD->getAnonField() : dyn_cast<FieldDecl>(D);
if (!FD || FD->isUnnamedBitfield() || FD->isAnonymousStructOrUnion())
if (!FD || FD->isUnnamedBitField() || FD->isAnonymousStructOrUnion())
continue;

llvm::SmallString<20> Format = llvm::StringRef("%s%s %s ");
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19529,6 +19529,13 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
// Okay, we successfully defined 'Record'.
if (Record) {
bool Completed = false;
if (S) {
Scope *Parent = S->getParent();
if (Parent && Parent->isTypeAliasScope() &&
Parent->isTemplateParamScope())
Record->setInvalidDecl();
}

if (CXXRecord) {
if (!CXXRecord->isInvalidDecl()) {
// Set access bits correctly on the directly-declared conversions.
Expand Down Expand Up @@ -19676,7 +19683,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
E = Record->field_end();
(NonBitFields == 0 || ZeroSize) && I != E; ++I) {
IsEmpty = false;
if (I->isUnnamedBitfield()) {
if (I->isUnnamedBitField()) {
if (!I->isZeroLengthBitField(Context))
ZeroSize = false;
} else {
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,21 @@ static void handleErrorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(EA);
}

static void handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
const auto *PD = isa<CXXRecordDecl>(D)
? cast<DeclContext>(D)
: D->getDeclContext()->getRedeclContext();
if (const auto *RD = dyn_cast<CXXRecordDecl>(PD); RD && RD->isLocalClass()) {
S.Diag(AL.getLoc(),
diag::warn_attribute_exclude_from_explicit_instantiation_local_class)
<< AL << /*IsMember=*/!isa<CXXRecordDecl>(D);
return;
}
D->addAttr(::new (S.Context)
ExcludeFromExplicitInstantiationAttr(S.Context, AL));
}

namespace {
/// Determines if a given Expr references any of the given function's
/// ParmVarDecls, or the function's implicit `this` parameter (if applicable).
Expand Down Expand Up @@ -9339,6 +9354,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_Error:
handleErrorAttr(S, D, AL);
break;
case ParsedAttr::AT_ExcludeFromExplicitInstantiation:
handleExcludeFromExplicitInstantiationAttr(S, D, AL);
break;
case ParsedAttr::AT_DiagnoseIf:
handleDiagnoseIfAttr(S, D, AL);
break;
Expand Down
24 changes: 12 additions & 12 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,

auto DiagnoseBadNumberOfBindings = [&]() -> bool {
unsigned NumFields = llvm::count_if(
RD->fields(), [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); });
RD->fields(), [](FieldDecl *FD) { return !FD->isUnnamedBitField(); });
assert(Bindings.size() != NumFields);
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
<< DecompType << (unsigned)Bindings.size() << NumFields << NumFields
Expand All @@ -1466,7 +1466,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
// E shall not have an anonymous union member, ...
unsigned I = 0;
for (auto *FD : RD->fields()) {
if (FD->isUnnamedBitfield())
if (FD->isUnnamedBitField())
continue;

// All the non-static data members are required to be nameable, so they
Expand Down Expand Up @@ -2067,7 +2067,7 @@ static bool CheckConstexprCtorInitializer(Sema &SemaRef,
if (Field->isInvalidDecl())
return true;

if (Field->isUnnamedBitfield())
if (Field->isUnnamedBitField())
return true;

// Anonymous unions with no variant members and empty anonymous structs do not
Expand Down Expand Up @@ -5509,7 +5509,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
// A declaration for a bit-field that omits the identifier declares an
// unnamed bit-field. Unnamed bit-fields are not members and cannot be
// initialized.
if (F->isUnnamedBitfield())
if (F->isUnnamedBitField())
continue;

// If we're not generating the implicit copy/move constructor, then we'll
Expand Down Expand Up @@ -5638,7 +5638,7 @@ static void DiagnoseBaseOrMemInitializerOrder(

// 3. Direct fields.
for (auto *Field : ClassDecl->fields()) {
if (Field->isUnnamedBitfield())
if (Field->isUnnamedBitField())
continue;

PopulateKeysForFields(Field, IdealInitKeys);
Expand Down Expand Up @@ -7030,7 +7030,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
!Record->isLambda()) {
bool Complained = false;
for (const auto *F : Record->fields()) {
if (F->hasInClassInitializer() || F->isUnnamedBitfield())
if (F->hasInClassInitializer() || F->isUnnamedBitField())
continue;

if (F->getType()->isReferenceType() ||
Expand Down Expand Up @@ -8037,7 +8037,7 @@ class DefaultedComparisonVisitor {
for (FieldDecl *Field : Record->fields()) {
// C++23 [class.bit]p2:
// Unnamed bit-fields are not members ...
if (Field->isUnnamedBitfield())
if (Field->isUnnamedBitField())
continue;
// Recursively expand anonymous structs.
if (Field->isAnonymousStructOrUnion()) {
Expand Down Expand Up @@ -9396,7 +9396,7 @@ struct SpecialMemberVisitor {
return true;

for (auto *F : RD->fields())
if (!F->isInvalidDecl() && !F->isUnnamedBitfield() &&
if (!F->isInvalidDecl() && !F->isUnnamedBitField() &&
getDerived().visitField(F))
return true;

Expand Down Expand Up @@ -9741,7 +9741,7 @@ bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() {
AllFieldsAreConst) {
bool AnyFields = false;
for (auto *F : MD->getParent()->fields())
if ((AnyFields = !F->isUnnamedBitfield()))
if ((AnyFields = !F->isUnnamedBitField()))
break;
if (!AnyFields)
return false;
Expand Down Expand Up @@ -10134,7 +10134,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
Sema::TrivialABIHandling TAH,
bool Diagnose) {
for (const auto *FI : RD->fields()) {
if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
if (FI->isInvalidDecl() || FI->isUnnamedBitField())
continue;

QualType FieldType = S.Context.getBaseElementType(FI->getType());
Expand Down Expand Up @@ -15201,7 +15201,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
for (auto *Field : ClassDecl->fields()) {
// FIXME: We should form some kind of AST representation for the implied
// memcpy in a union copy operation.
if (Field->isUnnamedBitfield() || Field->getParent()->isUnion())
if (Field->isUnnamedBitField() || Field->getParent()->isUnion())
continue;

if (Field->isInvalidDecl()) {
Expand Down Expand Up @@ -15586,7 +15586,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
for (auto *Field : ClassDecl->fields()) {
// FIXME: We should form some kind of AST representation for the implied
// memcpy in a union copy operation.
if (Field->isUnnamedBitfield() || Field->getParent()->isUnion())
if (Field->isUnnamedBitField() || Field->getParent()->isUnion())
continue;

if (Field->isInvalidDecl()) {
Expand Down
24 changes: 12 additions & 12 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
}

for (auto *Field : RDecl->fields()) {
if (Field->isUnnamedBitfield())
if (Field->isUnnamedBitField())
continue;

if (hadError)
Expand Down Expand Up @@ -1027,7 +1027,7 @@ int InitListChecker::numStructUnionElements(QualType DeclType) {
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(structDecl))
InitializableMembers += CXXRD->getNumBases();
for (const auto *Field : structDecl->fields())
if (!Field->isUnnamedBitfield())
if (!Field->isUnnamedBitField())
++InitializableMembers;

if (structDecl->isUnion())
Expand Down Expand Up @@ -2175,7 +2175,7 @@ void InitListChecker::CheckStructUnionTypes(
// bitfield.
for (RecordDecl::field_iterator FieldEnd = RD->field_end();
Field != FieldEnd; ++Field) {
if (!Field->isUnnamedBitfield()) {
if (!Field->isUnnamedBitField()) {
CheckEmptyInitializable(
InitializedEntity::InitializeMember(*Field, &Entity),
IList->getEndLoc());
Expand Down Expand Up @@ -2338,7 +2338,7 @@ void InitListChecker::CheckStructUnionTypes(
if (Field->getType()->isIncompleteArrayType())
break;

if (Field->isUnnamedBitfield()) {
if (Field->isUnnamedBitField()) {
// Don't initialize unnamed bitfields, e.g. "int : 20;"
++Field;
continue;
Expand Down Expand Up @@ -2398,7 +2398,7 @@ void InitListChecker::CheckStructUnionTypes(
if (HasDesignatedInit && InitializedFields.count(*it))
continue;

if (!it->isUnnamedBitfield() && !it->hasInClassInitializer() &&
if (!it->isUnnamedBitField() && !it->hasInClassInitializer() &&
!it->getType()->isIncompleteArrayType()) {
auto Diag = HasDesignatedInit
? diag::warn_missing_designated_field_initializers
Expand All @@ -2414,7 +2414,7 @@ void InitListChecker::CheckStructUnionTypes(
if (!StructuredList && Field != FieldEnd && !RD->isUnion() &&
!Field->getType()->isIncompleteArrayType()) {
for (; Field != FieldEnd && !hadError; ++Field) {
if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer())
if (!Field->isUnnamedBitField() && !Field->hasInClassInitializer())
CheckEmptyInitializable(
InitializedEntity::InitializeMember(*Field, &Entity),
IList->getEndLoc());
Expand Down Expand Up @@ -2784,7 +2784,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
unsigned FieldIndex = NumBases;

for (auto *FI : RD->fields()) {
if (FI->isUnnamedBitfield())
if (FI->isUnnamedBitField())
continue;
if (declaresSameEntity(KnownField, FI)) {
KnownField = FI;
Expand Down Expand Up @@ -2858,7 +2858,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Find the field that we just initialized.
FieldDecl *PrevField = nullptr;
for (auto FI = RD->field_begin(); FI != RD->field_end(); ++FI) {
if (FI->isUnnamedBitfield())
if (FI->isUnnamedBitField())
continue;
if (*NextField != RD->field_end() &&
declaresSameEntity(*FI, **NextField))
Expand Down Expand Up @@ -2976,7 +2976,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// If this the first designator, our caller will continue checking
// the rest of this struct/class/union subobject.
if (IsFirstDesignator) {
if (Field != RD->field_end() && Field->isUnnamedBitfield())
if (Field != RD->field_end() && Field->isUnnamedBitField())
++Field;

if (NextField)
Expand Down Expand Up @@ -5585,7 +5585,7 @@ static void TryOrBuildParenListInitialization(
for (FieldDecl *FD : RD->fields()) {
// Unnamed bitfields should not be initialized at all, either with an arg
// or by default.
if (FD->isUnnamedBitfield())
if (FD->isUnnamedBitField())
continue;

InitializedEntity SubEntity =
Expand Down Expand Up @@ -7930,7 +7930,7 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
for (const auto *I : RD->fields()) {
if (Index >= ILE->getNumInits())
break;
if (I->isUnnamedBitfield())
if (I->isUnnamedBitField())
continue;
Expr *SubInit = ILE->getInit(Index);
if (I->getType()->isReferenceType())
Expand Down Expand Up @@ -9532,7 +9532,7 @@ static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc,
return false;

for (const auto *FI : RD->fields()) {
if (FI->isUnnamedBitfield())
if (FI->isUnnamedBitField())
continue;

if (DiagnoseUninitializedReference(S, FI->getLocation(), FI->getType())) {
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/SemaInternal.h"
Expand Down Expand Up @@ -475,6 +476,9 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,

getASTContext().setCurrentNamedModule(Mod);

if (auto *Listener = getASTMutationListener())
Listener->EnteringModulePurview();

// We already potentially made an implicit import (in the case of a module
// implementation unit importing its interface). Make this module visible
// and return the import decl to be added to the current TU.
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3044,6 +3044,11 @@ FunctionTemplateDecl *DeclareAggregateDeductionGuideForTypeAlias(
return nullptr;

LocalInstantiationScope Scope(SemaRef);
Sema::InstantiatingTemplate BuildingDeductionGuides(
SemaRef, AliasTemplate->getLocation(), RHSDeductionGuide,
Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
if (BuildingDeductionGuides.isInvalid())
return nullptr;

// Build a new template parameter list for the synthesized aggregate deduction
// guide by transforming the one from RHSDeductionGuide.
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4729,7 +4729,8 @@ static bool shouldHaveNullability(QualType T) {
// It's unclear whether the pragma's behavior is useful for C++.
// e.g. treating type-aliases and template-type-parameters differently
// from types of declarations can be surprising.
!isa<RecordType>(T->getCanonicalTypeInternal());
!isa<RecordType, TemplateSpecializationType>(
T->getCanonicalTypeInternal());
}

static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
Expand Down
497 changes: 311 additions & 186 deletions clang/lib/Serialization/ASTWriter.cpp

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions clang/lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@ static void checkObjCUnusedIvar(const ObjCImplementationDecl *D,
// (d) are unnamed bitfields
if (Ivar->getAccessControl() != ObjCIvarDecl::Private ||
Ivar->hasAttr<UnusedAttr>() || Ivar->hasAttr<IBOutletAttr>() ||
Ivar->hasAttr<IBOutletCollectionAttr>() ||
Ivar->isUnnamedBitfield())
Ivar->hasAttr<IBOutletCollectionAttr>() || Ivar->isUnnamedBitField())
continue;

M[Ivar] = Unused;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/StaticAnalyzer/Core/RegionStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2570,7 +2570,7 @@ std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
return std::nullopt;

for (const auto *FD : RD->fields()) {
if (FD->isUnnamedBitfield())
if (FD->isUnnamedBitField())
continue;

// If there are too many fields, or if any of the fields are aggregates,
Expand Down Expand Up @@ -2697,7 +2697,7 @@ RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B,
break;

// Skip any unnamed bitfields to stay in sync with the initializers.
if (FI->isUnnamedBitfield())
if (FI->isUnnamedBitField())
continue;

QualType FTy = FI->getType();
Expand Down
24 changes: 24 additions & 0 deletions clang/test/AST/Interp/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,27 @@ _Static_assert(funcp == (void*)0, ""); // all-error {{failed due to requirement
// pedantic-warning {{expression is not an integer constant expression}}
_Static_assert(funcp == (void*)123, ""); // pedantic-warning {{equality comparison between function pointer and void pointer}} \
// pedantic-warning {{expression is not an integer constant expression}}

void unaryops(void) {
(void)(++(struct x {unsigned x;}){3}.x);
(void)(--(struct y {unsigned x;}){3}.x);
(void)(++(struct z {float x;}){3}.x);
(void)(--(struct w {float x;}){3}.x);

(void)((struct xx {unsigned x;}){3}.x++);
(void)((struct yy {unsigned x;}){3}.x--);
(void)((struct zz {float x;}){3}.x++);
(void)((struct ww {float x;}){3}.x--);
}

/// This used to fail because we didn't properly mark the struct
/// initialized through a CompoundLiteralExpr as initialized.
struct TestStruct {
int a;
int b;
};
int Y __attribute__((annotate(
"GlobalValAnnotationWithArgs",
42,
(struct TestStruct) { .a = 1, .b = 2 }
)));
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1317,3 +1317,16 @@ namespace {
F f;
static_assert(f.Z == 12, "");
}

namespace UnnamedBitFields {
struct A {
int : 1;
double f;
int : 1;
char c;
};

constexpr A a = (A){1.0, 'a'};
static_assert(a.f == 1.0, "");
static_assert(a.c == 'a', "");
}
11 changes: 9 additions & 2 deletions clang/test/CodeGen/X86/x86-cf-protection.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
// RUN: %clang_cc1 -E -triple i386 -dM -o - -fcf-protection=return %s | FileCheck %s --check-prefix=RETURN
// RUN: %clang_cc1 -E -triple i386 -dM -o - -fcf-protection=branch %s | FileCheck %s --check-prefix=BRANCH
// RUN: %clang_cc1 -E -triple i386 -dM -o - -fcf-protection=full %s | FileCheck %s --check-prefix=FULL
// RUN: %clang_cc1 -E -triple=x86_64 -dM -o - -fcf-protection=none %s | FileCheck %s --check-prefix=NOTCET
// RUN: not %clang_cc1 -emit-llvm-only -triple i386 -target-cpu pentium-mmx -fcf-protection=branch %s 2>&1 | FileCheck %s --check-prefix=NOCFPROT
// RUN: %clang_cc1 -triple=x86_64 -o - -fcf-protection=return %s -emit-llvm | FileCheck %s --check-prefixes=CFPROTR,CFPROTNONE
// RUN: %clang_cc1 -triple=x86_64 -o - -fcf-protection=branch %s -emit-llvm | FileCheck %s --check-prefixes=CFPROTB,CFPROTNONE
// RUN: %clang_cc1 -triple=x86_64 -o - -fcf-protection=full %s -emit-llvm | FileCheck %s --check-prefixes=CFPROTR,CFPROTB,CFPROTNONE
// RUN: %clang_cc1 -triple=x86_64 -o - -fcf-protection=none %s -emit-llvm | FileCheck %s --check-prefixes=CFPROTNONE

// RETURN: #define __CET__ 2
// BRANCH: #define __CET__ 1
// FULL: #define __CET__ 3
// CFPROT: !{i32 8, !"cf-protection-branch", i32 1}

// NOTCET-NOT: #define __CET__
// NOCFPROT: error: option 'cf-protection=branch' cannot be specified on this target
// CFPROTR: !{i32 8, !"cf-protection-return", i32 1}
// CFPROTB: !{i32 8, !"cf-protection-branch", i32 1}
// CFPROTNONE-NOT: cf-protection-

void foo() {}
24 changes: 8 additions & 16 deletions clang/test/CodeGen/aarch64-cpu-supports.c
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --version 2
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s

//.
// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
//.
// CHECK-LABEL: define dso_local i32 @main
// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 34359738368
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 34359738368
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 70368744177664
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 70368744177664
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
// CHECK-NEXT: store i32 1, ptr [[RETVAL]], align 4
// CHECK-NEXT: br label [[RETURN:%.*]]
// CHECK: if.end:
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 17716740096
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 17716740096
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 9070970929152
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 9070970929152
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT: br i1 [[TMP7]], label [[IF_THEN1:%.*]], label [[IF_END2:%.*]]
// CHECK: if.then1:
// CHECK-NEXT: store i32 2, ptr [[RETVAL]], align 4
// CHECK-NEXT: br label [[RETURN]]
// CHECK: if.end2:
// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 5222680231936
// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 5222680231936
// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 166633186212708352
// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 166633186212708352
// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]]
// CHECK-NEXT: br i1 [[TMP11]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]]
// CHECK: if.then3:
Expand All @@ -51,20 +49,14 @@ int main(void) {
if (__builtin_cpu_supports("sb"))
return 1;

if (__builtin_cpu_supports("sve2-aes+memtag"))
if (__builtin_cpu_supports("sve2-pmull128+memtag"))
return 2;

if (__builtin_cpu_supports("sme2+ls64+wfxt"))
if (__builtin_cpu_supports("sme2+ls64_v+wfxt"))
return 3;

if (__builtin_cpu_supports("avx2"))
return 4;

return 0;
}
//.
// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
//.
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
//.
12 changes: 6 additions & 6 deletions clang/test/CodeGen/aarch64-mixed-target-attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 131072
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 131072
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
Expand Down Expand Up @@ -143,8 +143,8 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 131072
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 131072
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
Expand Down Expand Up @@ -210,8 +210,8 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 131072
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 131072
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
Expand Down
77 changes: 39 additions & 38 deletions clang/test/CodeGen/attr-target-clones-aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fmv -S -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV

int __attribute__((target_clones("lse+aes", "sve2"))) ftc(void) { return 0; }
int __attribute__((target_clones("sha2", "sha2+memtag", " default "))) ftc_def(void) { return 1; }
int __attribute__((target_clones("sha2", "sha2+memtag2", " default "))) ftc_def(void) { return 1; }
int __attribute__((target_clones("sha2", "default"))) ftc_dup1(void) { return 2; }
int __attribute__((target_clones("fp", "crc+dotprod"))) ftc_dup2(void) { return 3; }
int foo() {
Expand All @@ -12,7 +12,7 @@ int foo() {

inline int __attribute__((target_clones("rng+simd", "rcpc+predres", "sve2-aes+wfxt"))) ftc_inline1(void) { return 1; }
inline int __attribute__((target_clones("fp16", "fcma+sve2-bitperm", "default"))) ftc_inline2(void);
inline int __attribute__((target_clones("mops", "sve+sb"))) ftc_inline3(void) { return 3; }
inline int __attribute__((target_clones("bti", "sve+sb"))) ftc_inline3(void) { return 3; }

int __attribute__((target_clones("default"))) ftc_direct(void) { return 4; }

Expand Down Expand Up @@ -56,16 +56,16 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 8320
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 8320
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 16512
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 16512
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @ftc._MaesMlse
// CHECK: resolver_else:
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 268435456
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 268435456
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 68719476736
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 68719476736
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
// CHECK: resolver_return1:
Expand All @@ -81,7 +81,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: @ftc_def._MmemtagMsha2(
// CHECK-LABEL: @ftc_def._Mmemtag2Msha2(
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 1
//
Expand All @@ -90,16 +90,16 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 17179871232
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 17179871232
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 17592186048512
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 17592186048512
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @ftc_def._MmemtagMsha2
// CHECK-NEXT: ret ptr @ftc_def._Mmemtag2Msha2
// CHECK: resolver_else:
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 2048
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 2048
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 4096
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 4096
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
// CHECK: resolver_return1:
Expand All @@ -118,8 +118,8 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 2048
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 2048
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 4096
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4096
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
Expand Down Expand Up @@ -198,16 +198,16 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 550292684800
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 550292684800
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 18014535948435456
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 18014535948435456
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @ftc_inline1._Msve2-aesMwfxt
// CHECK: resolver_else:
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 68720001024
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 68720001024
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 140737492549632
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 140737492549632
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
// CHECK: resolver_return1:
Expand All @@ -228,16 +228,16 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1074003968
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1074003968
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 549757911040
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 549757911040
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @ftc_inline2._MfcmaMsve2-bitperm
// CHECK: resolver_else:
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 16384
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 16384
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 65536
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 65536
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
// CHECK: resolver_return1:
Expand All @@ -250,20 +250,20 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 34393292800
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 34393292800
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 70369817919488
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 70369817919488
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @ftc_inline3._MsbMsve
// CHECK: resolver_else:
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 17592186044416
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 17592186044416
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 1125899906842624
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 1125899906842624
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
// CHECK: resolver_return1:
// CHECK-NEXT: ret ptr @ftc_inline3._Mmops
// CHECK-NEXT: ret ptr @ftc_inline3._Mbti
// CHECK: resolver_else2:
// CHECK-NEXT: ret ptr @ftc_inline3.default
//
Expand Down Expand Up @@ -329,7 +329,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: @ftc_inline3._Mmops(
// CHECK-LABEL: @ftc_inline3._Mbti(
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 3
//
Expand Down Expand Up @@ -407,16 +407,17 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
// CHECK: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon" }
// CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2" }
// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sha2" }
// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" }
// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+fp-armv8,+neon" }
// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm" }
// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rand" }
// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc" }
// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt" }
// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops" }
// CHECK: attributes #[[ATTR12:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sb,+sve" }
// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+mte,+neon,+sha2" }
// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" }
// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+fp-armv8,+neon" }
// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm" }
// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rand" }
// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc" }
// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt" }
// CHECK: attributes #[[ATTR12:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti" }
// CHECK: attributes #[[ATTR13:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sb,+sve" }
//.
// CHECK-NOFMV: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
// CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
Expand Down
326 changes: 164 additions & 162 deletions clang/test/CodeGen/attr-target-version.c

Large diffs are not rendered by default.

200 changes: 200 additions & 0 deletions clang/test/CodeGenCUDA/record-layout.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fdump-record-layouts \
// RUN: -emit-llvm -o %t -xhip %s 2>&1 | FileCheck %s --check-prefix=AST
// RUN: cat %t | FileCheck --check-prefixes=CHECK,HOST %s
// RUN: %clang_cc1 -fcuda-is-device -triple amdgcn-amd-amdhsa -target-cpu gfx1100 \
// RUN: -emit-llvm -fdump-record-layouts -aux-triple x86_64-pc-windows-msvc \
// RUN: -o %t -xhip %s | FileCheck %s --check-prefix=AST
// RUN: cat %t | FileCheck --check-prefixes=CHECK,DEV %s

#include "Inputs/cuda.h"

// AST: *** Dumping AST Record Layout
// AST-LABEL: 0 | struct C
// AST-NEXT: 0 | struct A (base) (empty)
// AST-NEXT: 1 | struct B (base) (empty)
// AST-NEXT: 4 | int i
// AST-NEXT: | [sizeof=8, align=4,
// AST-NEXT: | nvsize=8, nvalign=4]

// CHECK: %struct.C = type { [4 x i8], i32 }

struct A {};
struct B {};
struct C : A, B {
int i;
};

// AST: *** Dumping AST Record Layout
// AST-LABEL: 0 | struct I
// AST-NEXT: 0 | (I vftable pointer)
// AST-NEXT: 8 | int i
// AST-NEXT: | [sizeof=16, align=8,
// AST-NEXT: | nvsize=16, nvalign=8]

// AST: *** Dumping AST Record Layout
// AST-LABEL: 0 | struct J
// AST-NEXT: 0 | struct I (primary base)
// AST-NEXT: 0 | (I vftable pointer)
// AST-NEXT: 8 | int i
// AST-NEXT: 16 | int j
// AST-NEXT: | [sizeof=24, align=8,
// AST-NEXT: | nvsize=24, nvalign=8]

// CHECK: %struct.I = type { ptr, i32 }
// CHECK: %struct.J = type { %struct.I, i32 }

// HOST: @0 = private unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr @"??_R4J@@6B@", ptr @"?f@J@@UEAAXXZ", ptr null, ptr @"?h@J@@UEAAXXZ"] }, comdat($"??_7J@@6B@")
// HOST: @1 = private unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr @"??_R4I@@6B@", ptr @_purecall, ptr null, ptr @_purecall] }, comdat($"??_7I@@6B@")
// HOST: @"??_7J@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [4 x ptr] }, ptr @0, i32 0, i32 0, i32 1)
// HOST: @"??_7I@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [4 x ptr] }, ptr @1, i32 0, i32 0, i32 1)

// DEV: @_ZTV1J = linkonce_odr unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @_ZN1J1gEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1J1hEv to ptr addrspace(1))] }, comdat, align 8
// DEV: @_ZTV1I = linkonce_odr unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1))] }, comdat, align 8
struct I {
virtual void f() = 0;
__device__ virtual void g() = 0;
__device__ __host__ virtual void h() = 0;
int i;
};

struct J : I {
void f() override {}
__device__ void g() override {}
__device__ __host__ void h() override {}
int j;
};

// DEV: define dso_local amdgpu_kernel void @_Z8C_kernel1C(ptr addrspace(4) noundef byref(%struct.C) align 4 %0)
// DEV: %coerce = alloca %struct.C, align 4, addrspace(5)
// DEV: %c = addrspacecast ptr addrspace(5) %coerce to ptr
// DEV: call void @llvm.memcpy.p0.p4.i64(ptr align 4 %c, ptr addrspace(4) align 4 %0, i64 8, i1 false)
// DEV: %i = getelementptr inbounds %struct.C, ptr %c, i32 0, i32 1
// DEV: store i32 1, ptr %i, align 4

__global__ void C_kernel(C c)
{
c.i = 1;
}

// HOST-LABEL: define dso_local void @"?test_C@@YAXXZ"()
// HOST: %c = alloca %struct.C, align 4
// HOST: %i = getelementptr inbounds %struct.C, ptr %c, i32 0, i32 1
// HOST: store i32 11, ptr %i, align 4

void test_C() {
C c;
c.i = 11;
C_kernel<<<1, 1>>>(c);
}

// DEV: define dso_local void @_Z5J_devP1J(ptr noundef %j)
// DEV: %j.addr = alloca ptr, align 8, addrspace(5)
// DEV: %j.addr.ascast = addrspacecast ptr addrspace(5) %j.addr to ptr
// DEV: store ptr %j, ptr %j.addr.ascast, align 8
// DEV: %0 = load ptr, ptr %j.addr.ascast, align 8
// DEV: %i = getelementptr inbounds %struct.I, ptr %0, i32 0, i32 1
// DEV: store i32 2, ptr %i, align 8
// DEV: %1 = load ptr, ptr %j.addr.ascast, align 8
// DEV: %j1 = getelementptr inbounds %struct.J, ptr %1, i32 0, i32 1
// DEV: store i32 3, ptr %j1, align 8
// DEV: %2 = load ptr, ptr %j.addr.ascast, align 8
// DEV: %vtable = load ptr addrspace(1), ptr %2, align 8
// DEV: %vfn = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %vtable, i64 1
// DEV: %3 = load ptr addrspace(1), ptr addrspace(1) %vfn, align 8
// DEV: call addrspace(1) void %3(ptr noundef nonnull align 8 dereferenceable(24) %2)
// DEV: %4 = load ptr, ptr %j.addr.ascast, align 8
// DEV: %vtable2 = load ptr addrspace(1), ptr %4, align 8
// DEV: %vfn3 = getelementptr inbounds ptr addrspace(1), ptr addrspace(1) %vtable2, i64 2
// DEV: %5 = load ptr addrspace(1), ptr addrspace(1) %vfn3, align 8
// DEV: call addrspace(1) void %5(ptr noundef nonnull align 8 dereferenceable(24) %4)

__device__ void J_dev(J *j) {
j->i = 2;
j->j = 3;
j->g();
j->h();
}

// DEV: define dso_local amdgpu_kernel void @_Z8J_kernelv()
// DEV: %j = alloca %struct.J, align 8, addrspace(5)
// DEV: %j.ascast = addrspacecast ptr addrspace(5) %j to ptr
// DEV: call void @_ZN1JC1Ev(ptr noundef nonnull align 8 dereferenceable(24) %j.ascast)
// DEV: call void @_Z5J_devP1J(ptr noundef %j.ascast)

__global__ void J_kernel() {
J j;
J_dev(&j);
}

// HOST-LABEL: define dso_local void @"?J_host@@YAXPEAUJ@@@Z"(ptr noundef %j)
// HOST: %0 = load ptr, ptr %j.addr, align 8
// HOST: %i = getelementptr inbounds %struct.I, ptr %0, i32 0, i32 1
// HOST: store i32 12, ptr %i, align 8
// HOST: %1 = load ptr, ptr %j.addr, align 8
// HOST: %j1 = getelementptr inbounds %struct.J, ptr %1, i32 0, i32 1
// HOST: store i32 13, ptr %j1, align 8
// HOST: %2 = load ptr, ptr %j.addr, align 8
// HOST: %vtable = load ptr, ptr %2, align 8
// HOST: %vfn = getelementptr inbounds ptr, ptr %vtable, i64 0
// HOST: %3 = load ptr, ptr %vfn, align 8
// HOST: call void %3(ptr noundef nonnull align 8 dereferenceable(24) %2)
// HOST: %4 = load ptr, ptr %j.addr, align 8
// HOST: %vtable2 = load ptr, ptr %4, align 8
// HOST: %vfn3 = getelementptr inbounds ptr, ptr %vtable2, i64 2
// HOST: %5 = load ptr, ptr %vfn3, align 8
// HOST: call void %5(ptr noundef nonnull align 8 dereferenceable(24) %4)

void J_host(J *j) {
j->i = 12;
j->j = 13;
j->f();
j->h();
}

// HOST: define dso_local void @"?test_J@@YAXXZ"()
// HOST: %j = alloca %struct.J, align 8
// HOST: %call = call noundef ptr @"??0J@@QEAA@XZ"(ptr noundef nonnull align 8 dereferenceable(24) %j)
// HOST: call void @"?J_host@@YAXPEAUJ@@@Z"(ptr noundef %j)

void test_J() {
J j;
J_host(&j);
J_kernel<<<1, 1>>>();
}

// HOST: define linkonce_odr dso_local noundef ptr @"??0J@@QEAA@XZ"(ptr noundef nonnull returned align 8 dereferenceable(24) %this)
// HOST: %this.addr = alloca ptr, align 8
// HOST: store ptr %this, ptr %this.addr, align 8
// HOST: %this1 = load ptr, ptr %this.addr, align 8
// HOST: %call = call noundef ptr @"??0I@@QEAA@XZ"(ptr noundef nonnull align 8 dereferenceable(16) %this1) #5
// HOST: store ptr @"??_7J@@6B@", ptr %this1, align 8
// HOST: ret ptr %this1

// HOST: define linkonce_odr dso_local noundef ptr @"??0I@@QEAA@XZ"(ptr noundef nonnull returned align 8 dereferenceable(16) %this)
// HOST: %this.addr = alloca ptr, align 8
// HOST: store ptr %this, ptr %this.addr, align 8
// HOST: %this1 = load ptr, ptr %this.addr, align 8
// HOST: store ptr @"??_7I@@6B@", ptr %this1, align 8
// HOST: ret ptr %this1

// DEV: define linkonce_odr void @_ZN1JC1Ev(ptr noundef nonnull align 8 dereferenceable(24) %this)
// DEV: %this.addr = alloca ptr, align 8, addrspace(5)
// DEV: %this.addr.ascast = addrspacecast ptr addrspace(5) %this.addr to ptr
// DEV: store ptr %this, ptr %this.addr.ascast, align 8
// DEV: %this1 = load ptr, ptr %this.addr.ascast, align 8
// DEV: call void @_ZN1JC2Ev(ptr noundef nonnull align 8 dereferenceable(24) %this1)

// DEV: define linkonce_odr void @_ZN1JC2Ev(ptr noundef nonnull align 8 dereferenceable(24) %this)
// DEV: %this.addr = alloca ptr, align 8, addrspace(5)
// DEV: %this.addr.ascast = addrspacecast ptr addrspace(5) %this.addr to ptr
// DEV: store ptr %this, ptr %this.addr.ascast, align 8
// DEV: %this1 = load ptr, ptr %this.addr.ascast, align 8
// DEV: call void @_ZN1IC2Ev(ptr noundef nonnull align 8 dereferenceable(16) %this1)
// DEV: store ptr addrspace(1) getelementptr inbounds inrange(-16, 24) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1J, i32 0, i32 0, i32 2), ptr %this1, align 8

// DEV: define linkonce_odr void @_ZN1IC2Ev(ptr noundef nonnull align 8 dereferenceable(16) %this)
// DEV: %this.addr = alloca ptr, align 8, addrspace(5)
// DEV: %this.addr.ascast = addrspacecast ptr addrspace(5) %this.addr to ptr
// DEV: store ptr %this, ptr %this.addr.ascast, align 8
// DEV: %this1 = load ptr, ptr %this.addr.ascast, align 8
// DEV: store ptr addrspace(1) getelementptr inbounds inrange(-16, 24) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1I, i32 0, i32 0, i32 2), ptr %this1, align 8
41 changes: 22 additions & 19 deletions clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --include-generated-funcs
// RUN: %clang_cc1 -std=c++11 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck %s

int __attribute__((target_clones("ls64+fp16", "default"))) foo_ovl(int) { return 1; }
int __attribute__((target_clones("sme+ls64"))) foo_ovl(void) { return 2; }
int __attribute__((target_clones("ls64_v+fp16", "default"))) foo_ovl(int) { return 1; }
int __attribute__((target_clones("ls64_accdata+ls64"))) foo_ovl(void) { return 2; }

int bar() {
return foo_ovl(1) + foo_ovl();
Expand Down Expand Up @@ -35,6 +35,9 @@ void run_foo_tml() {
Mc4.foo_tml();
}




//.
// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
// CHECK: @_Z7foo_ovli.ifunc = weak_odr alias i32 (i32), ptr @_Z7foo_ovli
Expand All @@ -46,7 +49,7 @@ void run_foo_tml() {
// CHECK: @_ZN7MyClassIssE7foo_tmlEv = weak_odr ifunc i32 (ptr), ptr @_ZN7MyClassIssE7foo_tmlEv.resolver
// CHECK: @_ZN7MyClassIisE7foo_tmlEv = weak_odr ifunc i32 (ptr), ptr @_ZN7MyClassIisE7foo_tmlEv.resolver
//.
// CHECK-LABEL: @_Z7foo_ovli._Mfp16Mls64(
// CHECK-LABEL: @_Z7foo_ovli._Mfp16Mls64_v(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4
Expand All @@ -57,17 +60,17 @@ void run_foo_tml() {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 274877923328
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 274877923328
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 4503599627436032
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4503599627436032
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @_Z7foo_ovli._Mfp16Mls64
// CHECK-NEXT: ret ptr @_Z7foo_ovli._Mfp16Mls64_v
// CHECK: resolver_else:
// CHECK-NEXT: ret ptr @_Z7foo_ovli.default
//
//
// CHECK-LABEL: @_Z7foo_ovlv._Mls64Msme(
// CHECK-LABEL: @_Z7foo_ovlv._Mls64Mls64_accdata(
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 2
//
Expand All @@ -76,12 +79,12 @@ void run_foo_tml() {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 283467841536
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 283467841536
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 11258999068426240
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 11258999068426240
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @_Z7foo_ovlv._Mls64Msme
// CHECK-NEXT: ret ptr @_Z7foo_ovlv._Mls64Mls64_accdata
// CHECK: resolver_else:
// CHECK-NEXT: ret ptr @_Z7foo_ovlv.default
//
Expand Down Expand Up @@ -111,16 +114,16 @@ void run_foo_tml() {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1236950581248
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1236950581248
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 36310271995674624
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 36310271995674624
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @_ZN7MyClassIssE7foo_tmlEv._Msme-f64f64Mssbs
// CHECK: resolver_else:
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 2097152
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 2097152
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 16777216
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 16777216
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
// CHECK: resolver_return1:
Expand All @@ -133,16 +136,16 @@ void run_foo_tml() {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1236950581248
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1236950581248
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 36310271995674624
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 36310271995674624
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @_ZN7MyClassIisE7foo_tmlEv._Msme-f64f64Mssbs
// CHECK: resolver_else:
// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 2097152
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 2097152
// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 16777216
// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 16777216
// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]]
// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
// CHECK: resolver_return1:
Expand Down Expand Up @@ -228,7 +231,7 @@ void run_foo_tml() {
//
//.
// CHECK: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" }
// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
// CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint" }
// CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" }
Expand Down
22 changes: 11 additions & 11 deletions clang/test/CodeGenCXX/attr-target-version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

int __attribute__((target_version("sme-f64f64+bf16"))) foo(int) { return 1; }
int __attribute__((target_version("default"))) foo(int) { return 2; }
int __attribute__((target_version("sm4+bf16"))) foo(void) { return 3; }
int __attribute__((target_version("sm4+ebf16"))) foo(void) { return 3; }
int __attribute__((target_version("default"))) foo(void) { return 4; }

struct MyClass {
Expand Down Expand Up @@ -89,7 +89,7 @@ int bar() {
// CHECK-NEXT: ret i32 2
//
//
// CHECK-LABEL: @_Z3foov._Mbf16Msm4(
// CHECK-LABEL: @_Z3foov._Mebf16Msm4(
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 3
//
Expand Down Expand Up @@ -246,8 +246,8 @@ int bar() {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1099520016384
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1099520016384
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 36028797153181696
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 36028797153181696
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
Expand All @@ -260,12 +260,12 @@ int bar() {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 8388640
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 8388640
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 268435488
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 268435488
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @_Z3foov._Mbf16Msm4
// CHECK-NEXT: ret ptr @_Z3foov._Mebf16Msm4
// CHECK: resolver_else:
// CHECK-NEXT: ret ptr @_Z3foov.default
//
Expand All @@ -274,8 +274,8 @@ int bar() {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 33554432
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 33554432
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1073741824
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1073741824
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
Expand All @@ -288,8 +288,8 @@ int bar() {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 16384
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 16384
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 65536
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 65536
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
Expand Down
Loading