diff options
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 104 |
1 files changed, 54 insertions, 50 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 2cf55985811..68f0cc38301 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -5311,25 +5311,25 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) { /// Determine the declaration which an initialized entity ultimately refers to, /// for the purpose of lifetime-extending a temporary bound to a reference in /// the initialization of \p Entity. -static const ValueDecl * -getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity, - const ValueDecl *FallbackDecl = 0) { +static const InitializedEntity *getEntityForTemporaryLifetimeExtension( + const InitializedEntity *Entity, + const InitializedEntity *FallbackDecl = 0) { // C++11 [class.temporary]p5: - switch (Entity.getKind()) { + switch (Entity->getKind()) { case InitializedEntity::EK_Variable: // The temporary [...] persists for the lifetime of the reference - return Entity.getDecl(); + return Entity; case InitializedEntity::EK_Member: // For subobjects, we look at the complete object. - if (Entity.getParent()) - return getDeclForTemporaryLifetimeExtension(*Entity.getParent(), - Entity.getDecl()); + if (Entity->getParent()) + return getEntityForTemporaryLifetimeExtension(Entity->getParent(), + Entity); // except: // -- A temporary bound to a reference member in a constructor's // ctor-initializer persists until the constructor exits. - return Entity.getDecl(); + return Entity; case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: @@ -5344,7 +5344,7 @@ getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity, // -- A temporary bound to a reference in a new-initializer persists // until the completion of the full-expression containing the // new-initializer. - return 0; + return nullptr; case InitializedEntity::EK_Temporary: case InitializedEntity::EK_CompoundLiteralInit: @@ -5352,12 +5352,12 @@ getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity, // We don't yet know the storage duration of the surrounding temporary. // Assume it's got full-expression duration for now, it will patch up our // storage duration if that's not correct. - return 0; + return nullptr; case InitializedEntity::EK_ArrayElement: // For subobjects, we look at the complete object. - return getDeclForTemporaryLifetimeExtension(*Entity.getParent(), - FallbackDecl); + return getEntityForTemporaryLifetimeExtension(Entity->getParent(), + FallbackDecl); case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: @@ -5372,17 +5372,20 @@ getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity, case InitializedEntity::EK_Exception: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: - return 0; + return nullptr; } llvm_unreachable("unknown entity kind"); } -static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD); +static void performLifetimeExtension(Expr *Init, + const InitializedEntity *ExtendingEntity); /// Update a glvalue expression that is used as the initializer of a reference /// to note that its lifetime is extended. /// \return \c true if any temporary had its lifetime extended. -static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) { +static bool +performReferenceExtension(Expr *Init, + const InitializedEntity *ExtendingEntity) { if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { if (ILE->getNumInits() == 1 && ILE->isGLValue()) { // This is just redundant braces around an initializer. Step over it. @@ -5416,8 +5419,9 @@ static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) { if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) { // Update the storage duration of the materialized temporary. // FIXME: Rebuild the expression instead of mutating it. - ME->setExtendingDecl(ExtendingD); - performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingD); + ME->setExtendingDecl(ExtendingEntity->getDecl(), + ExtendingEntity->allocateManglingNumber()); + performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity); return true; } @@ -5426,7 +5430,8 @@ static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) { /// Update a prvalue expression that is going to be materialized as a /// lifetime-extended temporary. -static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) { +static void performLifetimeExtension(Expr *Init, + const InitializedEntity *ExtendingEntity) { // Dig out the expression which constructs the extended temporary. SmallVector<const Expr *, 2> CommaLHSs; SmallVector<SubobjectAdjustment, 2> Adjustments; @@ -5438,14 +5443,14 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) { if (CXXStdInitializerListExpr *ILE = dyn_cast<CXXStdInitializerListExpr>(Init)) { - performReferenceExtension(ILE->getSubExpr(), ExtendingD); + performReferenceExtension(ILE->getSubExpr(), ExtendingEntity); return; } if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { if (ILE->getType()->isArrayType()) { for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I) - performLifetimeExtension(ILE->getInit(I), ExtendingD); + performLifetimeExtension(ILE->getInit(I), ExtendingEntity); return; } @@ -5457,7 +5462,7 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) { // bound to temporaries, those temporaries are also lifetime-extended. if (RD->isUnion() && ILE->getInitializedFieldInUnion() && ILE->getInitializedFieldInUnion()->getType()->isReferenceType()) - performReferenceExtension(ILE->getInit(0), ExtendingD); + performReferenceExtension(ILE->getInit(0), ExtendingEntity); else { unsigned Index = 0; for (const auto *I : RD->fields()) { @@ -5467,13 +5472,13 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) { continue; Expr *SubInit = ILE->getInit(Index); if (I->getType()->isReferenceType()) - performReferenceExtension(SubInit, ExtendingD); + performReferenceExtension(SubInit, ExtendingEntity); else if (isa<InitListExpr>(SubInit) || isa<CXXStdInitializerListExpr>(SubInit)) // This may be either aggregate-initialization of a member or // initialization of a std::initializer_list object. Either way, // we should recursively lifetime-extend that initializer. - performLifetimeExtension(SubInit, ExtendingD); + performLifetimeExtension(SubInit, ExtendingEntity); ++Index; } } @@ -5759,12 +5764,12 @@ InitializationSequence::Perform(Sema &S, // Even though we didn't materialize a temporary, the binding may still // extend the lifetime of a temporary. This happens if we bind a reference // to the result of a cast to reference type. - if (const ValueDecl *ExtendingDecl = - getDeclForTemporaryLifetimeExtension(Entity)) { - if (performReferenceExtension(CurInit.get(), ExtendingDecl)) - warnOnLifetimeExtension(S, Entity, CurInit.get(), false, - ExtendingDecl); - } + if (const InitializedEntity *ExtendingEntity = + getEntityForTemporaryLifetimeExtension(&Entity)) + if (performReferenceExtension(CurInit.get(), ExtendingEntity)) + warnOnLifetimeExtension(S, Entity, CurInit.get(), + /*IsInitializerList=*/false, + ExtendingEntity->getDecl()); break; @@ -5776,19 +5781,18 @@ InitializationSequence::Perform(Sema &S, if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) return ExprError(); - // Maybe lifetime-extend the temporary's subobjects to match the - // entity's lifetime. - const ValueDecl *ExtendingDecl = - getDeclForTemporaryLifetimeExtension(Entity); - if (ExtendingDecl) { - performLifetimeExtension(CurInit.get(), ExtendingDecl); - warnOnLifetimeExtension(S, Entity, CurInit.get(), false, ExtendingDecl); - } - // Materialize the temporary into memory. MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr( Entity.getType().getNonReferenceType(), CurInit.get(), - Entity.getType()->isLValueReferenceType(), ExtendingDecl); + Entity.getType()->isLValueReferenceType()); + + // Maybe lifetime-extend the temporary's subobjects to match the + // entity's lifetime. + if (const InitializedEntity *ExtendingEntity = + getEntityForTemporaryLifetimeExtension(&Entity)) + if (performReferenceExtension(MTE, ExtendingEntity)) + warnOnLifetimeExtension(S, Entity, CurInit.get(), /*IsInitializerList=*/false, + ExtendingEntity->getDecl()); // If we're binding to an Objective-C object that has lifetime, we // need cleanups. Likewise if we're extending this temporary to automatic @@ -6176,19 +6180,19 @@ InitializationSequence::Perform(Sema &S, diag::warn_cxx98_compat_initializer_list_init) << CurInit.get()->getSourceRange(); - // Maybe lifetime-extend the array temporary's subobjects to match the - // entity's lifetime. - const ValueDecl *ExtendingDecl = - getDeclForTemporaryLifetimeExtension(Entity); - if (ExtendingDecl) { - performLifetimeExtension(CurInit.get(), ExtendingDecl); - warnOnLifetimeExtension(S, Entity, CurInit.get(), true, ExtendingDecl); - } - // Materialize the temporary into memory. MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(), - /*lvalue reference*/ false, ExtendingDecl); + /*BoundToLvalueReference=*/false); + + // Maybe lifetime-extend the array temporary's subobjects to match the + // entity's lifetime. + if (const InitializedEntity *ExtendingEntity = + getEntityForTemporaryLifetimeExtension(&Entity)) + if (performReferenceExtension(MTE, ExtendingEntity)) + warnOnLifetimeExtension(S, Entity, CurInit.get(), + /*IsInitializerList=*/true, + ExtendingEntity->getDecl()); // Wrap it in a construction of a std::initializer_list<T>. CurInit = S.Owned( |