diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp | 571 |
1 files changed, 370 insertions, 201 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index c3a89463dc69..060ee3eef212 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <map> + using namespace clang; //===----------------------------------------------------------------------===// @@ -204,6 +205,8 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, // Semantic checking for initializer lists. //===----------------------------------------------------------------------===// +namespace { + /// @brief Semantic checking for initializer lists. /// /// The InitListChecker class contains a set of routines that each @@ -231,11 +234,11 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, /// point. CheckDesignatedInitializer() recursively steps into the /// designated subobject and manages backing out the recursion to /// initialize the subobjects after the one designated. -namespace { class InitListChecker { Sema &SemaRef; bool hadError; bool VerifyOnly; // no diagnostics, no structure building + bool TreatUnavailableAsInvalid; // Used only in VerifyOnly mode. llvm::DenseMap<InitListExpr *, InitListExpr *> SyntacticToSemantic; InitListExpr *FullyStructuredList; @@ -280,6 +283,7 @@ class InitListChecker { unsigned &StructuredIndex); void CheckStructUnionTypes(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, + CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, @@ -317,7 +321,8 @@ class InitListChecker { static ExprResult PerformEmptyInit(Sema &SemaRef, SourceLocation Loc, const InitializedEntity &Entity, - bool VerifyOnly); + bool VerifyOnly, + bool TreatUnavailableAsInvalid); // Explanation on the "FillWithNoInit" mode: // @@ -338,6 +343,10 @@ class InitListChecker { // in the InitListExpr, the "holes" in Case#1 are filled not with empty // initializers but with special "NoInitExpr" place holders, which tells the // CodeGen not to generate any initializers for these parts. + void FillInEmptyInitForBase(unsigned Init, const CXXBaseSpecifier &Base, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, bool &RequiresSecondPass, + bool FillWithNoInit); void FillInEmptyInitForField(unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity, InitListExpr *ILE, bool &RequiresSecondPass, @@ -353,19 +362,22 @@ class InitListChecker { public: InitListChecker(Sema &S, const InitializedEntity &Entity, - InitListExpr *IL, QualType &T, bool VerifyOnly); + InitListExpr *IL, QualType &T, bool VerifyOnly, + bool TreatUnavailableAsInvalid); bool HadError() { return hadError; } // @brief Retrieves the fully-structured initializer list used for // semantic analysis and code generation. InitListExpr *getFullyStructuredList() const { return FullyStructuredList; } }; + } // end anonymous namespace ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef, SourceLocation Loc, const InitializedEntity &Entity, - bool VerifyOnly) { + bool VerifyOnly, + bool TreatUnavailableAsInvalid) { InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, true); MultiExprArg SubInit; @@ -419,8 +431,6 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef, if (CtorDecl->getMinRequiredArguments() == 0 && CtorDecl->isExplicit() && R->getDeclName() && SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) { - - bool IsInStd = false; for (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(R->getDeclContext()); ND && !IsInStd; ND = dyn_cast<NamespaceDecl>(ND->getParent())) { @@ -437,7 +447,8 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef, InitSeq.InitializeFrom( SemaRef, Entity, InitializationKind::CreateValue(Loc, Loc, Loc, true), - MultiExprArg(), /*TopLevelOfInitList=*/false); + MultiExprArg(), /*TopLevelOfInitList=*/false, + TreatUnavailableAsInvalid); // Emit a warning for this. System header warnings aren't shown // by default, but people working on system headers should see it. if (!VerifyOnly) { @@ -474,10 +485,43 @@ void InitListChecker::CheckEmptyInitializable(const InitializedEntity &Entity, SourceLocation Loc) { assert(VerifyOnly && "CheckEmptyInitializable is only inteded for verification mode."); - if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true).isInvalid()) + if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true, + TreatUnavailableAsInvalid).isInvalid()) hadError = true; } +void InitListChecker::FillInEmptyInitForBase( + unsigned Init, const CXXBaseSpecifier &Base, + const InitializedEntity &ParentEntity, InitListExpr *ILE, + bool &RequiresSecondPass, bool FillWithNoInit) { + assert(Init < ILE->getNumInits() && "should have been expanded"); + + InitializedEntity BaseEntity = InitializedEntity::InitializeBase( + SemaRef.Context, &Base, false, &ParentEntity); + + if (!ILE->getInit(Init)) { + ExprResult BaseInit = + FillWithNoInit ? new (SemaRef.Context) NoInitExpr(Base.getType()) + : PerformEmptyInit(SemaRef, ILE->getLocEnd(), BaseEntity, + /*VerifyOnly*/ false, + TreatUnavailableAsInvalid); + if (BaseInit.isInvalid()) { + hadError = true; + return; + } + + ILE->setInit(Init, BaseInit.getAs<Expr>()); + } else if (InitListExpr *InnerILE = + dyn_cast<InitListExpr>(ILE->getInit(Init))) { + FillInEmptyInitializations(BaseEntity, InnerILE, + RequiresSecondPass, FillWithNoInit); + } else if (DesignatedInitUpdateExpr *InnerDIUE = + dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init))) { + FillInEmptyInitializations(BaseEntity, InnerDIUE->getUpdater(), + RequiresSecondPass, /*FillWithNoInit =*/true); + } +} + void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, const InitializedEntity &ParentEntity, InitListExpr *ILE, @@ -535,7 +579,8 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, } ExprResult MemberInit = PerformEmptyInit(SemaRef, Loc, MemberEntity, - /*VerifyOnly*/false); + /*VerifyOnly*/false, + TreatUnavailableAsInvalid); if (MemberInit.isInvalid()) { hadError = true; return; @@ -592,14 +637,25 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, // The fields beyond ILE->getNumInits() are default initialized, so in // order to leave them uninitialized, the ILE is expanded and the extra // fields are then filled with NoInitExpr. - unsigned NumFields = 0; - for (auto *Field : RDecl->fields()) - if (!Field->isUnnamedBitfield()) - ++NumFields; - if (ILE->getNumInits() < NumFields) - ILE->resizeInits(SemaRef.Context, NumFields); + unsigned NumElems = numStructUnionElements(ILE->getType()); + if (RDecl->hasFlexibleArrayMember()) + ++NumElems; + if (ILE->getNumInits() < NumElems) + ILE->resizeInits(SemaRef.Context, NumElems); unsigned Init = 0; + + if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RDecl)) { + for (auto &Base : CXXRD->bases()) { + if (hadError) + return; + + FillInEmptyInitForBase(Init, Base, Entity, ILE, RequiresSecondPass, + FillWithNoInit); + ++Init; + } + } + for (auto *Field : RDecl->fields()) { if (Field->isUnnamedBitfield()) continue; @@ -661,7 +717,8 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, else { ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(), ElementEntity, - /*VerifyOnly*/false); + /*VerifyOnly*/false, + TreatUnavailableAsInvalid); if (ElementInit.isInvalid()) { hadError = true; return; @@ -707,11 +764,12 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, } } - InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, - bool VerifyOnly) - : SemaRef(S), VerifyOnly(VerifyOnly) { + bool VerifyOnly, + bool TreatUnavailableAsInvalid) + : SemaRef(S), VerifyOnly(VerifyOnly), + TreatUnavailableAsInvalid(TreatUnavailableAsInvalid) { // FIXME: Check that IL isn't already the semantic form of some other // InitListExpr. If it is, we'd create a broken AST. @@ -744,6 +802,8 @@ int InitListChecker::numArrayElements(QualType DeclType) { int InitListChecker::numStructUnionElements(QualType DeclType) { RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl(); int InitializableMembers = 0; + if (auto *CXXRD = dyn_cast<CXXRecordDecl>(structDecl)) + InitializableMembers += CXXRD->getNumBases(); for (const auto *Field : structDecl->fields()) if (!Field->isUnnamedBitfield()) ++InitializableMembers; @@ -888,7 +948,6 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity, } } - /// Check whether the initializer \p IList (that was written with explicit /// braces) can be used to initialize an object of type \p T. /// @@ -992,10 +1051,14 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, assert(DeclType->isAggregateType() && "non-aggregate records should be handed in CheckSubElementType"); RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); - CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(), - SubobjectIsDesignatorContext, Index, - StructuredList, StructuredIndex, - TopLevelObject); + auto Bases = + CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(), + CXXRecordDecl::base_class_iterator()); + if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) + Bases = CXXRD->bases(); + CheckStructUnionTypes(Entity, IList, DeclType, Bases, RD->field_begin(), + SubobjectIsDesignatorContext, Index, StructuredList, + StructuredIndex, TopLevelObject); } else if (DeclType->isArrayType()) { llvm::APSInt Zero( SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()), @@ -1130,8 +1193,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // Fall through for subaggregate initialization. } else { - assert((ElemType->isRecordType() || ElemType->isVectorType()) && - "Unexpected type"); + assert((ElemType->isRecordType() || ElemType->isVectorType() || + ElemType->isClkEventT()) && "Unexpected type"); // C99 6.7.8p13: // @@ -1220,7 +1283,6 @@ void InitListChecker::CheckComplexType(const InitializedEntity &Entity, } } - void InitListChecker::CheckScalarType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, @@ -1672,16 +1734,13 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity, return FlexArrayDiag != diag::ext_flexible_array_init; } -void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, - InitListExpr *IList, - QualType DeclType, - RecordDecl::field_iterator Field, - bool SubobjectIsDesignatorContext, - unsigned &Index, - InitListExpr *StructuredList, - unsigned &StructuredIndex, - bool TopLevelObject) { - RecordDecl* structDecl = DeclType->getAs<RecordType>()->getDecl(); +void InitListChecker::CheckStructUnionTypes( + const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, + CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field, + bool SubobjectIsDesignatorContext, unsigned &Index, + InitListExpr *StructuredList, unsigned &StructuredIndex, + bool TopLevelObject) { + RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl(); // If the record is invalid, some of it's members are invalid. To avoid // confusion, we forgo checking the intializer for the entire record. @@ -1726,13 +1785,35 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, return; } + bool InitializedSomething = false; + + // If we have any base classes, they are initialized prior to the fields. + for (auto &Base : Bases) { + Expr *Init = Index < IList->getNumInits() ? IList->getInit(Index) : nullptr; + SourceLocation InitLoc = Init ? Init->getLocStart() : IList->getLocEnd(); + + // Designated inits always initialize fields, so if we see one, all + // remaining base classes have no explicit initializer. + if (Init && isa<DesignatedInitExpr>(Init)) + Init = nullptr; + + InitializedEntity BaseEntity = InitializedEntity::InitializeBase( + SemaRef.Context, &Base, false, &Entity); + if (Init) { + CheckSubElementType(BaseEntity, IList, Base.getType(), Index, + StructuredList, StructuredIndex); + InitializedSomething = true; + } else if (VerifyOnly) { + CheckEmptyInitializable(BaseEntity, InitLoc); + } + } + // If structDecl is a forward declaration, this loop won't do // anything except look at designated initializers; That's okay, // because an error should get printed out elsewhere. It might be // worthwhile to skip over the rest of the initializer, though. RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); RecordDecl::field_iterator FieldEnd = RD->field_end(); - bool InitializedSomething = false; bool CheckForMissingFields = true; while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); @@ -1782,7 +1863,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, // Make sure we can use this declaration. bool InvalidUse; if (VerifyOnly) - InvalidUse = !SemaRef.CanUseDecl(*Field); + InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid); else InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, IList->getInit(Index)->getLocStart()); @@ -1895,8 +1976,8 @@ static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef, SmallVector<Expr*, 4> IndexExprs(NumIndexExprs); for (unsigned I = 0; I < NumIndexExprs; ++I) IndexExprs[I] = DIE->getSubExpr(I + 1); - return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators_begin(), - DIE->size(), IndexExprs, + return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators(), + IndexExprs, DIE->getEqualOrColonLoc(), DIE->usesGNUSyntax(), DIE->getInit()); } @@ -1919,7 +2000,7 @@ class FieldInitializerValidatorCCC : public CorrectionCandidateCallback { RecordDecl *Record; }; -} +} // end anonymous namespace /// @brief Check the well-formedness of a C99 designated initializer. /// @@ -2146,8 +2227,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, for (auto *FI : RT->getDecl()->fields()) { if (FI->isUnnamedBitfield()) continue; - if (KnownField == FI) + if (declaresSameEntity(KnownField, FI)) { + KnownField = FI; break; + } ++FieldIndex; } @@ -2160,11 +2243,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, FieldIndex = 0; if (!VerifyOnly) { FieldDecl *CurrentField = StructuredList->getInitializedFieldInUnion(); - if (CurrentField && CurrentField != *Field) { + if (CurrentField && !declaresSameEntity(CurrentField, *Field)) { assert(StructuredList->getNumInits() == 1 && "A union should never have more than one initializer!"); - // we're about to throw away an initializer, emit warning + // We're about to throw away an initializer, emit warning. SemaRef.Diag(D->getFieldLoc(), diag::warn_initializer_overrides) << D->getSourceRange(); @@ -2186,7 +2269,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Make sure we can use this declaration. bool InvalidUse; if (VerifyOnly) - InvalidUse = !SemaRef.CanUseDecl(*Field); + InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid); else InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc()); if (InvalidUse) { @@ -2276,7 +2359,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1, FieldType, nullptr, nullptr, Index, StructuredList, newStructuredIndex, - true, false)) + FinishSubobjectInit, false)) return true; } @@ -2304,8 +2387,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Check the remaining fields within this class/struct/union subobject. bool prevHadError = hadError; - CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index, - StructuredList, FieldIndex); + auto NoBases = + CXXRecordDecl::base_class_range(CXXRecordDecl::base_class_iterator(), + CXXRecordDecl::base_class_iterator()); + CheckStructUnionTypes(Entity, IList, CurrentObjectType, NoBases, Field, + false, Index, StructuredList, FieldIndex); return hadError && !prevHadError; } @@ -2467,11 +2553,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, Index = OldIndex; ElementEntity.setElementIndex(ElementIndex); - if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1, - ElementType, nullptr, nullptr, Index, - StructuredList, ElementIndex, - (DesignatedStartIndex == DesignatedEndIndex), - false)) + if (CheckDesignatedInitializer( + ElementEntity, IList, DIE, DesigIdx + 1, ElementType, nullptr, + nullptr, Index, StructuredList, ElementIndex, + FinishSubobjectInit && (DesignatedStartIndex == DesignatedEndIndex), + false)) return true; // Move to the next index in the array that we'll be initializing. @@ -2751,7 +2837,7 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, DesignatedInitExpr *DIE = DesignatedInitExpr::Create(Context, - Designators.data(), Designators.size(), + Designators, InitExpressions, Loc, GNUSyntax, Init.getAs<Expr>()); @@ -2787,10 +2873,11 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, const CXXBaseSpecifier *Base, - bool IsInheritedVirtualBase) { + bool IsInheritedVirtualBase, + const InitializedEntity *Parent) { InitializedEntity Result; Result.Kind = EK_Base; - Result.Parent = nullptr; + Result.Parent = Parent; Result.Base = reinterpret_cast<uintptr_t>(Base); if (IsInheritedVirtualBase) Result.Base |= 0x01; @@ -2928,7 +3015,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { return Depth + 1; } -void InitializedEntity::dump() const { +LLVM_DUMP_METHOD void InitializedEntity::dump() const { dumpImpl(llvm::errs()); } @@ -3137,13 +3224,9 @@ void InitializationSequence::AddListInitializationStep(QualType T) { Steps.push_back(S); } -void -InitializationSequence -::AddConstructorInitializationStep(CXXConstructorDecl *Constructor, - AccessSpecifier Access, - QualType T, - bool HadMultipleCandidates, - bool FromInitList, bool AsInitList) { +void InitializationSequence::AddConstructorInitializationStep( + DeclAccessPair FoundDecl, CXXConstructorDecl *Constructor, QualType T, + bool HadMultipleCandidates, bool FromInitList, bool AsInitList) { Step S; S.Kind = FromInitList ? AsInitList ? SK_StdInitializerListConstructorCall : SK_ConstructorInitializationFromList @@ -3151,7 +3234,7 @@ InitializationSequence S.Type = T; S.Function.HadMultipleCandidates = HadMultipleCandidates; S.Function.Function = Constructor; - S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access); + S.Function.FoundDecl = FoundDecl; Steps.push_back(S); } @@ -3313,7 +3396,8 @@ static void TryListInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, - InitializationSequence &Sequence); + InitializationSequence &Sequence, + bool TreatUnavailableAsInvalid); /// \brief When initializing from init list via constructor, handle /// initialization of an object of type std::initializer_list<T>. @@ -3323,7 +3407,8 @@ static void TryListInitialization(Sema &S, static bool TryInitializerListConstruction(Sema &S, InitListExpr *List, QualType DestType, - InitializationSequence &Sequence) { + InitializationSequence &Sequence, + bool TreatUnavailableAsInvalid) { QualType E; if (!S.isStdInitializerList(DestType, &E)) return false; @@ -3342,7 +3427,8 @@ static bool TryInitializerListConstruction(Sema &S, InitializedEntity::InitializeTemporary(ArrayType); InitializationKind Kind = InitializationKind::CreateDirectList(List->getExprLoc()); - TryListInitialization(S, HiddenArray, Kind, List, Sequence); + TryListInitialization(S, HiddenArray, Kind, List, Sequence, + TreatUnavailableAsInvalid); if (Sequence) Sequence.AddStdInitializerListConstructionStep(DestType); return true; @@ -3359,18 +3445,13 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, CandidateSet.clear(); for (NamedDecl *D : Ctors) { - DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - bool SuppressUserConversions = false; + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = nullptr; - FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D); - if (ConstructorTmpl) - Constructor = cast<CXXConstructorDecl>( - ConstructorTmpl->getTemplatedDecl()); - else { - Constructor = cast<CXXConstructorDecl>(D); + bool SuppressUserConversions = false; + if (!Info.ConstructorTmpl) { // C++11 [over.best.ics]p4: // ... and the constructor or user-defined conversion function is a // candidate by @@ -3387,15 +3468,15 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, // parameter of a constructor of X. if ((CopyInitializing || (IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]))) && - Constructor->isCopyOrMoveConstructor()) + Info.Constructor->isCopyOrMoveConstructor()) SuppressUserConversions = true; } - if (!Constructor->isInvalidDecl() && - (AllowExplicit || !Constructor->isExplicit()) && - (!OnlyListConstructors || S.isInitListConstructor(Constructor))) { - if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + if (!Info.Constructor->isInvalidDecl() && + (AllowExplicit || !Info.Constructor->isExplicit()) && + (!OnlyListConstructors || S.isInitListConstructor(Info.Constructor))) { + if (Info.ConstructorTmpl) + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Args, CandidateSet, SuppressUserConversions); else { @@ -3407,9 +3488,9 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, // are also considered. bool AllowExplicitConv = AllowExplicit && !CopyInitializing && Args.size() == 1 && - Constructor->isCopyOrMoveConstructor(); - S.AddOverloadCandidate(Constructor, FoundDecl, Args, CandidateSet, - SuppressUserConversions, + Info.Constructor->isCopyOrMoveConstructor(); + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args, + CandidateSet, SuppressUserConversions, /*PartialOverloading=*/false, /*AllowExplicit=*/AllowExplicitConv); } @@ -3517,18 +3598,23 @@ static void TryConstructorInitialization(Sema &S, // If a program calls for the default initialization of an object // of a const-qualified type T, T shall be a class type with a // user-provided default constructor. + // C++ core issue 253 proposal: + // If the implicit default constructor initializes all subobjects, no + // initializer should be required. + // The 253 proposal is for example needed to process libstdc++ headers in 5.x. + CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function); if (Kind.getKind() == InitializationKind::IK_Default && - Entity.getType().isConstQualified() && - !cast<CXXConstructorDecl>(Best->Function)->isUserProvided()) { - if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) - Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); - return; + Entity.getType().isConstQualified()) { + if (!CtorDecl->getParent()->allowConstDefaultInit()) { + if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + return; + } } // C++11 [over.match.list]p1: // In copy-list-initialization, if an explicit constructor is chosen, the // initializer is ill-formed. - CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function); if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); return; @@ -3538,7 +3624,7 @@ static void TryConstructorInitialization(Sema &S, // subsumed by the initialization. bool HadMultipleCandidates = (CandidateSet.size() > 1); Sequence.AddConstructorInitializationStep( - CtorDecl, Best->FoundDecl.getAccess(), DestType, HadMultipleCandidates, + Best->FoundDecl, CtorDecl, DestType, HadMultipleCandidates, IsListInit | IsInitListCopy, AsInitializerList); } @@ -3591,7 +3677,8 @@ static void TryReferenceListInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, - InitializationSequence &Sequence) { + InitializationSequence &Sequence, + bool TreatUnavailableAsInvalid) { // First, catch C++03 where this isn't possible. if (!S.getLangOpts().CPlusPlus11) { Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); @@ -3647,7 +3734,8 @@ static void TryReferenceListInitialization(Sema &S, // Not reference-related. Create a temporary and bind to that. InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); - TryListInitialization(S, TempEntity, Kind, InitList, Sequence); + TryListInitialization(S, TempEntity, Kind, InitList, Sequence, + TreatUnavailableAsInvalid); if (Sequence) { if (DestType->isRValueReferenceType() || (T1Quals.hasConst() && !T1Quals.hasVolatile())) @@ -3663,7 +3751,8 @@ static void TryListInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, - InitializationSequence &Sequence) { + InitializationSequence &Sequence, + bool TreatUnavailableAsInvalid) { QualType DestType = Entity.getType(); // C++ doesn't allow scalar initialization with more than one argument. @@ -3674,7 +3763,8 @@ static void TryListInitialization(Sema &S, return; } if (DestType->isReferenceType()) { - TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence); + TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence, + TreatUnavailableAsInvalid); return; } @@ -3718,7 +3808,8 @@ static void TryListInitialization(Sema &S, InitList->getRBraceLoc()) : Kind; Sequence.InitializeFrom(S, Entity, SubKind, SubInit, - /*TopLevelOfInitList*/ true); + /*TopLevelOfInitList*/ true, + TreatUnavailableAsInvalid); // TryStringLiteralInitialization() (in InitializeFrom()) will fail if // the element is not an appropriately-typed string literal, in which @@ -3750,7 +3841,8 @@ static void TryListInitialization(Sema &S, // - Otherwise, if T is a specialization of std::initializer_list<E>, // an initializer_list object constructed [...] - if (TryInitializerListConstruction(S, InitList, DestType, Sequence)) + if (TryInitializerListConstruction(S, InitList, DestType, Sequence, + TreatUnavailableAsInvalid)) return; // - Otherwise, if T is a class type, constructors are considered. @@ -3763,8 +3855,48 @@ static void TryListInitialization(Sema &S, } if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() && - InitList->getNumInits() == 1 && - InitList->getInit(0)->getType()->isRecordType()) { + InitList->getNumInits() == 1) { + Expr *E = InitList->getInit(0); + + // - Otherwise, if T is an enumeration with a fixed underlying type, + // the initializer-list has a single element v, and the initialization + // is direct-list-initialization, the object is initialized with the + // value T(v); if a narrowing conversion is required to convert v to + // the underlying type of T, the program is ill-formed. + auto *ET = DestType->getAs<EnumType>(); + if (S.getLangOpts().CPlusPlus1z && + Kind.getKind() == InitializationKind::IK_DirectList && + ET && ET->getDecl()->isFixed() && + !S.Context.hasSameUnqualifiedType(E->getType(), DestType) && + (E->getType()->isIntegralOrEnumerationType() || + E->getType()->isFloatingType())) { + // There are two ways that T(v) can work when T is an enumeration type. + // If there is either an implicit conversion sequence from v to T or + // a conversion function that can convert from v to T, then we use that. + // Otherwise, if v is of integral, enumeration, or floating-point type, + // it is converted to the enumeration type via its underlying type. + // There is no overlap possible between these two cases (except when the + // source value is already of the destination type), and the first + // case is handled by the general case for single-element lists below. + ImplicitConversionSequence ICS; + ICS.setStandard(); + ICS.Standard.setAsIdentityConversion(); + // If E is of a floating-point type, then the conversion is ill-formed + // due to narrowing, but go through the motions in order to produce the + // right diagnostic. + ICS.Standard.Second = E->getType()->isFloatingType() + ? ICK_Floating_Integral + : ICK_Integral_Conversion; + ICS.Standard.setFromType(E->getType()); + ICS.Standard.setToType(0, E->getType()); + ICS.Standard.setToType(1, DestType); + ICS.Standard.setToType(2, DestType); + Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2), + /*TopLevelOfInitList*/true); + Sequence.RewrapReferenceInitList(Entity.getType(), InitList); + return; + } + // - Otherwise, if the initializer list has a single element of type E // [...references are handled above...], the object or reference is // initialized from that element (by copy-initialization for @@ -3778,22 +3910,25 @@ static void TryListInitialization(Sema &S, // copy-initialization. This only matters if we might use an 'explicit' // conversion operator, so we only need to handle the cases where the source // is of record type. - InitializationKind SubKind = - Kind.getKind() == InitializationKind::IK_DirectList - ? InitializationKind::CreateDirect(Kind.getLocation(), - InitList->getLBraceLoc(), - InitList->getRBraceLoc()) - : Kind; - Expr *SubInit[1] = { InitList->getInit(0) }; - Sequence.InitializeFrom(S, Entity, SubKind, SubInit, - /*TopLevelOfInitList*/true); - if (Sequence) - Sequence.RewrapReferenceInitList(Entity.getType(), InitList); - return; + if (InitList->getInit(0)->getType()->isRecordType()) { + InitializationKind SubKind = + Kind.getKind() == InitializationKind::IK_DirectList + ? InitializationKind::CreateDirect(Kind.getLocation(), + InitList->getLBraceLoc(), + InitList->getRBraceLoc()) + : Kind; + Expr *SubInit[1] = { InitList->getInit(0) }; + Sequence.InitializeFrom(S, Entity, SubKind, SubInit, + /*TopLevelOfInitList*/true, + TreatUnavailableAsInvalid); + if (Sequence) + Sequence.RewrapReferenceInitList(Entity.getType(), InitList); + return; + } } InitListChecker CheckInitList(S, Entity, InitList, - DestType, /*VerifyOnly=*/true); + DestType, /*VerifyOnly=*/true, TreatUnavailableAsInvalid); if (CheckInitList.HadError()) { Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed); return; @@ -3847,26 +3982,19 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl()); for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) { - DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = nullptr; - FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D); - if (ConstructorTmpl) - Constructor = cast<CXXConstructorDecl>( - ConstructorTmpl->getTemplatedDecl()); - else - Constructor = cast<CXXConstructorDecl>(D); + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - if (!Constructor->isInvalidDecl() && - Constructor->isConvertingConstructor(AllowExplicit)) { - if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + if (!Info.Constructor->isInvalidDecl() && + Info.Constructor->isConvertingConstructor(AllowExplicit)) { + if (Info.ConstructorTmpl) + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, /*SuppressUserConversions=*/true); else - S.AddOverloadCandidate(Constructor, FoundDecl, + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, /*SuppressUserConversions=*/true); } @@ -4068,7 +4196,6 @@ convertQualifiersAndValueKindIfNecessary(Sema &S, return Initializer->getValueKind(); } - /// \brief Reference initialization without resolving overloaded functions. static void TryReferenceInitializationCore(Sema &S, const InitializedEntity &Entity, @@ -4303,7 +4430,6 @@ static void TryReferenceInitializationCore(Sema &S, } Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); - return; } /// \brief Attempt character array initialization from a string literal @@ -4472,27 +4598,19 @@ static void TryUserDefinedConversion(Sema &S, Con = CopyOfCon.begin(), ConEnd = CopyOfCon.end(); Con != ConEnd; ++Con) { NamedDecl *D = *Con; - DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - - // Find the constructor (which may be a template). - CXXConstructorDecl *Constructor = nullptr; - FunctionTemplateDecl *ConstructorTmpl - = dyn_cast<FunctionTemplateDecl>(D); - if (ConstructorTmpl) - Constructor = cast<CXXConstructorDecl>( - ConstructorTmpl->getTemplatedDecl()); - else - Constructor = cast<CXXConstructorDecl>(D); + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - if (!Constructor->isInvalidDecl() && - Constructor->isConvertingConstructor(AllowExplicit)) { - if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + if (!Info.Constructor->isInvalidDecl() && + Info.Constructor->isConvertingConstructor(AllowExplicit)) { + if (Info.ConstructorTmpl) + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, /*ExplicitArgs*/ nullptr, Initializer, CandidateSet, /*SuppressUserConversions=*/true); else - S.AddOverloadCandidate(Constructor, FoundDecl, + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Initializer, CandidateSet, /*SuppressUserConversions=*/true); } @@ -4689,8 +4807,8 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { // If isWeakAccess to true, there will be an implicit // load which requires a cleanup. if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess) - S.ExprNeedsCleanups = true; - + S.Cleanup.setExprNeedsCleanups(true); + if (iik == IIK_okay) return; S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback) @@ -4800,9 +4918,11 @@ InitializationSequence::InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - bool TopLevelOfInitList) + bool TopLevelOfInitList, + bool TreatUnavailableAsInvalid) : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) { - InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList); + InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList, + TreatUnavailableAsInvalid); } /// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the @@ -4820,7 +4940,8 @@ void InitializationSequence::InitializeFrom(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - bool TopLevelOfInitList) { + bool TopLevelOfInitList, + bool TreatUnavailableAsInvalid) { ASTContext &Context = S.Context; // Eliminate non-overload placeholder types in the arguments. We @@ -4874,7 +4995,8 @@ void InitializationSequence::InitializeFrom(Sema &S, // object is list-initialized (8.5.4). if (Kind.getKind() != InitializationKind::IK_Direct) { if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) { - TryListInitialization(S, Entity, Kind, InitList, *this); + TryListInitialization(S, Entity, Kind, InitList, *this, + TreatUnavailableAsInvalid); return; } } @@ -4958,7 +5080,7 @@ void InitializationSequence::InitializeFrom(Sema &S, Entity.getKind() == InitializedEntity::EK_Member && Initializer && isa<InitListExpr>(Initializer)) { TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer), - *this); + *this, TreatUnavailableAsInvalid); AddParenthesizedArrayInitStep(DestType); } else if (DestAT->getElementType()->isCharType()) SetFailed(FK_ArrayNeedsInitListOrStringLiteral); @@ -5232,38 +5354,33 @@ static void LookupCopyAndMoveConstructors(Sema &S, for (SmallVectorImpl<NamedDecl *>::iterator CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) { NamedDecl *D = *CI; - CXXConstructorDecl *Constructor = nullptr; + auto Info = getConstructorInfo(D); + if (!Info.Constructor) + continue; - if ((Constructor = dyn_cast<CXXConstructorDecl>(D))) { - // Handle copy/moveconstructors, only. - if (!Constructor || Constructor->isInvalidDecl() || - !Constructor->isCopyOrMoveConstructor() || - !Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + if (!Info.ConstructorTmpl) { + // Handle copy/move constructors, only. + if (Info.Constructor->isInvalidDecl() || + !Info.Constructor->isCopyOrMoveConstructor() || + !Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) continue; - DeclAccessPair FoundDecl - = DeclAccessPair::make(Constructor, Constructor->getAccess()); - S.AddOverloadCandidate(Constructor, FoundDecl, + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, CurInitExpr, CandidateSet); continue; } // Handle constructor templates. - FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(D); - if (ConstructorTmpl->isInvalidDecl()) + if (Info.ConstructorTmpl->isInvalidDecl()) continue; - Constructor = cast<CXXConstructorDecl>( - ConstructorTmpl->getTemplatedDecl()); - if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + if (!Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) continue; // FIXME: Do we need to limit this to copy-constructor-like // candidates? - DeclAccessPair FoundDecl - = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess()); - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, nullptr, - CurInitExpr, CandidateSet, true); + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, + nullptr, CurInitExpr, CandidateSet, true); } } @@ -5402,8 +5519,8 @@ static ExprResult CopyObject(Sema &S, SmallVector<Expr*, 8> ConstructorArgs; CurInit.get(); // Ownership transferred into MultiExprArg, below. - S.CheckConstructorAccess(Loc, Constructor, Entity, - Best->FoundDecl.getAccess(), IsExtraneousCopy); + S.CheckConstructorAccess(Loc, Constructor, Best->FoundDecl, Entity, + IsExtraneousCopy); if (IsExtraneousCopy) { // If this is a totally extraneous copy for C++03 reference @@ -5438,7 +5555,8 @@ static ExprResult CopyObject(Sema &S, return ExprError(); // Actually perform the constructor call. - CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, + CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor, + Elidable, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, @@ -5485,7 +5603,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, switch (OR) { case OR_Success: S.CheckConstructorAccess(Loc, cast<CXXConstructorDecl>(Best->Function), - Entity, Best->FoundDecl.getAccess(), Diag); + Best->FoundDecl, Entity, Diag); // FIXME: Check default arguments as far as that's possible. break; @@ -5611,7 +5729,6 @@ PerformConstructorInitialization(Sema &S, if (isExplicitTemporary(Entity, Kind, NumArgs)) { // An explicitly-constructed temporary, e.g., X(1, 2). - S.MarkFunctionReferenced(Loc, Constructor); if (S.DiagnoseUseOfDecl(Constructor, Loc)) return ExprError(); @@ -5623,10 +5740,19 @@ PerformConstructorInitialization(Sema &S, ? SourceRange(LBraceLoc, RBraceLoc) : Kind.getParenRange(); + if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>( + Step.Function.FoundDecl.getDecl())) { + Constructor = S.findInheritingConstructor(Loc, Constructor, Shadow); + if (S.DiagnoseUseOfDecl(Constructor, Loc)) + return ExprError(); + } + S.MarkFunctionReferenced(Loc, Constructor); + CurInit = new (S.Context) CXXTemporaryObjectExpr( - S.Context, Constructor, TSInfo, ConstructorArgs, ParenOrBraceRange, - HadMultipleCandidates, IsListInitialization, - IsStdInitListInitialization, ConstructorInitRequiresZeroInit); + S.Context, Constructor, TSInfo, + ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates, + IsListInitialization, IsStdInitListInitialization, + ConstructorInitRequiresZeroInit); } else { CXXConstructExpr::ConstructionKind ConstructKind = CXXConstructExpr::CK_Complete; @@ -5651,6 +5777,7 @@ PerformConstructorInitialization(Sema &S, // unconditionally. if (Entity.allowsNRVO()) CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Step.Function.FoundDecl, Constructor, /*Elidable=*/true, ConstructorArgs, HadMultipleCandidates, @@ -5661,6 +5788,7 @@ PerformConstructorInitialization(Sema &S, ParenOrBraceRange); else CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Step.Function.FoundDecl, Constructor, ConstructorArgs, HadMultipleCandidates, @@ -5674,8 +5802,7 @@ PerformConstructorInitialization(Sema &S, return ExprError(); // Only check access if all of that succeeded. - S.CheckConstructorAccess(Loc, Constructor, Entity, - Step.Function.FoundDecl.getAccess()); + S.CheckConstructorAccess(Loc, Constructor, Step.Function.FoundDecl, Entity); if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc)) return ExprError(); @@ -5777,6 +5904,11 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension( FallbackDecl); case InitializedEntity::EK_Base: + // For subobjects, we look at the complete object. + if (Entity->getParent()) + return getEntityForTemporaryLifetimeExtension(Entity->getParent(), + Entity); + // Fall through. case InitializedEntity::EK_Delegating: // We can reach this case for aggregate initialization in a constructor: // struct A { int &&r; }; @@ -6042,6 +6174,36 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr, << FixItHint::CreateRemoval(SourceRange(RParen, RParen)); } +static void CheckForNullPointerDereference(Sema &S, const Expr *E) { + // Check to see if we are dereferencing a null pointer. If so, this is + // undefined behavior, so warn about it. This only handles the pattern + // "*null", which is a very syntactic check. + if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts())) + if (UO->getOpcode() == UO_Deref && + UO->getSubExpr()->IgnoreParenCasts()-> + isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) { + S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::warn_binding_null_to_reference) + << UO->getSubExpr()->getSourceRange()); + } +} + +MaterializeTemporaryExpr * +Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, + bool BoundToLvalueReference) { + auto MTE = new (Context) + MaterializeTemporaryExpr(T, Temporary, BoundToLvalueReference); + + // Order an ExprWithCleanups for lifetime marks. + // + // TODO: It'll be good to have a single place to check the access of the + // destructor and generate ExprWithCleanups for various uses. Currently these + // are done in both CreateMaterializeTemporaryExpr and MaybeBindToTemporary, + // but there may be a chance to merge them. + Cleanup.setExprNeedsCleanups(false); + return MTE; +} + ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -6294,6 +6456,7 @@ InitializationSequence::Perform(Sema &S, /*IsInitializerList=*/false, ExtendingEntity->getDecl()); + CheckForNullPointerDereference(S, CurInit.get()); break; case SK_BindReferenceToTemporary: { @@ -6305,7 +6468,7 @@ InitializationSequence::Perform(Sema &S, return ExprError(); // Materialize the temporary into memory. - MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr( + MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( Entity.getType().getNonReferenceType(), CurInit.get(), Entity.getType()->isLValueReferenceType()); @@ -6325,7 +6488,7 @@ InitializationSequence::Perform(Sema &S, MTE->getType()->isObjCLifetimeType()) || (MTE->getStorageDuration() == SD_Automatic && MTE->getType().isDestructedType())) - S.ExprNeedsCleanups = true; + S.Cleanup.setExprNeedsCleanups(true); CurInit = MTE; break; @@ -6360,7 +6523,8 @@ InitializationSequence::Perform(Sema &S, return ExprError(); // Build an expression that constructs a temporary. - CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, + CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, + FoundFn, Constructor, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, @@ -6371,8 +6535,8 @@ InitializationSequence::Perform(Sema &S, if (CurInit.isInvalid()) return ExprError(); - S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity, - FoundFn.getAccess()); + S.CheckConstructorAccess(Kind.getLocation(), Constructor, FoundFn, + Entity); if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation())) return ExprError(); @@ -6499,7 +6663,8 @@ InitializationSequence::Perform(Sema &S, InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty); InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity; InitListChecker PerformInitList(S, InitEntity, - InitList, Ty, /*VerifyOnly=*/false); + InitList, Ty, /*VerifyOnly=*/false, + /*TreatUnavailableAsInvalid=*/false); if (PerformInitList.HadError()) return ExprError(); @@ -6715,9 +6880,9 @@ InitializationSequence::Perform(Sema &S, << CurInit.get()->getSourceRange(); // Materialize the temporary into memory. - MaterializeTemporaryExpr *MTE = new (S.Context) - MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(), - /*BoundToLvalueReference=*/false); + MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( + CurInit.get()->getType(), CurInit.get(), + /*BoundToLvalueReference=*/false); // Maybe lifetime-extend the array temporary's subobjects to match the // entity's lifetime. @@ -6870,7 +7035,8 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity, } InitListChecker DiagnoseInitList(S, Entity, InitList, DestType, - /*VerifyOnly=*/false); + /*VerifyOnly=*/false, + /*TreatUnavailableAsInvalid=*/false); assert(DiagnoseInitList.HadError() && "Inconsistent init list check result."); } @@ -7132,17 +7298,20 @@ bool InitializationSequence::Diagnose(Sema &S, isa<CXXConstructorDecl>(S.CurContext)) { // This is implicit default initialization of a member or // base within a constructor. If no viable function was - // found, notify the user that she needs to explicitly + // found, notify the user that they need to explicitly // initialize this base/member. CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext); + const CXXRecordDecl *InheritedFrom = nullptr; + if (auto Inherited = Constructor->getInheritedConstructor()) + InheritedFrom = Inherited.getShadowDecl()->getNominatedBaseClass(); if (Entity.getKind() == InitializedEntity::EK_Base) { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) - << (Constructor->getInheritedConstructor() ? 2 : - Constructor->isImplicit() ? 1 : 0) + << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*base=*/0 - << Entity.getType(); + << Entity.getType() + << InheritedFrom; RecordDecl *BaseDecl = Entity.getBaseSpecifier()->getType()->getAs<RecordType>() @@ -7151,11 +7320,11 @@ bool InitializationSequence::Diagnose(Sema &S, << S.Context.getTagDeclType(BaseDecl); } else { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) - << (Constructor->getInheritedConstructor() ? 2 : - Constructor->isImplicit() ? 1 : 0) + << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*member=*/1 - << Entity.getName(); + << Entity.getName() + << InheritedFrom; S.Diag(Entity.getDecl()->getLocation(), diag::note_member_declared_at); |