2 changes: 1 addition & 1 deletion clang/lib/AST/DeclFriend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
return FD;
}

FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID,
FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
unsigned FriendTypeNumTPLists) {
std::size_t Extra =
additionalSizeToAlloc<TemplateParameterList *>(FriendTypeNumTPLists);
Expand Down
24 changes: 12 additions & 12 deletions clang/lib/AST/DeclObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ ObjCMethodDecl *ObjCMethodDecl::Create(
isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
}

ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(),
Selector(), QualType(), nullptr, nullptr);
}
Expand Down Expand Up @@ -1486,7 +1486,7 @@ ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
}

ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
unsigned ID) {
Decl::DeclID ID) {
return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr,
ObjCTypeParamVariance::Invariant,
SourceLocation(), 0, SourceLocation(),
Expand Down Expand Up @@ -1551,7 +1551,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(
}

ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
auto *Result = new (C, ID)
ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr,
SourceLocation(), nullptr, false);
Expand Down Expand Up @@ -1865,7 +1865,7 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
synthesized);
}

ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(),
nullptr, QualType(), nullptr,
ObjCIvarDecl::None, nullptr, false);
Expand Down Expand Up @@ -1914,7 +1914,7 @@ ObjCAtDefsFieldDecl
}

ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(),
SourceLocation(), nullptr, QualType(),
nullptr);
Expand Down Expand Up @@ -1949,7 +1949,7 @@ ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
}

ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
ObjCProtocolDecl *Result =
new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(),
SourceLocation(), nullptr);
Expand Down Expand Up @@ -2148,7 +2148,7 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(
}

ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(),
SourceLocation(), SourceLocation(),
nullptr, nullptr, nullptr);
Expand Down Expand Up @@ -2189,7 +2189,7 @@ ObjCCategoryImplDecl *ObjCCategoryImplDecl::Create(
}

ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr,
SourceLocation(), SourceLocation(),
SourceLocation());
Expand Down Expand Up @@ -2296,7 +2296,7 @@ ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
}

ObjCImplementationDecl *
ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
ObjCImplementationDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr,
SourceLocation(), SourceLocation());
}
Expand Down Expand Up @@ -2339,7 +2339,7 @@ ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
}

ObjCCompatibleAliasDecl *
ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(),
nullptr, nullptr);
}
Expand All @@ -2360,7 +2360,7 @@ ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
}

ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr,
SourceLocation(), SourceLocation(),
QualType(), nullptr, None);
Expand Down Expand Up @@ -2393,7 +2393,7 @@ ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
}

ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(),
SourceLocation(), nullptr, Dynamic,
nullptr, SourceLocation());
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/AST/DeclOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
}

OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
Decl::DeclID ID,
unsigned N) {
return OMPDeclarativeDirective::createEmptyDirective<OMPThreadPrivateDecl>(
C, ID, 0, N);
Expand All @@ -63,7 +63,7 @@ OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC,
return D;
}

OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, unsigned ID,
OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
unsigned NVars,
unsigned NClauses) {
return OMPDeclarativeDirective::createEmptyDirective<OMPAllocateDecl>(
Expand All @@ -89,7 +89,7 @@ OMPRequiresDecl *OMPRequiresDecl::Create(ASTContext &C, DeclContext *DC,
L);
}

OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C, unsigned ID,
OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
unsigned N) {
return OMPDeclarativeDirective::createEmptyDirective<OMPRequiresDecl>(
C, ID, N, 0, SourceLocation());
Expand Down Expand Up @@ -117,7 +117,7 @@ OMPDeclareReductionDecl *OMPDeclareReductionDecl::Create(
}

OMPDeclareReductionDecl *
OMPDeclareReductionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
OMPDeclareReductionDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
return new (C, ID) OMPDeclareReductionDecl(
OMPDeclareReduction, /*DC=*/nullptr, SourceLocation(), DeclarationName(),
QualType(), /*PrevDeclInScope=*/nullptr);
Expand Down Expand Up @@ -148,7 +148,7 @@ OMPDeclareMapperDecl *OMPDeclareMapperDecl::Create(
}

OMPDeclareMapperDecl *OMPDeclareMapperDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
Decl::DeclID ID,
unsigned N) {
return OMPDeclarativeDirective::createEmptyDirective<OMPDeclareMapperDecl>(
C, ID, N, 1, SourceLocation(), DeclarationName(), QualType(),
Expand Down Expand Up @@ -179,7 +179,7 @@ OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC,
}

OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType(),
/*TInfo=*/nullptr, SourceLocation());
}
Expand Down
36 changes: 18 additions & 18 deletions clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
}

FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(),
DeclarationName(), nullptr, nullptr);
}
Expand Down Expand Up @@ -503,7 +503,7 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, DeclContext *DC,
}

ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(),
DeclarationName(), nullptr, nullptr);
}
Expand Down Expand Up @@ -652,14 +652,14 @@ TemplateTypeParmDecl *TemplateTypeParmDecl::Create(
}

TemplateTypeParmDecl *
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID) {
return new (C, ID)
TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
false, false, std::nullopt);
}

TemplateTypeParmDecl *
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID,
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID,
bool HasTypeConstraint) {
return new (C, ID,
additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0))
Expand Down Expand Up @@ -759,7 +759,7 @@ NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
}

NonTypeTemplateParmDecl *
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
bool HasTypeConstraint) {
return new (C, ID, additionalSizeToAlloc<std::pair<QualType,
TypeSourceInfo *>,
Expand All @@ -770,7 +770,7 @@ NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
}

NonTypeTemplateParmDecl *
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
unsigned NumExpandedTypes,
bool HasTypeConstraint) {
auto *NTTP =
Expand Down Expand Up @@ -836,13 +836,13 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
}

TemplateTemplateParmDecl *
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
false, nullptr, false, nullptr);
}

TemplateTemplateParmDecl *
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
unsigned NumExpansions) {
auto *TTP =
new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions))
Expand Down Expand Up @@ -949,7 +949,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,

ClassTemplateSpecializationDecl *
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
auto *Result =
new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
Result->setMayHaveOutOfDateDef(false);
Expand Down Expand Up @@ -1036,7 +1036,7 @@ ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
}

ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(),
DeclarationName(),
nullptr, nullptr);
Expand Down Expand Up @@ -1070,7 +1070,7 @@ ImplicitConceptSpecializationDecl *ImplicitConceptSpecializationDecl::Create(

ImplicitConceptSpecializationDecl *
ImplicitConceptSpecializationDecl::CreateDeserialized(
const ASTContext &C, unsigned ID, unsigned NumTemplateArgs) {
const ASTContext &C, Decl::DeclID ID, unsigned NumTemplateArgs) {
return new (C, ID, additionalSizeToAlloc<TemplateArgument>(NumTemplateArgs))
ImplicitConceptSpecializationDecl(EmptyShell{}, NumTemplateArgs);
}
Expand Down Expand Up @@ -1133,7 +1133,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC,

ClassTemplatePartialSpecializationDecl *
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
Result->setMayHaveOutOfDateDef(false);
return Result;
Expand All @@ -1160,7 +1160,7 @@ FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
}

FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) FriendTemplateDecl(EmptyShell());
}

Expand All @@ -1180,7 +1180,7 @@ TypeAliasTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
}

TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(),
DeclarationName(), nullptr, nullptr);
}
Expand Down Expand Up @@ -1218,7 +1218,7 @@ VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
}

VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(),
DeclarationName(), nullptr, nullptr);
}
Expand Down Expand Up @@ -1340,7 +1340,7 @@ VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
}

VarTemplateSpecializationDecl *
VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
return new (C, ID)
VarTemplateSpecializationDecl(VarTemplateSpecialization, C);
}
Expand Down Expand Up @@ -1432,7 +1432,7 @@ VarTemplatePartialSpecializationDecl::Create(

VarTemplatePartialSpecializationDecl *
VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
Decl::DeclID ID) {
return new (C, ID) VarTemplatePartialSpecializationDecl(C);
}

Expand Down Expand Up @@ -1546,7 +1546,7 @@ TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C,
}

TemplateParamObjectDecl *
TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue());
C.addDestruction(&TPOD->Value);
return TPOD;
Expand Down
28 changes: 14 additions & 14 deletions clang/lib/AST/ExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,15 +353,14 @@ SourceLocation CXXPseudoDestructorExpr::getEndLoc() const {
UnresolvedLookupExpr::UnresolvedLookupExpr(
const ASTContext &Context, CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded,
const DeclarationNameInfo &NameInfo, bool RequiresADL,
const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
UnresolvedSetIterator End, bool KnownDependent)
: OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc,
TemplateKWLoc, NameInfo, TemplateArgs, Begin, End,
KnownDependent, false, false),
NamingClass(NamingClass) {
UnresolvedLookupExprBits.RequiresADL = RequiresADL;
UnresolvedLookupExprBits.Overloaded = Overloaded;
}

UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty,
Expand All @@ -373,15 +372,16 @@ UnresolvedLookupExpr::UnresolvedLookupExpr(EmptyShell Empty,
UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
const ASTContext &Context, CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End,
bool KnownDependent) {
unsigned NumResults = End - Begin;
unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc>(NumResults, 0, 0);
void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
SourceLocation(), NameInfo, RequiresADL,
Overloaded, nullptr, Begin, End, false);
return new (Mem) UnresolvedLookupExpr(
Context, NamingClass, QualifierLoc,
/*TemplateKWLoc=*/SourceLocation(), NameInfo, RequiresADL,
/*TemplateArgs=*/nullptr, Begin, End, KnownDependent);
}

UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
Expand All @@ -390,16 +390,16 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
const DeclarationNameInfo &NameInfo, bool RequiresADL,
const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin,
UnresolvedSetIterator End, bool KnownDependent) {
assert(Args || TemplateKWLoc.isValid());
unsigned NumResults = End - Begin;
bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid();
unsigned NumTemplateArgs = Args ? Args->size() : 0;
unsigned Size =
totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc>(NumResults, 1, NumTemplateArgs);
unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc>(
NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
return new (Mem) UnresolvedLookupExpr(
Context, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, RequiresADL,
/*Overloaded=*/true, Args, Begin, End, KnownDependent);
return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
TemplateKWLoc, NameInfo, RequiresADL,
Args, Begin, End, KnownDependent);
}

UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty(
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16853,13 +16853,13 @@ bool Expr::EvaluateCharRangeAsString(std::string &Result,
if (!::EvaluateInteger(SizeExpression, SizeValue, Info))
return false;

int64_t Size = SizeValue.getExtValue();
uint64_t Size = SizeValue.getZExtValue();

if (!::EvaluatePointer(PtrExpression, String, Info))
return false;

QualType CharTy = PtrExpression->getType()->getPointeeType();
for (int64_t I = 0; I < Size; ++I) {
for (uint64_t I = 0; I < Size; ++I) {
APValue Char;
if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String,
Char))
Expand Down
30 changes: 26 additions & 4 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
return false;

PrimType T = classifyPrim(CE->getType());
if (T == PT_IntAP)
return this->emitCastPointerIntegralAP(Ctx.getBitWidth(CE->getType()),
CE);
if (T == PT_IntAPS)
return this->emitCastPointerIntegralAPS(Ctx.getBitWidth(CE->getType()),
CE);
return this->emitCastPointerIntegral(T, CE);
}

Expand Down Expand Up @@ -922,9 +928,9 @@ bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueIni
return true;
}

if (QT->isAnyComplexType()) {
if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {
assert(Initializing);
QualType ElemQT = QT->getAs<ComplexType>()->getElementType();
QualType ElemQT = ComplexTy->getElementType();
PrimType ElemT = classifyPrim(ElemQT);
for (unsigned I = 0; I < 2; ++I) {
if (!this->visitZeroInitializer(ElemT, ElemQT, E))
Expand All @@ -935,6 +941,20 @@ bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueIni
return true;
}

if (const auto *VecT = E->getType()->getAs<VectorType>()) {
unsigned NumVecElements = VecT->getNumElements();
QualType ElemQT = VecT->getElementType();
PrimType ElemT = classifyPrim(ElemQT);

for (unsigned I = 0; I < NumVecElements; ++I) {
if (!this->visitZeroInitializer(ElemT, ElemQT, E))
return false;
if (!this->emitInitElem(ElemT, I, E))
return false;
}
return true;
}

return false;
}

Expand Down Expand Up @@ -1098,13 +1118,13 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
return true;
}

if (T->isAnyComplexType()) {
if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {
unsigned NumInits = E->getNumInits();

if (NumInits == 1)
return this->delegate(E->inits()[0]);

QualType ElemQT = E->getType()->getAs<ComplexType>()->getElementType();
QualType ElemQT = ComplexTy->getElementType();
PrimType ElemT = classifyPrim(ElemQT);
if (NumInits == 0) {
// Zero-initialize both elements.
Expand Down Expand Up @@ -1337,6 +1357,8 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
const RecordDecl *RD = FD->getParent();
const Record *R = getRecord(RD);
if (!R)
return false;
const Record::Field *F = R->getField(FD);
// Leave a pointer to the field on the stack.
if (F->Decl->getType()->isReferenceType())
Expand Down
25 changes: 24 additions & 1 deletion clang/lib/AST/Interp/ByteCodeStmtGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,30 @@ bool ByteCodeStmtGen<Emitter>::visitDefaultStmt(const DefaultStmt *S) {

template <class Emitter>
bool ByteCodeStmtGen<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
// Ignore all attributes.

for (const Attr *A : S->getAttrs()) {
auto *AA = dyn_cast<CXXAssumeAttr>(A);
if (!AA)
continue;

assert(isa<NullStmt>(S->getSubStmt()));

const Expr *Assumption = AA->getAssumption();
if (Assumption->isValueDependent())
return false;

if (Assumption->HasSideEffects(this->Ctx.getASTContext()))
continue;

// Evaluate assumption.
if (!this->visitBool(Assumption))
return false;

if (!this->emitAssume(Assumption))
return false;
}

// Ignore other attributes.
return this->visitStmt(S->getSubStmt());
}

Expand Down
5 changes: 4 additions & 1 deletion clang/lib/AST/Interp/IntegralAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ template <bool Signed> class IntegralAP final {
}

IntegralAP truncate(unsigned BitWidth) const {
return IntegralAP(V.trunc(BitWidth));
if constexpr (Signed)
return IntegralAP(V.trunc(BitWidth).sextOrTrunc(this->bitWidth()));
else
return IntegralAP(V.trunc(BitWidth).zextOrTrunc(this->bitWidth()));
}

IntegralAP<false> toUnsigned() const {
Expand Down
63 changes: 51 additions & 12 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1548,17 +1548,16 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
if (!CheckArray(S, OpPC, Ptr))
return false;

// Get a version of the index comparable to the type.
T Index = T::from(Ptr.getIndex(), Offset.bitWidth());
// Compute the largest index into the array.
T MaxIndex = T::from(Ptr.getNumElems(), Offset.bitWidth());
uint64_t Index = Ptr.getIndex();
uint64_t MaxIndex = static_cast<uint64_t>(Ptr.getNumElems());

bool Invalid = false;
// Helper to report an invalid offset, computed as APSInt.
auto DiagInvalidOffset = [&]() -> void {
const unsigned Bits = Offset.bitWidth();
APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false);
APSInt APIndex(Index.toAPSInt().extend(Bits + 2), false);
APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), /*IsUnsigend=*/false);
APSInt APIndex(APInt(Bits + 2, Index, /*IsSigned=*/true),
/*IsUnsigned=*/false);
APSInt NewIndex =
(Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
Expand All @@ -1569,22 +1568,24 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
};

if (Ptr.isBlockPointer()) {
T MaxOffset = T::from(MaxIndex - Index, Offset.bitWidth());
uint64_t IOffset = static_cast<uint64_t>(Offset);
uint64_t MaxOffset = MaxIndex - Index;

if constexpr (Op == ArithOp::Add) {
// If the new offset would be negative, bail out.
if (Offset.isNegative() && (Offset.isMin() || -Offset > Index))
if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
DiagInvalidOffset();

// If the new offset would be out of bounds, bail out.
if (Offset.isPositive() && Offset > MaxOffset)
if (Offset.isPositive() && IOffset > MaxOffset)
DiagInvalidOffset();
} else {
// If the new offset would be negative, bail out.
if (Offset.isPositive() && Index < Offset)
if (Offset.isPositive() && Index < IOffset)
DiagInvalidOffset();

// If the new offset would be out of bounds, bail out.
if (Offset.isNegative() && (Offset.isMin() || -Offset > MaxOffset))
if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
DiagInvalidOffset();
}
}
Expand All @@ -1601,7 +1602,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
else
Result = WideIndex - WideOffset;

S.Stk.push<Pointer>(Ptr.atIndex(static_cast<unsigned>(Result)));
S.Stk.push<Pointer>(Ptr.atIndex(static_cast<uint64_t>(Result)));
return true;
}

Expand Down Expand Up @@ -1832,6 +1833,32 @@ bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
return true;
}

static inline bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);

S.Stk.push<IntegralAP<false>>(
IntegralAP<false>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}

static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);

S.Stk.push<IntegralAP<true>>(
IntegralAP<true>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}

//===----------------------------------------------------------------------===//
// Zero, Nullptr
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2300,6 +2327,18 @@ inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC,
return CheckDeclRef(S, OpPC, DR);
}

inline bool Assume(InterpState &S, CodePtr OpPC) {
const auto Val = S.Stk.pop<Boolean>();

if (Val)
return true;

// Else, diagnose.
const SourceLocation &Loc = S.Current->getLocation(OpPC);
S.CCEDiag(Loc, diag::note_constexpr_assumption_failed);
return false;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) {
llvm::SmallVector<int64_t> ArrayIndices;
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Boolean.h"
#include "Interp.h"
#include "PrimType.h"
#include "clang/AST/OSLog.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
Expand Down Expand Up @@ -1088,6 +1089,17 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
return false;
}

static bool interp__builtin_os_log_format_buffer_size(InterpState &S,
CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
analyze_os_log::OSLogBufferLayout Layout;
analyze_os_log::computeOSLogBufferLayout(S.getCtx(), Call, Layout);
pushInteger(S, Layout.size().getQuantity(), Call->getType());
return true;
}

bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call) {
const InterpFrame *Frame = S.Current;
Expand Down Expand Up @@ -1409,6 +1421,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
break;

case Builtin::BI__builtin_os_log_format_buffer_size:
if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, F, Call))
return false;
break;

default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)
Expand Down
15 changes: 13 additions & 2 deletions clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -664,10 +664,19 @@ def CastFloatingIntegralAPS : Opcode {
}

def CastPointerIntegral : Opcode {
let Types = [AluTypeClass];
let Args = [];
let Types = [FixedSizeIntegralTypeClass];
let HasGroup = 1;
}
def CastPointerIntegralAP : Opcode {
let Types = [];
let HasGroup = 0;
let Args = [ArgUint32];
}
def CastPointerIntegralAPS : Opcode {
let Types = [];
let HasGroup = 0;
let Args = [ArgUint32];
}

def DecayPtr : Opcode {
let Types = [PtrTypeClass, PtrTypeClass];
Expand Down Expand Up @@ -727,6 +736,8 @@ def InvalidDeclRef : Opcode {
let Args = [ArgDeclRef];
}

def Assume : Opcode;

def ArrayDecay : Opcode;

def CheckNonNullArg : Opcode {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/Interp/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Pointer::Pointer(Block *Pointee)
: Pointer(Pointee, Pointee->getDescriptor()->getMetadataSize(),
Pointee->getDescriptor()->getMetadataSize()) {}

Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset)
Pointer::Pointer(Block *Pointee, uint64_t BaseAndOffset)
: Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}

Pointer::Pointer(const Pointer &P)
Expand All @@ -34,7 +34,7 @@ Pointer::Pointer(const Pointer &P)
PointeeStorage.BS.Pointee->addPointer(this);
}

Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
Pointer::Pointer(Block *Pointee, unsigned Base, uint64_t Offset)
: Offset(Offset), StorageKind(Storage::Block) {
assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");

Expand Down
12 changes: 6 additions & 6 deletions clang/lib/AST/Interp/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ class Pointer {
PointeeStorage.Int.Desc = nullptr;
}
Pointer(Block *B);
Pointer(Block *B, unsigned BaseAndOffset);
Pointer(Block *B, uint64_t BaseAndOffset);
Pointer(const Pointer &P);
Pointer(Pointer &&P);
Pointer(uint64_t Address, const Descriptor *Desc, unsigned Offset = 0)
Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset = 0)
: Offset(Offset), StorageKind(Storage::Int) {
PointeeStorage.Int.Value = Address;
PointeeStorage.Int.Desc = Desc;
Expand Down Expand Up @@ -134,14 +134,14 @@ class Pointer {
std::optional<APValue> toRValue(const Context &Ctx) const;

/// Offsets a pointer inside an array.
[[nodiscard]] Pointer atIndex(unsigned Idx) const {
[[nodiscard]] Pointer atIndex(uint64_t Idx) const {
if (isIntegralPointer())
return Pointer(asIntPointer().Value, asIntPointer().Desc, Idx);

if (asBlockPointer().Base == RootPtrMark)
return Pointer(asBlockPointer().Pointee, RootPtrMark,
getDeclDesc()->getSize());
unsigned Off = Idx * elemSize();
uint64_t Off = Idx * elemSize();
if (getFieldDesc()->ElemDesc)
Off += sizeof(InlineDescriptor);
else
Expand Down Expand Up @@ -630,7 +630,7 @@ class Pointer {
friend class DeadBlock;
friend struct InitMap;

Pointer(Block *Pointee, unsigned Base, unsigned Offset);
Pointer(Block *Pointee, unsigned Base, uint64_t Offset);

/// Returns the embedded descriptor preceding a field.
InlineDescriptor *getInlineDesc() const {
Expand All @@ -656,7 +656,7 @@ class Pointer {
}

/// Offset into the storage.
unsigned Offset = 0;
uint64_t Offset = 0;

/// Previous link in the pointer chain.
Pointer *Prev = nullptr;
Expand Down
15 changes: 5 additions & 10 deletions clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,27 +108,23 @@ Pointer Program::getPtrGlobal(unsigned Idx) const {
}

std::optional<unsigned> Program::getGlobal(const ValueDecl *VD) {
auto It = GlobalIndices.find(VD);
if (It != GlobalIndices.end())
if (auto It = GlobalIndices.find(VD); It != GlobalIndices.end())
return It->second;

// Find any previous declarations which were already evaluated.
std::optional<unsigned> Index;
for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
auto It = GlobalIndices.find(P);
if (It != GlobalIndices.end()) {
for (const Decl *P = VD->getPreviousDecl(); P; P = P->getPreviousDecl()) {
if (auto It = GlobalIndices.find(P); It != GlobalIndices.end()) {
Index = It->second;
break;
}
}

// Map the decl to the existing index.
if (Index) {
if (Index)
GlobalIndices[VD] = *Index;
return std::nullopt;
}

return Index;
return std::nullopt;
}

std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
Expand Down Expand Up @@ -173,7 +169,6 @@ std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *VD) {

std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
const Expr *Init) {
assert(!getGlobal(VD));
bool IsStatic, IsExtern;
if (const auto *Var = dyn_cast<VarDecl>(VD)) {
IsStatic = Context::shouldBeGloballyIndexed(VD);
Expand Down
18 changes: 9 additions & 9 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1062,33 +1062,35 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
// ::= <local-name>
//
const DeclContext *DC = Context.getEffectiveDeclContext(ND);
bool IsLambda = isLambda(ND);

// If this is an extern variable declared locally, the relevant DeclContext
// is that of the containing namespace, or the translation unit.
// FIXME: This is a hack; extern variables declared locally should have
// a proper semantic declaration context!
if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
if (isLocalContainerContext(DC) && ND->hasLinkage() && !IsLambda)
while (!DC->isNamespace() && !DC->isTranslationUnit())
DC = Context.getEffectiveParentContext(DC);
else if (GetLocalClassDecl(ND)) {
else if (GetLocalClassDecl(ND) &&
(!IsLambda || isCompatibleWith(LangOptions::ClangABI::Ver18))) {
mangleLocalName(GD, AdditionalAbiTags);
return;
}

assert(!isa<LinkageSpecDecl>(DC) && "context cannot be LinkageSpecDecl");

if (isLocalContainerContext(DC)) {
mangleLocalName(GD, AdditionalAbiTags);
return;
}

// Closures can require a nested-name mangling even if they're semantically
// in the global namespace.
if (const NamedDecl *PrefixND = getClosurePrefix(ND)) {
mangleNestedNameWithClosurePrefix(GD, PrefixND, AdditionalAbiTags);
return;
}

if (isLocalContainerContext(DC)) {
mangleLocalName(GD, AdditionalAbiTags);
return;
}

if (DC->isTranslationUnit() || isStdNamespace(DC)) {
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
Expand Down Expand Up @@ -2201,8 +2203,6 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
if (NoFunction && isLocalContainerContext(DC))
return;

assert(!isLocalContainerContext(DC));

const NamedDecl *ND = cast<NamedDecl>(DC);
if (mangleSubstitution(ND))
return;
Expand Down
16 changes: 16 additions & 0 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ OpenACCVectorLengthClause::Create(const ASTContext &C, SourceLocation BeginLoc,
OpenACCVectorLengthClause(BeginLoc, LParenLoc, IntExpr, EndLoc);
}

OpenACCNumGangsClause *OpenACCNumGangsClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs,
SourceLocation EndLoc) {
void *Mem = C.Allocate(
OpenACCNumGangsClause::totalSizeToAlloc<Expr *>(IntExprs.size()));
return new (Mem) OpenACCNumGangsClause(BeginLoc, LParenLoc, IntExprs, EndLoc);
}

//===----------------------------------------------------------------------===//
// OpenACC clauses printing methods
//===----------------------------------------------------------------------===//
Expand All @@ -141,6 +151,12 @@ void OpenACCClausePrinter::VisitSelfClause(const OpenACCSelfClause &C) {
OS << "(" << CondExpr << ")";
}

void OpenACCClausePrinter::VisitNumGangsClause(const OpenACCNumGangsClause &C) {
OS << "num_gangs(";
llvm::interleaveComma(C.getIntExprs(), OS);
OS << ")";
}

void OpenACCClausePrinter::VisitNumWorkersClause(
const OpenACCNumWorkersClause &C) {
OS << "num_workers(" << C.getIntExpr() << ")";
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,12 @@ void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) {
Profiler.VisitStmt(Clause.getConditionExpr());
}

void OpenACCClauseProfiler::VisitNumGangsClause(
const OpenACCNumGangsClause &Clause) {
for (auto *E : Clause.getIntExprs())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitNumWorkersClause(
const OpenACCNumWorkersClause &Clause) {
assert(Clause.hasIntExpr() && "num_workers clause requires a valid int expr");
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
break;
case OpenACCClauseKind::If:
case OpenACCClauseKind::Self:
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::NumWorkers:
case OpenACCClauseKind::VectorLength:
// The condition expression will be printed as a part of the 'children',
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/ASTMatchers/Dynamic/Marshallers.h
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ class MapAnyOfMatcherDescriptor : public MatcherDescriptor {
public:
MapAnyOfMatcherDescriptor(ASTNodeKind CladeNodeKind,
std::vector<ASTNodeKind> NodeKinds)
: CladeNodeKind(CladeNodeKind), NodeKinds(NodeKinds) {}
: CladeNodeKind(CladeNodeKind), NodeKinds(std::move(NodeKinds)) {}

VariantMatcher create(SourceRange NameRange, ArrayRef<ParserValue> Args,
Diagnostics *Error) const override {
Expand Down Expand Up @@ -1026,7 +1026,7 @@ class MapAnyOfBuilderDescriptor : public MatcherDescriptor {
}

return std::make_unique<MapAnyOfMatcherDescriptor>(CladeNodeKind,
NodeKinds);
std::move(NodeKinds));
}

bool isVariadic() const override { return true; }
Expand Down
41 changes: 31 additions & 10 deletions clang/lib/Analysis/FlowSensitive/ASTOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,12 @@ bool containsSameFields(const FieldSet &Fields,
}

/// Returns the fields of a `RecordDecl` that are initialized by an
/// `InitListExpr`, in the order in which they appear in
/// `InitListExpr::inits()`.
/// `Init->getType()` must be a record type.
/// `InitListExpr` or `CXXParenListInitExpr`, in the order in which they appear
/// in `InitListExpr::inits()` / `CXXParenListInitExpr::getInitExprs()`.
/// `InitList->getType()` must be a record type.
template <class InitListT>
static std::vector<const FieldDecl *>
getFieldsForInitListExpr(const InitListExpr *InitList) {
getFieldsForInitListExpr(const InitListT *InitList) {
const RecordDecl *RD = InitList->getType()->getAsRecordDecl();
assert(RD != nullptr);

Expand All @@ -105,19 +106,29 @@ getFieldsForInitListExpr(const InitListExpr *InitList) {
return Fields;
}

RecordInitListHelper::RecordInitListHelper(const InitListExpr *InitList) {
auto *RD = InitList->getType()->getAsCXXRecordDecl();
assert(RD != nullptr);
RecordInitListHelper::RecordInitListHelper(const InitListExpr *InitList)
: RecordInitListHelper(InitList->getType(),
getFieldsForInitListExpr(InitList),
InitList->inits()) {}

RecordInitListHelper::RecordInitListHelper(
const CXXParenListInitExpr *ParenInitList)
: RecordInitListHelper(ParenInitList->getType(),
getFieldsForInitListExpr(ParenInitList),
ParenInitList->getInitExprs()) {}

std::vector<const FieldDecl *> Fields = getFieldsForInitListExpr(InitList);
ArrayRef<Expr *> Inits = InitList->inits();
RecordInitListHelper::RecordInitListHelper(
QualType Ty, std::vector<const FieldDecl *> Fields,
ArrayRef<Expr *> Inits) {
auto *RD = Ty->getAsCXXRecordDecl();
assert(RD != nullptr);

// Unions initialized with an empty initializer list need special treatment.
// For structs/classes initialized with an empty initializer list, Clang
// puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions,
// it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves.
SmallVector<Expr *> InitsForUnion;
if (InitList->getType()->isUnionType() && Inits.empty()) {
if (Ty->isUnionType() && Inits.empty()) {
assert(Fields.size() == 1);
ImplicitValueInitForUnion.emplace(Fields.front()->getType());
InitsForUnion.push_back(&*ImplicitValueInitForUnion);
Expand Down Expand Up @@ -217,6 +228,10 @@ static void getReferencedDecls(const Stmt &S, ReferencedDecls &Referenced) {
if (InitList->getType()->isRecordType())
for (const auto *FD : getFieldsForInitListExpr(InitList))
Referenced.Fields.insert(FD);
} else if (auto *ParenInitList = dyn_cast<CXXParenListInitExpr>(&S)) {
if (ParenInitList->getType()->isRecordType())
for (const auto *FD : getFieldsForInitListExpr(ParenInitList))
Referenced.Fields.insert(FD);
}
}

Expand Down Expand Up @@ -246,4 +261,10 @@ ReferencedDecls getReferencedDecls(const FunctionDecl &FD) {
return Result;
}

ReferencedDecls getReferencedDecls(const Stmt &S) {
ReferencedDecls Result;
getReferencedDecls(S, Result);
return Result;
}

} // namespace clang::dataflow
156 changes: 59 additions & 97 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <utility>
Expand Down Expand Up @@ -80,7 +81,6 @@ static bool equateUnknownValues(Value::Kind K) {
switch (K) {
case Value::Kind::Integer:
case Value::Kind::Pointer:
case Value::Kind::Record:
return true;
default:
return false;
Expand Down Expand Up @@ -145,25 +145,7 @@ static Value *joinDistinctValues(QualType Type, Value &Val1,
return &A.makeBoolValue(JoinedVal);
}

Value *JoinedVal = nullptr;
if (auto *RecordVal1 = dyn_cast<RecordValue>(&Val1)) {
auto *RecordVal2 = cast<RecordValue>(&Val2);

if (&RecordVal1->getLoc() == &RecordVal2->getLoc())
// `RecordVal1` and `RecordVal2` may have different properties associated
// with them. Create a new `RecordValue` with the same location but
// without any properties so that we soundly approximate both values. If a
// particular analysis needs to join properties, it should do so in
// `DataflowAnalysis::join()`.
JoinedVal = &JoinedEnv.create<RecordValue>(RecordVal1->getLoc());
else
// If the locations for the two records are different, need to create a
// completely new value.
JoinedVal = JoinedEnv.createValue(Type);
} else {
JoinedVal = JoinedEnv.createValue(Type);
}

Value *JoinedVal = JoinedEnv.createValue(Type);
if (JoinedVal)
Model.join(Type, Val1, Env1, Val2, Env2, *JoinedVal, JoinedEnv);

Expand Down Expand Up @@ -401,6 +383,28 @@ class ResultObjectVisitor : public RecursiveASTVisitor<ResultObjectVisitor> {
return true;
}

void
PropagateResultObjectToRecordInitList(const RecordInitListHelper &InitList,
RecordStorageLocation *Loc) {
for (auto [Base, Init] : InitList.base_inits()) {
assert(Base->getType().getCanonicalType() ==
Init->getType().getCanonicalType());

// Storage location for the base class is the same as that of the
// derived class because we "flatten" the object hierarchy and put all
// fields in `RecordStorageLocation` of the derived class.
PropagateResultObject(Init, Loc);
}

for (auto [Field, Init] : InitList.field_inits()) {
// Fields of non-record type are handled in
// `TransferVisitor::VisitInitListExpr()`.
if (Field->getType()->isRecordType())
PropagateResultObject(
Init, cast<RecordStorageLocation>(Loc->getChild(*Field)));
}
}

// Assigns `Loc` as the result object location of `E`, then propagates the
// location to all lower-level prvalues that initialize the same object as
// `E` (or one of its base classes or member variables).
Expand Down Expand Up @@ -440,26 +444,14 @@ class ResultObjectVisitor : public RecursiveASTVisitor<ResultObjectVisitor> {
return;
}

RecordInitListHelper InitListHelper(InitList);

for (auto [Base, Init] : InitListHelper.base_inits()) {
assert(Base->getType().getCanonicalType() ==
Init->getType().getCanonicalType());

// Storage location for the base class is the same as that of the
// derived class because we "flatten" the object hierarchy and put all
// fields in `RecordStorageLocation` of the derived class.
PropagateResultObject(Init, Loc);
}
PropagateResultObjectToRecordInitList(RecordInitListHelper(InitList),
Loc);
return;
}

for (auto [Field, Init] : InitListHelper.field_inits()) {
// Fields of non-record type are handled in
// `TransferVisitor::VisitInitListExpr()`.
if (!Field->getType()->isRecordType())
continue;
PropagateResultObject(
Init, cast<RecordStorageLocation>(Loc->getChild(*Field)));
}
if (auto *ParenInitList = dyn_cast<CXXParenListInitExpr>(E)) {
PropagateResultObjectToRecordInitList(RecordInitListHelper(ParenInitList),
Loc);
return;
}

Expand Down Expand Up @@ -555,7 +547,6 @@ void Environment::initialize() {
auto &ThisLoc =
cast<RecordStorageLocation>(createStorageLocation(ThisPointeeType));
setThisPointeeStorageLocation(ThisLoc);
refreshRecordValue(ThisLoc, *this);
// Initialize fields of `*this` with values, but only if we're not
// analyzing a constructor; after all, it's the constructor's job to do
// this (and we want to be able to test that).
Expand Down Expand Up @@ -619,8 +610,8 @@ Environment Environment::pushCall(const CallExpr *Call) const {
if (const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) {
if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) {
if (!isa<CXXThisExpr>(Arg))
Env.ThisPointeeLoc =
cast<RecordStorageLocation>(getStorageLocation(*Arg));
Env.ThisPointeeLoc =
cast<RecordStorageLocation>(getStorageLocation(*Arg));
// Otherwise (when the argument is `this`), retain the current
// environment's `ThisPointeeLoc`.
}
Expand Down Expand Up @@ -699,10 +690,6 @@ void Environment::popCall(const CXXConstructExpr *Call,
// See also comment in `popCall(const CallExpr *, const Environment &)` above.
this->LocToVal = std::move(CalleeEnv.LocToVal);
this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);

if (Value *Val = CalleeEnv.getValue(*CalleeEnv.ThisPointeeLoc)) {
setValue(*Call, *Val);
}
}

bool Environment::equivalentTo(const Environment &Other,
Expand Down Expand Up @@ -926,24 +913,23 @@ void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
}

void Environment::setValue(const StorageLocation &Loc, Value &Val) {
assert(!isa<RecordValue>(&Val) || &cast<RecordValue>(&Val)->getLoc() == &Loc);

// Records should not be associated with values.
assert(!isa<RecordStorageLocation>(Loc));
LocToVal[&Loc] = &Val;
}

void Environment::setValue(const Expr &E, Value &Val) {
const Expr &CanonE = ignoreCFGOmittedNodes(E);

if (auto *RecordVal = dyn_cast<RecordValue>(&Val)) {
assert(&RecordVal->getLoc() == &getResultObjectLocation(CanonE));
(void)RecordVal;
}

assert(CanonE.isPRValue());
// Records should not be associated with values.
assert(!CanonE.getType()->isRecordType());
ExprToVal[&CanonE] = &Val;
}

Value *Environment::getValue(const StorageLocation &Loc) const {
// Records should not be associated with values.
assert(!isa<RecordStorageLocation>(Loc));
return LocToVal.lookup(&Loc);
}

Expand All @@ -955,6 +941,9 @@ Value *Environment::getValue(const ValueDecl &D) const {
}

Value *Environment::getValue(const Expr &E) const {
// Records should not be associated with values.
assert(!E.getType()->isRecordType());

if (E.isPRValue()) {
auto It = ExprToVal.find(&ignoreCFGOmittedNodes(E));
return It == ExprToVal.end() ? nullptr : It->second;
Expand Down Expand Up @@ -983,6 +972,7 @@ Value *Environment::createValueUnlessSelfReferential(
int &CreatedValuesCount) {
assert(!Type.isNull());
assert(!Type->isReferenceType());
assert(!Type->isRecordType());

// Allow unlimited fields at depth 1; only cap at deeper nesting levels.
if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
Expand Down Expand Up @@ -1011,15 +1001,6 @@ Value *Environment::createValueUnlessSelfReferential(
return &arena().create<PointerValue>(PointeeLoc);
}

if (Type->isRecordType()) {
CreatedValuesCount++;
auto &Loc = cast<RecordStorageLocation>(createStorageLocation(Type));
initializeFieldsWithValues(Loc, Loc.getType(), Visited, Depth,
CreatedValuesCount);

return &refreshRecordValue(Loc, *this);
}

return nullptr;
}

Expand All @@ -1029,20 +1010,23 @@ Environment::createLocAndMaybeValue(QualType Ty,
int Depth, int &CreatedValuesCount) {
if (!Visited.insert(Ty.getCanonicalType()).second)
return createStorageLocation(Ty.getNonReferenceType());
Value *Val = createValueUnlessSelfReferential(
Ty.getNonReferenceType(), Visited, Depth, CreatedValuesCount);
Visited.erase(Ty.getCanonicalType());
auto EraseVisited = llvm::make_scope_exit(
[&Visited, Ty] { Visited.erase(Ty.getCanonicalType()); });

Ty = Ty.getNonReferenceType();

if (Val == nullptr)
return createStorageLocation(Ty);

if (Ty->isRecordType())
return cast<RecordValue>(Val)->getLoc();
if (Ty->isRecordType()) {
auto &Loc = cast<RecordStorageLocation>(createStorageLocation(Ty));
initializeFieldsWithValues(Loc, Ty, Visited, Depth, CreatedValuesCount);
return Loc;
}

StorageLocation &Loc = createStorageLocation(Ty);
setValue(Loc, *Val);

if (Value *Val = createValueUnlessSelfReferential(Ty, Visited, Depth,
CreatedValuesCount))
setValue(Loc, *Val);

return Loc;
}

Expand All @@ -1054,10 +1038,11 @@ void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
auto initField = [&](QualType FieldType, StorageLocation &FieldLoc) {
if (FieldType->isRecordType()) {
auto &FieldRecordLoc = cast<RecordStorageLocation>(FieldLoc);
setValue(FieldRecordLoc, create<RecordValue>(FieldRecordLoc));
initializeFieldsWithValues(FieldRecordLoc, FieldRecordLoc.getType(),
Visited, Depth + 1, CreatedValuesCount);
} else {
if (getValue(FieldLoc) != nullptr)
return;
if (!Visited.insert(FieldType.getCanonicalType()).second)
return;
if (Value *Val = createValueUnlessSelfReferential(
Expand Down Expand Up @@ -1098,7 +1083,7 @@ StorageLocation &Environment::createObjectInternal(const ValueDecl *D,
// be null.
if (InitExpr) {
if (auto *InitExprLoc = getStorageLocation(*InitExpr))
return *InitExprLoc;
return *InitExprLoc;
}

// Even though we have an initializer, we might not get an
Expand All @@ -1115,7 +1100,6 @@ StorageLocation &Environment::createObjectInternal(const ValueDecl *D,
auto &RecordLoc = cast<RecordStorageLocation>(Loc);
if (!InitExpr)
initializeFieldsWithValues(RecordLoc);
refreshRecordValue(RecordLoc, *this);
} else {
Value *Val = nullptr;
if (InitExpr)
Expand Down Expand Up @@ -1207,9 +1191,7 @@ void Environment::dump(raw_ostream &OS) const {
DACtx->dumpFlowCondition(FlowConditionToken, OS);
}

void Environment::dump() const {
dump(llvm::dbgs());
}
void Environment::dump() const { dump(llvm::dbgs()); }

Environment::PrValueToResultObject Environment::buildResultObjectMap(
DataflowAnalysisContext *DACtx, const FunctionDecl *FuncDecl,
Expand Down Expand Up @@ -1254,25 +1236,5 @@ RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
return Env.get<RecordStorageLocation>(*Base);
}

RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env) {
auto &NewVal = Env.create<RecordValue>(Loc);
Env.setValue(Loc, NewVal);
return NewVal;
}

RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env) {
assert(Expr.getType()->isRecordType());

if (Expr.isPRValue())
refreshRecordValue(Env.getResultObjectLocation(Expr), Env);

if (auto *Loc = Env.get<RecordStorageLocation>(Expr))
refreshRecordValue(*Loc, Env);

auto &NewVal = *cast<RecordValue>(Env.createValue(Expr.getType()));
Env.setStorageLocation(Expr, NewVal.getLoc());
return NewVal;
}

} // namespace dataflow
} // namespace clang
2 changes: 0 additions & 2 deletions clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ llvm::StringRef debugString(Value::Kind Kind) {
return "Integer";
case Value::Kind::Pointer:
return "Pointer";
case Value::Kind::Record:
return "Record";
case Value::Kind::AtomicBool:
return "AtomicBool";
case Value::Kind::TopBool:
Expand Down
13 changes: 7 additions & 6 deletions clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ class ModelDumper {

switch (V.getKind()) {
case Value::Kind::Integer:
case Value::Kind::Record:
case Value::Kind::TopBool:
case Value::Kind::AtomicBool:
case Value::Kind::FormulaBool:
Expand Down Expand Up @@ -126,8 +125,9 @@ class ModelDumper {
return;

JOS.attribute("type", L.getType().getAsString());
if (auto *V = Env.getValue(L))
dump(*V);
if (!L.getType()->isRecordType())
if (auto *V = Env.getValue(L))
dump(*V);

if (auto *RLoc = dyn_cast<RecordStorageLocation>(&L)) {
for (const auto &Child : RLoc->children())
Expand Down Expand Up @@ -281,9 +281,10 @@ class HTMLLogger : public Logger {
Iters.back().Block->Elements[ElementIndex - 1].getAs<CFGStmt>();
if (const Expr *E = S ? llvm::dyn_cast<Expr>(S->getStmt()) : nullptr) {
if (E->isPRValue()) {
if (auto *V = State.Env.getValue(*E))
JOS.attributeObject(
"value", [&] { ModelDumper(JOS, State.Env).dump(*V); });
if (!E->getType()->isRecordType())
if (auto *V = State.Env.getValue(*E))
JOS.attributeObject(
"value", [&] { ModelDumper(JOS, State.Env).dump(*V); });
} else {
if (auto *Loc = State.Env.getStorageLocation(*E))
JOS.attributeObject(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,17 +339,6 @@ void setHasValue(RecordStorageLocation &OptionalLoc, BoolValue &HasValueVal,
Env.setValue(locForHasValue(OptionalLoc), HasValueVal);
}

/// Creates a symbolic value for an `optional` value at an existing storage
/// location. Uses `HasValueVal` as the symbolic value of the "has_value"
/// property.
RecordValue &createOptionalValue(RecordStorageLocation &Loc,
BoolValue &HasValueVal, Environment &Env) {
auto &OptionalVal = Env.create<RecordValue>(Loc);
Env.setValue(Loc, OptionalVal);
setHasValue(Loc, HasValueVal, Env);
return OptionalVal;
}

/// Returns the symbolic value that represents the "has_value" property of the
/// optional at `OptionalLoc`. Returns null if `OptionalLoc` is null.
BoolValue *getHasValue(Environment &Env, RecordStorageLocation *OptionalLoc) {
Expand Down Expand Up @@ -413,9 +402,8 @@ void transferArrowOpCall(const Expr *UnwrapExpr, const Expr *ObjectExpr,
void transferMakeOptionalCall(const CallExpr *E,
const MatchFinder::MatchResult &,
LatticeTransferState &State) {
State.Env.setValue(
*E, createOptionalValue(State.Env.getResultObjectLocation(*E),
State.Env.getBoolLiteralValue(true), State.Env));
setHasValue(State.Env.getResultObjectLocation(*E),
State.Env.getBoolLiteralValue(true), State.Env);
}

void transferOptionalHasValueCall(const CXXMemberCallExpr *CallExpr,
Expand Down Expand Up @@ -483,9 +471,6 @@ void transferValueOrNotEqX(const Expr *ComparisonExpr,
void transferCallReturningOptional(const CallExpr *E,
const MatchFinder::MatchResult &Result,
LatticeTransferState &State) {
if (State.Env.getValue(*E) != nullptr)
return;

RecordStorageLocation *Loc = nullptr;
if (E->isPRValue()) {
Loc = &State.Env.getResultObjectLocation(*E);
Expand All @@ -497,16 +482,16 @@ void transferCallReturningOptional(const CallExpr *E,
}
}

RecordValue &Val =
createOptionalValue(*Loc, State.Env.makeAtomicBoolValue(), State.Env);
if (E->isPRValue())
State.Env.setValue(*E, Val);
if (State.Env.getValue(locForHasValue(*Loc)) != nullptr)
return;

setHasValue(*Loc, State.Env.makeAtomicBoolValue(), State.Env);
}

void constructOptionalValue(const Expr &E, Environment &Env,
BoolValue &HasValueVal) {
RecordStorageLocation &Loc = Env.getResultObjectLocation(E);
Env.setValue(E, createOptionalValue(Loc, HasValueVal, Env));
setHasValue(Loc, HasValueVal, Env);
}

/// Returns a symbolic value for the "has_value" property of an `optional<T>`
Expand Down Expand Up @@ -555,7 +540,7 @@ void transferAssignment(const CXXOperatorCallExpr *E, BoolValue &HasValueVal,
assert(E->getNumArgs() > 0);

if (auto *Loc = State.Env.get<RecordStorageLocation>(*E->getArg(0))) {
createOptionalValue(*Loc, HasValueVal, State.Env);
setHasValue(*Loc, HasValueVal, State.Env);

// Assign a storage location for the whole expression.
State.Env.setStorageLocation(*E, *Loc);
Expand Down Expand Up @@ -587,11 +572,11 @@ void transferSwap(RecordStorageLocation *Loc1, RecordStorageLocation *Loc2,

if (Loc1 == nullptr) {
if (Loc2 != nullptr)
createOptionalValue(*Loc2, Env.makeAtomicBoolValue(), Env);
setHasValue(*Loc2, Env.makeAtomicBoolValue(), Env);
return;
}
if (Loc2 == nullptr) {
createOptionalValue(*Loc1, Env.makeAtomicBoolValue(), Env);
setHasValue(*Loc1, Env.makeAtomicBoolValue(), Env);
return;
}

Expand All @@ -609,8 +594,8 @@ void transferSwap(RecordStorageLocation *Loc1, RecordStorageLocation *Loc2,
if (BoolVal2 == nullptr)
BoolVal2 = &Env.makeAtomicBoolValue();

createOptionalValue(*Loc1, *BoolVal2, Env);
createOptionalValue(*Loc2, *BoolVal1, Env);
setHasValue(*Loc1, *BoolVal2, Env);
setHasValue(*Loc2, *BoolVal1, Env);
}

void transferSwapCall(const CXXMemberCallExpr *E,
Expand Down Expand Up @@ -806,8 +791,7 @@ auto buildTransferMatchSwitch() {
LatticeTransferState &State) {
if (RecordStorageLocation *Loc =
getImplicitObjectLocation(*E, State.Env)) {
createOptionalValue(*Loc, State.Env.getBoolLiteralValue(true),
State.Env);
setHasValue(*Loc, State.Env.getBoolLiteralValue(true), State.Env);
}
})

Expand All @@ -818,8 +802,8 @@ auto buildTransferMatchSwitch() {
LatticeTransferState &State) {
if (RecordStorageLocation *Loc =
getImplicitObjectLocation(*E, State.Env)) {
createOptionalValue(*Loc, State.Env.getBoolLiteralValue(false),
State.Env);
setHasValue(*Loc, State.Env.getBoolLiteralValue(false),
State.Env);
}
})

Expand Down
3 changes: 0 additions & 3 deletions clang/lib/Analysis/FlowSensitive/RecordOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst,
copySyntheticField(SrcFieldLoc->getType(), *SrcFieldLoc,
Dst.getSyntheticField(Name), Env);
}

RecordValue *DstVal = &Env.create<RecordValue>(Dst);
Env.setValue(Dst, *DstVal);
}

bool recordsEqual(const RecordStorageLocation &Loc1, const Environment &Env1,
Expand Down
62 changes: 21 additions & 41 deletions clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ static Value *maybeUnpackLValueExpr(const Expr &E, Environment &Env) {
}

static void propagateValue(const Expr &From, const Expr &To, Environment &Env) {
if (From.getType()->isRecordType())
return;
if (auto *Val = Env.getValue(From))
Env.setValue(To, *Val);
}
Expand Down Expand Up @@ -403,6 +405,9 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
return;

if (Ret->isPRValue()) {
if (Ret->getType()->isRecordType())
return;

auto *Val = Env.getValue(*Ret);
if (Val == nullptr)
return;
Expand Down Expand Up @@ -457,15 +462,9 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
assert(ArgExpr != nullptr);
propagateValueOrStorageLocation(*ArgExpr, *S, Env);

// If this is a prvalue of record type, we consider it to be an "original
// record constructor", which we always require to have a `RecordValue`.
// So make sure we have a value if we didn't propagate one above.
if (S->isPRValue() && S->getType()->isRecordType()) {
if (Env.getValue(*S) == nullptr) {
auto &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
refreshRecordValue(Loc, Env);
}
auto &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
}
}

Expand Down Expand Up @@ -495,7 +494,6 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
}

RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.setValue(*S, refreshRecordValue(Loc, Env));

if (ConstructorDecl->isCopyOrMoveConstructor()) {
// It is permissible for a copy/move constructor to have additional
Expand Down Expand Up @@ -542,8 +540,7 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {

RecordStorageLocation *LocSrc = nullptr;
if (Arg1->isPRValue()) {
if (auto *Val = Env.get<RecordValue>(*Arg1))
LocSrc = &Val->getLoc();
LocSrc = &Env.getResultObjectLocation(*Arg1);
} else {
LocSrc = Env.get<RecordStorageLocation>(*Arg1);
}
Expand Down Expand Up @@ -575,15 +572,6 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
propagateValue(*RBO->getSemanticForm(), *RBO, Env);
}

void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
if (S->getCastKind() == CK_ConstructorConversion) {
const Expr *SubExpr = S->getSubExpr();
assert(SubExpr != nullptr);

propagateValue(*SubExpr, *S, Env);
}
}

void VisitCallExpr(const CallExpr *S) {
// Of clang's builtins, only `__builtin_expect` is handled explicitly, since
// others (like trap, debugtrap, and unreachable) are handled by CFG
Expand Down Expand Up @@ -613,31 +601,27 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {

// If this call produces a prvalue of record type, initialize its fields
// with values.
if (S->getType()->isRecordType() && S->isPRValue())
if (Env.getValue(*S) == nullptr) {
RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
Env.setValue(*S, refreshRecordValue(Loc, Env));
}
if (S->getType()->isRecordType() && S->isPRValue()) {
RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
}
}
}

void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
const Expr *SubExpr = S->getSubExpr();
assert(SubExpr != nullptr);

Value *SubExprVal = Env.getValue(*SubExpr);
if (SubExprVal == nullptr)
return;
StorageLocation &Loc = Env.createStorageLocation(*S);
Env.setStorageLocation(*S, Loc);

if (RecordValue *RecordVal = dyn_cast<RecordValue>(SubExprVal)) {
Env.setStorageLocation(*S, RecordVal->getLoc());
if (SubExpr->getType()->isRecordType())
// Nothing else left to do -- we initialized the record when transferring
// `SubExpr`.
return;
}

StorageLocation &Loc = Env.createStorageLocation(*S);
Env.setValue(Loc, *SubExprVal);
Env.setStorageLocation(*S, Loc);
if (Value *SubExprVal = Env.getValue(*SubExpr))
Env.setValue(Loc, *SubExprVal);
}

void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
Expand Down Expand Up @@ -683,15 +667,11 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
return;
}

// In case the initializer list is transparent, we just need to propagate
// the value that it contains.
if (S->isSemanticForm() && S->isTransparent()) {
propagateValue(*S->getInit(0), *S, Env);
// If the initializer list is transparent, there's nothing to do.
if (S->isSemanticForm() && S->isTransparent())
return;
}

RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.setValue(*S, refreshRecordValue(Loc, Env));

// Initialization of base classes and fields of record type happens when we
// visit the nested `CXXConstructExpr` or `InitListExpr` for that base class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,11 @@ builtinTransferInitializer(const CFGInitializer &Elt,
return;

ParentLoc->setChild(*Member, InitExprLoc);
} else if (auto *InitExprVal = Env.getValue(*InitExpr)) {
assert(MemberLoc != nullptr);
// Record-type initializers construct themselves directly into the result
// object, so there is no need to handle them here.
if (!Member->getType()->isRecordType())
} else if (!Member->getType()->isRecordType()) {
assert(MemberLoc != nullptr);
if (auto *InitExprVal = Env.getValue(*InitExpr))
Env.setValue(*MemberLoc, *InitExprVal);
}
}
Expand Down
2 changes: 0 additions & 2 deletions clang/lib/Analysis/FlowSensitive/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ raw_ostream &operator<<(raw_ostream &OS, const Value &Val) {
return OS << "Integer(@" << &Val << ")";
case Value::Kind::Pointer:
return OS << "Pointer(" << &cast<PointerValue>(Val).getPointeeLoc() << ")";
case Value::Kind::Record:
return OS << "Record(" << &cast<RecordValue>(Val).getLoc() << ")";
case Value::Kind::TopBool:
return OS << "TopBool(" << cast<TopBoolValue>(Val).getAtom() << ")";
case Value::Kind::AtomicBool:
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 @@ -157,7 +157,7 @@ llvm::Value *CodeGen::emitRoundPointerUpToAlignment(CodeGenFunction &CGF,
llvm::Value *RoundUp = CGF.Builder.CreateConstInBoundsGEP1_32(
CGF.Builder.getInt8Ty(), Ptr, Align.getQuantity() - 1);
return CGF.Builder.CreateIntrinsic(
llvm::Intrinsic::ptrmask, {CGF.AllocaInt8PtrTy, CGF.IntPtrTy},
llvm::Intrinsic::ptrmask, {Ptr->getType(), CGF.IntPtrTy},
{RoundUp, llvm::ConstantInt::get(CGF.IntPtrTy, -Align.getQuantity())},
nullptr, Ptr->getName() + ".aligned");
}
Expand Down
57 changes: 35 additions & 22 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,21 @@ static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP(
"sanitizer-early-opt-ep", cl::Optional,
cl::desc("Insert sanitizers on OptimizerEarlyEP."));

// Experiment to mark cold functions as optsize/minsize/optnone.
// TODO: remove once this is exposed as a proper driver flag.
static cl::opt<PGOOptions::ColdFuncOpt> ClPGOColdFuncAttr(
"pgo-cold-func-opt", cl::init(PGOOptions::ColdFuncOpt::Default), cl::Hidden,
cl::desc(
"Function attribute to apply to cold functions as determined by PGO"),
cl::values(clEnumValN(PGOOptions::ColdFuncOpt::Default, "default",
"Default (no attribute)"),
clEnumValN(PGOOptions::ColdFuncOpt::OptSize, "optsize",
"Mark cold functions with optsize."),
clEnumValN(PGOOptions::ColdFuncOpt::MinSize, "minsize",
"Mark cold functions with minsize."),
clEnumValN(PGOOptions::ColdFuncOpt::OptNone, "optnone",
"Mark cold functions with optnone.")));

extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate;

// Re-link builtin bitcodes after optimization
Expand Down Expand Up @@ -768,42 +783,41 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
CodeGenOpts.InstrProfileOutput.empty() ? getDefaultProfileGenName()
: CodeGenOpts.InstrProfileOutput,
"", "", CodeGenOpts.MemoryProfileUsePath, nullptr, PGOOptions::IRInstr,
PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default,
PGOOptions::NoCSAction, ClPGOColdFuncAttr,
CodeGenOpts.DebugInfoForProfiling,
/*PseudoProbeForProfiling=*/false, CodeGenOpts.AtomicProfileUpdate);
else if (CodeGenOpts.hasProfileIRUse()) {
// -fprofile-use.
auto CSAction = CodeGenOpts.hasProfileCSIRUse() ? PGOOptions::CSIRUse
: PGOOptions::NoCSAction;
PGOOpt = PGOOptions(
CodeGenOpts.ProfileInstrumentUsePath, "",
CodeGenOpts.ProfileRemappingFile, CodeGenOpts.MemoryProfileUsePath, VFS,
PGOOptions::IRUse, CSAction, PGOOptions::ColdFuncOpt::Default,
CodeGenOpts.DebugInfoForProfiling);
PGOOpt = PGOOptions(CodeGenOpts.ProfileInstrumentUsePath, "",
CodeGenOpts.ProfileRemappingFile,
CodeGenOpts.MemoryProfileUsePath, VFS,
PGOOptions::IRUse, CSAction, ClPGOColdFuncAttr,
CodeGenOpts.DebugInfoForProfiling);
} else if (!CodeGenOpts.SampleProfileFile.empty())
// -fprofile-sample-use
PGOOpt = PGOOptions(
CodeGenOpts.SampleProfileFile, "", CodeGenOpts.ProfileRemappingFile,
CodeGenOpts.MemoryProfileUsePath, VFS, PGOOptions::SampleUse,
PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default,
PGOOptions::NoCSAction, ClPGOColdFuncAttr,
CodeGenOpts.DebugInfoForProfiling, CodeGenOpts.PseudoProbeForProfiling);
else if (!CodeGenOpts.MemoryProfileUsePath.empty())
// -fmemory-profile-use (without any of the above options)
PGOOpt = PGOOptions("", "", "", CodeGenOpts.MemoryProfileUsePath, VFS,
PGOOptions::NoAction, PGOOptions::NoCSAction,
PGOOptions::ColdFuncOpt::Default,
CodeGenOpts.DebugInfoForProfiling);
ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling);
else if (CodeGenOpts.PseudoProbeForProfiling)
// -fpseudo-probe-for-profiling
PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr,
PGOOptions::NoAction, PGOOptions::NoCSAction,
PGOOptions::ColdFuncOpt::Default,
CodeGenOpts.DebugInfoForProfiling, true);
PGOOpt =
PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr,
PGOOptions::NoAction, PGOOptions::NoCSAction,
ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, true);
else if (CodeGenOpts.DebugInfoForProfiling)
// -fdebug-info-for-profiling
PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr,
PGOOptions::NoAction, PGOOptions::NoCSAction,
PGOOptions::ColdFuncOpt::Default, true);
ClPGOColdFuncAttr, true);

// Check to see if we want to generate a CS profile.
if (CodeGenOpts.hasProfileCSIRInstr()) {
Expand All @@ -820,14 +834,13 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
: CodeGenOpts.InstrProfileOutput;
PGOOpt->CSAction = PGOOptions::CSIRInstr;
} else
PGOOpt =
PGOOptions("",
CodeGenOpts.InstrProfileOutput.empty()
? getDefaultProfileGenName()
: CodeGenOpts.InstrProfileOutput,
"", /*MemoryProfile=*/"", nullptr, PGOOptions::NoAction,
PGOOptions::CSIRInstr, PGOOptions::ColdFuncOpt::Default,
CodeGenOpts.DebugInfoForProfiling);
PGOOpt = PGOOptions("",
CodeGenOpts.InstrProfileOutput.empty()
? getDefaultProfileGenName()
: CodeGenOpts.InstrProfileOutput,
"", /*MemoryProfile=*/"", nullptr,
PGOOptions::NoAction, PGOOptions::CSIRInstr,
ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling);
}
if (TM)
TM->setPGOOption(PGOOpt);
Expand Down
66 changes: 38 additions & 28 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,29 +826,32 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
ASTContext &Ctx, const RecordDecl *RD, StringRef Name, uint64_t &Offset) {
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
getLangOpts().getStrictFlexArraysLevel();
unsigned FieldNo = 0;
bool IsUnion = RD->isUnion();
uint32_t FieldNo = 0;

for (const Decl *D : RD->decls()) {
if (const auto *Field = dyn_cast<FieldDecl>(D);
Field && (Name.empty() || Field->getNameAsString() == Name) &&
if (RD->isImplicit())
return nullptr;

for (const FieldDecl *FD : RD->fields()) {
if ((Name.empty() || FD->getNameAsString() == Name) &&
Decl::isFlexibleArrayMemberLike(
Ctx, Field, Field->getType(), StrictFlexArraysLevel,
Ctx, FD, FD->getType(), StrictFlexArraysLevel,
/*IgnoreTemplateOrMacroSubstitution=*/true)) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
Offset += Layout.getFieldOffset(FieldNo);
return Field;
return FD;
}

if (const auto *Record = dyn_cast<RecordDecl>(D))
if (const FieldDecl *Field =
FindFlexibleArrayMemberField(Ctx, Record, Name, Offset)) {
QualType Ty = FD->getType();
if (Ty->isRecordType()) {
if (const FieldDecl *Field = FindFlexibleArrayMemberField(
Ctx, Ty->getAsRecordDecl(), Name, Offset)) {
const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
Offset += Layout.getFieldOffset(FieldNo);
return Field;
}
}

if (!IsUnion && isa<FieldDecl>(D))
if (!RD->isUnion())
++FieldNo;
}

Expand All @@ -858,14 +861,13 @@ const FieldDecl *CodeGenFunction::FindFlexibleArrayMemberField(
static unsigned CountCountedByAttrs(const RecordDecl *RD) {
unsigned Num = 0;

for (const Decl *D : RD->decls()) {
if (const auto *FD = dyn_cast<FieldDecl>(D);
FD && FD->getType()->isCountAttributedType()) {
for (const FieldDecl *FD : RD->fields()) {
if (FD->getType()->isCountAttributedType())
return ++Num;
}

if (const auto *Rec = dyn_cast<RecordDecl>(D))
Num += CountCountedByAttrs(Rec);
QualType Ty = FD->getType();
if (Ty->isRecordType())
Num += CountCountedByAttrs(Ty->getAsRecordDecl());
}

return Num;
Expand Down Expand Up @@ -18265,8 +18267,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
llvm_unreachable("lerp operand must have a float representation");
return Builder.CreateIntrinsic(
/*ReturnType=*/X->getType(), Intrinsic::dx_lerp,
ArrayRef<Value *>{X, Y, S}, nullptr, "dx.lerp");
/*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(),
ArrayRef<Value *>{X, Y, S}, nullptr, "hlsl.lerp");
}
case Builtin::BI__builtin_hlsl_elementwise_frac: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Expand Down Expand Up @@ -18294,20 +18296,28 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
Value *M = EmitScalarExpr(E->getArg(0));
Value *A = EmitScalarExpr(E->getArg(1));
Value *B = EmitScalarExpr(E->getArg(2));
if (E->getArg(0)->getType()->hasFloatingRepresentation()) {
if (E->getArg(0)->getType()->hasFloatingRepresentation())
return Builder.CreateIntrinsic(
/*ReturnType*/ M->getType(), Intrinsic::fmuladd,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.fmad");
}
ArrayRef<Value *>{M, A, B}, nullptr, "hlsl.fmad");

if (E->getArg(0)->getType()->hasSignedIntegerRepresentation()) {
return Builder.CreateIntrinsic(
/*ReturnType*/ M->getType(), Intrinsic::dx_imad,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.imad");
if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
return Builder.CreateIntrinsic(
/*ReturnType*/ M->getType(), Intrinsic::dx_imad,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.imad");

Value *Mul = Builder.CreateNSWMul(M, A);
return Builder.CreateNSWAdd(Mul, B);
}
assert(E->getArg(0)->getType()->hasUnsignedIntegerRepresentation());
return Builder.CreateIntrinsic(
/*ReturnType=*/M->getType(), Intrinsic::dx_umad,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.umad");
if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
return Builder.CreateIntrinsic(
/*ReturnType=*/M->getType(), Intrinsic::dx_umad,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.umad");

Value *Mul = Builder.CreateNUWMul(M, A);
return Builder.CreateNUWAdd(Mul, B);
}
case Builtin::BI__builtin_hlsl_elementwise_rcp: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Expand Down
33 changes: 24 additions & 9 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,15 @@ struct BinOpInfo {
return UnOp->getSubExpr()->getType()->isFixedPointType();
return false;
}

/// Check if the RHS has a signed integer representation.
bool rhsHasSignedIntegerRepresentation() const {
if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) {
QualType RHSType = BinOp->getRHS()->getType();
return RHSType->hasSignedIntegerRepresentation();
}
return false;
}
};

static bool MustVisitNullValue(const Expr *E) {
Expand Down Expand Up @@ -782,7 +791,7 @@ class ScalarExprEmitter
void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops,
llvm::Value *Zero,bool isDiv);
// Common helper for getting how wide LHS of shift is.
static Value *GetMaximumShiftAmount(Value *LHS, Value *RHS);
static Value *GetMaximumShiftAmount(Value *LHS, Value *RHS, bool RHSIsSigned);

// Used for shifting constraints for OpenCL, do mask for powers of 2, URem for
// non powers of two.
Expand Down Expand Up @@ -1531,7 +1540,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
if (auto DstPT = dyn_cast<llvm::PointerType>(DstTy)) {
// The source value may be an integer, or a pointer.
if (isa<llvm::PointerType>(SrcTy))
return Builder.CreateBitCast(Src, DstTy, "conv");
return Src;

assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?");
// First, convert to the correct width so that we control the kind of
Expand Down Expand Up @@ -4344,7 +4353,8 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
return Builder.CreateExactSDiv(diffInChars, divisor, "sub.ptr.div");
}

Value *ScalarExprEmitter::GetMaximumShiftAmount(Value *LHS, Value *RHS) {
Value *ScalarExprEmitter::GetMaximumShiftAmount(Value *LHS, Value *RHS,
bool RHSIsSigned) {
llvm::IntegerType *Ty;
if (llvm::VectorType *VT = dyn_cast<llvm::VectorType>(LHS->getType()))
Ty = cast<llvm::IntegerType>(VT->getElementType());
Expand All @@ -4355,7 +4365,9 @@ Value *ScalarExprEmitter::GetMaximumShiftAmount(Value *LHS, Value *RHS) {
// this in ConstantInt::get, this results in the value getting truncated.
// Constrain the return value to be max(RHS) in this case.
llvm::Type *RHSTy = RHS->getType();
llvm::APInt RHSMax = llvm::APInt::getMaxValue(RHSTy->getScalarSizeInBits());
llvm::APInt RHSMax =
RHSIsSigned ? llvm::APInt::getSignedMaxValue(RHSTy->getScalarSizeInBits())
: llvm::APInt::getMaxValue(RHSTy->getScalarSizeInBits());
if (RHSMax.ult(Ty->getBitWidth()))
return llvm::ConstantInt::get(RHSTy, RHSMax);
return llvm::ConstantInt::get(RHSTy, Ty->getBitWidth() - 1);
Expand All @@ -4370,7 +4382,7 @@ Value *ScalarExprEmitter::ConstrainShiftValue(Value *LHS, Value *RHS,
Ty = cast<llvm::IntegerType>(LHS->getType());

if (llvm::isPowerOf2_64(Ty->getBitWidth()))
return Builder.CreateAnd(RHS, GetMaximumShiftAmount(LHS, RHS), Name);
return Builder.CreateAnd(RHS, GetMaximumShiftAmount(LHS, RHS, false), Name);

return Builder.CreateURem(
RHS, llvm::ConstantInt::get(RHS->getType(), Ty->getBitWidth()), Name);
Expand Down Expand Up @@ -4403,7 +4415,9 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
isa<llvm::IntegerType>(Ops.LHS->getType())) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
SmallVector<std::pair<Value *, SanitizerMask>, 2> Checks;
llvm::Value *WidthMinusOne = GetMaximumShiftAmount(Ops.LHS, Ops.RHS);
bool RHSIsSigned = Ops.rhsHasSignedIntegerRepresentation();
llvm::Value *WidthMinusOne =
GetMaximumShiftAmount(Ops.LHS, Ops.RHS, RHSIsSigned);
llvm::Value *ValidExponent = Builder.CreateICmpULE(Ops.RHS, WidthMinusOne);

if (SanitizeExponent) {
Expand All @@ -4421,7 +4435,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
Builder.CreateCondBr(ValidExponent, CheckShiftBase, Cont);
llvm::Value *PromotedWidthMinusOne =
(RHS == Ops.RHS) ? WidthMinusOne
: GetMaximumShiftAmount(Ops.LHS, RHS);
: GetMaximumShiftAmount(Ops.LHS, RHS, RHSIsSigned);
CGF.EmitBlock(CheckShiftBase);
llvm::Value *BitsShiftedOff = Builder.CreateLShr(
Ops.LHS, Builder.CreateSub(PromotedWidthMinusOne, RHS, "shl.zeros",
Expand Down Expand Up @@ -4471,8 +4485,9 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) &&
isa<llvm::IntegerType>(Ops.LHS->getType())) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
llvm::Value *Valid =
Builder.CreateICmpULE(Ops.RHS, GetMaximumShiftAmount(Ops.LHS, Ops.RHS));
bool RHSIsSigned = Ops.rhsHasSignedIntegerRepresentation();
llvm::Value *Valid = Builder.CreateICmpULE(
Ops.RHS, GetMaximumShiftAmount(Ops.LHS, Ops.RHS, RHSIsSigned));
EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::ShiftExponent), Ops);
}

Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class CGHLSLRuntime {

GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CGLoopInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,8 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
setPipelineDisabled(true);
break;
case LoopHintAttr::UnrollCount:
setUnrollState(LoopAttributes::Disable);
break;
case LoopHintAttr::UnrollAndJamCount:
case LoopHintAttr::VectorizeWidth:
case LoopHintAttr::InterleaveCount:
Expand Down
21 changes: 13 additions & 8 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,12 @@ struct CounterCoverageMappingBuilder
/// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
std::optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
SourceLocation BeforeLoc) {
// Some statements (like AttributedStmt and ImplicitValueInitExpr) don't
// have valid source locations. Do not emit a gap region if this is the case
// in either AfterLoc end or BeforeLoc end.
if (AfterLoc.isInvalid() || BeforeLoc.isInvalid())
return std::nullopt;

// If AfterLoc is in function-like macro, use the right parenthesis
// location.
if (AfterLoc.isMacroID()) {
Expand Down Expand Up @@ -1368,9 +1374,8 @@ struct CounterCoverageMappingBuilder
for (const Stmt *Child : S->children())
if (Child) {
// If last statement contains terminate statements, add a gap area
// between the two statements. Skipping attributed statements, because
// they don't have valid start location.
if (LastStmt && HasTerminateStmt && !isa<AttributedStmt>(Child)) {
// between the two statements.
if (LastStmt && HasTerminateStmt) {
auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
Expand Down Expand Up @@ -2011,11 +2016,13 @@ struct CounterCoverageMappingBuilder
Counter TrueCount = llvm::EnableSingleByteCoverage
? getRegionCounter(E->getTrueExpr())
: getRegionCounter(E);

propagateCounts(ParentCount, E->getCond());
Counter OutCount;

if (!isa<BinaryConditionalOperator>(E)) {
if (const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
propagateCounts(ParentCount, BCO->getCommon());
OutCount = TrueCount;
} else {
propagateCounts(ParentCount, E->getCond());
// The 'then' count applies to the area immediately after the condition.
auto Gap =
findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr()));
Expand All @@ -2024,8 +2031,6 @@ struct CounterCoverageMappingBuilder

extendRegion(E->getTrueExpr());
OutCount = propagateCounts(TrueCount, E->getTrueExpr());
} else {
OutCount = TrueCount;
}

extendRegion(E->getFalseExpr());
Expand Down
54 changes: 38 additions & 16 deletions clang/lib/Driver/OffloadBundler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1010,13 +1010,19 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,

uint16_t CompressionMethod = static_cast<uint16_t>(P.format);
uint32_t UncompressedSize = Input.getBuffer().size();
uint32_t TotalFileSize = MagicNumber.size() + sizeof(TotalFileSize) +
sizeof(Version) + sizeof(CompressionMethod) +
sizeof(UncompressedSize) + sizeof(TruncatedHash) +
CompressedBuffer.size();

SmallVector<char, 0> FinalBuffer;
llvm::raw_svector_ostream OS(FinalBuffer);
OS << MagicNumber;
OS.write(reinterpret_cast<const char *>(&Version), sizeof(Version));
OS.write(reinterpret_cast<const char *>(&CompressionMethod),
sizeof(CompressionMethod));
OS.write(reinterpret_cast<const char *>(&TotalFileSize),
sizeof(TotalFileSize));
OS.write(reinterpret_cast<const char *>(&UncompressedSize),
sizeof(UncompressedSize));
OS.write(reinterpret_cast<const char *>(&TruncatedHash),
Expand All @@ -1034,6 +1040,8 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,
(UncompressedSize / (1024.0 * 1024.0)) / CompressionTimeSeconds;

llvm::errs() << "Compressed bundle format version: " << Version << "\n"
<< "Total file size (including headers): "
<< formatWithCommas(TotalFileSize) << " bytes\n"
<< "Compression method used: " << MethodUsed << "\n"
<< "Compression level: " << P.level << "\n"
<< "Binary size before compression: "
Expand All @@ -1059,31 +1067,42 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,

StringRef Blob = Input.getBuffer();

if (Blob.size() < HeaderSize) {
if (Blob.size() < V1HeaderSize)
return llvm::MemoryBuffer::getMemBufferCopy(Blob);
}

if (llvm::identify_magic(Blob) !=
llvm::file_magic::offload_bundle_compressed) {
if (Verbose)
llvm::errs() << "Uncompressed bundle.\n";
return llvm::MemoryBuffer::getMemBufferCopy(Blob);
}

size_t CurrentOffset = MagicSize;

uint16_t ThisVersion;
memcpy(&ThisVersion, Blob.data() + CurrentOffset, sizeof(uint16_t));
CurrentOffset += VersionFieldSize;

uint16_t CompressionMethod;
memcpy(&CompressionMethod, Blob.data() + CurrentOffset, sizeof(uint16_t));
CurrentOffset += MethodFieldSize;

uint32_t TotalFileSize;
if (ThisVersion >= 2) {
if (Blob.size() < V2HeaderSize)
return createStringError(inconvertibleErrorCode(),
"Compressed bundle header size too small");
memcpy(&TotalFileSize, Blob.data() + CurrentOffset, sizeof(uint32_t));
CurrentOffset += FileSizeFieldSize;
}

uint32_t UncompressedSize;
memcpy(&UncompressedSize, Blob.data() + CurrentOffset, sizeof(uint32_t));
CurrentOffset += UncompressedSizeFieldSize;

uint64_t StoredHash;
memcpy(&ThisVersion, Input.getBuffer().data() + MagicNumber.size(),
sizeof(uint16_t));
memcpy(&CompressionMethod, Blob.data() + MagicSize + VersionFieldSize,
sizeof(uint16_t));
memcpy(&UncompressedSize,
Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize,
sizeof(uint32_t));
memcpy(&StoredHash,
Blob.data() + MagicSize + VersionFieldSize + MethodFieldSize +
SizeFieldSize,
sizeof(uint64_t));
memcpy(&StoredHash, Blob.data() + CurrentOffset, sizeof(uint64_t));
CurrentOffset += HashFieldSize;

llvm::compression::Format CompressionFormat;
if (CompressionMethod ==
Expand All @@ -1102,7 +1121,7 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
DecompressTimer.startTimer();

SmallVector<uint8_t, 0> DecompressedData;
StringRef CompressedData = Blob.substr(HeaderSize);
StringRef CompressedData = Blob.substr(CurrentOffset);
if (llvm::Error DecompressionError = llvm::compression::decompress(
CompressionFormat, llvm::arrayRefFromStringRef(CompressedData),
DecompressedData, UncompressedSize))
Expand Down Expand Up @@ -1135,8 +1154,11 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
double DecompressionSpeedMBs =
(UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds;

llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n"
<< "Decompression method: "
llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n";
if (ThisVersion >= 2)
llvm::errs() << "Total file size (from header): "
<< formatWithCommas(TotalFileSize) << " bytes\n";
llvm::errs() << "Decompression method: "
<< (CompressionFormat == llvm::compression::Format::Zlib
? "zlib"
: "zstd")
Expand Down
24 changes: 20 additions & 4 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,16 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_O_Group))
RelaxDefault = A->getOption().matches(options::OPT_O0);

// RISC-V requires an indirect jump for offsets larger than 1MiB. This cannot
// be done by assembler branch relaxation as it needs a free temporary
// register. Because of this, branch relaxation is handled by a MachineIR
// pass before the assembler. Forcing assembler branch relaxation for -O0
// makes the MachineIR branch relaxation inaccurate and it will miss cases
// where an indirect branch is necessary. To avoid this issue we are
// sacrificing the compile time improvement of using -mrelax-all for -O0.
if (C.getDefaultToolChain().getTriple().isRISCV())
RelaxDefault = false;

if (RelaxDefault) {
RelaxDefault = false;
for (const auto &Act : C.getActions()) {
Expand Down Expand Up @@ -4634,7 +4644,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,

// Emit DW_TAG_template_alias for template aliases? True by default for SCE.
bool UseDebugTemplateAlias =
DebuggerTuning == llvm::DebuggerKind::SCE && RequestedDWARFVersion >= 5;
DebuggerTuning == llvm::DebuggerKind::SCE && RequestedDWARFVersion >= 4;
if (const auto *DebugTemplateAlias = Args.getLastArg(
options::OPT_gtemplate_alias, options::OPT_gno_template_alias)) {
// DW_TAG_template_alias is only supported from DWARFv5 but if a user
Expand Down Expand Up @@ -4733,7 +4743,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,
Output.getFilename());
}

static void ProcessVSRuntimeLibrary(const ArgList &Args,
static void ProcessVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
unsigned RTOptionID = options::OPT__SLASH_MT;

Expand Down Expand Up @@ -4796,6 +4806,12 @@ static void ProcessVSRuntimeLibrary(const ArgList &Args,
// implemented in clang.
CmdArgs.push_back("--dependent-lib=oldnames");
}

// All Arm64EC object files implicitly add softintrin.lib. This is necessary
// even if the file doesn't actually refer to any of the routines because
// the CRT itself has incomplete dependency markings.
if (TC.getTriple().isWindowsArm64EC())
CmdArgs.push_back("--dependent-lib=softintrin");
}

void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Expand Down Expand Up @@ -7051,7 +7067,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,

if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode() &&
Args.hasArg(options::OPT_fms_runtime_lib_EQ))
ProcessVSRuntimeLibrary(Args, CmdArgs);
ProcessVSRuntimeLibrary(getToolChain(), Args, CmdArgs);

// Handle -fgcc-version, if present.
VersionTuple GNUCVer;
Expand Down Expand Up @@ -8178,7 +8194,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
ArgStringList &CmdArgs) const {
bool isNVPTX = getToolChain().getTriple().isNVPTX();

ProcessVSRuntimeLibrary(Args, CmdArgs);
ProcessVSRuntimeLibrary(getToolChain(), Args, CmdArgs);

if (Arg *ShowIncludes =
Args.getLastArg(options::OPT__SLASH_showIncludes,
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2116,8 +2116,12 @@ unsigned tools::getDwarfVersion(const ToolChain &TC,
const llvm::opt::ArgList &Args) {
unsigned DwarfVersion = ParseDebugDefaultVersion(TC, Args);
if (const Arg *GDwarfN = getDwarfNArg(Args))
if (int N = DwarfVersionNum(GDwarfN->getSpelling()))
if (int N = DwarfVersionNum(GDwarfN->getSpelling())) {
DwarfVersion = N;
if (DwarfVersion == 5 && TC.getTriple().isOSAIX())
TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
<< GDwarfN->getSpelling() << TC.getTriple().str();
}
if (DwarfVersion == 0) {
DwarfVersion = TC.GetDefaultDwarfVersion();
assert(DwarfVersion && "toolchain default DWARF version must be nonzero");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
Arg *gNArg = Args.getLastArg(options::OPT_gN_Group);
DebugInfoKind = debugLevelToInfoKind(*gNArg);
} else if (Args.hasArg(options::OPT_g_Flag)) {
DebugInfoKind = llvm::codegenoptions::DebugLineTablesOnly;
DebugInfoKind = llvm::codegenoptions::FullDebugInfo;
} else {
DebugInfoKind = llvm::codegenoptions::NoDebugInfo;
}
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,7 @@ class AnnotatingParser {
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
!Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
!Line.startsWith(tok::l_paren) &&
!Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) {
if (const auto *Previous = Tok->Previous;
!Previous ||
Expand Down Expand Up @@ -2726,8 +2727,10 @@ class AnnotatingParser {
}
}

if (Tok.Next->isOneOf(tok::question, tok::ampamp))
if (Tok.Next->is(tok::question) ||
(Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(IsCpp))) {
return false;
}

// `foreach((A a, B b) in someList)` should not be seen as a cast.
if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp())
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3660,6 +3660,9 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
case LangOptions::ClangABI::Ver17:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0");
break;
case LangOptions::ClangABI::Ver18:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0");
break;
case LangOptions::ClangABI::Latest:
break;
}
Expand Down Expand Up @@ -4167,6 +4170,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.setClangABICompat(LangOptions::ClangABI::Ver15);
else if (Major <= 17)
Opts.setClangABICompat(LangOptions::ClangABI::Ver17);
else if (Major <= 18)
Opts.setClangABICompat(LangOptions::ClangABI::Ver18);
} else if (Ver != "latest") {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Headers/avxintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,7 @@ _mm256_permutevar_pd(__m256d __a, __m256i __c)

/// Copies the values stored in a 128-bit vector of [4 x float] as
/// specified by the 128-bit integer vector operand.
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> VPERMILPS </c> instruction.
Expand Down
24 changes: 19 additions & 5 deletions clang/lib/Interpreter/IncrementalParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ IncrementalParser::IncrementalParser(Interpreter &Interp,
if (Err)
return;
CI->ExecuteAction(*Act);

if (getCodeGen())
CachedInCodeGenModule = GenModule();

std::unique_ptr<ASTConsumer> IncrConsumer =
std::make_unique<IncrementalASTConsumer>(Interp, CI->takeASTConsumer());
CI->setASTConsumer(std::move(IncrConsumer));
Expand All @@ -224,11 +228,8 @@ IncrementalParser::IncrementalParser(Interpreter &Interp,
return; // PTU.takeError();
}

if (CodeGenerator *CG = getCodeGen()) {
std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
M->getContext());
PTU->TheModule = std::move(M);
if (getCodeGen()) {
PTU->TheModule = GenModule();
assert(PTU->TheModule && "Failed to create initial PTU");
}
}
Expand Down Expand Up @@ -364,6 +365,19 @@ IncrementalParser::Parse(llvm::StringRef input) {
std::unique_ptr<llvm::Module> IncrementalParser::GenModule() {
static unsigned ID = 0;
if (CodeGenerator *CG = getCodeGen()) {
// Clang's CodeGen is designed to work with a single llvm::Module. In many
// cases for convenience various CodeGen parts have a reference to the
// llvm::Module (TheModule or Module) which does not change when a new
// module is pushed. However, the execution engine wants to take ownership
// of the module which does not map well to CodeGen's design. To work this
// around we created an empty module to make CodeGen happy. We should make
// sure it always stays empty.
assert((!CachedInCodeGenModule ||
(CachedInCodeGenModule->empty() &&
CachedInCodeGenModule->global_empty() &&
CachedInCodeGenModule->alias_empty() &&
CachedInCodeGenModule->ifunc_empty())) &&
"CodeGen wrote to a readonly module");
std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
return M;
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Interpreter/IncrementalParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <memory>
namespace llvm {
class LLVMContext;
class Module;
} // namespace llvm

namespace clang {
Expand Down Expand Up @@ -57,6 +58,10 @@ class IncrementalParser {
/// of code.
std::list<PartialTranslationUnit> PTUs;

/// When CodeGen is created the first llvm::Module gets cached in many places
/// and we must keep it alive.
std::unique_ptr<llvm::Module> CachedInCodeGenModule;

IncrementalParser();

public:
Expand Down
Loading