aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-06-04 19:01:35 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-22 18:22:50 +0000
commit2efbaac7a07fff163640a67873b3ac250794ec3f (patch)
tree6773547d294a46d478a9afe78e381b94d52c1944 /contrib/llvm-project/clang
parenta324c34037ef2e1101962fca4ad0c021253288e1 (diff)
parent3b922bd9516f6dc5146815ed8d4363fcbe97997f (diff)
Diffstat (limited to 'contrib/llvm-project/clang')
-rw-r--r--contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h8
-rw-r--r--contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--contrib/llvm-project/clang/include/clang/Sema/Initialization.h18
-rw-r--r--contrib/llvm-project/clang/lib/AST/ASTContext.cpp3
-rw-r--r--contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp19
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp1
-rw-r--r--contrib/llvm-project/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp6
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaAccess.cpp3
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaInit.cpp335
10 files changed, 253 insertions, 145 deletions
diff --git a/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h b/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h
index f02c140c14c1..746a5b2fbfc6 100644
--- a/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h
+++ b/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h
@@ -64,6 +64,7 @@ protected:
const ConstraintSatisfaction *Satisfaction);
ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction,
bool Dependent,
@@ -85,6 +86,13 @@ public:
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack);
+ static ConceptSpecializationExpr *
+ Create(const ASTContext &C, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ImplicitConceptSpecializationDecl *SpecDecl,
+ const ConstraintSatisfaction *Satisfaction, bool Dependent,
+ bool ContainsUnexpandedParameterPack);
+
ArrayRef<TemplateArgument> getTemplateArguments() const {
return SpecDecl->getTemplateArguments();
}
diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 31a27558bca4..e4651678603d 100644
--- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2124,7 +2124,8 @@ def err_init_conversion_failed : Error<
"exception object|a member subobject|an array element|a new value|a value|a "
"base class|a constructor delegation|a vector element|a block element|a "
"block element|a complex element|a lambda capture|a compound literal "
- "initializer|a related result|a parameter of CF audited function}0 "
+ "initializer|a related result|a parameter of CF audited function|a "
+ "structured binding|a member subobject}0 "
"%diff{of type $ with an %select{rvalue|lvalue}2 of type $|"
"with an %select{rvalue|lvalue}2 of incompatible type}1,3"
"%select{|: different classes%diff{ ($ vs $)|}5,6"
diff --git a/contrib/llvm-project/clang/include/clang/Sema/Initialization.h b/contrib/llvm-project/clang/include/clang/Sema/Initialization.h
index e5a98ba97f4f..e1bbea0d118d 100644
--- a/contrib/llvm-project/clang/include/clang/Sema/Initialization.h
+++ b/contrib/llvm-project/clang/include/clang/Sema/Initialization.h
@@ -123,6 +123,10 @@ public:
/// decomposition declaration.
EK_Binding,
+ /// The entity being initialized is a non-static data member subobject of an
+ /// object initialized via parenthesized aggregate initialization.
+ EK_ParenAggInitMember,
+
// Note: err_init_conversion_failed in DiagnosticSemaKinds.td uses this
// enum as an index for its first %select. When modifying this list,
// that diagnostic text needs to be updated as well.
@@ -227,8 +231,10 @@ private:
/// Create the initialization entity for a member subobject.
InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
- bool Implicit, bool DefaultMemberInit)
- : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
+ bool Implicit, bool DefaultMemberInit,
+ bool IsParenAggInit = false)
+ : Kind(IsParenAggInit ? EK_ParenAggInitMember : EK_Member),
+ Parent(Parent), Type(Member->getType()),
Variable{Member, Implicit, DefaultMemberInit} {}
/// Create the initialization entity for an array element.
@@ -388,6 +394,14 @@ public:
return InitializedEntity(Member->getAnonField(), Parent, Implicit, false);
}
+ /// Create the initialization entity for a member subobject initialized via
+ /// parenthesized aggregate init.
+ static InitializedEntity InitializeMemberFromParenAggInit(FieldDecl *Member) {
+ return InitializedEntity(Member, /*Parent=*/nullptr, /*Implicit=*/false,
+ /*DefaultMemberInit=*/false,
+ /*IsParenAggInit=*/true);
+ }
+
/// Create the initialization entity for a default member initializer.
static InitializedEntity
InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) {
diff --git a/contrib/llvm-project/clang/lib/AST/ASTContext.cpp b/contrib/llvm-project/clang/lib/AST/ASTContext.cpp
index 2884fe660422..8054eb2e12d3 100644
--- a/contrib/llvm-project/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm-project/clang/lib/AST/ASTContext.cpp
@@ -765,7 +765,8 @@ canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC,
CSE->getNamedConcept()->getLocation(), NewConverted);
Expr *NewIDC = ConceptSpecializationExpr::Create(
- C, CSE->getNamedConcept(), CSD, nullptr, CSE->isInstantiationDependent(),
+ C, CSE->getNamedConcept(), CSE->getTemplateArgsAsWritten(), CSD,
+ /*Satisfaction=*/nullptr, CSE->isInstantiationDependent(),
CSE->containsUnexpandedParameterPack());
if (auto *OrigFold = dyn_cast<CXXFoldExpr>(IDC))
diff --git a/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp b/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp
index fc8f1eb2abf1..cdc13c2d3969 100644
--- a/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp
+++ b/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp
@@ -59,6 +59,15 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
: Expr(ConceptSpecializationExprClass, Empty) {}
ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
+ const ASTContext &C, ConceptDecl *NamedConcept,
+ ImplicitConceptSpecializationDecl *SpecDecl,
+ const ConstraintSatisfaction *Satisfaction, bool Dependent,
+ bool ContainsUnexpandedParameterPack) {
+ return Create(C, NamedConcept, /*ArgsAsWritten*/ nullptr, SpecDecl, Satisfaction,
+ Dependent, ContainsUnexpandedParameterPack);
+}
+
+ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
const ASTContext &C, NestedNameSpecifierLoc NNS,
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
@@ -72,13 +81,14 @@ ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
ConceptSpecializationExpr::ConceptSpecializationExpr(
const ASTContext &C, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack)
: Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
DeclarationNameInfo(), NamedConcept, NamedConcept,
- nullptr),
+ ArgsAsWritten),
SpecDecl(SpecDecl),
Satisfaction(Satisfaction
? ASTConstraintSatisfaction::Create(C, *Satisfaction)
@@ -95,12 +105,13 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(
ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
const ASTContext &C, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack) {
- return new (C)
- ConceptSpecializationExpr(C, NamedConcept, SpecDecl, Satisfaction,
- Dependent, ContainsUnexpandedParameterPack);
+ return new (C) ConceptSpecializationExpr(C, NamedConcept, ArgsAsWritten,
+ SpecDecl, Satisfaction, Dependent,
+ ContainsUnexpandedParameterPack);
}
const TypeConstraint *
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
index 238507e06335..77554aa2c462 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7801,6 +7801,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
} else {
D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << GuardArgs;
}
+ A->claim();
}
}
diff --git a/contrib/llvm-project/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/contrib/llvm-project/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
index 44034e44adec..3cc68673cd13 100644
--- a/contrib/llvm-project/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
+++ b/contrib/llvm-project/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
@@ -113,7 +113,11 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
continue;
}
if (Style.isCpp()) {
- if (const auto Pos = Text.find_first_of("_i"); Pos != StringRef::npos) {
+ // Hex alpha digits a-f/A-F must be at the end of the string literal.
+ StringRef Suffixes = "_himnsuyd";
+ if (const auto Pos =
+ Text.find_first_of(IsBase16 ? Suffixes.drop_back() : Suffixes);
+ Pos != StringRef::npos) {
Text = Text.substr(0, Pos);
Length = Pos;
}
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm-project/clang/lib/Sema/SemaAccess.cpp
index cbda62497e6a..4a39c2d065e6 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaAccess.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaAccess.cpp
@@ -1651,7 +1651,8 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
<< Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor);
break;
- case InitializedEntity::EK_Member: {
+ case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember: {
const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl());
PD = PDiag(diag::err_access_field_ctor);
PD << Field->getType() << getSpecialMember(Constructor);
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
index 051fad04219f..0fbef1cc8b52 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
@@ -8693,7 +8693,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
}
// Check that SVE types are only used in functions with SVE available.
- if (T->isSVESizelessBuiltinType() && CurContext->isFunctionOrMethod()) {
+ if (T->isSVESizelessBuiltinType() && isa<FunctionDecl>(CurContext)) {
const FunctionDecl *FD = cast<FunctionDecl>(CurContext);
llvm::StringMap<bool> CallerFeatureMap;
Context.getFunctionFeatureMap(CallerFeatureMap, FD);
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp b/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp
index 44adb167dcc0..cc8d1405ec55 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaInit.cpp
@@ -1152,6 +1152,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
case InitializedEntity::EK_Parameter_CF_Audited:
case InitializedEntity::EK_TemplateParameter:
case InitializedEntity::EK_Result:
+ case InitializedEntity::EK_ParenAggInitMember:
// Extra braces here are suspicious.
DiagID = diag::warn_braces_around_init;
break;
@@ -3348,6 +3349,7 @@ DeclarationName InitializedEntity::getName() const {
case EK_Variable:
case EK_Member:
+ case EK_ParenAggInitMember:
case EK_Binding:
case EK_TemplateParameter:
return Variable.VariableOrMember->getDeclName();
@@ -3379,6 +3381,7 @@ ValueDecl *InitializedEntity::getDecl() const {
switch (getKind()) {
case EK_Variable:
case EK_Member:
+ case EK_ParenAggInitMember:
case EK_Binding:
case EK_TemplateParameter:
return Variable.VariableOrMember;
@@ -3420,6 +3423,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Parameter_CF_Audited:
case EK_TemplateParameter:
case EK_Member:
+ case EK_ParenAggInitMember:
case EK_Binding:
case EK_New:
case EK_Temporary:
@@ -3454,7 +3458,10 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
case EK_Result: OS << "Result"; break;
case EK_StmtExprResult: OS << "StmtExprResult"; break;
case EK_Exception: OS << "Exception"; break;
- case EK_Member: OS << "Member"; break;
+ case EK_Member:
+ case EK_ParenAggInitMember:
+ OS << "Member";
+ break;
case EK_Binding: OS << "Binding"; break;
case EK_New: OS << "New"; break;
case EK_Temporary: OS << "Temporary"; break;
@@ -5274,179 +5281,224 @@ static void TryOrBuildParenListInitialization(
Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
ArrayRef<Expr *> Args, InitializationSequence &Sequence, bool VerifyOnly,
ExprResult *Result = nullptr) {
- unsigned ArgIndexToProcess = 0;
+ unsigned EntityIndexToProcess = 0;
SmallVector<Expr *, 4> InitExprs;
QualType ResultType;
Expr *ArrayFiller = nullptr;
FieldDecl *InitializedFieldInUnion = nullptr;
- // Process entities (i.e. array members, base classes, or class fields) by
- // adding an initialization expression to InitExprs for each entity to
- // initialize.
- auto ProcessEntities = [&](auto Range) -> bool {
- bool IsUnionType = Entity.getType()->isUnionType();
- for (InitializedEntity SubEntity : Range) {
- // Unions should only have one initializer expression.
- // If there are more initializers than it will be caught when we check
- // whether Index equals Args.size().
- if (ArgIndexToProcess == 1 && IsUnionType)
- return true;
-
- bool IsMember = SubEntity.getKind() == InitializedEntity::EK_Member;
-
- // Unnamed bitfields should not be initialized at all, either with an arg
- // or by default.
- if (IsMember && cast<FieldDecl>(SubEntity.getDecl())->isUnnamedBitfield())
- continue;
-
- if (ArgIndexToProcess < Args.size()) {
- // There are still expressions in Args that haven't been processed.
- // Let's match them to the current entity to initialize.
- Expr *E = Args[ArgIndexToProcess++];
-
- // Incomplete array types indicate flexible array members. Do not allow
- // paren list initializations of structs with these members, as GCC
- // doesn't either.
- if (IsMember) {
- auto *FD = cast<FieldDecl>(SubEntity.getDecl());
- if (FD->getType()->isIncompleteArrayType()) {
- if (!VerifyOnly) {
- S.Diag(E->getBeginLoc(), diag::err_flexible_array_init)
- << SourceRange(E->getBeginLoc(), E->getEndLoc());
- S.Diag(FD->getLocation(), diag::note_flexible_array_member) << FD;
- }
- Sequence.SetFailed(
- InitializationSequence::FK_ParenthesizedListInitFailed);
- return false;
- }
- }
-
- InitializationKind SubKind = InitializationKind::CreateForInit(
- E->getExprLoc(), /*isDirectInit=*/false, E);
- InitializationSequence SubSeq(S, SubEntity, SubKind, E);
-
- if (SubSeq.Failed()) {
- if (!VerifyOnly)
- SubSeq.Diagnose(S, SubEntity, SubKind, E);
- else
- Sequence.SetFailed(
- InitializationSequence::FK_ParenthesizedListInitFailed);
+ auto HandleInitializedEntity = [&](const InitializedEntity &SubEntity,
+ const InitializationKind &SubKind,
+ Expr *Arg, Expr **InitExpr = nullptr) {
+ InitializationSequence IS = [&]() {
+ if (Arg)
+ return InitializationSequence(S, SubEntity, SubKind, Arg);
+ return InitializationSequence(S, SubEntity, SubKind, std::nullopt);
+ }();
- return false;
- }
- if (!VerifyOnly) {
- ExprResult ER = SubSeq.Perform(S, SubEntity, SubKind, E);
- InitExprs.push_back(ER.get());
- if (IsMember && IsUnionType)
- InitializedFieldInUnion = cast<FieldDecl>(SubEntity.getDecl());
- }
+ if (IS.Failed()) {
+ if (!VerifyOnly) {
+ if (Arg)
+ IS.Diagnose(S, SubEntity, SubKind, Arg);
+ else
+ IS.Diagnose(S, SubEntity, SubKind, std::nullopt);
} else {
- // We've processed all of the args, but there are still entities that
- // have to be initialized.
- if (IsMember) {
- // C++ [dcl.init]p17.6.2.2
- // The remaining elements are initialized with their default member
- // initializers, if any
- auto *FD = cast<FieldDecl>(SubEntity.getDecl());
- if (FD->hasInClassInitializer()) {
- if (!VerifyOnly) {
- ExprResult DIE = S.BuildCXXDefaultInitExpr(FD->getLocation(), FD);
- if (DIE.isInvalid())
- return false;
- S.checkInitializerLifetime(SubEntity, DIE.get());
- InitExprs.push_back(DIE.get());
- }
- continue;
- }
- }
- // Remaining class elements without default member initializers and
- // array elements are value initialized:
- //
- // C++ [dcl.init]p17.6.2.2
- // The remaining elements...otherwise are value initialzed
- //
- // C++ [dcl.init]p17.5
- // if the destination type is an array, the object is initialized as
- // . follows. Let x1, . . . , xk be the elements of the expression-list
- // ...Let n denote the array size...the ith array element is...value-
- // initialized for each k < i <= n.
- InitializationKind SubKind = InitializationKind::CreateValue(
- Kind.getLocation(), Kind.getLocation(), Kind.getLocation(), true);
- InitializationSequence SubSeq(S, SubEntity, SubKind, std::nullopt);
- if (SubSeq.Failed()) {
- if (!VerifyOnly)
- SubSeq.Diagnose(S, SubEntity, SubKind, std::nullopt);
- return false;
- }
- if (!VerifyOnly) {
- ExprResult ER = SubSeq.Perform(S, SubEntity, SubKind, std::nullopt);
- if (SubEntity.getKind() == InitializedEntity::EK_ArrayElement) {
- ArrayFiller = ER.get();
- return true;
- }
- InitExprs.push_back(ER.get());
- }
+ Sequence.SetFailed(
+ InitializationSequence::FK_ParenthesizedListInitFailed);
}
+
+ return false;
+ }
+ if (!VerifyOnly) {
+ ExprResult ER;
+ if (Arg)
+ ER = IS.Perform(S, SubEntity, SubKind, Arg);
+ else
+ ER = IS.Perform(S, SubEntity, SubKind, std::nullopt);
+ if (InitExpr)
+ *InitExpr = ER.get();
+ else
+ InitExprs.push_back(ER.get());
}
return true;
};
if (const ArrayType *AT =
S.getASTContext().getAsArrayType(Entity.getType())) {
-
SmallVector<InitializedEntity, 4> ElementEntities;
uint64_t ArrayLength;
- // C++ [dcl.init]p17.5
+ // C++ [dcl.init]p16.5
// if the destination type is an array, the object is initialized as
// follows. Let x1, . . . , xk be the elements of the expression-list. If
- // the destination type is an array of unknown bound, it is define as
+ // the destination type is an array of unknown bound, it is defined as
// having k elements.
if (const ConstantArrayType *CAT =
- S.getASTContext().getAsConstantArrayType(Entity.getType()))
+ S.getASTContext().getAsConstantArrayType(Entity.getType())) {
ArrayLength = CAT->getSize().getZExtValue();
- else
+ ResultType = Entity.getType();
+ } else if (const VariableArrayType *VAT =
+ S.getASTContext().getAsVariableArrayType(Entity.getType())) {
+ // Braced-initialization of variable array types is not allowed, even if
+ // the size is greater than or equal to the number of args, so we don't
+ // allow them to be initialized via parenthesized aggregate initialization
+ // either.
+ const Expr *SE = VAT->getSizeExpr();
+ S.Diag(SE->getBeginLoc(), diag::err_variable_object_no_init)
+ << SE->getSourceRange();
+ return;
+ } else {
+ assert(isa<IncompleteArrayType>(Entity.getType()));
ArrayLength = Args.size();
+ }
+ EntityIndexToProcess = ArrayLength;
- if (ArrayLength >= Args.size()) {
- for (uint64_t I = 0; I < ArrayLength; ++I)
- ElementEntities.push_back(
- InitializedEntity::InitializeElement(S.getASTContext(), I, Entity));
-
- if (!ProcessEntities(ElementEntities))
+ // ...the ith array element is copy-initialized with xi for each
+ // 1 <= i <= k
+ for (Expr *E : Args) {
+ InitializedEntity SubEntity = InitializedEntity::InitializeElement(
+ S.getASTContext(), EntityIndexToProcess, Entity);
+ InitializationKind SubKind = InitializationKind::CreateForInit(
+ E->getExprLoc(), /*isDirectInit=*/false, E);
+ if (!HandleInitializedEntity(SubEntity, SubKind, E))
+ return;
+ }
+ // ...and value-initialized for each k < i <= n;
+ if (ArrayLength > Args.size()) {
+ InitializedEntity SubEntity = InitializedEntity::InitializeElement(
+ S.getASTContext(), Args.size(), Entity);
+ InitializationKind SubKind = InitializationKind::CreateValue(
+ Kind.getLocation(), Kind.getLocation(), Kind.getLocation(), true);
+ if (!HandleInitializedEntity(SubEntity, SubKind, nullptr, &ArrayFiller))
return;
+ }
+ if (ResultType.isNull()) {
ResultType = S.Context.getConstantArrayType(
AT->getElementType(), llvm::APInt(/*numBits=*/32, ArrayLength),
- nullptr, ArrayType::Normal, 0);
+ /*SizeExpr=*/nullptr, ArrayType::Normal, 0);
}
} else if (auto *RT = Entity.getType()->getAs<RecordType>()) {
+ bool IsUnion = RT->isUnionType();
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- auto BaseRange = map_range(RD->bases(), [&](auto &base) {
- return InitializedEntity::InitializeBase(S.getASTContext(), &base, false,
- &Entity);
- });
- auto FieldRange = map_range(RD->fields(), [](auto *field) {
- return InitializedEntity::InitializeMember(field);
- });
+ if (!IsUnion) {
+ for (const CXXBaseSpecifier &Base : RD->bases()) {
+ InitializedEntity SubEntity = InitializedEntity::InitializeBase(
+ S.getASTContext(), &Base, false, &Entity);
+ if (EntityIndexToProcess < Args.size()) {
+ // C++ [dcl.init]p16.6.2.2.
+ // ...the object is initialized is follows. Let e1, ..., en be the
+ // elements of the aggregate([dcl.init.aggr]). Let x1, ..., xk be
+ // the elements of the expression-list...The element ei is
+ // copy-initialized with xi for 1 <= i <= k.
+ Expr *E = Args[EntityIndexToProcess];
+ InitializationKind SubKind = InitializationKind::CreateForInit(
+ E->getExprLoc(), /*isDirectInit=*/false, E);
+ if (!HandleInitializedEntity(SubEntity, SubKind, E))
+ return;
+ } else {
+ // We've processed all of the args, but there are still base classes
+ // that have to be initialized.
+ // C++ [dcl.init]p17.6.2.2
+ // The remaining elements...otherwise are value initialzed
+ InitializationKind SubKind = InitializationKind::CreateValue(
+ Kind.getLocation(), Kind.getLocation(), Kind.getLocation(),
+ /*IsImplicit=*/true);
+ if (!HandleInitializedEntity(SubEntity, SubKind, nullptr))
+ return;
+ }
+ EntityIndexToProcess++;
+ }
+ }
- if (!ProcessEntities(BaseRange))
- return;
+ for (FieldDecl *FD : RD->fields()) {
+ // Unnamed bitfields should not be initialized at all, either with an arg
+ // or by default.
+ if (FD->isUnnamedBitfield())
+ continue;
- if (!ProcessEntities(FieldRange))
- return;
+ InitializedEntity SubEntity =
+ InitializedEntity::InitializeMemberFromParenAggInit(FD);
+ if (EntityIndexToProcess < Args.size()) {
+ // ...The element ei is copy-initialized with xi for 1 <= i <= k.
+ Expr *E = Args[EntityIndexToProcess];
+
+ // Incomplete array types indicate flexible array members. Do not allow
+ // paren list initializations of structs with these members, as GCC
+ // doesn't either.
+ if (FD->getType()->isIncompleteArrayType()) {
+ if (!VerifyOnly) {
+ S.Diag(E->getBeginLoc(), diag::err_flexible_array_init)
+ << SourceRange(E->getBeginLoc(), E->getEndLoc());
+ S.Diag(FD->getLocation(), diag::note_flexible_array_member) << FD;
+ }
+ Sequence.SetFailed(
+ InitializationSequence::FK_ParenthesizedListInitFailed);
+ return;
+ }
+
+ InitializationKind SubKind = InitializationKind::CreateForInit(
+ E->getExprLoc(), /*isDirectInit=*/false, E);
+ if (!HandleInitializedEntity(SubEntity, SubKind, E))
+ return;
+
+ // Unions should have only one initializer expression, so we bail out
+ // after processing the first field. If there are more initializers then
+ // it will be caught when we later check whether EntityIndexToProcess is
+ // less than Args.size();
+ if (IsUnion) {
+ InitializedFieldInUnion = FD;
+ EntityIndexToProcess = 1;
+ break;
+ }
+ } else {
+ // We've processed all of the args, but there are still members that
+ // have to be initialized.
+ if (FD->hasInClassInitializer()) {
+ if (!VerifyOnly) {
+ // C++ [dcl.init]p16.6.2.2
+ // The remaining elements are initialized with their default
+ // member initializers, if any
+ ExprResult DIE = S.BuildCXXDefaultInitExpr(FD->getLocation(), FD);
+ if (DIE.isInvalid())
+ return;
+ S.checkInitializerLifetime(SubEntity, DIE.get());
+ InitExprs.push_back(DIE.get());
+ }
+ } else {
+ // C++ [dcl.init]p17.6.2.2
+ // The remaining elements...otherwise are value initialzed
+ if (FD->getType()->isReferenceType()) {
+ Sequence.SetFailed(
+ InitializationSequence::FK_ParenthesizedListInitFailed);
+ if (!VerifyOnly) {
+ SourceRange SR = Kind.getParenOrBraceRange();
+ S.Diag(SR.getEnd(), diag::err_init_reference_member_uninitialized)
+ << FD->getType() << SR;
+ S.Diag(FD->getLocation(), diag::note_uninit_reference_member);
+ }
+ return;
+ }
+ InitializationKind SubKind = InitializationKind::CreateValue(
+ Kind.getLocation(), Kind.getLocation(), Kind.getLocation(), true);
+ if (!HandleInitializedEntity(SubEntity, SubKind, nullptr))
+ return;
+ }
+ }
+ EntityIndexToProcess++;
+ }
ResultType = Entity.getType();
}
// Not all of the args have been processed, so there must've been more args
- // then were required to initialize the element.
- if (ArgIndexToProcess < Args.size()) {
+ // than were required to initialize the element.
+ if (EntityIndexToProcess < Args.size()) {
Sequence.SetFailed(InitializationSequence::FK_ParenthesizedListInitFailed);
if (!VerifyOnly) {
QualType T = Entity.getType();
int InitKind = T->isArrayType() ? 0 : T->isUnionType() ? 3 : 4;
- SourceRange ExcessInitSR(Args[ArgIndexToProcess]->getBeginLoc(),
+ SourceRange ExcessInitSR(Args[EntityIndexToProcess]->getBeginLoc(),
Args.back()->getEndLoc());
S.Diag(Kind.getLocation(), diag::err_excess_initializers)
<< InitKind << ExcessInitSR;
@@ -6412,6 +6464,7 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
return Sema::AA_Converting;
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember:
case InitializedEntity::EK_Binding:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_VectorElement:
@@ -6432,6 +6485,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember:
case InitializedEntity::EK_Result:
case InitializedEntity::EK_StmtExprResult:
case InitializedEntity::EK_New:
@@ -6476,6 +6530,7 @@ static bool shouldDestroyEntity(const InitializedEntity &Entity) {
return false;
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember:
case InitializedEntity::EK_Binding:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Parameter:
@@ -6512,6 +6567,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_ParenAggInitMember:
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
case InitializedEntity::EK_TemplateParameter:
@@ -7080,7 +7136,15 @@ static LifetimeResult getEntityLifetime(
case InitializedEntity::EK_Exception:
// FIXME: Can we diagnose lifetime problems with exceptions?
return {nullptr, LK_FullExpression};
+
+ case InitializedEntity::EK_ParenAggInitMember:
+ // -- A temporary object bound to a reference element of an aggregate of
+ // class type initialized from a parenthesized expression-list
+ // [dcl.init, 9.3] persists until the completion of the full-expression
+ // containing the expression-list.
+ return {nullptr, LK_FullExpression};
}
+
llvm_unreachable("unknown entity kind");
}
@@ -9196,7 +9260,9 @@ ExprResult InitializationSequence::Perform(Sema &S,
S.checkInitializerLifetime(Entity, Init);
// Diagnose non-fatal problems with the completed initialization.
- if (Entity.getKind() == InitializedEntity::EK_Member &&
+ if (InitializedEntity::EntityKind EK = Entity.getKind();
+ (EK == InitializedEntity::EK_Member ||
+ EK == InitializedEntity::EK_ParenAggInitMember) &&
cast<FieldDecl>(Entity.getDecl())->isBitField())
S.CheckBitFieldInitialization(Kind.getLocation(),
cast<FieldDecl>(Entity.getDecl()),
@@ -9650,7 +9716,8 @@ bool InitializationSequence::Diagnose(Sema &S,
case OR_No_Viable_Function:
if (Kind.getKind() == InitializationKind::IK_Default &&
(Entity.getKind() == InitializedEntity::EK_Base ||
- Entity.getKind() == InitializedEntity::EK_Member) &&
+ Entity.getKind() == InitializedEntity::EK_Member ||
+ Entity.getKind() == InitializedEntity::EK_ParenAggInitMember) &&
isa<CXXConstructorDecl>(S.CurContext)) {
// This is implicit default initialization of a member or
// base within a constructor. If no viable function was