aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r--clang/lib/Sema/SemaInit.cpp402
1 files changed, 349 insertions, 53 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index d3b454843234..ddb2b5cf5cd1 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -81,12 +81,22 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT,
const QualType ElemTy =
Context.getCanonicalType(AT->getElementType()).getUnqualifiedType();
+ auto IsCharOrUnsignedChar = [](const QualType &T) {
+ const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr());
+ return BT && BT->isCharType() && BT->getKind() != BuiltinType::SChar;
+ };
+
switch (SL->getKind()) {
case StringLiteral::UTF8:
// char8_t array can be initialized with a UTF-8 string.
- if (ElemTy->isChar8Type())
+ // - C++20 [dcl.init.string] (DR)
+ // Additionally, an array of char or unsigned char may be initialized
+ // by a UTF-8 string literal.
+ if (ElemTy->isChar8Type() ||
+ (Context.getLangOpts().Char8 &&
+ IsCharOrUnsignedChar(ElemTy.getCanonicalType())))
return SIF_None;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case StringLiteral::Ordinary:
// char array can be initialized with a narrow string.
// Only allow char x[] = "foo"; not char x[] = L"foo";
@@ -229,6 +239,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
if (StrLength > CAT->getSize().getZExtValue())
S.Diag(Str->getBeginLoc(),
diag::err_initializer_string_for_char_array_too_long)
+ << CAT->getSize().getZExtValue() << StrLength
<< Str->getSourceRange();
} else {
// C99 6.7.8p14.
@@ -493,7 +504,7 @@ ExprResult InitListChecker::PerformEmptyInit(SourceLocation Loc,
true);
MultiExprArg SubInit;
Expr *InitExpr;
- InitListExpr DummyInitList(SemaRef.Context, Loc, None, Loc);
+ InitListExpr DummyInitList(SemaRef.Context, Loc, std::nullopt, Loc);
// C++ [dcl.init.aggr]p7:
// If there are fewer initializer-clauses in the list than there are
@@ -512,8 +523,10 @@ ExprResult InitListChecker::PerformEmptyInit(SourceLocation Loc,
//
// Only do this if we're initializing a class type, to avoid filling in
// the initializer list where possible.
- InitExpr = VerifyOnly ? &DummyInitList : new (SemaRef.Context)
- InitListExpr(SemaRef.Context, Loc, None, Loc);
+ InitExpr = VerifyOnly
+ ? &DummyInitList
+ : new (SemaRef.Context)
+ InitListExpr(SemaRef.Context, Loc, std::nullopt, Loc);
InitExpr->setType(SemaRef.Context.VoidTy);
SubInit = InitExpr;
Kind = InitializationKind::CreateCopy(Loc, Loc);
@@ -695,10 +708,10 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
// member of reference type uninitialized, the program is
// ill-formed.
SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
- << Field->getType()
- << ILE->getSyntacticForm()->getSourceRange();
- SemaRef.Diag(Field->getLocation(),
- diag::note_uninit_reference_member);
+ << Field->getType()
+ << (ILE->isSyntacticForm() ? ILE : ILE->getSyntacticForm())
+ ->getSourceRange();
+ SemaRef.Diag(Field->getLocation(), diag::note_uninit_reference_member);
}
hadError = true;
return;
@@ -1518,8 +1531,8 @@ void InitListChecker::CheckComplexType(const InitializedEntity &Entity,
// As an extension, clang supports complex initializers, which initialize
// a complex number component-wise. When an explicit initializer list for
- // a complex number contains two two initializers, this extension kicks in:
- // it exepcts the initializer list to contain two elements convertible to
+ // a complex number contains two initializers, this extension kicks in:
+ // it expects the initializer list to contain two elements convertible to
// the element type of the complex type. The first element initializes
// the real part, and the second element intitializes the imaginary part.
@@ -2934,7 +2947,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Compute the type of the integer literals.
QualType PromotedCharTy = CharTy;
- if (CharTy->isPromotableIntegerType())
+ if (Context.isPromotableIntegerType(CharTy))
PromotedCharTy = Context.getPromotedIntegerType(CharTy);
unsigned PromotedCharTyWidth = Context.getTypeSize(PromotedCharTy);
@@ -3110,10 +3123,8 @@ InitListExpr *
InitListChecker::createInitListExpr(QualType CurrentObjectType,
SourceRange InitRange,
unsigned ExpectedNumInits) {
- InitListExpr *Result
- = new (SemaRef.Context) InitListExpr(SemaRef.Context,
- InitRange.getBegin(), None,
- InitRange.getEnd());
+ InitListExpr *Result = new (SemaRef.Context) InitListExpr(
+ SemaRef.Context, InitRange.getBegin(), std::nullopt, InitRange.getEnd());
QualType ResultType = CurrentObjectType;
if (!ResultType->isArrayType())
@@ -3519,6 +3530,7 @@ void InitializationSequence::Step::Destroy() {
case SK_StdInitializerListConstructorCall:
case SK_OCLSamplerInit:
case SK_OCLZeroOpaqueType:
+ case SK_ParenthesizedListInit:
break;
case SK_ConversionSequence:
@@ -3578,6 +3590,7 @@ bool InitializationSequence::isAmbiguous() const {
case FK_PlaceholderType:
case FK_ExplicitConstructor:
case FK_AddressOfUnaddressableFunction:
+ case FK_ParenthesizedListInitFailed:
return false;
case FK_ReferenceInitOverloadFailed:
@@ -3813,6 +3826,13 @@ void InitializationSequence::AddOCLZeroOpaqueTypeStep(QualType T) {
Steps.push_back(S);
}
+void InitializationSequence::AddParenthesizedListInitStep(QualType T) {
+ Step S;
+ S.Kind = SK_ParenthesizedListInit;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::RewrapReferenceInitList(QualType T,
InitListExpr *Syntactic) {
assert(Syntactic->getNumInits() == 1 &&
@@ -5227,7 +5247,7 @@ static void TryDefaultInitialization(Sema &S,
// constructor for T is called (and the initialization is ill-formed if
// T has no accessible default constructor);
if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) {
- TryConstructorInitialization(S, Entity, Kind, None, DestType,
+ TryConstructorInitialization(S, Entity, Kind, std::nullopt, DestType,
Entity.getType(), Sequence);
return;
}
@@ -5250,6 +5270,208 @@ static void TryDefaultInitialization(Sema &S,
}
}
+static void TryOrBuildParenListInitialization(
+ Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
+ ArrayRef<Expr *> Args, InitializationSequence &Sequence, bool VerifyOnly,
+ ExprResult *Result = nullptr) {
+ unsigned ArgIndexToProcess = 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);
+
+ 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());
+ }
+ } 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 (Expr *ICE = FD->getInClassInitializer(); ICE && !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());
+ }
+ }
+ }
+ return true;
+ };
+
+ if (const ArrayType *AT =
+ S.getASTContext().getAsArrayType(Entity.getType())) {
+
+ SmallVector<InitializedEntity, 4> ElementEntities;
+ uint64_t ArrayLength;
+ // 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. If
+ // the destination type is an array of unknown bound, it is define as
+ // having k elements.
+ if (const ConstantArrayType *CAT =
+ S.getASTContext().getAsConstantArrayType(Entity.getType()))
+ ArrayLength = CAT->getSize().getZExtValue();
+ else
+ ArrayLength = Args.size();
+
+ if (ArrayLength >= Args.size()) {
+ for (uint64_t I = 0; I < ArrayLength; ++I)
+ ElementEntities.push_back(
+ InitializedEntity::InitializeElement(S.getASTContext(), I, Entity));
+
+ if (!ProcessEntities(ElementEntities))
+ return;
+
+ ResultType = S.Context.getConstantArrayType(
+ AT->getElementType(), llvm::APInt(/*numBits=*/32, ArrayLength),
+ nullptr, ArrayType::Normal, 0);
+ }
+ } else if (auto *RT = Entity.getType()->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ auto BaseRange = map_range(RD->bases(), [&S](auto &base) {
+ return InitializedEntity::InitializeBase(S.getASTContext(), &base, false);
+ });
+ auto FieldRange = map_range(RD->fields(), [](auto *field) {
+ return InitializedEntity::InitializeMember(field);
+ });
+
+ if (!ProcessEntities(BaseRange))
+ return;
+
+ if (!ProcessEntities(FieldRange))
+ return;
+
+ 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()) {
+ 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(),
+ Args.back()->getEndLoc());
+ S.Diag(Kind.getLocation(), diag::err_excess_initializers)
+ << InitKind << ExcessInitSR;
+ }
+ return;
+ }
+
+ if (VerifyOnly) {
+ Sequence.setSequenceKind(InitializationSequence::NormalSequence);
+ Sequence.AddParenthesizedListInitStep(Entity.getType());
+ } else if (Result) {
+ SourceRange SR = Kind.getParenOrBraceRange();
+ auto *CPLIE = CXXParenListInitExpr::Create(
+ S.getASTContext(), InitExprs, ResultType, Args.size(),
+ Kind.getLocation(), SR.getBegin(), SR.getEnd());
+ if (ArrayFiller)
+ CPLIE->setArrayFiller(ArrayFiller);
+ if (InitializedFieldInUnion)
+ CPLIE->setInitializedFieldInUnion(InitializedFieldInUnion);
+ *Result = CPLIE;
+ S.Diag(Kind.getLocation(),
+ diag::warn_cxx17_compat_aggregate_init_paren_list)
+ << Kind.getLocation() << SR << ResultType;
+ }
+
+ return;
+}
+
/// Attempt a user-defined conversion between two types (C++ [dcl.init]),
/// which enumerates all conversion functions and performs overload resolution
/// to select the best.
@@ -5905,7 +6127,11 @@ void InitializationSequence::InitializeFrom(Sema &S,
TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer),
*this, TreatUnavailableAsInvalid);
AddParenthesizedArrayInitStep(DestType);
- } else if (DestAT->getElementType()->isCharType())
+ } else if (S.getLangOpts().CPlusPlus20 && !TopLevelOfInitList &&
+ Kind.getKind() == InitializationKind::IK_Direct)
+ TryOrBuildParenListInitialization(S, Entity, Kind, Args, *this,
+ /*VerifyOnly=*/true);
+ else if (DestAT->getElementType()->isCharType())
SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
else if (IsWideCharCompatible(DestAT->getElementType(), Context))
SetFailed(FK_ArrayNeedsInitListOrWideStringLiteral);
@@ -5952,18 +6178,53 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Direct ||
(Kind.getKind() == InitializationKind::IK_Copy &&
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
- S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType, DestType))))
- TryConstructorInitialization(S, Entity, Kind, Args,
- DestType, DestType, *this);
- // - Otherwise (i.e., for the remaining copy-initialization cases),
- // user-defined conversion sequences that can convert from the source
- // type to the destination type or (when a conversion function is
- // used) to a derived class thereof are enumerated as described in
- // 13.3.1.4, and the best one is chosen through overload resolution
- // (13.3).
- else
+ S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType, DestType)))) {
+ TryConstructorInitialization(S, Entity, Kind, Args, DestType, DestType,
+ *this);
+
+ // We fall back to the "no matching constructor" path if the
+ // failed candidate set has functions other than the three default
+ // constructors. For example, conversion function.
+ if (const auto *RD =
+ dyn_cast<CXXRecordDecl>(DestType->getAs<RecordType>()->getDecl());
+ // In general, we should call isCompleteType for RD to check its
+ // completeness, we don't call it here as it was already called in the
+ // above TryConstructorInitialization.
+ S.getLangOpts().CPlusPlus20 && RD && RD->hasDefinition() &&
+ RD->isAggregate() && Failed() &&
+ getFailureKind() == FK_ConstructorOverloadFailed) {
+ // Do not attempt paren list initialization if overload resolution
+ // resolves to a deleted function .
+ //
+ // We may reach this condition if we have a union wrapping a class with
+ // a non-trivial copy or move constructor and we call one of those two
+ // constructors. The union is an aggregate, but the matched constructor
+ // is implicitly deleted, so we need to prevent aggregate initialization
+ // (otherwise, it'll attempt aggregate initialization by initializing
+ // the first element with a reference to the union).
+ OverloadCandidateSet::iterator Best;
+ OverloadingResult OR = getFailedCandidateSet().BestViableFunction(
+ S, Kind.getLocation(), Best);
+ if (OR != OverloadingResult::OR_Deleted) {
+ // C++20 [dcl.init] 17.6.2.2:
+ // - Otherwise, if no constructor is viable, the destination type is
+ // an
+ // aggregate class, and the initializer is a parenthesized
+ // expression-list.
+ TryOrBuildParenListInitialization(S, Entity, Kind, Args, *this,
+ /*VerifyOnly=*/true);
+ }
+ }
+ } else {
+ // - Otherwise (i.e., for the remaining copy-initialization cases),
+ // user-defined conversion sequences that can convert from the
+ // source type to the destination type or (when a conversion
+ // function is used) to a derived class thereof are enumerated as
+ // described in 13.3.1.4, and the best one is chosen through
+ // overload resolution (13.3).
TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,
TopLevelOfInitList);
+ }
return;
}
@@ -5977,7 +6238,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
!Context.hasSameUnqualifiedType(SourceType, DestType))) {
llvm::SmallVector<Expr *> InitArgs;
- for (auto Arg : Args) {
+ for (auto *Arg : Args) {
if (Arg->getType()->isExtVectorType()) {
const auto *VTy = Arg->getType()->castAs<ExtVectorType>();
unsigned Elm = VTy->getNumElements();
@@ -7085,11 +7346,11 @@ static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
if (auto *CE = dyn_cast<CallExpr>(Call)) {
Callee = CE->getDirectCallee();
- Args = llvm::makeArrayRef(CE->getArgs(), CE->getNumArgs());
+ Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
} else {
auto *CCE = cast<CXXConstructExpr>(Call);
Callee = CCE->getConstructor();
- Args = llvm::makeArrayRef(CCE->getArgs(), CCE->getNumArgs());
+ Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
}
if (!Callee)
return;
@@ -7572,7 +7833,7 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
case IndirectLocalPathEntry::VarInit:
if (cast<VarDecl>(Path[I].D)->isImplicit())
return SourceRange();
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case IndirectLocalPathEntry::DefaultInit:
return Path[I].E->getSourceRange();
@@ -7586,15 +7847,15 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
}
static bool pathOnlyInitializesGslPointer(IndirectLocalPath &Path) {
- for (auto It = Path.rbegin(), End = Path.rend(); It != End; ++It) {
- if (It->Kind == IndirectLocalPathEntry::VarInit)
+ for (const auto &It : llvm::reverse(Path)) {
+ if (It.Kind == IndirectLocalPathEntry::VarInit)
continue;
- if (It->Kind == IndirectLocalPathEntry::AddressOf)
+ if (It.Kind == IndirectLocalPathEntry::AddressOf)
continue;
- if (It->Kind == IndirectLocalPathEntry::LifetimeBoundCall)
+ if (It.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
continue;
- return It->Kind == IndirectLocalPathEntry::GslPointerInit ||
- It->Kind == IndirectLocalPathEntry::GslReferenceInit;
+ return It.Kind == IndirectLocalPathEntry::GslPointerInit ||
+ It.Kind == IndirectLocalPathEntry::GslReferenceInit;
}
return false;
}
@@ -7846,7 +8107,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
break;
// FIXME: We can't easily tell apart an init-capture from a nested
// capture of an init-capture.
- const VarDecl *VD = Elem.Capture->getCapturedVar();
+ const ValueDecl *VD = Elem.Capture->getCapturedVar();
Diag(Elem.Capture->getLocation(), diag::note_lambda_capture_initializer)
<< VD << VD->isInitCapture() << Elem.Capture->isExplicit()
<< (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
@@ -8053,19 +8314,29 @@ ExprResult InitializationSequence::Perform(Sema &S,
return ExprError();
}
if (!ZeroInitializationFixit.empty()) {
- unsigned DiagID = diag::err_default_init_const;
- if (Decl *D = Entity.getDecl())
- if (S.getLangOpts().MSVCCompat && D->hasAttr<SelectAnyAttr>())
- DiagID = diag::ext_default_init_const;
+ const Decl *D = Entity.getDecl();
+ const auto *VD = dyn_cast_or_null<VarDecl>(D);
+ QualType DestType = Entity.getType();
// The initialization would have succeeded with this fixit. Since the fixit
// is on the error, we need to build a valid AST in this case, so this isn't
// handled in the Failed() branch above.
- QualType DestType = Entity.getType();
- S.Diag(Kind.getLocation(), DiagID)
- << DestType << (bool)DestType->getAs<RecordType>()
- << FixItHint::CreateInsertion(ZeroInitializationFixitLoc,
- ZeroInitializationFixit);
+ if (!DestType->isRecordType() && VD && VD->isConstexpr()) {
+ // Use a more useful diagnostic for constexpr variables.
+ S.Diag(Kind.getLocation(), diag::err_constexpr_var_requires_const_init)
+ << VD
+ << FixItHint::CreateInsertion(ZeroInitializationFixitLoc,
+ ZeroInitializationFixit);
+ } else {
+ unsigned DiagID = diag::err_default_init_const;
+ if (S.getLangOpts().MSVCCompat && D && D->hasAttr<SelectAnyAttr>())
+ DiagID = diag::ext_default_init_const;
+
+ S.Diag(Kind.getLocation(), DiagID)
+ << DestType << (bool)DestType->getAs<RecordType>()
+ << FixItHint::CreateInsertion(ZeroInitializationFixitLoc,
+ ZeroInitializationFixit);
+ }
}
if (getKind() == DependentSequence) {
@@ -8213,6 +8484,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
case SK_ConstructorInitializationFromList:
case SK_StdInitializerListConstructorCall:
case SK_ZeroInitialization:
+ case SK_ParenthesizedListInit:
break;
}
@@ -8739,7 +9011,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
<< Step->Type << CurInit.get()->getType()
<< CurInit.get()->getSourceRange();
updateGNUCompoundLiteralRValue(CurInit.get());
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case SK_ArrayInit:
// If the destination type is an incomplete array type, update the
// type accordingly.
@@ -8902,6 +9174,14 @@ ExprResult InitializationSequence::Perform(Sema &S,
CurInit.get()->getValueKind());
break;
}
+ case SK_ParenthesizedListInit: {
+ CurInit = nullptr;
+ TryOrBuildParenListInitialization(S, Entity, Kind, Args, *this,
+ /*VerifyOnly=*/false, &CurInit);
+ if (CurInit.get() && ResultType)
+ *ResultType = CurInit.get()->getType();
+ break;
+ }
}
}
@@ -9104,9 +9384,8 @@ bool InitializationSequence::Diagnose(Sema &S,
<< FixItHint::CreateInsertion(Args.front()->getBeginLoc(), "u8");
break;
case FK_UTF8StringIntoPlainChar:
- S.Diag(Kind.getLocation(),
- diag::err_array_init_utf8_string_into_char)
- << S.getLangOpts().CPlusPlus20;
+ S.Diag(Kind.getLocation(), diag::err_array_init_utf8_string_into_char)
+ << DestType->isSignedIntegerType() << S.getLangOpts().CPlusPlus20;
break;
case FK_ArrayTypeMismatch:
case FK_NonConstantArrayInit:
@@ -9201,7 +9480,7 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
break;
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case FK_NonConstLValueReferenceBindingToUnrelated:
S.Diag(Kind.getLocation(),
@@ -9464,6 +9743,10 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Entity.getName();
S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
<< Entity.getName();
+ } else if (const auto *VD = dyn_cast_if_present<VarDecl>(Entity.getDecl());
+ VD && VD->isConstexpr()) {
+ S.Diag(Kind.getLocation(), diag::err_constexpr_var_requires_const_init)
+ << VD;
} else {
S.Diag(Kind.getLocation(), diag::err_default_init_const)
<< DestType << (bool)DestType->getAs<RecordType>();
@@ -9500,6 +9783,11 @@ bool InitializationSequence::Diagnose(Sema &S,
diag::note_explicit_ctor_deduction_guide_here) << false;
break;
}
+
+ case FK_ParenthesizedListInitFailed:
+ TryOrBuildParenListInitialization(S, Entity, Kind, Args, *this,
+ /*VerifyOnly=*/false);
+ break;
}
PrintInitLocationNote(S, Entity);
@@ -9666,6 +9954,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
case FK_ExplicitConstructor:
OS << "list copy initialization chose explicit constructor";
break;
+
+ case FK_ParenthesizedListInitFailed:
+ OS << "parenthesized list initialization failed";
+ break;
}
OS << '\n';
return;
@@ -9837,6 +10129,9 @@ void InitializationSequence::dump(raw_ostream &OS) const {
case SK_OCLZeroOpaqueType:
OS << "OpenCL opaque type from zero";
break;
+ case SK_ParenthesizedListInit:
+ OS << "initialization from a parenthesized list of values";
+ break;
}
OS << " [" << S->Type << ']';
@@ -9868,6 +10163,7 @@ static void DiagnoseNarrowingInInitList(Sema &S,
SCS = &ICS.UserDefined.After;
break;
case ImplicitConversionSequence::AmbiguousConversion:
+ case ImplicitConversionSequence::StaticObjectArgumentConversion:
case ImplicitConversionSequence::EllipsisConversion:
case ImplicitConversionSequence::BadConversion:
return;