r337627 - Fold dangling-field warning into general initialization lifetime checks.
Ilya Biryukov via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 22 23:32:55 PDT 2018
Reverted in r337671
On Mon, Jul 23, 2018 at 8:24 AM Ilya Biryukov <ibiryukov at google.com> wrote:
> Hi Richard,
>
> this commit seems to cause invalid warning in the following example:
>
> struct foo {
> foo(char *x) : x_(&x[10]) {} //
> private:
> char *x_;
> };
>
> The warning itself:
> 1.cpp:2:21: warning: initializing pointer member 'x_' with the stack
> address of parameter 'x' [-Wdangling-field]
>
> I'll revert the change to unbreak our integrate.
>
>
> On Sat, Jul 21, 2018 at 12:31 AM Richard Smith via cfe-commits <
> cfe-commits at lists.llvm.org> wrote:
>
>> Author: rsmith
>> Date: Fri Jul 20 15:25:55 2018
>> New Revision: 337627
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=337627&view=rev
>> Log:
>> Fold dangling-field warning into general initialization lifetime checks.
>>
>> Modified:
>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>> cfe/trunk/lib/Sema/SemaInit.cpp
>> cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
>> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
>>
>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=337627&r1=337626&r2=337627&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jul 20
>> 15:25:55 2018
>> @@ -7870,11 +7870,11 @@ def note_ref_var_local_bind : Note<
>> // Check for initializing a member variable with the address or a
>> reference to
>> // a constructor parameter.
>> def warn_bind_ref_member_to_parameter : Warning<
>> - "binding reference member %0 to stack allocated parameter %1">,
>> - InGroup<DanglingField>;
>> + "binding reference member %0 to stack allocated "
>> + "%select{variable|parameter}2 %1">, InGroup<DanglingField>;
>> def warn_init_ptr_member_to_parameter_addr : Warning<
>> - "initializing pointer member %0 with the stack address of parameter
>> %1">,
>> - InGroup<DanglingField>;
>> + "initializing pointer member %0 with the stack address of "
>> + "%select{variable|parameter}2 %1">, InGroup<DanglingField>;
>> def note_ref_or_ptr_member_declared_here : Note<
>> "%select{reference|pointer}0 member declared here">;
>>
>>
>> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=337627&r1=337626&r2=337627&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jul 20 15:25:55 2018
>> @@ -3946,53 +3946,6 @@ Sema::BuildMemInitializer(Decl *Construc
>> return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl,
>> EllipsisLoc);
>> }
>>
>> -/// Checks a member initializer expression for cases where reference (or
>> -/// pointer) members are bound to by-value parameters (or their
>> addresses).
>> -static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl
>> *Member,
>> - Expr *Init,
>> - SourceLocation IdLoc) {
>> - QualType MemberTy = Member->getType();
>> -
>> - // We only handle pointers and references currently.
>> - // FIXME: Would this be relevant for ObjC object pointers? Or block
>> pointers?
>> - if (!MemberTy->isReferenceType() && !MemberTy->isPointerType())
>> - return;
>> -
>> - const bool IsPointer = MemberTy->isPointerType();
>> - if (IsPointer) {
>> - if (const UnaryOperator *Op
>> - = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) {
>> - // The only case we're worried about with pointers requires taking
>> the
>> - // address.
>> - if (Op->getOpcode() != UO_AddrOf)
>> - return;
>> -
>> - Init = Op->getSubExpr();
>> - } else {
>> - // We only handle address-of expression initializers for pointers.
>> - return;
>> - }
>> - }
>> -
>> - if (const DeclRefExpr *DRE =
>> dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
>> - // We only warn when referring to a non-reference parameter
>> declaration.
>> - const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl());
>> - if (!Parameter || Parameter->getType()->isReferenceType())
>> - return;
>> -
>> - S.Diag(Init->getExprLoc(),
>> - IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
>> - : diag::warn_bind_ref_member_to_parameter)
>> - << Member << Parameter << Init->getSourceRange();
>> - } else {
>> - // Other initializers are fine.
>> - return;
>> - }
>> -
>> - S.Diag(Member->getLocation(),
>> diag::note_ref_or_ptr_member_declared_here)
>> - << (unsigned)IsPointer;
>> -}
>> -
>> MemInitResult
>> Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
>> SourceLocation IdLoc) {
>> @@ -4047,8 +4000,6 @@ Sema::BuildMemberInitializer(ValueDecl *
>> if (MemberInit.isInvalid())
>> return true;
>>
>> - CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(),
>> IdLoc);
>> -
>> // C++11 [class.base.init]p7:
>> // The initialization of each base and member constitutes a
>> // full-expression.
>>
>> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=337627&r1=337626&r2=337627&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Jul 20 15:25:55 2018
>> @@ -6227,7 +6227,7 @@ using LifetimeResult =
>> /// 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 LifetimeResult getEntityForTemporaryLifetimeExtension(
>> +static LifetimeResult getEntityLifetime(
>> const InitializedEntity *Entity,
>> const InitializedEntity *InitField = nullptr) {
>> // C++11 [class.temporary]p5:
>> @@ -6239,8 +6239,7 @@ static LifetimeResult getEntityForTempor
>> case InitializedEntity::EK_Member:
>> // For subobjects, we look at the complete object.
>> if (Entity->getParent())
>> - return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
>> - Entity);
>> + return getEntityLifetime(Entity->getParent(), Entity);
>>
>> // except:
>> // C++17 [class.base.init]p8:
>> @@ -6291,14 +6290,12 @@ static LifetimeResult getEntityForTempor
>>
>> case InitializedEntity::EK_ArrayElement:
>> // For subobjects, we look at the complete object.
>> - return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
>> - InitField);
>> + return getEntityLifetime(Entity->getParent(), InitField);
>>
>> case InitializedEntity::EK_Base:
>> // For subobjects, we look at the complete object.
>> if (Entity->getParent())
>> - return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
>> - InitField);
>> + return getEntityLifetime(Entity->getParent(), InitField);
>> return {InitField, LK_MemInitializer};
>>
>> case InitializedEntity::EK_Delegating:
>> @@ -6311,46 +6308,61 @@ static LifetimeResult getEntityForTempor
>> case InitializedEntity::EK_BlockElement:
>> case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
>> case InitializedEntity::EK_LambdaCapture:
>> - case InitializedEntity::EK_Exception:
>> case InitializedEntity::EK_VectorElement:
>> case InitializedEntity::EK_ComplexElement:
>> return {nullptr, LK_FullExpression};
>> +
>> + case InitializedEntity::EK_Exception:
>> + // FIXME: Can we diagnose lifetime problems with exceptions?
>> + return {nullptr, LK_FullExpression};
>> }
>> llvm_unreachable("unknown entity kind");
>> }
>>
>> namespace {
>> -enum ExtensionKind {
>> +enum ReferenceKind {
>> /// Lifetime would be extended by a reference binding to a temporary.
>> - EK_ReferenceBinding,
>> + RK_ReferenceBinding,
>> /// Lifetime would be extended by a std::initializer_list object
>> binding to
>> /// its backing array.
>> - EK_StdInitializerList,
>> + RK_StdInitializerList,
>> };
>> -using IndirectTemporaryPathEntry =
>> - llvm::PointerUnion<CXXDefaultInitExpr *, ValueDecl *>;
>> -using IndirectTemporaryPath =
>> llvm::SmallVectorImpl<IndirectTemporaryPathEntry>;
>> +
>> +/// A temporary or local variable.
>> +using Local = llvm::PointerUnion<MaterializeTemporaryExpr*, ValueDecl*>;
>> +
>> +/// Expressions we stepped over when looking for the local state. Any
>> steps
>> +/// that would inhibit lifetime extension or take us out of
>> subexpressions of
>> +/// the initializer are included.
>> +struct IndirectLocalPathEntry {
>> + enum {
>> + DefaultInit,
>> + AddressOf,
>> + } Kind;
>> + Expr *E;
>> +};
>> +
>> +using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
>>
>> struct RevertToOldSizeRAII {
>> - IndirectTemporaryPath &Path;
>> + IndirectLocalPath &Path;
>> unsigned OldSize = Path.size();
>> - RevertToOldSizeRAII(IndirectTemporaryPath &Path) : Path(Path) {}
>> + RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
>> ~RevertToOldSizeRAII() { Path.resize(OldSize); }
>> };
>> }
>>
>> -template <typename TemporaryVisitor>
>> -static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath
>> &Path,
>> - Expr *Init,
>> - TemporaryVisitor
>> Visit);
>> -
>> -/// Visit the temporaries whose lifetimes would be extended by binding a
>> -/// reference to the glvalue expression \c Init.
>> -template <typename TemporaryVisitor>
>> -static void
>> -visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path,
>> - Expr *Init, ExtensionKind EK,
>> - TemporaryVisitor Visit) {
>> +template <typename LocalVisitor>
>> +static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
>> + Expr *Init, LocalVisitor
>> Visit,
>> + bool RevisitSubinits);
>> +
>> +/// Visit the locals that would be reachable through a reference bound
>> to the
>> +/// glvalue expression \c Init.
>> +template <typename LocalVisitor>
>> +static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath
>> &Path,
>> + Expr *Init,
>> ReferenceKind RK,
>> + LocalVisitor Visit) {
>> RevertToOldSizeRAII RAII(Path);
>>
>> // Walk past any constructs which we can lifetime-extend across.
>> @@ -6382,7 +6394,7 @@ visitTemporariesExtendedByReferenceBindi
>> // Step into CXXDefaultInitExprs so we can diagnose cases where a
>> // constructor inherits one as an implicit mem-initializer.
>> if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
>> - Path.push_back(DIE);
>> + Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE});
>> Init = DIE->getExpr();
>>
>> if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
>> @@ -6391,25 +6403,36 @@ visitTemporariesExtendedByReferenceBindi
>> } while (Init != Old);
>>
>> if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
>> - if (Visit(Path, MTE, EK))
>> - visitTemporariesExtendedByInitializer(Path,
>> MTE->GetTemporaryExpr(),
>> - Visit);
>> + if (Visit(Path, Local(MTE), RK))
>> + visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(),
>> Visit,
>> + true);
>> + }
>> +
>> + // If we find the name of a local non-reference parameter, we could
>> have a
>> + // lifetime problem.
>> + if (auto *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
>> + auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
>> + if (VD && VD->hasLocalStorage() &&
>> + !DRE->refersToEnclosingVariableOrCapture()) {
>> + // FIXME: Recurse to the initializer of a local reference.
>> + if (!VD->getType()->isReferenceType())
>> + Visit(Path, Local(VD), RK);
>> + }
>> }
>> }
>>
>> -/// Visit the temporaries whose lifetimes would be extended by
>> -/// lifetime-extending the object initialized by the prvalue expression
>> \c
>> -/// Init.
>> -template <typename TemporaryVisitor>
>> -static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath
>> &Path,
>> - Expr *Init,
>> - TemporaryVisitor
>> Visit) {
>> +/// Visit the locals that would be reachable through an object
>> initialized by
>> +/// the prvalue expression \c Init.
>> +template <typename LocalVisitor>
>> +static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
>> + Expr *Init, LocalVisitor
>> Visit,
>> + bool RevisitSubinits) {
>> RevertToOldSizeRAII RAII(Path);
>>
>> // Step into CXXDefaultInitExprs so we can diagnose cases where a
>> // constructor inherits one as an implicit mem-initializer.
>> if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) {
>> - Path.push_back(DIE);
>> + Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE});
>> Init = DIE->getExpr();
>>
>> if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
>> @@ -6426,17 +6449,24 @@ static void visitTemporariesExtendedByIn
>> // initializing an initializer_list object from the array extends the
>> // lifetime of the array exactly like binding a reference to a
>> temporary.
>> if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init))
>> - return visitTemporariesExtendedByReferenceBinding(
>> - Path, ILE->getSubExpr(), EK_StdInitializerList, Visit);
>> + return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(),
>> + RK_StdInitializerList,
>> Visit);
>>
>> if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
>> + // We already visited the elements of this initializer list while
>> + // performing the initialization. Don't visit them again unless we've
>> + // changed the lifetime of the initialized entity.
>> + if (!RevisitSubinits)
>> + return;
>> +
>> if (ILE->isTransparent())
>> - return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0),
>> - Visit);
>> + return visitLocalsRetainedByInitializer(Path, ILE->getInit(0),
>> Visit,
>> + RevisitSubinits);
>>
>> if (ILE->getType()->isArrayType()) {
>> for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
>> - visitTemporariesExtendedByInitializer(Path, ILE->getInit(I),
>> Visit);
>> + visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit,
>> + RevisitSubinits);
>> return;
>> }
>>
>> @@ -6448,8 +6478,8 @@ static void visitTemporariesExtendedByIn
>> // bound to temporaries, those temporaries are also
>> lifetime-extended.
>> if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
>>
>> ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
>> - visitTemporariesExtendedByReferenceBinding(Path, ILE->getInit(0),
>> - EK_ReferenceBinding,
>> Visit);
>> + visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0),
>> + RK_ReferenceBinding,
>> Visit);
>> else {
>> unsigned Index = 0;
>> for (const auto *I : RD->fields()) {
>> @@ -6459,25 +6489,38 @@ static void visitTemporariesExtendedByIn
>> continue;
>> Expr *SubInit = ILE->getInit(Index);
>> if (I->getType()->isReferenceType())
>> - visitTemporariesExtendedByReferenceBinding(
>> - Path, SubInit, EK_ReferenceBinding, Visit);
>> + visitLocalsRetainedByReferenceBinding(Path, SubInit,
>> + RK_ReferenceBinding,
>> Visit);
>> else
>> // This might be either aggregate-initialization of a member
>> or
>> // initialization of a std::initializer_list object.
>> Regardless,
>> // we should recursively lifetime-extend that initializer.
>> - visitTemporariesExtendedByInitializer(Path, SubInit, Visit);
>> + visitLocalsRetainedByInitializer(Path, SubInit, Visit,
>> + RevisitSubinits);
>> ++Index;
>> }
>> }
>> }
>> + return;
>> + }
>> +
>> + // If the initializer is the address of a local, we could have a
>> lifetime
>> + // problem.
>> + if (auto *Op = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) {
>> + if (Op->getOpcode() == UO_AddrOf) {
>> + Path.push_back({IndirectLocalPathEntry::AddressOf, Op});
>> + Init = Op->getSubExpr();
>> + return visitLocalsRetainedByReferenceBinding(Path, Init,
>> + RK_ReferenceBinding,
>> Visit);
>> + }
>> }
>> }
>>
>> /// Determine whether this is an indirect path to a temporary that we are
>> /// supposed to lifetime-extend along (but don't).
>> -static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath
>> &Path) {
>> +static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath
>> &Path) {
>> for (auto Elem : Path) {
>> - if (!Elem.is<CXXDefaultInitExpr*>())
>> + if (Elem.Kind != IndirectLocalPathEntry::DefaultInit)
>> return false;
>> }
>> return true;
>> @@ -6485,7 +6528,7 @@ static bool shouldLifetimeExtendThroughP
>>
>> void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
>> Expr *Init) {
>> - LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity);
>> + LifetimeResult LR = getEntityLifetime(&Entity);
>> LifetimeKind LK = LR.getInt();
>> const InitializedEntity *ExtendingEntity = LR.getPointer();
>>
>> @@ -6494,9 +6537,54 @@ void Sema::checkInitializerLifetime(cons
>> if (LK == LK_FullExpression)
>> return;
>>
>> - auto TemporaryVisitor = [&](IndirectTemporaryPath &Path,
>> - MaterializeTemporaryExpr *MTE,
>> - ExtensionKind EK) -> bool {
>> + auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
>> + ReferenceKind RK) -> bool {
>> + // If we found a path to a local variable or similar, check whether
>> the
>> + // initialized object will outlive it.
>> + if (auto *VD = L.dyn_cast<ValueDecl*>()) {
>> + switch (LK) {
>> + case LK_FullExpression:
>> + llvm_unreachable("already handled this");
>> +
>> + case LK_Extended:
>> + break;
>> +
>> + case LK_MemInitializer: {
>> + // Paths via a default initializer can only occur during error
>> recovery
>> + // (there's no other way that a default initializer can refer to
>> a
>> + // local). Don't produce a bogus warning on those cases.
>> + if (std::any_of(Path.begin(), Path.end(),
>> [](IndirectLocalPathEntry E) {
>> + return E.Kind == IndirectLocalPathEntry::DefaultInit;
>> + }))
>> + break;
>> +
>> + if (auto *Member =
>> + ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
>> + bool AddressTaken =
>> + !Path.empty() &&
>> + Path.back().Kind == IndirectLocalPathEntry::AddressOf;
>> + Diag(Init->getExprLoc(),
>> + AddressTaken ?
>> diag::warn_init_ptr_member_to_parameter_addr
>> + : diag::warn_bind_ref_member_to_parameter)
>> + << Member << VD << isa<ParmVarDecl>(VD) <<
>> Init->getSourceRange();
>> + Diag(Member->getLocation(),
>> + diag::note_ref_or_ptr_member_declared_here)
>> + << (unsigned)AddressTaken;
>> + }
>> + break;
>> + }
>> +
>> + case LK_New:
>> + break;
>> +
>> + case LK_Return:
>> + // FIXME: Move -Wreturn-stack-address checks here.
>> + return false;
>> + }
>> + return false;
>> + }
>> +
>> + auto *MTE = L.get<MaterializeTemporaryExpr*>();
>> switch (LK) {
>> case LK_FullExpression:
>> llvm_unreachable("already handled this");
>> @@ -6520,11 +6608,11 @@ void Sema::checkInitializerLifetime(cons
>> // would be to clone the initializer expression on each use that
>> would
>> // lifetime extend its temporaries.
>> Diag(MTE->getExprLoc(),
>> - EK == EK_ReferenceBinding
>> + RK == RK_ReferenceBinding
>> ? diag::warn_default_member_init_temporary_not_extended
>> :
>> diag::warn_default_member_init_init_list_not_extended);
>> } else {
>> - llvm_unreachable("unexpected indirect temporary path");
>> + // FIXME: Warn on this.
>> }
>> break;
>>
>> @@ -6532,18 +6620,20 @@ void Sema::checkInitializerLifetime(cons
>> // Under C++ DR1696, if a mem-initializer (or a default member
>> // initializer used by the absence of one) would lifetime-extend a
>> // temporary, the program is ill-formed.
>> - if (auto *ExtendingDecl = ExtendingEntity->getDecl()) {
>> + if (auto *ExtendingDecl =
>> + ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
>> bool IsSubobjectMember = ExtendingEntity != &Entity;
>> Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary)
>> << ExtendingDecl << Init->getSourceRange() <<
>> IsSubobjectMember
>> - << EK;
>> + << RK;
>> // Don't bother adding a note pointing to the field if we're
>> inside its
>> // default member initializer; our primary diagnostic points to
>> the
>> // same place in that case.
>> - if (Path.empty() || !Path.back().is<CXXDefaultInitExpr*>()) {
>> + if (Path.empty() ||
>> + Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
>> Diag(ExtendingDecl->getLocation(),
>> diag::note_lifetime_extending_member_declared_here)
>> - << EK << IsSubobjectMember;
>> + << RK << IsSubobjectMember;
>> }
>> } else {
>> // We have a mem-initializer but no particular field within it;
>> this
>> @@ -6557,7 +6647,7 @@ void Sema::checkInitializerLifetime(cons
>> break;
>>
>> case LK_New:
>> - if (EK == EK_ReferenceBinding) {
>> + if (RK == RK_ReferenceBinding) {
>> Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference);
>> } else {
>> Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list)
>> @@ -6573,9 +6663,14 @@ void Sema::checkInitializerLifetime(cons
>> // FIXME: Model these as CodeSynthesisContexts to fix the note
>> emission
>> // order.
>> for (auto Elem : llvm::reverse(Path)) {
>> - if (auto *DIE = Elem.dyn_cast<CXXDefaultInitExpr*>()) {
>> - Diag(DIE->getExprLoc(),
>> diag::note_in_default_member_initalizer_here)
>> - << DIE->getField();
>> + switch (Elem.Kind) {
>> + case IndirectLocalPathEntry::DefaultInit:
>> + Diag(Elem.E->getExprLoc(),
>> diag::note_in_default_member_initalizer_here)
>> + << cast<CXXDefaultInitExpr>(Elem.E)->getField();
>> + break;
>> +
>> + case IndirectLocalPathEntry::AddressOf:
>> + break;
>> }
>> }
>>
>> @@ -6584,12 +6679,12 @@ void Sema::checkInitializerLifetime(cons
>> return false;
>> };
>>
>> - llvm::SmallVector<IndirectTemporaryPathEntry, 8> Path;
>> + llvm::SmallVector<IndirectLocalPathEntry, 8> Path;
>> if (Init->isGLValue())
>> - visitTemporariesExtendedByReferenceBinding(Path, Init,
>> EK_ReferenceBinding,
>> - TemporaryVisitor);
>> + visitLocalsRetainedByReferenceBinding(Path, Init,
>> RK_ReferenceBinding,
>> + TemporaryVisitor);
>> else
>> - visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor);
>> + visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor,
>> false);
>> }
>>
>> static void DiagnoseNarrowingInInitList(Sema &S,
>> @@ -6853,6 +6948,7 @@ InitializationSequence::Perform(Sema &S,
>>
>> // Diagnose cases where we initialize a pointer to an array temporary,
>> and the
>> // pointer obviously outlives the temporary.
>> + // FIXME: Fold this into checkInitializerLifetime.
>> if (Args.size() == 1 && Args[0]->getType()->isArrayType() &&
>> Entity.getType()->isPointerType() &&
>> InitializedEntityOutlivesFullExpression(Entity)) {
>> @@ -7015,11 +7111,6 @@ 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.
>> - S.checkInitializerLifetime(Entity, CurInit.get());
>> -
>> CheckForNullPointerDereference(S, CurInit.get());
>> break;
>>
>> @@ -7036,10 +7127,6 @@ InitializationSequence::Perform(Sema &S,
>> Step->Type, CurInit.get(),
>> Entity.getType()->isLValueReferenceType());
>> CurInit = MTE;
>>
>> - // Maybe lifetime-extend the temporary's subobjects to match the
>> - // entity's lifetime.
>> - S.checkInitializerLifetime(Entity, CurInit.get());
>> -
>> // If we're extending this temporary to automatic storage duration
>> -- we
>> // need to register its cleanup during the full-expression's
>> cleanups.
>> if (MTE->getStorageDuration() == SD_Automatic &&
>> @@ -7490,10 +7577,6 @@ InitializationSequence::Perform(Sema &S,
>> // Wrap it in a construction of a std::initializer_list<T>.
>> CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type,
>> MTE);
>>
>> - // Maybe lifetime-extend the array temporary's subobjects to match
>> the
>> - // entity's lifetime.
>> - S.checkInitializerLifetime(Entity, CurInit.get());
>> -
>> // Bind the result, in case the library has given initializer_list
>> a
>> // non-trivial destructor.
>> if (shouldBindAsTemporary(Entity))
>> @@ -7612,6 +7695,11 @@ InitializationSequence::Perform(Sema &S,
>> }
>> }
>>
>> + // Check whether the initializer has a shorter lifetime than the
>> initialized
>> + // entity, and if not, either lifetime-extend or warn as appropriate.
>> + if (auto *Init = CurInit.get())
>> + S.checkInitializerLifetime(Entity, Init);
>> +
>> // Diagnose non-fatal problems with the completed initialization.
>> if (Entity.getKind() == InitializedEntity::EK_Member &&
>> cast<FieldDecl>(Entity.getDecl())->isBitField())
>>
>> Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=337627&r1=337626&r2=337627&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
>> (original)
>> +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Fri Jul
>> 20 15:25:55 2018
>> @@ -235,10 +235,10 @@ void fVoidPointerTest2() {
>> }
>>
>> class VoidPointerRRefTest1 {
>> - void *&&vptrrref;
>> + void *&&vptrrref; // expected-note {{here}}
>>
>> public:
>> - VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast<void
>> *&&>(vptr)) {
>> + VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast<void
>> *&&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to
>> stack allocated parameter 'vptr'}}
>> // All good!
>> }
>> };
>> @@ -249,10 +249,10 @@ void fVoidPointerRRefTest1() {
>> }
>>
>> class VoidPointerRRefTest2 {
>> - void **&&vpptrrref;
>> + void **&&vpptrrref; // expected-note {{here}}
>>
>> public:
>> - VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast<void
>> **&&>(vptr)) {
>> + VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast<void
>> **&&>(vptr)) { // expected-warning {{binding reference member 'vpptrrref'
>> to stack allocated parameter 'vptr'}}
>> // All good!
>> }
>> };
>> @@ -263,10 +263,10 @@ void fVoidPointerRRefTest2() {
>> }
>>
>> class VoidPointerLRefTest {
>> - void *&vptrrref;
>> + void *&vptrrref; // expected-note {{here}}
>>
>> public:
>> - VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast<void
>> *&>(vptr)) {
>> + VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast<void
>> *&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to
>> stack allocated parameter 'vptr'}}
>> // All good!
>> }
>> };
>>
>> Modified:
>> cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=337627&r1=337626&r2=337627&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
>> (original)
>> +++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
>> Fri Jul 20 15:25:55 2018
>> @@ -72,18 +72,18 @@ std::initializer_list<int> thread_local
>>
>> // X86: @_ZN15partly_constant1kE = global i32 0, align 4
>> // X86: @_ZN15partly_constant2ilE = global {{.*}} null, align 8
>> -// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] =
>> internal global {{.*}} zeroinitializer, align 8
>> -// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] =
>> internal global [3 x {{.*}}] zeroinitializer, align 8
>> -// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] =
>> internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4
>> -// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] =
>> internal global [2 x i32] zeroinitializer, align 4
>> -// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] =
>> internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4
>> +// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] =
>> internal global {{.*}} zeroinitializer, align 8
>> +// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] =
>> internal global [3 x {{.*}}] zeroinitializer, align 8
>> +// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] =
>> internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4
>> +// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] =
>> internal global [2 x i32] zeroinitializer, align 4
>> +// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] =
>> internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4
>> // AMDGCN: @_ZN15partly_constant1kE = addrspace(1) global i32 0, align 4
>> // AMDGCN: @_ZN15partly_constant2ilE = addrspace(4) global {{.*}} null,
>> align 8
>> -// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] =
>> internal addrspace(4) global {{.*}} zeroinitializer, align 8
>> -// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] =
>> internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8
>> -// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] =
>> internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4
>> -// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] =
>> internal addrspace(4) global [2 x i32] zeroinitializer, align 4
>> -// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] =
>> internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8],
>> align 4
>> +// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] =
>> internal addrspace(4) global {{.*}} zeroinitializer, align 8
>> +// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] =
>> internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8
>> +// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] =
>> internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4
>> +// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] =
>> internal addrspace(4) global [2 x i32] zeroinitializer, align 4
>> +// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] =
>> internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8],
>> align 4
>>
>> // X86: @[[REFTMP1:.*]] = private constant [2 x i32] [i32 42, i32 43],
>> align 4
>> // X86: @[[REFTMP2:.*]] = private constant [3 x %{{.*}}] [%{{.*}} { i32
>> 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4
>> @@ -375,7 +375,7 @@ namespace partly_constant {
>> // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
>> // CHECK: store i32* getelementptr inbounds ({{.*}}, {{.*}}*
>> {{.*}}@[[PARTLY_CONSTANT_THIRD]]{{.*}}, i64 0, i64 0),
>> // CHECK: i32** getelementptr inbounds ({{.*}}, {{.*}}*
>> {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 0)
>> - // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}*
>> {{.*}}@_ZGRN15partly_constant2ilE4_{{.*}}, i64 0, i64 2, i32 1)
>> + // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}*
>> {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 1)
>> // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
>> //
>> // Outer init list.
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>
>
> --
> Regards,
> Ilya Biryukov
>
--
Regards,
Ilya Biryukov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180723/0f1dda55/attachment-0001.html>
More information about the cfe-commits
mailing list