r337255 - Temporarily revert r337226 "Restructure checking for, and warning on, lifetime extension."

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 17 15:29:42 PDT 2018


Thank you. I added an 'alignas(8)' and reapplied in r337329.

On Tue, 17 Jul 2018 at 02:28, Florian Hahn via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: fhahn
> Date: Tue Jul 17 02:23:31 2018
> New Revision: 337255
>
> URL: http://llvm.org/viewvc/llvm-project?rev=337255&view=rev
> Log:
> Temporarily revert r337226 "Restructure checking for, and warning on,
> lifetime extension."
>
> This change breaks on ARM because pointers to clang::InitializedEntity are
> only
> 4 byte aligned and do not have 3 bits to store values. A possible solution
> would be to change the fields in clang::InitializedEntity to enforce a
> bigger
> alignment requirement.
>
> The error message is
>
> llvm/include/llvm/ADT/PointerIntPair.h:132:3: error: static_assert failed
> "PointerIntPair with integer size too large for pointer"
>   static_assert(IntBits <= PtrTraits::NumLowBitsAvailable,
> include/llvm/ADT/PointerIntPair.h:73:13: note: in instantiation of
> template class 'llvm::PointerIntPairInfo<const clang::InitializedEntity *,
> 3, llvm::PointerLikeTypeTraits<const clang::InitializedEntity *> >'
> requested here
>     Value = Info::updateInt(Info::updatePointer(0, PtrVal),
> llvm/include/llvm/ADT/PointerIntPair.h:51:5: note: in instantiation of
> member function 'llvm::PointerIntPair<const clang::InitializedEntity *, 3,
> (anonymous namespace)::LifetimeKind, llvm::PointerLikeTypeTraits<const
> clang::InitializedEntity *>, llvm::PointerIntPairInfo<const
> clang::InitializedEntity *, 3, llvm::PointerLikeTypeTraits<const
> clang::InitializedEntity *> > >::setPointerAndInt' requested here
>     setPointerAndInt(PtrVal, IntVal);
>     ^
> llvm/tools/clang/lib/Sema/SemaInit.cpp:6237:12: note: in instantiation of
> member function 'llvm::PointerIntPair<const clang::InitializedEntity *, 3,
> (anonymous namespace)::LifetimeKind, llvm::PointerLikeTypeTraits<const
> clang::InitializedEntity *>, llvm::PointerIntPairInfo<const
> clang::InitializedEntity *, 3, llvm::PointerLikeTypeTraits<const
> clang::InitializedEntity *> > >::PointerIntPair' requested here
>     return {Entity, LK_Extended};
>
> Full log here:
> http://lab.llvm.org:8011/builders/clang-cmake-armv7-global-isel/builds/1330
> http://lab.llvm.org:8011/builders/clang-cmake-armv7-full/builds/1394
>
>
>
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticGroups.td
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/include/clang/Sema/Initialization.h
>     cfe/trunk/include/clang/Sema/Sema.h
>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>     cfe/trunk/lib/Sema/SemaExprCXX.cpp
>     cfe/trunk/lib/Sema/SemaInit.cpp
>     cfe/trunk/test/Analysis/initializer.cpp
>     cfe/trunk/test/CXX/drs/dr16xx.cpp
>     cfe/trunk/test/CXX/drs/dr18xx.cpp
>     cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp
>     cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp
>     cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp
>     cfe/trunk/test/CXX/temp/temp.param/p5.cpp
>     cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
>     cfe/trunk/test/CodeGenCXX/temporaries.cpp
>     cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
>     cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp
>     cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
>     cfe/trunk/test/SemaCXX/eval-crashes.cpp
>     cfe/trunk/test/SemaCXX/member-init.cpp
>     cfe/trunk/test/SemaCXX/warn-dangling-field.cpp
>     cfe/trunk/www/cxx_dr_status.html
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Jul 17 02:23:31
> 2018
> @@ -272,7 +272,6 @@ def ShiftOpParentheses: DiagGroup<"shift
>  def OverloadedShiftOpParentheses:
> DiagGroup<"overloaded-shift-op-parentheses">;
>  def DanglingElse: DiagGroup<"dangling-else">;
>  def DanglingField : DiagGroup<"dangling-field">;
> -def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
>  def DistributedObjectModifiers :
> DiagGroup<"distributed-object-modifiers">;
>  def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
>  def FlagEnum : DiagGroup<"flag-enum">;
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jul 17
> 02:23:31 2018
> @@ -2049,6 +2049,10 @@ def err_implied_std_initializer_list_not
>    "not found; include <initializer_list>">;
>  def err_malformed_std_initializer_list : Error<
>    "std::initializer_list must be a class template with a single type
> parameter">;
> +def warn_dangling_std_initializer_list : Warning<
> +  "array backing the initializer list will be destroyed at the end of "
> +  "%select{the full-expression|the constructor}0">,
> +  InGroup<DiagGroup<"dangling-initializer-list">>;
>  def err_auto_init_list_from_c : Error<
>    "cannot use __auto_type with initializer list in C">;
>  def err_auto_bitfield : Error<
> @@ -7840,39 +7844,13 @@ def warn_bind_ref_member_to_parameter :
>  def warn_init_ptr_member_to_parameter_addr : Warning<
>    "initializing pointer member %0 with the stack address of parameter
> %1">,
>    InGroup<DanglingField>;
> +def warn_bind_ref_member_to_temporary : Warning<
> +  "binding reference %select{|subobject of }1member %0 to a temporary
> value">,
> +  InGroup<DanglingField>;
>  def note_ref_or_ptr_member_declared_here : Note<
>    "%select{reference|pointer}0 member declared here">;
> -
> -def err_bind_ref_member_to_temporary : Error<
> -  "%select{reference|backing array for 'std::initializer_list'}2 "
> -  "%select{|subobject of }1member %0 "
> -  "%select{binds to|is}2 a temporary object "
> -  "whose lifetime would be shorter than the constructed object">;
> -def note_lifetime_extending_member_declared_here : Note<
> -  "%select{%select{reference|'std::initializer_list'}0 member|"
> -  "member with %select{reference|'std::initializer_list'}0 subobject}1 "
> -  "declared here">;
> -def warn_new_dangling_reference : Warning<
> -  "temporary bound to reference member of allocated object "
> -  "will be destroyed at the end of the full-expression">,
> -  InGroup<DanglingField>;
> -def warn_new_dangling_initializer_list : Warning<
> -  "array backing "
> -  "%select{initializer list subobject of the allocated object|"
> -  "the allocated initializer list}0 "
> -  "will be destroyed at the end of the full-expression">,
> -  InGroup<DanglingInitializerList>;
> -def warn_default_member_init_temporary_not_extended : Warning<
> -  "sorry, lifetime extension of temporary created by aggregate
> initialization "
> -  "using default member initializer is not supported; lifetime of
> temporary "
> -  "will end at the end of the full-expression">, InGroup<DanglingField>;
> -def warn_default_member_init_init_list_not_extended : Warning<
> -  "sorry, lifetime extension of backing array of initializer list "
> -  "created by aggregate initialization using default member initializer "
> -  "is not supported; lifetime of backing array will end at the end of the
> "
> -  "full-expression">, InGroup<DanglingInitializerList>;
> -def note_in_default_member_initalizer_here : Note<
> -  "in default member initializer for field %0 used here">;
> +def note_ref_subobject_of_member_declared_here : Note<
> +  "member with reference subobject declared here">;
>
>  // For non-floating point, expressions of the form x == x or x != x
>  // should result in a warning, since these always evaluate to a constant.
>
> Modified: cfe/trunk/include/clang/Sema/Initialization.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Initialization.h (original)
> +++ cfe/trunk/include/clang/Sema/Initialization.h Tue Jul 17 02:23:31 2018
> @@ -63,7 +63,7 @@ public:
>      /// is being thrown.
>      EK_Exception,
>
> -    /// The entity being initialized is a non-static data member
> +    /// The entity being initialized is a non-static data member
>      /// subobject.
>      EK_Member,
>
> @@ -123,7 +123,7 @@ public:
>      // enum as an index for its first %select.  When modifying this list,
>      // that diagnostic text needs to be updated as well.
>    };
> -
> +
>  private:
>    /// The kind of entity being initialized.
>    EntityKind Kind;
> @@ -158,10 +158,6 @@ private:
>      /// initialization in a copy or move constructor. These can perform
> array
>      /// copies.
>      bool IsImplicitFieldInit;
> -
> -    /// When Kind == EK_Member, whether this is the initial initialization
> -    /// check for a default member initializer.
> -    bool IsDefaultMemberInit;
>    };
>
>    struct C {
> @@ -207,7 +203,7 @@ private:
>
>    /// Create the initialization entity for a variable.
>    InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)
> -      : Kind(EK), Type(Var->getType()), Variable{Var, false, false} {}
> +      : Kind(EK), Type(Var->getType()), Variable{Var, false} {}
>
>    /// Create the initialization entity for the result of a
>    /// function, throwing an object, performing an explicit cast, or
> @@ -221,9 +217,9 @@ private:
>
>    /// Create the initialization entity for a member subobject.
>    InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
> -                    bool Implicit, bool DefaultMemberInit)
> +                    bool Implicit)
>        : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
> -        Variable{Member, Implicit, DefaultMemberInit} {}
> +        Variable{Member, Implicit} {}
>
>    /// Create the initialization entity for an array element.
>    InitializedEntity(ASTContext &Context, unsigned Index,
> @@ -343,27 +339,21 @@ public:
>    static InitializedEntity InitializeDelegation(QualType Type) {
>      return InitializedEntity(EK_Delegating, SourceLocation(), Type);
>    }
> -
> +
>    /// Create the initialization entity for a member subobject.
>    static InitializedEntity
>    InitializeMember(FieldDecl *Member,
>                     const InitializedEntity *Parent = nullptr,
>                     bool Implicit = false) {
> -    return InitializedEntity(Member, Parent, Implicit, false);
> +    return InitializedEntity(Member, Parent, Implicit);
>    }
> -
> +
>    /// Create the initialization entity for a member subobject.
>    static InitializedEntity
>    InitializeMember(IndirectFieldDecl *Member,
>                     const InitializedEntity *Parent = nullptr,
>                     bool Implicit = false) {
> -    return InitializedEntity(Member->getAnonField(), Parent, Implicit,
> false);
> -  }
> -
> -  /// Create the initialization entity for a default member initializer.
> -  static InitializedEntity
> -  InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) {
> -    return InitializedEntity(Member, nullptr, false, true);
> +    return InitializedEntity(Member->getAnonField(), Parent, Implicit);
>    }
>
>    /// Create the initialization entity for an array element.
> @@ -463,12 +453,6 @@ public:
>      return getKind() == EK_Member && Variable.IsImplicitFieldInit;
>    }
>
> -  /// Is this the default member initializer of a member (specified inside
> -  /// the class definition)?
> -  bool isDefaultMemberInitializer() const {
> -    return getKind() == EK_Member && Variable.IsDefaultMemberInit;
> -  }
> -
>    /// Determine the location of the 'return' keyword when initializing
>    /// the result of a function call.
>    SourceLocation getReturnLoc() const {
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Jul 17 02:23:31 2018
> @@ -2582,11 +2582,6 @@ public:
>                                                   NamedDecl *FoundDecl,
>                                                   CXXMethodDecl *Method);
>
> -  /// Check that the lifetime of the initializer (and its subobjects) is
> -  /// sufficient for initializing the entity, and perform lifetime
> extension
> -  /// (when permitted) if not.
> -  void checkInitializerLifetime(const InitializedEntity &Entity, Expr
> *Init);
> -
>    ExprResult PerformContextuallyConvertToBool(Expr *From);
>    ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
>
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jul 17 02:23:31 2018
> @@ -3621,8 +3621,7 @@ void Sema::ActOnFinishCXXInClassMemberIn
>
>    ExprResult Init = InitExpr;
>    if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
> -    InitializedEntity Entity =
> -
> InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
> +    InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
>      InitializationKind Kind =
>          FD->getInClassInitStyle() == ICIS_ListInit
>              ?
> InitializationKind::CreateDirectList(InitExpr->getLocStart(),
> @@ -4647,10 +4646,6 @@ static bool CollectFieldInitializer(Sema
>          SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
>      if (DIE.isInvalid())
>        return true;
> -
> -    auto Entity = InitializedEntity::InitializeMember(Field, nullptr,
> true);
> -    SemaRef.checkInitializerLifetime(Entity, DIE.get());
> -
>      CXXCtorInitializer *Init;
>      if (Indirect)
>        Init = new (SemaRef.Context)
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Jul 17 02:23:31 2018
> @@ -1864,6 +1864,13 @@ Sema::BuildCXXNew(SourceRange Range, boo
>    if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
>      return ExprError();
>
> +  if (initStyle == CXXNewExpr::ListInit &&
> +      isStdInitializerList(AllocType, nullptr)) {
> +    Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
> +         diag::warn_dangling_std_initializer_list)
> +        << /*at end of FE*/0 << Inits[0]->getSourceRange();
> +  }
> +
>    // In ARC, infer 'retaining' for the allocated
>    if (getLangOpts().ObjCAutoRefCount &&
>        AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
>
> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Jul 17 02:23:31 2018
> @@ -572,7 +572,6 @@ void InitListChecker::FillInEmptyInitFor
>          hadError = true;
>          return;
>        }
> -      SemaRef.checkInitializerLifetime(MemberEntity, DIE.get());
>        if (Init < NumInits)
>          ILE->setInit(Init, DIE.get());
>        else {
> @@ -6198,43 +6197,17 @@ InitializedEntityOutlivesFullExpression(
>    llvm_unreachable("unknown entity kind");
>  }
>
> -namespace {
> -enum LifetimeKind {
> -  /// The lifetime of a temporary bound to this entity ends at the end of
> the
> -  /// full-expression, and that's (probably) fine.
> -  LK_FullExpression,
> -
> -  /// The lifetime of a temporary bound to this entity is extended to the
> -  /// lifeitme of the entity itself.
> -  LK_Extended,
> -
> -  /// The lifetime of a temporary bound to this entity probably ends too
> soon,
> -  /// because the entity is allocated in a new-expression.
> -  LK_New,
> -
> -  /// The lifetime of a temporary bound to this entity ends too soon,
> because
> -  /// the entity is a return object.
> -  LK_Return,
> -
> -  /// This is a mem-initializer: if it would extend a temporary (other
> than via
> -  /// a default member initializer), the program is ill-formed.
> -  LK_MemInitializer,
> -};
> -using LifetimeResult =
> -    llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
> -}
> -
>  /// 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 const InitializedEntity *getEntityForTemporaryLifetimeExtension(
>      const InitializedEntity *Entity,
> -    const InitializedEntity *InitField = nullptr) {
> +    const InitializedEntity *FallbackDecl = nullptr) {
>    // C++11 [class.temporary]p5:
>    switch (Entity->getKind()) {
>    case InitializedEntity::EK_Variable:
>      //   The temporary [...] persists for the lifetime of the reference
> -    return {Entity, LK_Extended};
> +    return Entity;
>
>    case InitializedEntity::EK_Member:
>      // For subobjects, we look at the complete object.
> @@ -6243,43 +6216,29 @@ static LifetimeResult getEntityForTempor
>                                                      Entity);
>
>      //   except:
> -    // C++17 [class.base.init]p8:
> -    //   A temporary expression bound to a reference member in a
> -    //   mem-initializer is ill-formed.
> -    // C++17 [class.base.init]p11:
> -    //   A temporary expression bound to a reference member from a
> -    //   default member initializer is ill-formed.
> -    //
> -    // The context of p11 and its example suggest that it's only the use
> of a
> -    // default member initializer from a constructor that makes the
> program
> -    // ill-formed, not its mere existence, and that it can even be used by
> -    // aggregate initialization.
> -    return {Entity, Entity->isDefaultMemberInitializer() ? LK_Extended
> -                                                         :
> LK_MemInitializer};
> +    //   -- A temporary bound to a reference member in a constructor's
> +    //      ctor-initializer persists until the constructor exits.
> +    return Entity;
>
>    case InitializedEntity::EK_Binding:
>      // Per [dcl.decomp]p3, the binding is treated as a variable of
> reference
>      // type.
> -    return {Entity, LK_Extended};
> +    return Entity;
>
>    case InitializedEntity::EK_Parameter:
>    case InitializedEntity::EK_Parameter_CF_Audited:
>      //   -- A temporary bound to a reference parameter in a function call
>      //      persists until the completion of the full-expression
> containing
>      //      the call.
> -    return {nullptr, LK_FullExpression};
> -
>    case InitializedEntity::EK_Result:
>      //   -- The lifetime of a temporary bound to the returned value in a
>      //      function return statement is not extended; the temporary is
>      //      destroyed at the end of the full-expression in the return
> statement.
> -    return {nullptr, LK_Return};
> -
>    case InitializedEntity::EK_New:
>      //   -- A temporary bound to a reference in a new-initializer persists
>      //      until the completion of the full-expression containing the
>      //      new-initializer.
> -    return {nullptr, LK_New};
> +    return nullptr;
>
>    case InitializedEntity::EK_Temporary:
>    case InitializedEntity::EK_CompoundLiteralInit:
> @@ -6287,26 +6246,25 @@ static LifetimeResult getEntityForTempor
>      // 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 {nullptr, LK_FullExpression};
> +    return nullptr;
>
>    case InitializedEntity::EK_ArrayElement:
>      // For subobjects, we look at the complete object.
>      return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
> -                                                  InitField);
> +                                                  FallbackDecl);
>
>    case InitializedEntity::EK_Base:
>      // For subobjects, we look at the complete object.
>      if (Entity->getParent())
>        return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
> -                                                    InitField);
> -    return {InitField, LK_MemInitializer};
> -
> +                                                    Entity);
> +    LLVM_FALLTHROUGH;
>    case InitializedEntity::EK_Delegating:
>      // We can reach this case for aggregate initialization in a
> constructor:
>      //   struct A { int &&r; };
>      //   struct B : A { B() : A{0} {} };
> -    // In this case, use the outermost field decl as the context.
> -    return {InitField, LK_MemInitializer};
> +    // In this case, use the innermost field decl as the context.
> +    return FallbackDecl;
>
>    case InitializedEntity::EK_BlockElement:
>    case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
> @@ -6314,54 +6272,30 @@ static LifetimeResult getEntityForTempor
>    case InitializedEntity::EK_Exception:
>    case InitializedEntity::EK_VectorElement:
>    case InitializedEntity::EK_ComplexElement:
> -    return {nullptr, LK_FullExpression};
> +    return nullptr;
>    }
>    llvm_unreachable("unknown entity kind");
>  }
>
> -namespace {
> -enum ExtensionKind {
> -  /// Lifetime would be extended by a reference binding to a temporary.
> -  EK_ReferenceBinding,
> -  /// Lifetime would be extended by a std::initializer_list object
> binding to
> -  /// its backing array.
> -  EK_StdInitializerList,
> -};
> -using IndirectTemporaryPathEntry =
> -    llvm::PointerUnion<CXXDefaultInitExpr *, ValueDecl *>;
> -using IndirectTemporaryPath =
> llvm::SmallVectorImpl<IndirectTemporaryPathEntry>;
> -
> -struct RevertToOldSizeRAII {
> -  IndirectTemporaryPath &Path;
> -  unsigned OldSize = Path.size();
> -  RevertToOldSizeRAII(IndirectTemporaryPath &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) {
> -  RevertToOldSizeRAII RAII(Path);
> +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 InitializedEntity *ExtendingEntity) {
>    // Walk past any constructs which we can lifetime-extend across.
>    Expr *Old;
>    do {
>      Old = Init;
>
>      if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
> -      // If this is just redundant braces around an initializer, step
> over it.
> -      if (ILE->isTransparent())
> +      if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
> +        // This is just redundant braces around an initializer. Step over
> it.
>          Init = ILE->getInit(0);
> +      }
>      }
>
>      // Step over any subobject adjustments; we may have a materialized
> @@ -6378,65 +6312,40 @@ visitTemporariesExtendedByReferenceBindi
>      // when performing lifetime extension.
>      if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init))
>        Init = ASE->getBase();
> -
> -    // 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);
> -      Init = DIE->getExpr();
> -
> -      if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
> -        Init = EWC->getSubExpr();
> -    }
>    } while (Init != Old);
>
> -  if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) {
> -    if (Visit(Path, MTE, EK))
> -      visitTemporariesExtendedByInitializer(Path, MTE->GetTemporaryExpr(),
> -                                            Visit);
> +  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(ExtendingEntity->getDecl(),
> +                         ExtendingEntity->allocateManglingNumber());
> +    performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
> +    return true;
>    }
> -}
>
> -/// 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)
> {
> -  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);
> -    Init = DIE->getExpr();
> -
> -    if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
> -      Init = EWC->getSubExpr();
> -  }
> +  return false;
> +}
>
> +/// Update a prvalue expression that is going to be materialized as a
> +/// lifetime-extended temporary.
> +static void performLifetimeExtension(Expr *Init,
> +                                     const InitializedEntity
> *ExtendingEntity) {
>    // Dig out the expression which constructs the extended temporary.
>    Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
>
>    if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
>      Init = BTE->getSubExpr();
>
> -  // C++17 [dcl.init.list]p6:
> -  //   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);
> +  if (CXXStdInitializerListExpr *ILE =
> +          dyn_cast<CXXStdInitializerListExpr>(Init)) {
> +    performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
> +    return;
> +  }
>
>    if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
> -    if (ILE->isTransparent())
> -      return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0),
> -                                                   Visit);
> -
>      if (ILE->getType()->isArrayType()) {
>        for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
> -        visitTemporariesExtendedByInitializer(Path, ILE->getInit(I),
> Visit);
> +        performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
>        return;
>      }
>
> @@ -6448,8 +6357,7 @@ 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);
> +        performReferenceExtension(ILE->getInit(0), ExtendingEntity);
>        else {
>          unsigned Index = 0;
>          for (const auto *I : RD->fields()) {
> @@ -6459,13 +6367,13 @@ static void visitTemporariesExtendedByIn
>              continue;
>            Expr *SubInit = ILE->getInit(Index);
>            if (I->getType()->isReferenceType())
> -            visitTemporariesExtendedByReferenceBinding(
> -                Path, SubInit, EK_ReferenceBinding, Visit);
> -          else
> -            // This might be either aggregate-initialization of a member
> or
> -            // initialization of a std::initializer_list object.
> Regardless,
> +            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.
> -            visitTemporariesExtendedByInitializer(Path, SubInit, Visit);
> +            performLifetimeExtension(SubInit, ExtendingEntity);
>            ++Index;
>          }
>        }
> @@ -6473,123 +6381,37 @@ static void visitTemporariesExtendedByIn
>    }
>  }
>
> -/// 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) {
> -  for (auto Elem : Path) {
> -    if (!Elem.is<CXXDefaultInitExpr*>())
> -      return false;
> -  }
> -  return true;
> -}
> -
> -void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
> -                                    Expr *Init) {
> -  LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity);
> -  LifetimeKind LK = LR.getInt();
> -  const InitializedEntity *ExtendingEntity = LR.getPointer();
> -
> -  // If this entity doesn't have an interesting lifetime, don't bother
> looking
> -  // for temporaries within its initializer.
> -  if (LK == LK_FullExpression)
> -    return;
> -
> -  auto TemporaryVisitor = [&](IndirectTemporaryPath &Path,
> -                              MaterializeTemporaryExpr *MTE,
> -                              ExtensionKind EK) -> bool {
> -    switch (LK) {
> -    case LK_FullExpression:
> -      llvm_unreachable("already handled this");
> -
> -    case LK_Extended:
> -      // Lifetime-extend the temporary.
> -      if (Path.empty()) {
> -        // Update the storage duration of the materialized temporary.
> -        // FIXME: Rebuild the expression instead of mutating it.
> -        MTE->setExtendingDecl(ExtendingEntity->getDecl(),
> -                              ExtendingEntity->allocateManglingNumber());
> -        // Also visit the temporaries lifetime-extended by this
> initializer.
> -        return true;
> -      }
> -
> -      if (shouldLifetimeExtendThroughPath(Path)) {
> -        // We're supposed to lifetime-extend the temporary along this
> path (per
> -        // the resolution of DR1815), but we don't support that yet.
> -        //
> -        // FIXME: Properly handle this situation. Perhaps the easiest
> approach
> -        // would be to clone the initializer expression on each use that
> would
> -        // lifetime extend its temporaries.
> -        Diag(MTE->getExprLoc(),
> -             EK == EK_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");
> -      }
> -      break;
> -
> -    case LK_MemInitializer:
> -      // 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()) {
> -        bool IsSubobjectMember = ExtendingEntity != &Entity;
> -        Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary)
> -            << ExtendingDecl << Init->getSourceRange() <<
> IsSubobjectMember
> -            << EK;
> -        // 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*>()) {
> -          Diag(ExtendingDecl->getLocation(),
> -               diag::note_lifetime_extending_member_declared_here)
> -              << EK << IsSubobjectMember;
> -        }
> -      } else {
> -        // We have a mem-initializer but no particular field within it;
> this
> -        // is either a base class or a delegating initializer directly
> -        // initializing the base-class from something that doesn't live
> long
> -        // enough. Either way, that can't happen.
> -        // FIXME: Move CheckForDanglingReferenceOrPointer checks here.
> -        llvm_unreachable(
> -            "temporary initializer for base class / delegating ctor");
> -      }
> -      break;
> -
> -    case LK_New:
> -      if (EK == EK_ReferenceBinding) {
> -        Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference);
> -      } else {
> -        Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list)
> -            << (ExtendingEntity != &Entity);
> -      }
> -      break;
> -
> -    case LK_Return:
> -      // FIXME: Move -Wreturn-stack-address checks here.
> -      return false;
> +static void warnOnLifetimeExtension(Sema &S, const InitializedEntity
> &Entity,
> +                                    const Expr *Init, bool
> IsInitializerList,
> +                                    const ValueDecl *ExtendingDecl) {
> +  // Warn if a field lifetime-extends a temporary.
> +  if (isa<FieldDecl>(ExtendingDecl)) {
> +    if (IsInitializerList) {
> +      S.Diag(Init->getExprLoc(), diag::warn_dangling_std_initializer_list)
> +        << /*at end of constructor*/true;
> +      return;
>      }
>
> -    // 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();
> +    bool IsSubobjectMember = false;
> +    for (const InitializedEntity *Ent = Entity.getParent(); Ent;
> +         Ent = Ent->getParent()) {
> +      if (Ent->getKind() != InitializedEntity::EK_Base) {
> +        IsSubobjectMember = true;
> +        break;
>        }
>      }
> -
> -    // We didn't lifetime-extend, so don't go any further; we don't need
> more
> -    // warnings or errors on inner temporaries within this one's
> initializer.
> -    return false;
> -  };
> -
> -  llvm::SmallVector<IndirectTemporaryPathEntry, 8> Path;
> -  if (Init->isGLValue())
> -    visitTemporariesExtendedByReferenceBinding(Path, Init,
> EK_ReferenceBinding,
> -                                               TemporaryVisitor);
> -  else
> -    visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor);
> +    S.Diag(Init->getExprLoc(),
> +           diag::warn_bind_ref_member_to_temporary)
> +      << ExtendingDecl << Init->getSourceRange()
> +      << IsSubobjectMember << IsInitializerList;
> +    if (IsSubobjectMember)
> +      S.Diag(ExtendingDecl->getLocation(),
> +             diag::note_ref_subobject_of_member_declared_here);
> +    else
> +      S.Diag(ExtendingDecl->getLocation(),
> +             diag::note_ref_or_ptr_member_declared_here)
> +        << /*is pointer*/false;
> +  }
>  }
>
>  static void DiagnoseNarrowingInInitList(Sema &S,
> @@ -7016,9 +6838,14 @@ 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());
> +      // extend the lifetime of a temporary. This happens if we bind a
> reference
> +      // to the result of a cast to reference type.
> +      if (const InitializedEntity *ExtendingEntity =
> +              getEntityForTemporaryLifetimeExtension(&Entity))
> +        if (performReferenceExtension(CurInit.get(), ExtendingEntity))
> +          warnOnLifetimeExtension(S, Entity, CurInit.get(),
> +                                  /*IsInitializerList=*/false,
> +                                  ExtendingEntity->getDecl());
>
>        CheckForNullPointerDereference(S, CurInit.get());
>        break;
> @@ -7034,17 +6861,23 @@ InitializationSequence::Perform(Sema &S,
>        // Materialize the temporary into memory.
>        MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
>            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 (const InitializedEntity *ExtendingEntity =
> +              getEntityForTemporaryLifetimeExtension(&Entity))
> +        if (performReferenceExtension(MTE, ExtendingEntity))
> +          warnOnLifetimeExtension(S, Entity, CurInit.get(),
> +                                  /*IsInitializerList=*/false,
> +                                  ExtendingEntity->getDecl());
>
>        // 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 &&
>            MTE->getType().isDestructedType())
>          S.Cleanup.setExprNeedsCleanups(true);
> +
> +      CurInit = MTE;
>        break;
>      }
>
> @@ -7487,12 +7320,17 @@ InitializationSequence::Perform(Sema &S,
>            CurInit.get()->getType(), CurInit.get(),
>            /*BoundToLvalueReference=*/false);
>
> -      // 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());
> +      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 = new (S.Context) CXXStdInitializerListExpr(Step->Type,
> MTE);
>
>        // Bind the result, in case the library has given initializer_list a
>        // non-trivial destructor.
>
> Modified: cfe/trunk/test/Analysis/initializer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/initializer.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/Analysis/initializer.cpp (original)
> +++ cfe/trunk/test/Analysis/initializer.cpp Tue Jul 17 02:23:31 2018
> @@ -178,6 +178,29 @@ namespace ReferenceInitialization {
>      const MyStruct &myStruct(OtherStruct(5));
>      myStruct.method(); // no-warning
>    }
> +
> +  struct HasMyStruct {
> +    const MyStruct &ms; // expected-note {{reference member declared
> here}}
> +    const MyStruct &msWithCleanups; // expected-note {{reference member
> declared here}}
> +
> +    // clang's Sema issues a warning when binding a reference member to a
> +    // temporary value.
> +    HasMyStruct() : ms(5), msWithCleanups(OtherStruct(5)) {
> +        // expected-warning at -1 {{binding reference member 'ms' to a
> temporary value}}
> +        // expected-warning at -2 {{binding reference member
> 'msWithCleanups' to a temporary value}}
> +
> +      // At this point the members are not garbage so we should not
> expect an
> +      // analyzer warning here even though binding a reference member
> +      // to a member is a terrible idea.
> +      ms.method(); // no-warning
> +      msWithCleanups.method(); // no-warning
> +    }
> +  };
> +
> +  void referenceInitializeField() {
> +    HasMyStruct hms;
> +  }
> +
>  };
>
>  namespace PR31592 {
>
> Modified: cfe/trunk/test/CXX/drs/dr16xx.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr16xx.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/drs/dr16xx.cpp (original)
> +++ cfe/trunk/test/CXX/drs/dr16xx.cpp Tue Jul 17 02:23:31 2018
> @@ -9,20 +9,6 @@
>  #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
>  #endif
>
> -#if __cplusplus >= 201103L
> -namespace std {
> -  typedef decltype(sizeof(int)) size_t;
> -
> -  template<typename E> class initializer_list {
> -    const E *begin;
> -    size_t size;
> -
> -  public:
> -    initializer_list();
> -  };
> -} // std
> -#endif
> -
>  namespace dr1611 { // dr1611: dup 1658
>    struct A { A(int); };
>    struct B : virtual A { virtual void f() = 0; };
> @@ -283,83 +269,3 @@ namespace dr1687 { // dr1687: 7
>    auto c = To<E1>() <=> To<E2>(); // expected-error {{invalid operands to
> binary expression ('To<dr1687::E1>' and 'To<dr1687::E2>')}}
>  #endif
>  }
> -
> -namespace dr1696 { // dr1696: 7
> -  namespace std_examples {
> -#if __cplusplus >= 201402L
> -    extern struct A a;
> -    struct A {
> -      const A &x = { A{a, a} };
> -      const A &y = { A{} }; // expected-error {{default member
> initializer for 'y' needed within definition of enclosing class 'A' outside
> of member functions}} expected-note {{here}}
> -    };
> -    A a{a, a};
> -#endif
> -  }
> -
> -  struct A { A(); ~A(); };
> -#if __cplusplus >= 201103L
> -  struct B {
> -    A &&a; // expected-note {{declared here}}
> -    B() : a{} {} // expected-error {{reference member 'a' binds to a
> temporary object whose lifetime would be shorter than the constructed
> object}}
> -  } b;
> -#endif
> -
> -  struct C {
> -    C();
> -    const A &a; // expected-note {{declared here}}
> -  };
> -  C::C() : a(A()) {} // expected-error {{reference member 'a' binds to a
> temporary object whose lifetime would be shorter than the constructed
> object}}
> -
> -#if __cplusplus >= 201103L
> -  // This is OK in C++14 onwards, per DR1815, though we don't support
> that yet:
> -  //   D1 d1 = {};
> -  // is equivalent to
> -  //   D1 d1 = {A()};
> -  // ... which lifetime-extends the A temporary.
> -  struct D1 {
> -    const A &a = A();
> -#if __cplusplus < 201402L
> -    // expected-error at -2 {{binds to a temporary}}
> -    // expected-note at -4 {{here}}
> -#else
> -    // expected-warning-re at -5 {{sorry, lifetime extension {{.*}} not
> supported}}
> -#endif
> -  };
> -  D1 d1 = {}; // expected-note {{here}}
> -
> -  struct D2 {
> -    const A &a = A(); // expected-error {{binds to a temporary}}
> -    D2() {} // expected-note {{used here}}
> -  };
> -
> -  struct D3 { // expected-note {{used here}}
> -    const A &a = A(); // expected-error {{binds to a temporary}}
> -  };
> -  D3 d3; // expected-note {{first required here}}
> -
> -  struct haslist1 {
> -    std::initializer_list<int> il; // expected-note
> {{'std::initializer_list' member}}
> -    haslist1(int i) : il{i, 2, 3} {} // expected-error {{backing array
> for 'std::initializer_list' member 'il' is a temporary object}}
> -  };
> -
> -  struct haslist2 {
> -    std::initializer_list<int> il; // expected-note
> {{'std::initializer_list' member}}
> -    haslist2();
> -  };
> -  haslist2::haslist2() : il{1, 2} {} // expected-error {{backing array
> for 'std::initializer_list' member 'il' is a temporary object}}
> -
> -  struct haslist3 {
> -    std::initializer_list<int> il = {1, 2, 3};
> -  };
> -
> -  struct haslist4 { // expected-note {{in default member initializer}}
> -    std::initializer_list<int> il = {1, 2, 3}; // expected-error
> {{backing array for 'std::initializer_list' member 'il' is a temporary
> object}}
> -  };
> -  haslist4 hl4; // expected-note {{in implicit default constructor}}
> -
> -  struct haslist5 {
> -    std::initializer_list<int> il = {1, 2, 3}; // expected-error
> {{backing array for 'std::initializer_list' member 'il' is a temporary
> object}}
> -    haslist5() {} // expected-note {{in default member initializer}}
> -  };
> -#endif
> -}
>
> Modified: cfe/trunk/test/CXX/drs/dr18xx.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr18xx.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/drs/dr18xx.cpp (original)
> +++ cfe/trunk/test/CXX/drs/dr18xx.cpp Tue Jul 17 02:23:31 2018
> @@ -30,17 +30,6 @@ namespace dr1813 { // dr1813: 7
>    static_assert(!__is_standard_layout(U), "");
>  }
>
> -namespace dr1815 { // dr1815: no
> -#if __cplusplus >= 201402L
> -  // FIXME: needs codegen test
> -  struct A { int &&r = 0; }; // FIXME expected-warning {{not supported}}
> -  A a = {}; // expected-note {{here}}
> -
> -  struct B { int &&r = 0; }; // expected-error {{binds to a temporary}}
> expected-note {{here}}
> -  B b; // expected-note {{here}}
> -#endif
> -}
> -
>  namespace dr1881 { // dr1881: 7
>    struct A { int a : 4; };
>    struct B : A { int b : 3; };
>
> Modified: cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp (original)
> +++ cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp Tue Jul 17
> 02:23:31 2018
> @@ -121,22 +121,13 @@ extern HasNoAccessDtorBase HNADBa;
>  HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted
> copy constructor}}
>
>  // -- a non-static data member of rvalue reference type
> -int some_int;
>  struct RValue {
> -  int && ri = static_cast<int&&>(some_int); // expected-note{{copy
> constructor of 'RValue' is implicitly deleted because field 'ri' is of
> rvalue reference type 'int &&'}}
> +  int && ri = 1; // expected-note{{copy constructor of 'RValue' is
> implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
> +  // expected-warning at -1{{binding reference member 'ri' to a temporary}}
> expected-note at -1 {{here}}
>  };
>  RValue RVa;
>  RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy
> constructor}}
>
> -// FIXME: The note on the class-name is attached to the location of the
> -// constructor. This is not especially clear.
> -struct RValueTmp { // expected-note {{used here}}
> -  int && ri = 1; // expected-note{{copy constructor of 'RValueTmp' is
> implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
> -  // expected-error at -1 {{reference member 'ri' binds to a temporary}}
> -};
> -RValueTmp RVTa; // expected-note {{implicit default constructor for
> 'RValueTmp' first required here}}
> -RValueTmp RVTb(RVTa); // expected-error{{call to implicitly-deleted copy
> constructor}}
> -
>  namespace PR13381 {
>    struct S {
>      S(const S&);
>
> Modified: cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp (original)
> +++ cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp Tue Jul 17
> 02:23:31 2018
> @@ -145,7 +145,7 @@ HasNoAccessDtorBase HNADBb(HNADBa); // e
>  // The restriction on rvalue reference members applies to only the copy
>  // constructor.
>  struct RValue {
> -  int &&ri = 1;
> +  int &&ri = 1; // expected-warning {{binding reference member 'ri' to a
> temporary}} expected-note {{here}}
>    RValue(RValue&&);
>  };
>  RValue::RValue(RValue&&) = default;
>
> Modified: cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp (original)
> +++ cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp Tue Jul 17 02:23:31
> 2018
> @@ -43,12 +43,8 @@ class NotDeleted2a { int &a = n; };
>  NotDeleted2a nd2a;
>  class NotDeleted2b { int &a = error; }; // expected-error {{undeclared
> identifier}}
>  NotDeleted2b nd2b;
> -class NotDeleted2c { int &&a = static_cast<int&&>(n); };
> +class NotDeleted2c { int &&a = 0; }; // expected-warning {{binding
> reference member 'a' to a temporary}} expected-note {{here}}
>  NotDeleted2c nd2c;
> -// Note: this one does not have a deleted default constructor even though
> the
> -// implicit default constructor is ill-formed!
> -class NotDeleted2d { int &&a = 0; }; // expected-error {{reference member
> 'a' binds to a temporary object}} expected-note {{here}}
> -NotDeleted2d nd2d; // expected-note {{first required here}}
>
>  // - any non-variant non-static data member of const qualified type (or
> array
>  // thereof) with no brace-or-equal-initializer does not have a
> user-provided
>
> Modified: cfe/trunk/test/CXX/temp/temp.param/p5.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.param/p5.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/temp/temp.param/p5.cpp (original)
> +++ cfe/trunk/test/CXX/temp/temp.param/p5.cpp Tue Jul 17 02:23:31 2018
> @@ -1,13 +1,13 @@
>  // RUN: %clang_cc1 -verify %s -std=c++14
>
> -template<const int I> struct S { // expected-note {{in default member
> initializer}}
> +template<const int I> struct S {
>    decltype(I) n;
> -  int &&r = I; // expected-error {{reference member 'r' binds to a
> temporary object}}
> +  int &&r = I; // expected-warning 2{{binding reference member 'r' to a
> temporary value}} expected-note 2{{declared here}}
>  };
> -S<5> s; // expected-note {{implicit default constructor}}
> +S<5> s; // expected-note {{instantiation}}
>
> -template<typename T, T v> struct U { // expected-note {{in default member
> initializer}}
> +template<typename T, T v> struct U {
>    decltype(v) n;
> -  int &&r = v; // expected-error {{reference member 'r' binds to a
> temporary object}}
> +  int &&r = v; // expected-warning {{binding reference member 'r' to a
> temporary value}} expected-note {{declared here}}
>  };
> -U<const int, 6> u; // expected-note {{implicit default constructor}}
> +U<const int, 6> u; // expected-note {{instantiation}}
>
> 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=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
> (original)
> +++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp Tue
> Jul 17 02:23:31 2018
> @@ -236,6 +236,36 @@ void fn9() {
>    // CHECK: ret void
>  }
>
> +struct haslist1 {
> +  std::initializer_list<int> il;
> +  haslist1(int i);
> +};
> +
> +// CHECK-LABEL: define void @_ZN8haslist1C2Ei
> +haslist1::haslist1(int i)
> +// CHECK: alloca [3 x i32]
> +// CHECK: store i32 %
> +// CHECK: store i32 2
> +// CHECK: store i32 3
> +  : il{i, 2, 3}
> +{
> +  destroyme2 dm2;
> +}
> +
> +struct haslist2 {
> +  std::initializer_list<destroyme1> il;
> +  haslist2();
> +};
> +
> +// CHECK-LABEL: define void @_ZN8haslist2C2Ev
> +haslist2::haslist2()
> +  : il{destroyme1(), destroyme1()}
> +{
> +  destroyme2 dm2;
> +  // CHECK: call void @_ZN10destroyme2D1Ev
> +  // CHECK: call void @_ZN10destroyme1D1Ev
> +}
> +
>  void fn10(int i) {
>    // CHECK-LABEL: define void @_Z4fn10i
>    // CHECK: alloca [3 x i32]
>
> Modified: cfe/trunk/test/CodeGenCXX/temporaries.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/temporaries.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/temporaries.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/temporaries.cpp Tue Jul 17 02:23:31 2018
> @@ -198,6 +198,20 @@ B::B()
>    f();
>  }
>
> +struct C {
> +  C();
> +
> +  const B& b;
> +};
> +
> +C::C()
> +  // CHECK: call void @_ZN6PR50771BC1Ev
> +  : b(B()) {
> +  // CHECK: call void @_ZN6PR50771fEv
> +  f();
> +
> +  // CHECK: call void @_ZN6PR50771BD1Ev
> +}
>  }
>
>  A f8() {
> @@ -802,3 +816,16 @@ namespace PR14130 {
>    // CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 0)
>    // CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE
>  }
> +
> +namespace Ctor {
> +  struct A { A(); ~A(); };
> +  void f();
> +  struct B {
> +    A &&a;
> +    B() : a{} { f(); }
> +  } b;
> +  // CHECK: define {{.*}}void @_ZN4Ctor1BC1Ev(
> +  // CHECK: call void @_ZN4Ctor1AC1Ev(
> +  // CHECK: call void @_ZN4Ctor1fEv(
> +  // CHECK: call void @_ZN4Ctor1AD1Ev(
> +}
>
> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Tue Jul 17
> 02:23:31 2018
> @@ -1892,15 +1892,14 @@ namespace Lifetime {
>    }
>
>    constexpr int &get(int &&n) { return n; }
> -  constexpr int &&get_rv(int &&n) { return static_cast<int&&>(n); }
>    struct S {
> -    int &&r;
> +    int &&r; // expected-note 2{{declared here}}
>      int &s;
>      int t;
> -    constexpr S() : r(get_rv(0)), s(get(0)), t(r) {} // expected-note
> {{read of object outside its lifetime}}
> -    constexpr S(int) : r(get_rv(0)), s(get(0)), t(s) {} // expected-note
> {{read of object outside its lifetime}}
> +    constexpr S() : r(0), s(get(0)), t(r) {} // expected-warning
> {{temporary}}
> +    constexpr S(int) : r(0), s(get(0)), t(s) {} // expected-warning
> {{temporary}} expected-note {{read of object outside its lifetime}}
>    };
> -  constexpr int k1 = S().t; // expected-error {{constant expression}}
> expected-note {{in call}}
> +  constexpr int k1 = S().t; // ok, int is lifetime-extended to end of
> constructor
>    constexpr int k2 = S(0).t; // expected-error {{constant expression}}
> expected-note {{in call}}
>  }
>
>
> Modified: cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constexpr-default-arg.cpp Tue Jul 17 02:23:31
> 2018
> @@ -31,8 +31,8 @@ void test_default_arg2() {
>  }
>
>  // Check that multiple CXXDefaultInitExprs don't cause an assertion
> failure.
> -struct A { int &&r = 0; }; // expected-warning 2{{not supported}}
> +struct A { int &&r = 0; }; // expected-warning {{binding reference
> member}} // expected-note {{reference member declared here}}
>  struct B { A x, y; };
> -B b = {}; // expected-note 2{{in default member initializer for field 'r'
> used here}}
> +B b = {};
>
>  }
>
> Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
> (original)
> +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Tue
> Jul 17 02:23:31 2018
> @@ -153,14 +153,13 @@ void dangle() {
>  }
>
>  struct haslist1 {
> -  std::initializer_list<int> il // expected-note {{declared here}}
> -    = {1, 2, 3}; // ok, unused
> -  std::initializer_list<int> jl{1, 2, 3}; // expected-error {{backing
> array for 'std::initializer_list' member 'jl' is a temporary object}}
> +  std::initializer_list<int> il = {1, 2, 3}; // expected-warning{{at the
> end of the constructor}}
> +  std::initializer_list<int> jl{1, 2, 3}; // expected-warning{{at the end
> of the constructor}}
>    haslist1();
>  };
>
> -haslist1::haslist1() // expected-note {{used here}}
> -: il{1, 2, 3} // expected-error {{backing array for
> 'std::initializer_list' member 'il' is a temporary object}}
> +haslist1::haslist1()
> +: il{1, 2, 3} // expected-warning{{at the end of the constructor}}
>  {}
>
>  namespace PR12119 {
>
> Modified: cfe/trunk/test/SemaCXX/eval-crashes.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/eval-crashes.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/eval-crashes.cpp (original)
> +++ cfe/trunk/test/SemaCXX/eval-crashes.cpp Tue Jul 17 02:23:31 2018
> @@ -26,10 +26,10 @@ namespace pr33140_0b {
>
>  namespace pr33140_2 {
>    // FIXME: The declaration of 'b' below should lifetime-extend two int
> -  // temporaries.
> -  struct A { int &&r = 0; }; // expected-warning 2{{not supported}}
> +  // temporaries, invalidating this warning to some extent.
> +  struct A { int &&r = 0; }; // expected-warning {{binding reference
> member 'r' to a temporary}} expected-note {{here}}
>    struct B { A x, y; };
> -  B b = {}; // expected-note 2{{used here}}
> +  B b = {};
>  }
>
>  namespace pr33140_3 {
>
> Modified: cfe/trunk/test/SemaCXX/member-init.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-init.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/member-init.cpp (original)
> +++ cfe/trunk/test/SemaCXX/member-init.cpp Tue Jul 17 02:23:31 2018
> @@ -86,8 +86,9 @@ namespace PR14838 {
>    };
>    struct thing {};
>    struct another {
> -    another() : r(thing()) {} // expected-error {{binds to a temporary
> object}}
> +    another() : r(thing()) {}
>      // expected-error at -1 {{temporary of type 'PR14838::function' has
> private destructor}}
> +    // expected-warning at -2 {{binding reference member 'r' to a temporary
> value}}
>      const function &r; // expected-note {{reference member declared here}}
>    } af;
>  }
>
> Modified: cfe/trunk/test/SemaCXX/warn-dangling-field.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-dangling-field.cpp?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/warn-dangling-field.cpp (original)
> +++ cfe/trunk/test/SemaCXX/warn-dangling-field.cpp Tue Jul 17 02:23:31 2018
> @@ -20,7 +20,7 @@ struct S {
>
>  struct S2 {
>    const X &x; // expected-note {{reference member declared here}}
> -  S2(int i) : x(i) {} // expected-error {{member 'x' binds to a
> temporary}}
> +  S2(int i) : x(i) {} // expected-warning {{binding reference member 'x'
> to a temporary}}
>  };
>
>  struct S3 {
> @@ -43,9 +43,9 @@ S5 s5 = { 0 }; // ok, lifetime-extended
>
>  struct S6 {
>    S5 s5; // expected-note {{here}}
> -  S6() : s5 { 0 } {} // expected-error {{reference subobject of member
> 's5' binds to a temporary}}
> +  S6() : s5 { 0 } {} // expected-warning {{binding reference subobject of
> member 's5' to a temporary}}
>  };
>
>  struct S7 : S5 {
> -  S7() : S5 { 0 } {} // expected-error {{reference member 'x' binds to a
> temporary}}
> +  S7() : S5 { 0 } {} // expected-warning {{binding reference member 'x'
> to a temporary}}
>  };
>
> Modified: cfe/trunk/www/cxx_dr_status.html
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=337255&r1=337254&r2=337255&view=diff
>
> ==============================================================================
> --- cfe/trunk/www/cxx_dr_status.html (original)
> +++ cfe/trunk/www/cxx_dr_status.html Tue Jul 17 02:23:31 2018
> @@ -9991,7 +9991,7 @@ and <I>POD class</I></td>
>      <td><a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1696
> ">1696</a></td>
>      <td>CD4</td>
>      <td>Temporary lifetime and non-static data member initializers</td>
> -    <td class="svn" align="center">SVN</td>
> +    <td class="none" align="center">Unknown</td>
>    </tr>
>    <tr class="open" id="1697">
>      <td><a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1697
> ">1697</a></td>
> @@ -10705,7 +10705,7 @@ and <I>POD class</I></td>
>      <td><a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1815
> ">1815</a></td>
>      <td>CD4</td>
>      <td>Lifetime extension in aggregate initialization</td>
> -    <td class="none" align="center">No</td>
> +    <td class="none" align="center">Unknown</td>
>    </tr>
>    <tr id="1816">
>      <td><a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1816
> ">1816</a></td>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180717/b5f948ec/attachment-0001.html>


More information about the cfe-commits mailing list