135 changes: 91 additions & 44 deletions clang/include/clang/ExtractAPI/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,20 @@ struct APIRecord {
RK_ClassTemplate,
RK_ClassTemplateSpecialization,
RK_ClassTemplatePartialSpecialization,
RK_LastRecordContext,
RK_GlobalFunction,
RK_GlobalFunctionTemplate,
RK_GlobalFunctionTemplateSpecialization,
RK_StructField,
RK_UnionField,
RK_CXXField,
RK_StaticField,
RK_CXXFieldTemplate,
RK_GlobalVariable,
RK_GlobalVariableTemplate,
RK_GlobalVariableTemplateSpecialization,
RK_GlobalVariableTemplatePartialSpecialization,
RK_LastRecordContext,
RK_GlobalFunction,
RK_GlobalFunctionTemplate,
RK_GlobalFunctionTemplateSpecialization,
RK_EnumConstant,
RK_StructField,
RK_UnionField,
RK_StaticField,
RK_CXXField,
RK_CXXFieldTemplate,
RK_Concept,
RK_CXXStaticMethod,
RK_CXXInstanceMethod,
Expand Down Expand Up @@ -321,6 +321,10 @@ class RecordContext {

RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {}

/// Append \p Other children chain into ours and empty out Other's record
/// chain.
void stealRecordChain(RecordContext &Other);

APIRecord::RecordKind getKind() const { return Kind; }

struct record_iterator {
Expand Down Expand Up @@ -370,6 +374,7 @@ class RecordContext {
APIRecord::RecordKind Kind;
mutable APIRecord *First = nullptr;
mutable APIRecord *Last = nullptr;
bool IsWellFormed() const;

protected:
friend class APISet;
Expand Down Expand Up @@ -475,31 +480,36 @@ struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
};

/// This holds information associated with global functions.
struct GlobalVariableRecord : APIRecord {
struct GlobalVariableRecord : APIRecord, RecordContext {
GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment, Declaration,
SubHeading, IsFromSystemHeader) {}
SubHeading, IsFromSystemHeader),
RecordContext(RK_GlobalVariable) {}

GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent,

PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
IsFromSystemHeader),
RecordContext(Kind) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_GlobalVariable; }
static bool classofKind(RecordKind K) {
return K == RK_GlobalVariable || K == RK_GlobalVariableTemplate ||
K == RK_GlobalVariableTemplateSpecialization ||
K == RK_GlobalVariableTemplatePartialSpecialization;
}

private:
virtual void anchor();
Expand Down Expand Up @@ -591,36 +601,64 @@ struct EnumConstantRecord : APIRecord {
virtual void anchor();
};

struct TagRecord : APIRecord, RecordContext {
TagRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
bool IsFromSystemHeader, bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind),
IsEmbeddedInVarDeclarator(IsEmbeddedInVarDeclarator){};

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_Struct || K == RK_Union || K == RK_Enum;
}

bool IsEmbeddedInVarDeclarator;

virtual ~TagRecord() = 0;
};

/// This holds information associated with enums.
struct EnumRecord : APIRecord, RecordContext {
struct EnumRecord : TagRecord {
EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(RK_Enum) {}
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: TagRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}

static bool classofKind(RecordKind K) { return K == RK_Enum; }

private:
virtual void anchor();
};

/// This holds information associated with struct or union fields fields.
struct RecordFieldRecord : APIRecord {
struct RecordFieldRecord : APIRecord, RecordContext {
RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
IsFromSystemHeader),
RecordContext(Kind) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand All @@ -633,16 +671,17 @@ struct RecordFieldRecord : APIRecord {
};

/// This holds information associated with structs and unions.
struct RecordRecord : APIRecord, RecordContext {
struct RecordRecord : TagRecord {
RecordRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(Kind) {}
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: TagRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand All @@ -651,6 +690,8 @@ struct RecordRecord : APIRecord, RecordContext {
return K == RK_Struct || K == RK_Union;
}

bool isAnonymousWithNoTypedef() { return Name.empty(); }

virtual ~RecordRecord() = 0;
};

Expand All @@ -676,9 +717,11 @@ struct StructRecord : RecordRecord {
StructRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator)
: RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand Down Expand Up @@ -711,9 +754,11 @@ struct UnionRecord : RecordRecord {
UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator)
: RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand All @@ -724,15 +769,16 @@ struct UnionRecord : RecordRecord {
virtual void anchor();
};

struct CXXFieldRecord : APIRecord {
struct CXXFieldRecord : APIRecord, RecordContext {
CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
: APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)) {}
IsFromSystemHeader, std::move(Access)),
RecordContext(RK_CXXField) {}

CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
Expand All @@ -742,7 +788,8 @@ struct CXXFieldRecord : APIRecord {
bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)) {}
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand Down Expand Up @@ -1118,18 +1165,18 @@ struct ObjCContainerRecord : APIRecord, RecordContext {
virtual ~ObjCContainerRecord() = 0;
};

struct CXXClassRecord : APIRecord, RecordContext {
struct CXXClassRecord : RecordRecord {
SmallVector<SymbolReference> Bases;

CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, RecordKind Kind,
AccessControl Access, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind) {}
AccessControl Access, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator = false)
: RecordRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand Down
16 changes: 14 additions & 2 deletions clang/include/clang/ExtractAPI/APIRecords.inc
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ CONCRETE_RECORD(GlobalVariableTemplateSpecializationRecord,
CONCRETE_RECORD(GlobalVariableTemplatePartialSpecializationRecord,
GlobalVariableRecord,
RK_GlobalVariableTemplatePartialSpecialization)
ABSTRACT_RECORD(TagRecord, APIRecord)
CONCRETE_RECORD(EnumConstantRecord, APIRecord, RK_EnumConstant)
CONCRETE_RECORD(EnumRecord, APIRecord, RK_Enum)
CONCRETE_RECORD(EnumRecord, TagRecord, RK_Enum)
ABSTRACT_RECORD(RecordFieldRecord, APIRecord)
ABSTRACT_RECORD(RecordRecord, APIRecord)
ABSTRACT_RECORD(RecordRecord, TagRecord)
CONCRETE_RECORD(StructFieldRecord, RecordFieldRecord, RK_StructField)
CONCRETE_RECORD(StructRecord, APIRecord, RK_Struct)
CONCRETE_RECORD(UnionFieldRecord, RecordFieldRecord, RK_UnionField)
Expand Down Expand Up @@ -99,5 +100,16 @@ RECORD_CONTEXT(ClassTemplateSpecializationRecord,
RK_ClassTemplateSpecialization)
RECORD_CONTEXT(ClassTemplatePartialSpecializationRecord,
RK_ClassTemplatePartialSpecialization)
RECORD_CONTEXT(StructFieldRecord, RK_StructField)
RECORD_CONTEXT(UnionFieldRecord, RK_UnionField)
RECORD_CONTEXT(CXXFieldRecord, RK_CXXField)
RECORD_CONTEXT(StaticFieldRecord, RK_StaticField)
RECORD_CONTEXT(CXXFieldTemplateRecord, RK_CXXFieldTemplate)
RECORD_CONTEXT(GlobalVariableRecord, RK_GlobalVariable)
RECORD_CONTEXT(GlobalVariableTemplateRecord, RK_GlobalVariableTemplate)
RECORD_CONTEXT(GlobalVariableTemplateSpecializationRecord,
RK_GlobalVariableTemplateSpecialization)
RECORD_CONTEXT(GlobalVariableTemplatePartialSpecializationRecord,
RK_GlobalVariableTemplatePartialSpecialization)

#undef RECORD_CONTEXT
84 changes: 57 additions & 27 deletions clang/include/clang/ExtractAPI/DeclarationFragments.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/MacroInfo.h"
#include <iterator>
#include <utility>
#include <vector>

namespace clang {
Expand Down Expand Up @@ -113,28 +115,26 @@ class DeclarationFragments {

ConstFragmentIterator cend() const { return Fragments.cend(); }

// Add a new Fragment at an arbitrary offset.
DeclarationFragments &insert(FragmentIterator It, StringRef Spelling,
FragmentKind Kind,
StringRef PreciseIdentifier = "",
const Decl *Declaration = nullptr) {
Fragments.insert(It,
Fragment(Spelling, Kind, PreciseIdentifier, Declaration));
return *this;
/// Prepend another DeclarationFragments to the beginning.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive operations.
DeclarationFragments &prepend(DeclarationFragments Other) {
return insert(begin(), std::move(Other));
}

DeclarationFragments &insert(FragmentIterator It,
DeclarationFragments &&Other) {
Fragments.insert(It, std::make_move_iterator(Other.Fragments.begin()),
std::make_move_iterator(Other.Fragments.end()));
Other.Fragments.clear();
return *this;
/// Append another DeclarationFragments to the end.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive operations.
DeclarationFragments &append(DeclarationFragments Other) {
return insert(end(), std::move(Other));
}

/// Append a new Fragment to the end of the Fragments.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
/// appending to chain up consecutive operations.
DeclarationFragments &append(StringRef Spelling, FragmentKind Kind,
StringRef PreciseIdentifier = "",
const Decl *Declaration = nullptr) {
Expand All @@ -149,18 +149,48 @@ class DeclarationFragments {
return *this;
}

/// Append another DeclarationFragments to the end.
///
/// Note: \p Other is moved from and cannot be used after a call to this
/// method.
/// Inserts another DeclarationFragments at \p It.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
DeclarationFragments &append(DeclarationFragments &&Other) {
Fragments.insert(Fragments.end(),
std::make_move_iterator(Other.Fragments.begin()),
std::make_move_iterator(Other.Fragments.end()));
Other.Fragments.clear();
/// appending to chain up consecutive operations.
DeclarationFragments &insert(FragmentIterator It,
DeclarationFragments Other) {
if (Other.Fragments.empty())
return *this;

if (Fragments.empty()) {
Fragments = std::move(Other.Fragments);
return *this;
}

const auto &OtherFrags = Other.Fragments;
auto ToInsertBegin = std::make_move_iterator(Other.begin());
auto ToInsertEnd = std::make_move_iterator(Other.end());

// If we aren't inserting at the end let's make sure that we merge their
// last fragment with It if both are text fragments.
if (It != end() && It->Kind == FragmentKind::Text &&
OtherFrags.back().Kind == FragmentKind::Text) {
auto &TheirBackSpelling = OtherFrags.back().Spelling;
It->Spelling.reserve(It->Spelling.size() + TheirBackSpelling.size());
It->Spelling.insert(It->Spelling.begin(), TheirBackSpelling.begin(),
TheirBackSpelling.end());
--ToInsertEnd;
}

// If we aren't inserting at the beginning we want to merge their first
// fragment with the fragment before It if both are text fragments.
if (It != begin() && std::prev(It)->Kind == FragmentKind::Text &&
OtherFrags.front().Kind == FragmentKind::Text) {
auto PrevIt = std::prev(It);
auto &TheirFrontSpelling = OtherFrags.front().Spelling;
PrevIt->Spelling.reserve(PrevIt->Spelling.size() +
TheirFrontSpelling.size());
PrevIt->Spelling.append(TheirFrontSpelling);
++ToInsertBegin;
}

Fragments.insert(It, ToInsertBegin, ToInsertEnd);
return *this;
}

Expand All @@ -177,13 +207,13 @@ class DeclarationFragments {
/// Append a text Fragment of a space character.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
/// appending to chain up consecutive operations.
DeclarationFragments &appendSpace();

/// Append a text Fragment of a semicolon character.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
/// appending to chain up consecutive operations.
DeclarationFragments &appendSemicolon();

/// Removes a trailing semicolon character if present.
Expand Down
76 changes: 53 additions & 23 deletions clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,29 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {

return API.createSymbolReference(Name, USR, getOwningModuleName(D));
}

bool isEmbeddedInVarDeclarator(const TagDecl &D) {
return D.getName().empty() && getTypedefName(&D).empty() &&
D.isEmbeddedInDeclarator();
}

void maybeMergeWithAnonymousTag(const DeclaratorDecl &D,
RecordContext *NewRecordContext) {
if (!NewRecordContext)
return;
auto *Tag = D.getType()->getAsTagDecl();
SmallString<128> TagUSR;
clang::index::generateUSRForDecl(Tag, TagUSR);
if (auto *Record = llvm::dyn_cast_if_present<TagRecord>(
API.findRecordForUSR(TagUSR))) {
if (Record->IsEmbeddedInVarDeclarator) {
NewRecordContext->stealRecordChain(*Record);
auto *NewRecord = cast<APIRecord>(NewRecordContext);
if (NewRecord->Comment.empty())
NewRecord->Comment = Record->Comment;
}
}
}
};

template <typename Derived>
Expand Down Expand Up @@ -273,12 +296,18 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
SubHeading, Access, isInSystemHeader(Decl));
} else
} else {
// Add the global variable record to the API set.
API.createRecord<GlobalVariableRecord>(
auto *NewRecord = API.createRecord<GlobalVariableRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
SubHeading, isInSystemHeader(Decl));

// If this global variable has a non typedef'd anonymous tag type let's
// pretend the type's child records are under us in the hierarchy.
maybeMergeWithAnonymousTag(*Decl, NewRecord);
}

return true;
}

Expand Down Expand Up @@ -364,7 +393,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
if (Name.empty()) {
llvm::raw_svector_ostream OS(QualifiedNameBuffer);
Decl->printQualifiedName(OS);
Name = QualifiedNameBuffer.str();
Name = QualifiedNameBuffer;
}

SmallString<128> USR;
Expand All @@ -385,7 +414,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
auto *ER = API.createRecord<EnumRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
isInSystemHeader(Decl));
isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));

// Now collect information about the enumerators in this enum.
getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators());
Expand Down Expand Up @@ -510,16 +539,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;

SmallString<128> QualifiedNameBuffer;
// Collect symbol information.
StringRef Name = Decl->getName();
if (Name.empty())
Name = getTypedefName(Decl);
if (Name.empty()) {
llvm::raw_svector_ostream OS(QualifiedNameBuffer);
Decl->printQualifiedName(OS);
Name = QualifiedNameBuffer.str();
}

SmallString<128> USR;
index::generateUSRForDecl(Decl, USR);
Expand All @@ -541,12 +564,12 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
API.createRecord<UnionRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));
else
API.createRecord<StructRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));

return true;
}
Expand All @@ -559,6 +582,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
return true;

StringRef Name = Decl->getName();
if (Name.empty())
Name = getTypedefName(Decl);

SmallString<128> USR;
index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Expand All @@ -585,8 +611,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
CXXClassRecord *Record;
if (Decl->getDescribedClassTemplate()) {
// Inject template fragments before class fragments.
Declaration.insert(
Declaration.begin(),
Declaration.prepend(
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
Decl->getDescribedClassTemplate()));
Record = API.createRecord<ClassTemplateRecord>(
Expand All @@ -598,7 +623,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
Record = API.createRecord<CXXClassRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, Kind, Access, isInSystemHeader(Decl));
SubHeading, Kind, Access, isInSystemHeader(Decl),
isEmbeddedInVarDeclarator(*Decl));

Record->Bases = getBases(Decl);

Expand Down Expand Up @@ -1075,18 +1101,17 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
// If the underlying type was defined as part of the typedef modify it's
// fragments directly and pretend the typedef doesn't exist.
if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) {
if (TagDecl->getName() == Decl->getName() &&
TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition()) {
if (TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition() &&
Decl->getName() == TagDecl->getName()) {
SmallString<128> TagUSR;
index::generateUSRForDecl(TagDecl, TagUSR);
if (auto *Record = API.findRecordForUSR(TagUSR)) {
DeclarationFragments LeadingFragments;
LeadingFragments.append("typedef",
DeclarationFragments::FragmentKind::Keyword, "",
nullptr);
DeclarationFragments::FragmentKind::Keyword);
LeadingFragments.appendSpace();
Record->Declaration.removeTrailingSemicolon()
.insert(Record->Declaration.begin(), std::move(LeadingFragments))
.prepend(std::move(LeadingFragments))
.append(" { ... } ", DeclarationFragments::FragmentKind::Text)
.append(Name, DeclarationFragments::FragmentKind::Identifier)
.appendSemicolon();
Expand Down Expand Up @@ -1221,26 +1246,31 @@ bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);

RecordContext *NewRecord = nullptr;
if (isa<CXXRecordDecl>(Decl->getDeclContext())) {
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);

API.createRecord<CXXFieldRecord>(
NewRecord = API.createRecord<CXXFieldRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, Access, isInSystemHeader(Decl));
} else if (auto *RD = dyn_cast<RecordDecl>(Decl->getDeclContext())) {
if (RD->isUnion())
API.createRecord<UnionFieldRecord>(
NewRecord = API.createRecord<UnionFieldRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
else
API.createRecord<StructFieldRecord>(
NewRecord = API.createRecord<StructFieldRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
}

// If this field has a non typedef'd anonymous tag type let's pretend the
// type's child records are under us in the hierarchy.
maybeMergeWithAnonymousTag(*Decl, NewRecord);

return true;
}

Expand Down
14 changes: 10 additions & 4 deletions clang/include/clang/Lex/HeaderSearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ class TargetInfo;
/// The preprocessor keeps track of this information for each
/// file that is \#included.
struct HeaderFileInfo {
// TODO: Whether the file was included is not a property of the file itself.
// It's a preprocessor state, move it there.
/// True if this file has been included (or imported) **locally**.
LLVM_PREFERRED_TYPE(bool)
unsigned IsLocallyIncluded : 1;

// TODO: Whether the file was imported is not a property of the file itself.
// It's a preprocessor state, move it there.
/// True if this is a \#import'd file.
Expand Down Expand Up @@ -135,10 +141,10 @@ struct HeaderFileInfo {
StringRef Framework;

HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isTextualModuleHeader(false),
isCompilingModuleHeader(false), Resolved(false),
IndexHeaderMapHeader(false), IsValid(false) {}
: IsLocallyIncluded(false), isImport(false), isPragmaOnce(false),
DirInfo(SrcMgr::C_User), External(false), isModuleHeader(false),
isTextualModuleHeader(false), isCompilingModuleHeader(false),
Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {}

/// Retrieve the controlling macro for this header file, if
/// any.
Expand Down
23 changes: 14 additions & 9 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -822,8 +822,9 @@ CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type,
return ConstantInt::get(ResType, ObjectSize, /*isSigned=*/true);
}

const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
ASTContext &Ctx, const RecordDecl *RD, StringRef Name, uint64_t &Offset) {
const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberFieldAndOffset(
ASTContext &Ctx, const RecordDecl *RD, const FieldDecl *FAMDecl,
uint64_t &Offset) {
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
getLangOpts().getStrictFlexArraysLevel();
uint32_t FieldNo = 0;
Expand All @@ -832,7 +833,7 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
return nullptr;

for (const FieldDecl *FD : RD->fields()) {
if ((Name.empty() || FD->getNameAsString() == Name) &&
if ((!FAMDecl || FD == FAMDecl) &&
Decl::isFlexibleArrayMemberLike(
Ctx, FD, FD->getType(), StrictFlexArraysLevel,
/*IgnoreTemplateOrMacroSubstitution=*/true)) {
Expand All @@ -843,8 +844,8 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(

QualType Ty = FD->getType();
if (Ty->isRecordType()) {
if (const FieldDecl *Field = FindFlexibleArrayMemberField(
Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
if (const FieldDecl *Field = FindFlexibleArrayMemberFieldAndOffset(
Ctx, Ty->getAsRecordDecl(), FAMDecl, Offset)) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
Offset += Layout.getFieldOffset(FieldNo);
return Field;
Expand Down Expand Up @@ -930,12 +931,14 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type,

// Get the flexible array member Decl.
const RecordDecl *OuterRD = nullptr;
std::string FAMName;
const FieldDecl *FAMDecl = nullptr;
if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
// Check if \p Base is referencing the FAM itself.
const ValueDecl *VD = ME->getMemberDecl();
OuterRD = VD->getDeclContext()->getOuterLexicalRecordContext();
FAMName = VD->getNameAsString();
FAMDecl = dyn_cast<FieldDecl>(VD);
if (!FAMDecl)
return nullptr;
} else if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
// Check if we're pointing to the whole struct.
QualType Ty = DRE->getDecl()->getType();
Expand Down Expand Up @@ -974,9 +977,11 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type,
if (!OuterRD)
return nullptr;

// We call FindFlexibleArrayMemberAndOffset even if FAMDecl is non-null to
// get its offset.
uint64_t Offset = 0;
const FieldDecl *FAMDecl =
FindFlexibleArrayMemberField(Ctx, OuterRD, FAMName, Offset);
FAMDecl =
FindFlexibleArrayMemberFieldAndOffset(Ctx, OuterRD, FAMDecl, Offset);
Offset = Ctx.toCharUnitsFromBits(Offset).getQuantity();

if (!FAMDecl || !FAMDecl->getType()->isCountAttributedType())
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3204,12 +3204,12 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::Value *Index, QualType IndexType,
QualType IndexedType, bool Accessed);

// Find a struct's flexible array member. It may be embedded inside multiple
// sub-structs, but must still be the last field.
const FieldDecl *FindFlexibleArrayMemberField(ASTContext &Ctx,
const RecordDecl *RD,
StringRef Name,
uint64_t &Offset);
// Find a struct's flexible array member and get its offset. It may be
// embedded inside multiple sub-structs, but must still be the last field.
const FieldDecl *
FindFlexibleArrayMemberFieldAndOffset(ASTContext &Ctx, const RecordDecl *RD,
const FieldDecl *FAMDecl,
uint64_t &Offset);

/// Find the FieldDecl specified in a FAM's "counted_by" attribute. Returns
/// \p nullptr if either the attribute or the field doesn't exist.
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Driver/ToolChains/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,7 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {

std::string Linker = getToolChain().GetProgramPath(getShortName());
std::string Linker = getToolChain().GetLinkerPath();
ArgStringList CmdArgs;
CmdArgs.push_back("--no-undefined");
CmdArgs.push_back("-shared");
Expand Down
22 changes: 22 additions & 0 deletions clang/lib/ExtractAPI/API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,28 @@ RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) {
}
}

bool RecordContext::IsWellFormed() const {
// Check that First and Last are both null or both non-null.
return (First == nullptr) == (Last == nullptr);
}

void RecordContext::stealRecordChain(RecordContext &Other) {
assert(IsWellFormed());
// If we don't have an empty chain append Other's chain into ours.
if (First)
Last->NextInContext = Other.First;
else
First = Other.First;

Last = Other.Last;

// Delete Other's chain to ensure we don't accidentally traverse it.
Other.First = nullptr;
Other.Last = nullptr;
}

void RecordContext::addToRecordChain(APIRecord *Record) const {
assert(IsWellFormed());
if (!First) {
First = Record;
Last = Record;
Expand Down Expand Up @@ -95,6 +116,7 @@ SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
}

APIRecord::~APIRecord() {}
TagRecord::~TagRecord() {}
RecordRecord::~RecordRecord() {}
RecordFieldRecord::~RecordFieldRecord() {}
ObjCContainerRecord::~ObjCContainerRecord() {}
Expand Down
17 changes: 13 additions & 4 deletions clang/lib/ExtractAPI/DeclarationFragments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,8 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
const TagDecl *Decl = TagTy->getDecl();
// Anonymous decl, skip this fragment.
if (Decl->getName().empty())
return Fragments;
return Fragments.append("{ ... }",
DeclarationFragments::FragmentKind::Text);
SmallString<128> TagUSR;
clang::index::generateUSRForDecl(Decl, TagUSR);
return Fragments.append(Decl->getName(),
Expand Down Expand Up @@ -743,11 +744,16 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {

QualType IntegerType = EnumDecl->getIntegerType();
if (!IntegerType.isNull())
Fragments.append(": ", DeclarationFragments::FragmentKind::Text)
Fragments.appendSpace()
.append(": ", DeclarationFragments::FragmentKind::Text)
.append(
getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
.append(std::move(After));

if (EnumDecl->getName().empty())
Fragments.appendSpace().append("{ ... }",
DeclarationFragments::FragmentKind::Text);

return Fragments.appendSemicolon();
}

Expand Down Expand Up @@ -778,9 +784,12 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
else
Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);

Fragments.appendSpace();
if (!Record->getName().empty())
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
Fragments.append(Record->getName(),
DeclarationFragments::FragmentKind::Identifier);
else
Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text);

return Fragments.appendSemicolon();
}
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,14 @@ bool SymbolGraphSerializer::shouldSkip(const APIRecord *Record) const {
if (Record->Availability.isUnconditionallyUnavailable())
return true;

// Filter out symbols without a name as we can generate correct symbol graphs
// for them. In practice these are anonymous record types that aren't attached
// to a declaration.
if (auto *Tag = dyn_cast<TagRecord>(Record)) {
if (Tag->IsEmbeddedInVarDeclarator)
return true;
}

// Filter out symbols prefixed with an underscored as they are understood to
// be symbols clients should not use.
if (Record->Name.starts_with("_"))
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Lex/HeaderSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,7 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
}
}

FileInfo.IsLocallyIncluded = true;
IsFirstIncludeOfFile = PP.markIncluded(File);
return true;
}
Expand Down
18 changes: 13 additions & 5 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7953,7 +7953,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
// For variadic functions, we may have more args than parameters.
// For some K&R functions, we may have less args than parameters.
const auto N = std::min<unsigned>(Proto->getNumParams(), Args.size());
bool AnyScalableArgsOrRet = Proto->getReturnType()->isSizelessVectorType();
bool IsScalableRet = Proto->getReturnType()->isSizelessVectorType();
bool IsScalableArg = false;
for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
// Args[ArgIdx] can be null in malformed code.
if (const Expr *Arg = Args[ArgIdx]) {
Expand All @@ -7968,7 +7969,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,

QualType ParamTy = Proto->getParamType(ArgIdx);
if (ParamTy->isSizelessVectorType())
AnyScalableArgsOrRet = true;
IsScalableArg = true;
QualType ArgTy = Arg->getType();
CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1),
ArgTy, ParamTy);
Expand All @@ -7993,7 +7994,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
// arguments or return values, then warn the user that the streaming and
// non-streaming vector lengths may be different.
const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext);
if (CallerFD && (!FD || !FD->getBuiltinID()) && AnyScalableArgsOrRet) {
if (CallerFD && (!FD || !FD->getBuiltinID()) &&
(IsScalableArg || IsScalableRet)) {
bool IsCalleeStreaming =
ExtInfo.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask;
bool IsCalleeStreamingCompatible =
Expand All @@ -8002,8 +8004,14 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD);
if (!IsCalleeStreamingCompatible &&
(CallerFnType == ArmStreamingCompatible ||
((CallerFnType == ArmStreaming) ^ IsCalleeStreaming)))
Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming);
((CallerFnType == ArmStreaming) ^ IsCalleeStreaming))) {
if (IsScalableArg)
Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
<< /*IsArg=*/true;
if (IsScalableRet)
Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
<< /*IsArg=*/false;
}
}

FunctionType::ArmStateValue CalleeArmZAState =
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12417,12 +12417,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
bool UsesZT0 = Attr && Attr->isNewZT0();

if (NewFD->hasAttr<ArmLocallyStreamingAttr>()) {
if (NewFD->getReturnType()->isSizelessVectorType() ||
llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) {
if (NewFD->getReturnType()->isSizelessVectorType())
Diag(NewFD->getLocation(),
diag::warn_sme_locally_streaming_has_vl_args_returns)
<< /*IsArg=*/false;
if (llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) {
return P->getOriginalType()->isSizelessVectorType();
}))
Diag(NewFD->getLocation(),
diag::warn_sme_locally_streaming_has_vl_args_returns);
diag::warn_sme_locally_streaming_has_vl_args_returns)
<< /*IsArg=*/true;
}
if (const auto *FPT = NewFD->getType()->getAs<FunctionProtoType>()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5184,6 +5184,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,

ParmVarDecl *Parm = Function->getParamDecl(0);
TypeSourceInfo *NewParmSI = IR.TransformType(Parm->getTypeSourceInfo());
assert(NewParmSI && "Type transformation failed.");
Parm->setType(NewParmSI->getType());
Parm->setTypeSourceInfo(NewParmSI);
};
Expand Down
78 changes: 44 additions & 34 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,34 +171,9 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {
.ModulesPruneNonAffectingModuleMaps)
return std::nullopt;

SmallVector<const Module *> ModulesToProcess{RootModule};

const HeaderSearch &HS = PP.getHeaderSearchInfo();

SmallVector<OptionalFileEntryRef, 16> FilesByUID;
HS.getFileMgr().GetUniqueIDMapping(FilesByUID);

if (FilesByUID.size() > HS.header_file_size())
FilesByUID.resize(HS.header_file_size());

for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {
OptionalFileEntryRef File = FilesByUID[UID];
if (!File)
continue;

const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);
if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
continue;

for (const auto &KH : HS.findResolvedModulesForHeader(*File)) {
if (!KH.getModule())
continue;
ModulesToProcess.push_back(KH.getModule());
}
}

const ModuleMap &MM = HS.getModuleMap();
SourceManager &SourceMgr = PP.getSourceManager();
const SourceManager &SourceMgr = PP.getSourceManager();

std::set<const FileEntry *> ModuleMaps;
auto CollectIncludingModuleMaps = [&](FileID FID, FileEntryRef F) {
Expand Down Expand Up @@ -233,12 +208,48 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {
}
};

for (const Module *CurrentModule : ModulesToProcess) {
// Handle all the affecting modules referenced from the root module.

std::queue<const Module *> Q;
Q.push(RootModule);
while (!Q.empty()) {
const Module *CurrentModule = Q.front();
Q.pop();

CollectIncludingMapsFromAncestors(CurrentModule);
for (const Module *ImportedModule : CurrentModule->Imports)
CollectIncludingMapsFromAncestors(ImportedModule);
for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses)
CollectIncludingMapsFromAncestors(UndeclaredModule);

for (auto *M : CurrentModule->submodules())
Q.push(M);
}

// Handle textually-included headers that belong to other modules.

SmallVector<OptionalFileEntryRef, 16> FilesByUID;
HS.getFileMgr().GetUniqueIDMapping(FilesByUID);

if (FilesByUID.size() > HS.header_file_size())
FilesByUID.resize(HS.header_file_size());

for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {
OptionalFileEntryRef File = FilesByUID[UID];
if (!File)
continue;

const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);
if (!HFI)
continue; // We have no information on this being a header file.
if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader)
continue; // Modular header, handled in the above module-based loop.
if (!HFI->isCompilingModuleHeader && !HFI->IsLocallyIncluded)
continue; // Non-modular header not included locally is not affecting.

for (const auto &KH : HS.findResolvedModulesForHeader(*File))
if (const Module *M = KH.getModule())
CollectIncludingMapsFromAncestors(M);
}

return ModuleMaps;
Expand Down Expand Up @@ -2053,14 +2064,13 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
if (!File)
continue;

// Get the file info. Skip emitting this file if we have no information on
// it as a header file (in which case HFI will be null) or if it hasn't
// changed since it was loaded. Also skip it if it's for a modular header
// from a different module; in that case, we rely on the module(s)
// containing the header to provide this information.
const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);
if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
continue;
if (!HFI)
continue; // We have no information on this being a header file.
if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader)
continue; // Header file info is tracked by the owning module file.
if (!HFI->isCompilingModuleHeader && !PP->alreadyIncluded(*File))
continue; // Non-modular header not included is not needed.

// Massage the file path into an appropriate form.
StringRef Filename = File->getName();
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ struct StreamOperationEvaluator {
SValBuilder &SVB;
const ASTContext &ACtx;

SymbolRef StreamSym;
SymbolRef StreamSym = nullptr;
const StreamState *SS = nullptr;
const CallExpr *CE = nullptr;
StreamErrorState NewES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesdf_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdf_vv_u32m8(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesdf_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesdf.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesdf_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdf_vs_u32m8_u32m8(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesdm_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdm_vv_u32m8(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesdm_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesdm.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesdm_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdm_vs_u32m8_u32m8(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesef_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesef_vv_u32m8(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesef_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesef.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesef_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesef_vs_u32m8_u32m8(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesem_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesem_vv_u32m8(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesem_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesem.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesem_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesem_vs_u32m8_u32m8(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,3 @@ vuint32m8_t test_vaesz_vs_u32m4_u32m8(vuint32m8_t vd, vuint32m4_t vs2, size_t vl
return __riscv_vaesz_vs_u32m4_u32m8(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesz_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesz.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesz_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesz_vs_u32m8_u32m8(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vsm4r_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vsm4r_vv_u32m8(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vsm4r_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vsm4r.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vsm4r_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vsm4r_vs_u32m8_u32m8(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesdf_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdf_vv(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesdf_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesdf.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesdf_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdf_vs(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesdm_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdm_vv(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesdm_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesdm.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesdm_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdm_vs(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesef_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesef_vv(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesef_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesef.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesef_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesef_vs(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesem_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesem_vv(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesem_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesem.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesem_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesem_vs(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,3 @@ vuint32m8_t test_vaesz_vs_u32m4_u32m8(vuint32m8_t vd, vuint32m4_t vs2, size_t vl
return __riscv_vaesz(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesz_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesz.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesz_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesz(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vsm4r_vv_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vsm4r_vv(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vsm4r_vs_u32m8_u32m8
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vsm4r.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vsm4r_vs_u32m8_u32m8(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vsm4r_vs(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesdf_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl)
return __riscv_vaesdf_vv_u32m8_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesdf_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesdf.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesdf_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdf_vs_u32m8_u32m8_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesdm_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl)
return __riscv_vaesdm_vv_u32m8_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesdm_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesdm.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesdm_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdm_vs_u32m8_u32m8_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesef_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl)
return __riscv_vaesef_vv_u32m8_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesef_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesef.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesef_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesef_vs_u32m8_u32m8_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesem_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl)
return __riscv_vaesem_vv_u32m8_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesem_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesem.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesem_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesem_vs_u32m8_u32m8_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,3 @@ vuint32m8_t test_vaesz_vs_u32m4_u32m8_tu(vuint32m8_t vd, vuint32m4_t vs2, size_t
return __riscv_vaesz_vs_u32m4_u32m8_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesz_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesz.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesz_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesz_vs_u32m8_u32m8_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vsm4r_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vsm4r_vv_u32m8_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vsm4r_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vsm4r.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vsm4r_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vsm4r_vs_u32m8_u32m8_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesdf_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl)
return __riscv_vaesdf_vv_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesdf_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesdf.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesdf_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdf_vs_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesdm_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl)
return __riscv_vaesdm_vv_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesdm_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesdm.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesdm_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesdm_vs_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesef_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl)
return __riscv_vaesef_vv_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesef_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesef.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesef_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesef_vs_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vaesem_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl)
return __riscv_vaesem_vv_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesem_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesem.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesem_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesem_vs_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,3 @@ vuint32m8_t test_vaesz_vs_u32m4_u32m8_tu(vuint32m8_t vd, vuint32m4_t vs2, size_t
return __riscv_vaesz_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vaesz_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vaesz.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vaesz_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vaesz_tu(vd, vs2, vl);
}

Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,3 @@ vuint32m8_t test_vsm4r_vv_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vsm4r_vv_tu(vd, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x i32> @test_vsm4r_vs_u32m8_u32m8_tu
// CHECK-RV64-SAME: (<vscale x 16 x i32> [[VD:%.*]], <vscale x 16 x i32> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x i32> @llvm.riscv.vsm4r.vs.nxv16i32.nxv16i32.i64(<vscale x 16 x i32> [[VD]], <vscale x 16 x i32> [[VS2]], i64 [[VL]], i64 2)
// CHECK-RV64-NEXT: ret <vscale x 16 x i32> [[TMP0]]
//
vuint32m8_t test_vsm4r_vs_u32m8_u32m8_tu(vuint32m8_t vd, vuint32m8_t vs2, size_t vl) {
return __riscv_vsm4r_vs_tu(vd, vs2, vl);
}

48 changes: 24 additions & 24 deletions clang/test/CodeGen/SystemZ/builtins-systemz-zvector.c
Original file line number Diff line number Diff line change
Expand Up @@ -2489,78 +2489,78 @@ void test_integer(void) {
// CHECK-ASM: vno

vuc = vec_cntlz(vsc);
// CHECK: call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK-ASM: vclzb
vuc = vec_cntlz(vuc);
// CHECK: call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK-ASM: vclzb
vus = vec_cntlz(vss);
// CHECK: call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK-ASM: vclzh
vus = vec_cntlz(vus);
// CHECK: call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK-ASM: vclzh
vui = vec_cntlz(vsi);
// CHECK: call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK-ASM: vclzf
vui = vec_cntlz(vui);
// CHECK: call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK-ASM: vclzf
vul = vec_cntlz(vsl);
// CHECK: call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK-ASM: vclzg
vul = vec_cntlz(vul);
// CHECK: call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK-ASM: vclzg

vuc = vec_cnttz(vsc);
// CHECK: call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK-ASM: vctzb
vuc = vec_cnttz(vuc);
// CHECK: call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK-ASM: vctzb
vus = vec_cnttz(vss);
// CHECK: call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK-ASM: vctzh
vus = vec_cnttz(vus);
// CHECK: call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK-ASM: vctzh
vui = vec_cnttz(vsi);
// CHECK: call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK-ASM: vctzf
vui = vec_cnttz(vui);
// CHECK: call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK-ASM: vctzf
vul = vec_cnttz(vsl);
// CHECK: call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK-ASM: vctzg
vul = vec_cnttz(vul);
// CHECK: call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK-ASM: vctzg

vuc = vec_popcnt(vsc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK-ASM: vpopct
vuc = vec_popcnt(vuc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK-ASM: vpopct
vus = vec_popcnt(vss);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// (emulated)
vus = vec_popcnt(vus);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// (emulated)
vui = vec_popcnt(vsi);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// (emulated)
vui = vec_popcnt(vui);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// (emulated)
vul = vec_popcnt(vsl);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// (emulated)
vul = vec_popcnt(vul);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// (emulated)

vsc = vec_rl(vsc, vuc);
Expand Down
16 changes: 8 additions & 8 deletions clang/test/CodeGen/SystemZ/builtins-systemz-zvector2.c
Original file line number Diff line number Diff line change
Expand Up @@ -577,28 +577,28 @@ void test_integer(void) {
// CHECK-ASM: vnx

vuc = vec_popcnt(vsc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK-ASM: vpopctb
vuc = vec_popcnt(vuc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK-ASM: vpopctb
vus = vec_popcnt(vss);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK-ASM: vpopcth
vus = vec_popcnt(vus);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK-ASM: vpopcth
vui = vec_popcnt(vsi);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK-ASM: vpopctf
vui = vec_popcnt(vui);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK-ASM: vpopctf
vul = vec_popcnt(vsl);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK-ASM: vpopctg
vul = vec_popcnt(vul);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK-ASM: vpopctg

vf = vec_slb(vf, vsi);
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/builtins-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ i32x4 bitselect(i32x4 x, i32x4 y, i32x4 c) {

i8x16 popcnt(i8x16 x) {
return __builtin_wasm_popcnt_i8x16(x);
// WEBASSEMBLY: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %x)
// WEBASSEMBLY: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %x)
// WEBASSEMBLY-NEXT: ret
}

Expand Down
20 changes: 10 additions & 10 deletions clang/test/CodeGen/ms-intrinsics-other.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ unsigned char test_BitScanForward(unsigned LONG *Index, unsigned LONG Mask) {
// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[INDEX:%[0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 %Mask, i1 true)
// CHECK: store i32 [[INDEX]], ptr %Index, align 4
// CHECK: br label %[[END_LABEL]]

Expand All @@ -70,7 +70,7 @@ unsigned char test_BitScanReverse(unsigned LONG *Index, unsigned LONG Mask) {
// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[REVINDEX:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %Mask, i1 true)
// CHECK: [[REVINDEX:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = xor i32 [[REVINDEX]], 31
// CHECK: store i32 [[INDEX]], ptr %Index, align 4
// CHECK: br label %[[END_LABEL]]
Expand All @@ -86,7 +86,7 @@ unsigned char test_BitScanForward64(unsigned LONG *Index, unsigned __int64 Mask)
// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[INDEX:%[0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 %Mask, i1 true)
// CHECK: [[TRUNC_INDEX:%[0-9]+]] = trunc nuw nsw i64 [[INDEX]] to i32
// CHECK: store i32 [[TRUNC_INDEX]], ptr %Index, align 4
// CHECK: br label %[[END_LABEL]]
Expand All @@ -101,7 +101,7 @@ unsigned char test_BitScanReverse64(unsigned LONG *Index, unsigned __int64 Mask)
// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[REVINDEX:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %Mask, i1 true)
// CHECK: [[REVINDEX:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %Mask, i1 true)
// CHECK: [[TRUNC_REVINDEX:%[0-9]+]] = trunc nuw nsw i64 [[REVINDEX]] to i32
// CHECK: [[INDEX:%[0-9]+]] = xor i32 [[TRUNC_REVINDEX]], 63
// CHECK: store i32 [[INDEX]], ptr %Index, align 4
Expand Down Expand Up @@ -187,47 +187,47 @@ unsigned short test__lzcnt16(unsigned short x) {
return __lzcnt16(x);
}
// CHECK: i16 @test__lzcnt16
// CHECK: [[RESULT:%[0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 %x, i1 false)
// CHECK: ret i16 [[RESULT]]
// CHECK: }

unsigned int test__lzcnt(unsigned int x) {
return __lzcnt(x);
}
// CHECK: i32 @test__lzcnt
// CHECK: [[RESULT:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %x, i1 false)
// CHECK: ret i32 [[RESULT]]
// CHECK: }

unsigned __int64 test__lzcnt64(unsigned __int64 x) {
return __lzcnt64(x);
}
// CHECK: i64 @test__lzcnt64
// CHECK: [[RESULT:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %x, i1 false)
// CHECK: ret i64 [[RESULT]]
// CHECK: }

unsigned short test__popcnt16(unsigned short x) {
return __popcnt16(x);
}
// CHECK: i16 @test__popcnt16
// CHECK: [[RESULT:%[0-9]+]] = tail call i16 @llvm.ctpop.i16(i16 %x)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i16 0, 17) i16 @llvm.ctpop.i16(i16 %x)
// CHECK: ret i16 [[RESULT]]
// CHECK: }

unsigned int test__popcnt(unsigned int x) {
return __popcnt(x);
}
// CHECK: i32 @test__popcnt
// CHECK: [[RESULT:%[0-9]+]] = tail call i32 @llvm.ctpop.i32(i32 %x)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 %x)
// CHECK: ret i32 [[RESULT]]
// CHECK: }

unsigned __int64 test__popcnt64(unsigned __int64 x) {
return __popcnt64(x);
}
// CHECK: i64 @test__popcnt64
// CHECK: [[RESULT:%[0-9]+]] = tail call i64 @llvm.ctpop.i64(i64 %x)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 %x)
// CHECK: ret i64 [[RESULT]]
// CHECK: }

Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/ms-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ unsigned char test_BitScanForward(unsigned long *Index, unsigned long Mask) {
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[IDXGEP:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr %Index, {{i64|i32}} 4
// CHECK: [[INDEX:%[0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 %Mask, i1 true)
// CHECK: store i32 [[INDEX]], ptr [[IDXGEP]], align 4
// CHECK: br label %[[END_LABEL]]

Expand All @@ -172,7 +172,7 @@ unsigned char test_BitScanReverse(unsigned long *Index, unsigned long Mask) {
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[IDXGEP:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr %Index, {{i64|i32}} 4
// CHECK: [[REVINDEX:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %Mask, i1 true)
// CHECK: [[REVINDEX:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = xor i32 [[REVINDEX]], 31
// CHECK: store i32 [[INDEX]], ptr [[IDXGEP]], align 4
// CHECK: br label %[[END_LABEL]]
Expand All @@ -188,7 +188,7 @@ unsigned char test_BitScanForward64(unsigned long *Index, unsigned __int64 Mask)
// CHECK-ARM-X64: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK-ARM-X64: ret i8 [[RESULT]]
// CHECK-ARM-X64: [[ISNOTZERO_LABEL]]:
// CHECK-ARM-X64: [[INDEX:%[0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %Mask, i1 true)
// CHECK-ARM-X64: [[INDEX:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 %Mask, i1 true)
// CHECK-ARM-X64: [[TRUNC_INDEX:%[0-9]+]] = trunc nuw nsw i64 [[INDEX]] to i32
// CHECK-ARM-X64: store i32 [[TRUNC_INDEX]], ptr %Index, align 4
// CHECK-ARM-X64: br label %[[END_LABEL]]
Expand All @@ -203,7 +203,7 @@ unsigned char test_BitScanReverse64(unsigned long *Index, unsigned __int64 Mask)
// CHECK-ARM-X64: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK-ARM-X64: ret i8 [[RESULT]]
// CHECK-ARM-X64: [[ISNOTZERO_LABEL]]:
// CHECK-ARM-X64: [[REVINDEX:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %Mask, i1 true)
// CHECK-ARM-X64: [[REVINDEX:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %Mask, i1 true)
// CHECK-ARM-X64: [[TRUNC_REVINDEX:%[0-9]+]] = trunc nuw nsw i64 [[REVINDEX]] to i32
// CHECK-ARM-X64: [[INDEX:%[0-9]+]] = xor i32 [[TRUNC_REVINDEX]], 63
// CHECK-ARM-X64: store i32 [[INDEX]], ptr %Index, align 4
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenOpenCL/builtins-generic-amdgcn.cl
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
#pragma OPENCL EXTENSION cl_khr_fp16 : enable

// CHECK-LABEL: @test_builtin_clz(
// CHECK: tail call i32 @llvm.ctlz.i32(i32 %a, i1 true)
// CHECK: tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %a, i1 true)
void test_builtin_clz(global int* out, int a)
{
*out = __builtin_clz(a);
}

// CHECK-LABEL: @test_builtin_clzl(
// CHECK: tail call i64 @llvm.ctlz.i64(i64 %a, i1 true)
// CHECK: tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %a, i1 true)
void test_builtin_clzl(global long* out, long a)
{
*out = __builtin_clzl(a);
Expand Down
4 changes: 4 additions & 0 deletions clang/test/Driver/amdgpu-toolchain.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@
// RUN: -L. -fconvergent-functions %s 2>&1 | FileCheck -check-prefix=MCPU %s
// LTO: clang{{.*}} "-flto=full"{{.*}}"-fconvergent-functions"
// MCPU: ld.lld{{.*}}"-L."{{.*}}"-plugin-opt=mcpu=gfx906"

// RUN: %clang -### --target=amdgcn-amd-amdhsa -mcpu=gfx906 -nogpulib \
// RUN: -fuse-ld=ld %s 2>&1 | FileCheck -check-prefixes=LD %s
// LD: ld.lld"
333 changes: 159 additions & 174 deletions clang/test/Driver/fast-math.c

Large diffs are not rendered by default.

565 changes: 165 additions & 400 deletions clang/test/ExtractAPI/anonymous_record_no_typedef.c

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions clang/test/ExtractAPI/enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ enum {
},
{
"kind": "text",
"spelling": ": "
"spelling": " : "
},
{
"kind": "typeIdentifier",
Expand Down Expand Up @@ -459,7 +459,7 @@ enum {
},
{
"kind": "text",
"spelling": ": "
"spelling": " : "
},
{
"kind": "typeIdentifier",
Expand Down Expand Up @@ -686,7 +686,7 @@ enum {
},
{
"kind": "text",
"spelling": ": "
"spelling": " : "
},
{
"kind": "typeIdentifier",
Expand All @@ -695,7 +695,7 @@ enum {
},
{
"kind": "text",
"spelling": ";"
"spelling": " { ... };"
}
],
"identifier": {
Expand Down Expand Up @@ -778,7 +778,7 @@ enum {
},
{
"kind": "text",
"spelling": ": "
"spelling": " : "
},
{
"kind": "typeIdentifier",
Expand All @@ -787,7 +787,7 @@ enum {
},
{
"kind": "text",
"spelling": ";"
"spelling": " { ... };"
}
],
"identifier": {
Expand Down
18 changes: 3 additions & 15 deletions clang/test/ExtractAPI/function_noexcepts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ void getFooBar() noexcept(false);
},
{
"kind": "text",
"spelling": "()"
},
{
"kind": "text",
"spelling": " "
"spelling": "() "
},
{
"kind": "keyword",
Expand Down Expand Up @@ -139,11 +135,7 @@ void getFooBar() noexcept(false);
},
{
"kind": "text",
"spelling": "()"
},
{
"kind": "text",
"spelling": " "
"spelling": "() "
},
{
"kind": "keyword",
Expand Down Expand Up @@ -223,11 +215,7 @@ void getFooBar() noexcept(false);
},
{
"kind": "text",
"spelling": "()"
},
{
"kind": "text",
"spelling": " "
"spelling": "() "
},
{
"kind": "keyword",
Expand Down
6 changes: 1 addition & 5 deletions clang/test/ExtractAPI/methods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,7 @@ class Foo {
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "text",
// SETL-NEXT: "spelling": ")"
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "text",
// SETL-NEXT: "spelling": " "
// SETL-NEXT: "spelling": ") "
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "keyword",
Expand Down
48 changes: 8 additions & 40 deletions clang/test/ExtractAPI/objc_block.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ -(void)methodBlockNoParam:(void (^)())block;
// NOPARAM-NEXT: },
// NOPARAM-NEXT: {
// NOPARAM-NEXT: "kind": "text",
// NOPARAM-NEXT: "spelling": " (^"
// NOPARAM-NEXT: },
// NOPARAM-NEXT: {
// NOPARAM-NEXT: "kind": "text",
// NOPARAM-NEXT: "spelling": ")()) "
// NOPARAM-NEXT: "spelling": " (^)()) "
// NOPARAM-NEXT: },
// NOPARAM-NEXT: {
// NOPARAM-NEXT: "kind": "internalParam",
Expand All @@ -65,11 +61,7 @@ -(void)methodBlockNoParam:(void (^)())block;
// NOPARAM-NEXT: },
// NOPARAM-NEXT: {
// NOPARAM-NEXT: "kind": "text",
// NOPARAM-NEXT: "spelling": " (^"
// NOPARAM-NEXT: },
// NOPARAM-NEXT: {
// NOPARAM-NEXT: "kind": "text",
// NOPARAM-NEXT: "spelling": ")()) "
// NOPARAM-NEXT: "spelling": " (^)()) "
// NOPARAM-NEXT: },
// NOPARAM-NEXT: {
// NOPARAM-NEXT: "kind": "internalParam",
Expand Down Expand Up @@ -120,11 +112,7 @@ -(void)methodBlockWithParam:(int (^)(int foo))block;
// PARAM-NEXT: },
// PARAM-NEXT: {
// PARAM-NEXT: "kind": "text",
// PARAM-NEXT: "spelling": " (^"
// PARAM-NEXT: },
// PARAM-NEXT: {
// PARAM-NEXT: "kind": "text",
// PARAM-NEXT: "spelling": ")("
// PARAM-NEXT: "spelling": " (^)("
// PARAM-NEXT: },
// PARAM-NEXT: {
// PARAM-NEXT: "kind": "typeIdentifier",
Expand Down Expand Up @@ -167,11 +155,7 @@ -(void)methodBlockWithParam:(int (^)(int foo))block;
// PARAM-NEXT: },
// PARAM-NEXT: {
// PARAM-NEXT: "kind": "text",
// PARAM-NEXT: "spelling": " (^"
// PARAM-NEXT: },
// PARAM-NEXT: {
// PARAM-NEXT: "kind": "text",
// PARAM-NEXT: "spelling": ")("
// PARAM-NEXT: "spelling": " (^)("
// PARAM-NEXT: },
// PARAM-NEXT: {
// PARAM-NEXT: "kind": "typeIdentifier",
Expand Down Expand Up @@ -239,11 +223,7 @@ -(void)methodBlockWithMultipleParam:(int (^)(int foo, unsigned baz))block;
// MULTIPARAM-NEXT: },
// MULTIPARAM-NEXT: {
// MULTIPARAM-NEXT: "kind": "text",
// MULTIPARAM-NEXT: "spelling": " (^"
// MULTIPARAM-NEXT: },
// MULTIPARAM-NEXT: {
// MULTIPARAM-NEXT: "kind": "text",
// MULTIPARAM-NEXT: "spelling": ")("
// MULTIPARAM-NEXT: "spelling": " (^)("
// MULTIPARAM-NEXT: },
// MULTIPARAM-NEXT: {
// MULTIPARAM-NEXT: "kind": "typeIdentifier",
Expand Down Expand Up @@ -303,11 +283,7 @@ -(void)methodBlockWithMultipleParam:(int (^)(int foo, unsigned baz))block;
// MULTIPARAM-NEXT: },
// MULTIPARAM-NEXT: {
// MULTIPARAM-NEXT: "kind": "text",
// MULTIPARAM-NEXT: "spelling": " (^"
// MULTIPARAM-NEXT: },
// MULTIPARAM-NEXT: {
// MULTIPARAM-NEXT: "kind": "text",
// MULTIPARAM-NEXT: "spelling": ")("
// MULTIPARAM-NEXT: "spelling": " (^)("
// MULTIPARAM-NEXT: },
// MULTIPARAM-NEXT: {
// MULTIPARAM-NEXT: "kind": "typeIdentifier",
Expand Down Expand Up @@ -392,11 +368,7 @@ -(void)methodBlockVariadic:(int (^)(int foo, ...))block;
// VARIADIC-NEXT: },
// VARIADIC-NEXT: {
// VARIADIC-NEXT: "kind": "text",
// VARIADIC-NEXT: "spelling": " (^"
// VARIADIC-NEXT: },
// VARIADIC-NEXT: {
// VARIADIC-NEXT: "kind": "text",
// VARIADIC-NEXT: "spelling": ")("
// VARIADIC-NEXT: "spelling": " (^)("
// VARIADIC-NEXT: },
// VARIADIC-NEXT: {
// VARIADIC-NEXT: "kind": "typeIdentifier",
Expand Down Expand Up @@ -439,11 +411,7 @@ -(void)methodBlockVariadic:(int (^)(int foo, ...))block;
// VARIADIC-NEXT: },
// VARIADIC-NEXT: {
// VARIADIC-NEXT: "kind": "text",
// VARIADIC-NEXT: "spelling": " (^"
// VARIADIC-NEXT: },
// VARIADIC-NEXT: {
// VARIADIC-NEXT: "kind": "text",
// VARIADIC-NEXT: "spelling": ")("
// VARIADIC-NEXT: "spelling": " (^)("
// VARIADIC-NEXT: },
// VARIADIC-NEXT: {
// VARIADIC-NEXT: "kind": "typeIdentifier",
Expand Down
4 changes: 2 additions & 2 deletions clang/test/ExtractAPI/typedef_anonymous_record.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ typedef struct { } MyStruct;
// MYSTRUCT-NEXT: },
// MYSTRUCT-NEXT: {
// MYSTRUCT-NEXT: "kind": "text",
// MYSTRUCT-NEXT: "spelling": " "
// MYSTRUCT-NEXT: "spelling": " { ... } "
// MYSTRUCT-NEXT: },
// MYSTRUCT-NEXT: {
// MYSTRUCT-NEXT: "kind": "identifier",
Expand Down Expand Up @@ -97,7 +97,7 @@ typedef enum { Case } MyEnum;
// MYENUM-NEXT: },
// MYENUM-NEXT: {
// MYENUM-NEXT: "kind": "text",
// MYENUM-NEXT: "spelling": " "
// MYENUM-NEXT: "spelling": " { ... } "
// MYENUM-NEXT: },
// MYENUM-NEXT: {
// MYENUM-NEXT: "kind": "identifier",
Expand Down
2 changes: 1 addition & 1 deletion clang/test/ExtractAPI/typedef_struct_enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ typedef enum Test2 {
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "text",
// TEST2-NEXT: "spelling": ": "
// TEST2-NEXT: "spelling": " : "
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "typeIdentifier",
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Headers/wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1572,7 +1572,7 @@ uint32_t test_i8x16_bitmask(v128_t a) {
// CHECK-LABEL: @test_i8x16_popcnt(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8>
// CHECK-NEXT: [[TMP1:%.*]] = tail call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> [[TMP0]]), !range [[RNG5:![0-9]+]]
// CHECK-NEXT: [[TMP1:%.*]] = tail call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> [[TMP0]])
// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
// CHECK-NEXT: ret <4 x i32> [[TMP2]]
//
Expand Down
46 changes: 46 additions & 0 deletions clang/test/Modules/prune-non-affecting-module-map-files-textual.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// This test checks that a module map with a textual header can be marked as
// non-affecting.

// RUN: rm -rf %t && mkdir %t
// RUN: split-file %s %t

//--- X.modulemap
module X { textual header "X.h" }
//--- X.h
typedef int X_int;

//--- Y.modulemap
module Y { textual header "Y.h" }
//--- Y.h
typedef int Y_int;

//--- A.modulemap
module A { header "A.h" export * }
//--- A.h
#include "X.h"

// RUN: %clang_cc1 -fmodules -emit-module %t/A.modulemap -fmodule-name=A -o %t/A0.pcm \
// RUN: -fmodule-map-file=%t/X.modulemap
// RUN: %clang_cc1 -fsyntax-only -module-file-info %t/A0.pcm | FileCheck %s --check-prefix=A0 --implicit-check-not=Y.modulemap
// A0: Input file: {{.*}}X.modulemap

// RUN: %clang_cc1 -fmodules -emit-module %t/A.modulemap -fmodule-name=A -o %t/A1.pcm \
// RUN: -fmodule-map-file=%t/X.modulemap -fmodule-map-file=%t/Y.modulemap
// RUN: %clang_cc1 -fsyntax-only -module-file-info %t/A0.pcm | FileCheck %s --check-prefix=A1 \
// RUN: --implicit-check-not=Y.modulemap
// A1: Input file: {{.*}}X.modulemap

// RUN: diff %t/A0.pcm %t/A1.pcm

//--- B.modulemap
module B { header "B.h" export * }
//--- B.h
#include "A.h"
typedef X_int B_int;

// RUN: %clang_cc1 -fmodules -emit-module %t/B.modulemap -fmodule-name=B -o %t/B.pcm \
// RUN: -fmodule-file=A=%t/A0.pcm \
// RUN: -fmodule-map-file=%t/A.modulemap -fmodule-map-file=%t/X.modulemap -fmodule-map-file=%t/Y.modulemap
// RUN: %clang_cc1 -fsyntax-only -module-file-info %t/B.pcm | FileCheck %s --check-prefix=B \
// RUN: --implicit-check-not=X.modulemap --implicit-check-not=Y.modulemap
// B: Input file: {{.*}}B.modulemap
12 changes: 8 additions & 4 deletions clang/test/Sema/aarch64-incompat-sm-builtin-calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ svuint32_t incompat_sve_sm(svbool_t pg, svuint32_t a, int16_t b) __arm_streaming
return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
// expected-warning@+2 {{returning a VL-dependent argument from a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
// expected-warning@+1 {{passing a VL-dependent argument to a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
__arm_locally_streaming svuint32_t incompat_sve_ls(svbool_t pg, svuint32_t a, int64_t b) {
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b);
Expand All @@ -49,7 +50,8 @@ svuint32_t incompat_sve2_sm(svbool_t pg, svuint32_t a, int64_t b) __arm_streamin
return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
// expected-warning@+2 {{returning a VL-dependent argument from a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
// expected-warning@+1 {{passing a VL-dependent argument to a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
__arm_locally_streaming svuint32_t incompat_sve2_ls(svbool_t pg, svuint32_t a, int64_t b) {
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b);
Expand All @@ -70,7 +72,8 @@ svfloat64_t streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) __arm_
return svadd_n_f64_m(pg, a, b);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
// expected-warning@+2 {{returning a VL-dependent argument from a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
// expected-warning@+1 {{passing a VL-dependent argument to a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
__arm_locally_streaming svfloat64_t locally_streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) {
// expected-no-warning
return svadd_n_f64_m(pg, a, b);
Expand All @@ -86,7 +89,8 @@ svint16_t streaming_caller_sve2(svint16_t op1, svint16_t op2) __arm_streaming {
return svmul_lane_s16(op1, op2, 0);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
// expected-warning@+2 {{returning a VL-dependent argument from a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
// expected-warning@+1 {{passing a VL-dependent argument to a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
__arm_locally_streaming svint16_t locally_streaming_caller_sve2(svint16_t op1, svint16_t op2) {
// expected-no-warning
return svmul_lane_s16(op1, op2, 0);
Expand Down
Loading