r329342 - PR36992: do not store beyond the dsize of a class object unless we know

via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 6 16:16:52 PDT 2018


Hi Richard, unfortunately there is another problem, again on the ARM bots:

http://lab.llvm.org:8011/builders/clang-cmake-armv7-quick/builds/769:

******************** TEST 'Clang :: CodeGenCXX/tail-padding.cpp' FAILED ********************
Script:
--
/home/buildslave/buildslave/clang-cmake-armv7-quick/stage1/bin/clang -cc1 -internal-isystem /home/buildslave/buildslave/clang-cmake-armv7-quick/stage1/lib/clang/7.0.0/include -nostdsysteminc -triple armv7l-unknown-linux-gnueabihf -emit-llvm -o - /home/buildslave/buildslave/clang-cmake-armv7-quick/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp | /home/buildslave/buildslave/clang-cmake-armv7-quick/stage1/bin/FileCheck /home/buildslave/buildslave/clang-cmake-armv7-quick/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp
--
Exit Code: 1

Command Output (stderr):
--
/home/buildslave/buildslave/clang-cmake-armv7-quick/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp:8:47: warning: static_assert with no message is a C++17 extension
  static_assert(sizeof(C) == sizeof(void*) + 8);
                                              ^
                                              , ""
/home/buildslave/buildslave/clang-cmake-armv7-quick/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp:25:46: warning: static_assert with no message is a C++17 extension
  static_assert(sizeof(C) > sizeof(void*) + 8);
                                             ^
                                             , ""
2 warnings generated.
/home/buildslave/buildslave/clang-cmake-armv7-quick/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp:14:12: error: expected string not found in input
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 7, i1 false)
           ^
<stdin>:97:62: note: scanning from here
%call = call %"struct.Implicit::A"* @_ZN8Implicit1AC2ERKS0_(%"struct.Implicit::A"* %3, %"struct.Implicit::A"* dereferenceable(1) %8)
                                                             ^
<stdin>:107:2: note: possible intended match here
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %15, i8* align 4 %16, i32 7, i1 false)
^

--

********************

Douglas Yung

From: Richard Smith [mailto:richard at metafoo.co.uk]
Sent: Friday, April 06, 2018 13:10
To: Yung, Douglas
Cc: cfe-commits
Subject: Re: r329342 - PR36992: do not store beyond the dsize of a class object unless we know

Hopefully r329449 will fix this.

On 6 April 2018 at 12:37, Richard Smith <richard at metafoo.co.uk<mailto:richard at metafoo.co.uk>> wrote:
Thanks, I see the problem.

On Fri, 6 Apr 2018, 11:56 via cfe-commits, <cfe-commits at lists.llvm.org<mailto:cfe-commits at lists.llvm.org>> wrote:
Hi Richard,

I don't know if you are aware, but the test you added in this commit, tail-padding.cpp is currently failing on one of the ARM bots. Can you take a look?

http://lab.llvm.org:8011/builders/clang-cmake-armv7-selfhost-neon/builds/178

******************** TEST 'Clang :: CodeGenCXX/tail-padding.cpp' FAILED ********************
Script:
--
/home/buildslave/buildslave/clang-cmake-armv7-selfhost-neon/stage2/bin/clang -cc1 -internal-isystem /home/buildslave/buildslave/clang-cmake-armv7-selfhost-neon/stage2/lib/clang/7.0.0/include -nostdsysteminc -triple armv7l-unknown-linux-gnueabihf -emit-llvm -o - /home/buildslave/buildslave/clang-cmake-armv7-selfhost-neon/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp | /home/buildslave/buildslave/clang-cmake-armv7-selfhost-neon/stage2/bin/FileCheck /home/buildslave/buildslave/clang-cmake-armv7-selfhost-neon/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp
--
Exit Code: 1

Command Output (stderr):
--
/home/buildslave/buildslave/clang-cmake-armv7-selfhost-neon/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp:8:47: warning: static_assert with no message is a C++17 extension
  static_assert(sizeof(C) == sizeof(void*) + 8);
                                              ^
                                              , ""
/home/buildslave/buildslave/clang-cmake-armv7-selfhost-neon/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp:25:46: warning: static_assert with no message is a C++17 extension
  static_assert(sizeof(C) > sizeof(void*) + 8);
                                             ^
                                             , ""
2 warnings generated.
/home/buildslave/buildslave/clang-cmake-armv7-selfhost-neon/llvm/tools/clang/test/CodeGenCXX/tail-padding.cpp:12:12: error: expected string not found in input
 // CHECK: call void @_ZN8Implicit1AC2ERKS0_(
           ^
<stdin>:78:66: note: scanning from here
define linkonce_odr %"struct.Implicit::C"* @_ZN8Implicit1CC1EOS0_(%"struct.Implicit::C"* returned %this, %"struct.Implicit::C"* dereferenceable(12)) unnamed_addr #0 comdat align 2 {
                                                                 ^
<stdin>:97:28: note: possible intended match here
 %call = call %"struct.Implicit::A"* @_ZN8Implicit1AC2ERKS0_(%"struct.Implicit::A"* %3, %"struct.Implicit::A"* dereferenceable(1) %8)
                           ^

--

********************

Douglas Yung

> -----Original Message-----
> From: cfe-commits [mailto:cfe-commits-bounces at lists.llvm.org<mailto:cfe-commits-bounces at lists.llvm.org>] On Behalf Of
> Richard Smith via cfe-commits
> Sent: Thursday, April 05, 2018 13:53
> To: cfe-commits at lists.llvm.org<mailto:cfe-commits at lists.llvm.org>
> Subject: r329342 - PR36992: do not store beyond the dsize of a class object
> unless we know
>
> Author: rsmith
> Date: Thu Apr  5 13:52:58 2018
> New Revision: 329342
>
> URL: http://llvm.org/viewvc/llvm-project?rev=329342&view=rev
> Log:
> PR36992: do not store beyond the dsize of a class object unless we know the
> tail padding is not reused.
>
> We track on the AggValueSlot (and through a couple of other initialization
> actions) whether we're dealing with an object that might share its tail
> padding with some other object, so that we can avoid emitting stores into the
> tail padding if that's the case. We still widen stores into tail padding when
> we can do so.
>
> Differential Revision: https://reviews.llvm.org/D45306
>
> Added:
>     cfe/trunk/test/CodeGenCXX/tail-padding.cpp
> Modified:
>     cfe/trunk/lib/CodeGen/CGAtomic.cpp
>     cfe/trunk/lib/CodeGen/CGBlocks.cpp
>     cfe/trunk/lib/CodeGen/CGCall.cpp
>     cfe/trunk/lib/CodeGen/CGClass.cpp
>     cfe/trunk/lib/CodeGen/CGDecl.cpp
>     cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
>     cfe/trunk/lib/CodeGen/CGExpr.cpp
>     cfe/trunk/lib/CodeGen/CGExprAgg.cpp
>     cfe/trunk/lib/CodeGen/CGExprCXX.cpp
>     cfe/trunk/lib/CodeGen/CGObjC.cpp
>     cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
>     cfe/trunk/lib/CodeGen/CGStmt.cpp
>     cfe/trunk/lib/CodeGen/CGValue.h
>     cfe/trunk/lib/CodeGen/CodeGenFunction.h
>     cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>
> Modified: cfe/trunk/lib/CodeGen/CGAtomic.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGAtomic.cpp?rev=329342&r1=329341&r2=329342&view
> =diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGAtomic.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGAtomic.cpp Thu Apr  5 13:52:58 2018
> @@ -1513,7 +1513,8 @@ void AtomicInfo::emitCopyIntoMemory(RVal
>                                      getAtomicType());
>      bool IsVolatile = rvalue.isVolatileQualified() ||
>                        LVal.isVolatileQualified();
> -    CGF.EmitAggregateCopy(Dest, Src, getAtomicType(), IsVolatile);
> +    CGF.EmitAggregateCopy(Dest, Src, getAtomicType(),
> +                          AggValueSlot::DoesNotOverlap, IsVolatile);
>      return;
>    }
>
> @@ -2008,6 +2009,7 @@ void CodeGenFunction::EmitAtomicInit(Exp
>                                          AggValueSlot::IsNotDestructed,
>                                          AggValueSlot::DoesNotNeedGCBarriers,
>                                          AggValueSlot::IsNotAliased,
> +                                        AggValueSlot::DoesNotOverlap,
>                                          Zeroed ? AggValueSlot::IsZeroed :
>                                                   AggValueSlot::IsNotZeroed);
>
>
> Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=329342&r1=329341&r2=329342&view
> =diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu Apr  5 13:52:58 2018
> @@ -929,7 +929,8 @@ llvm::Value *CodeGenFunction::EmitBlockL
>              AggValueSlot::forAddr(blockField, Qualifiers(),
>                                    AggValueSlot::IsDestructed,
>                                    AggValueSlot::DoesNotNeedGCBarriers,
> -                                  AggValueSlot::IsNotAliased);
> +                                  AggValueSlot::IsNotAliased,
> +                                  AggValueSlot::DoesNotOverlap);
>          EmitAggExpr(copyExpr, Slot);
>        } else {
>          EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr);
>
> Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=329342&r1=329341&r2=329342&view=d
> iff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Apr  5 13:52:58 2018
> @@ -3018,7 +3018,8 @@ static AggValueSlot createPlaceholderSlo
>                                 Ty.getQualifiers(),
>                                 AggValueSlot::IsNotDestructed,
>                                 AggValueSlot::DoesNotNeedGCBarriers,
> -                               AggValueSlot::IsNotAliased);
> +                               AggValueSlot::IsNotAliased,
> +                               AggValueSlot::DoesNotOverlap);
>  }
>
>  void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, @@ -3486,7
> +3487,8 @@ RValue CallArg::getRValue(CodeGenFunctio
>    if (!HasLV)
>      return RV;
>    LValue Copy = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty), Ty);
> -  CGF.EmitAggregateCopy(Copy, LV, Ty, LV.isVolatile());
> +  CGF.EmitAggregateCopy(Copy, LV, Ty, AggValueSlot::DoesNotOverlap,
> +                        LV.isVolatile());
>    IsUsed = true;
>    return RValue::getAggregate(Copy.getAddress());
>  }
> @@ -3500,7 +3502,8 @@ void CallArg::copyInto(CodeGenFunction &
>    else {
>      auto Addr = HasLV ? LV.getAddress() : RV.getAggregateAddress();
>      LValue SrcLV = CGF.MakeAddrLValue(Addr, Ty);
> -    CGF.EmitAggregateCopy(Dst, SrcLV, Ty,
> +    // We assume that call args are never copied into subobjects.
> +    CGF.EmitAggregateCopy(Dst, SrcLV, Ty, AggValueSlot::DoesNotOverlap,
>                            HasLV ? LV.isVolatileQualified()
>                                  : RV.isVolatileQualified());
>    }
>
> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=329342&r1=329341&r2=329342&view=
> diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Thu Apr  5 13:52:58 2018
> @@ -555,10 +555,12 @@ static void EmitBaseInitializer(CodeGenF
>                                                BaseClassDecl,
>                                                isBaseVirtual);
>    AggValueSlot AggSlot =
> -    AggValueSlot::forAddr(V, Qualifiers(),
> -                          AggValueSlot::IsDestructed,
> -                          AggValueSlot::DoesNotNeedGCBarriers,
> -                          AggValueSlot::IsNotAliased);
> +      AggValueSlot::forAddr(
> +          V, Qualifiers(),
> +          AggValueSlot::IsDestructed,
> +          AggValueSlot::DoesNotNeedGCBarriers,
> +          AggValueSlot::IsNotAliased,
> +          CGF.overlapForBaseInit(ClassDecl, BaseClassDecl,
> + isBaseVirtual));
>
>    CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);
>
> @@ -647,7 +649,8 @@ static void EmitMemberInitializer(CodeGe
>        LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field);
>
>        // Copy the aggregate.
> -      CGF.EmitAggregateCopy(LHS, Src, FieldType, LHS.isVolatileQualified());
> +      CGF.EmitAggregateCopy(LHS, Src, FieldType,
> CGF.overlapForFieldInit(Field),
> +                            LHS.isVolatileQualified());
>        // Ensure that we destroy the objects if an exception is thrown later
> in
>        // the constructor.
>        QualType::DestructionKind dtorKind = FieldType.isDestructedType(); @@ -
> 677,10 +680,12 @@ void CodeGenFunction::EmitInitializerFor
>      break;
>    case TEK_Aggregate: {
>      AggValueSlot Slot =
> -      AggValueSlot::forLValue(LHS,
> -                              AggValueSlot::IsDestructed,
> -                              AggValueSlot::DoesNotNeedGCBarriers,
> -                              AggValueSlot::IsNotAliased);
> +        AggValueSlot::forLValue(
> +            LHS,
> +            AggValueSlot::IsDestructed,
> +            AggValueSlot::DoesNotNeedGCBarriers,
> +            AggValueSlot::IsNotAliased,
> +            overlapForFieldInit(Field));
>      EmitAggExpr(Init, Slot);
>      break;
>    }
> @@ -911,15 +916,15 @@ namespace {
>      }
>
>      CharUnits getMemcpySize(uint64_t FirstByteOffset) const {
> +      ASTContext &Ctx = CGF.getContext();
>        unsigned LastFieldSize =
> -        LastField->isBitField() ?
> -          LastField->getBitWidthValue(CGF.getContext()) :
> -          CGF.getContext().getTypeSize(LastField->getType());
> -      uint64_t MemcpySizeBits =
> -        LastFieldOffset + LastFieldSize - FirstByteOffset +
> -        CGF.getContext().getCharWidth() - 1;
> -      CharUnits MemcpySize =
> -        CGF.getContext().toCharUnitsFromBits(MemcpySizeBits);
> +          LastField->isBitField()
> +              ? LastField->getBitWidthValue(Ctx)
> +              : Ctx.toBits(
> +                    Ctx.getTypeInfoDataSizeInChars(LastField-
> >getType()).first);
> +      uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -
> +                                FirstByteOffset + Ctx.getCharWidth() - 1;
> +      CharUnits MemcpySize = Ctx.toCharUnitsFromBits(MemcpySizeBits);
>        return MemcpySize;
>      }
>
> @@ -1960,7 +1965,8 @@ void CodeGenFunction::EmitCXXAggrConstru
>      }
>
>      EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false,
> -                           /*Delegating=*/false, curAddr, E);
> +                           /*Delegating=*/false, curAddr, E,
> +                           AggValueSlot::DoesNotOverlap);
>    }
>
>    // Go to the next element.
> @@ -1995,7 +2001,8 @@ void CodeGenFunction::EmitCXXConstructor
>                                               CXXCtorType Type,
>                                               bool ForVirtualBase,
>                                               bool Delegating, Address This,
> -                                             const CXXConstructExpr *E) {
> +                                             const CXXConstructExpr *E,
> +                                             AggValueSlot::Overlap_t
> + Overlap) {
>    CallArgList Args;
>
>    // Push the this ptr.
> @@ -2011,7 +2018,7 @@ void CodeGenFunction::EmitCXXConstructor
>      LValue Src = EmitLValue(Arg);
>      QualType DestTy = getContext().getTypeDeclType(D->getParent());
>      LValue Dest = MakeAddrLValue(This, DestTy);
> -    EmitAggregateCopyCtor(Dest, Src);
> +    EmitAggregateCopyCtor(Dest, Src, Overlap);
>      return;
>    }
>
> @@ -2023,7 +2030,8 @@ void CodeGenFunction::EmitCXXConstructor
>    EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor(),
>                 /*ParamsToSkip*/ 0, Order);
>
> -  EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args);
> +  EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args,
> +                         Overlap);
>  }
>
>  static bool canEmitDelegateCallArgs(CodeGenFunction &CGF, @@ -2055,7 +2063,8
> @@ void CodeGenFunction::EmitCXXConstructor
>                                               bool ForVirtualBase,
>                                               bool Delegating,
>                                               Address This,
> -                                             CallArgList &Args) {
> +                                             CallArgList &Args,
> +                                             AggValueSlot::Overlap_t
> + Overlap) {
>    const CXXRecordDecl *ClassDecl = D->getParent();
>
>    // C++11 [class.mfct.non-static]p2:
> @@ -2082,7 +2091,7 @@ void CodeGenFunction::EmitCXXConstructor
>      LValue SrcLVal = MakeAddrLValue(Src, SrcTy);
>      QualType DestTy = getContext().getTypeDeclType(ClassDecl);
>      LValue DestLVal = MakeAddrLValue(This, DestTy);
> -    EmitAggregateCopyCtor(DestLVal, SrcLVal);
> +    EmitAggregateCopyCtor(DestLVal, SrcLVal, Overlap);
>      return;
>    }
>
> @@ -2171,7 +2180,7 @@ void CodeGenFunction::EmitInheritedCXXCo
>    }
>
>    EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false,
> -                         This, Args);
> +                         This, Args, AggValueSlot::MayOverlap);
>  }
>
>  void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
> @@ -2267,7 +2276,8 @@ CodeGenFunction::EmitSynthesizedCXXCopyC
>    EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(),
>                 /*ParamsToSkip*/ 1);
>
> -  EmitCXXConstructorCall(D, Ctor_Complete, false, false, This, Args);
> +  EmitCXXConstructorCall(D, Ctor_Complete, false, false, This, Args,
> +                         AggValueSlot::MayOverlap);
>  }
>
>  void
> @@ -2302,7 +2312,8 @@ CodeGenFunction::EmitDelegateCXXConstruc
>    }
>
>    EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false,
> -                         /*Delegating=*/true, This, DelegateArgs);
> +                         /*Delegating=*/true, This, DelegateArgs,
> +                         AggValueSlot::MayOverlap);
>  }
>
>  namespace {
> @@ -2333,7 +2344,8 @@ CodeGenFunction::EmitDelegatingCXXConstr
>      AggValueSlot::forAddr(ThisPtr, Qualifiers(),
>                            AggValueSlot::IsDestructed,
>                            AggValueSlot::DoesNotNeedGCBarriers,
> -                          AggValueSlot::IsNotAliased);
> +                          AggValueSlot::IsNotAliased,
> +                          AggValueSlot::MayOverlap);
>
>    EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);
>
>
> Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=329342&r1=329341&r2=329342&view=d
> iff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Apr  5 13:52:58 2018
> @@ -1416,17 +1416,17 @@ void CodeGenFunction::EmitAutoVarInit(co
>    }
>  }
>
> -/// Emit an expression as an initializer for a variable at the given -///
> location.  The expression is not necessarily the normal -/// initializer for
> the variable, and the address is not necessarily
> +/// Emit an expression as an initializer for an object (variable,
> +field, etc.) /// at the given location.  The expression is not
> +necessarily the normal /// initializer for the object, and the address
> +is not necessarily
>  /// its normal location.
>  ///
>  /// \param init the initializing expression -/// \param var the variable to
> act as if we're initializing
> +/// \param D the object to act as if we're initializing
>  /// \param loc the address to initialize; its type is a pointer
> -///   to the LLVM mapping of the variable's type
> +///   to the LLVM mapping of the object's type
>  /// \param alignment the alignment of the address -/// \param capturedByInit
> true if the variable is a __block variable
> +/// \param capturedByInit true if \p D is a __block variable
>  ///   whose address is potentially changed by the initializer
>  void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D,
>                                       LValue lvalue, bool capturedByInit) { @@
> -1454,11 +1454,17 @@ void CodeGenFunction::EmitExprAsInit(con
>      if (type->isAtomicType()) {
>        EmitAtomicInit(const_cast<Expr*>(init), lvalue);
>      } else {
> +      AggValueSlot::Overlap_t Overlap = AggValueSlot::MayOverlap;
> +      if (isa<VarDecl>(D))
> +        Overlap = AggValueSlot::DoesNotOverlap;
> +      else if (auto *FD = dyn_cast<FieldDecl>(D))
> +        Overlap = overlapForFieldInit(FD);
>        // TODO: how can we delay here if D is captured by its initializer?
>        EmitAggExpr(init, AggValueSlot::forLValue(lvalue,
>                                                AggValueSlot::IsDestructed,
>                                           AggValueSlot::DoesNotNeedGCBarriers,
> -                                              AggValueSlot::IsNotAliased));
> +                                              AggValueSlot::IsNotAliased,
> +                                              Overlap));
>      }
>      return;
>    }
>
> Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=329342&r1=329341&r2=329342&vie
> w=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Thu Apr  5 13:52:58 2018
> @@ -53,7 +53,8 @@ static void EmitDeclInit(CodeGenFunction
>    case TEK_Aggregate:
>      CGF.EmitAggExpr(Init,
> AggValueSlot::forLValue(lv,AggValueSlot::IsDestructed,
>
> AggValueSlot::DoesNotNeedGCBarriers,
> -
> AggValueSlot::IsNotAliased));
> +                                                  AggValueSlot::IsNotAliased,
> +
> + AggValueSlot::DoesNotOverlap));
>      return;
>    }
>    llvm_unreachable("bad evaluation kind");
>
> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=329342&r1=329341&r2=329342&view=d
> iff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Apr  5 13:52:58 2018
> @@ -214,7 +214,8 @@ void CodeGenFunction::EmitAnyExprToMem(c
>      EmitAggExpr(E, AggValueSlot::forAddr(Location, Quals,
>
> AggValueSlot::IsDestructed_t(IsInit),
>                                           AggValueSlot::DoesNotNeedGCBarriers,
> -
> AggValueSlot::IsAliased_t(!IsInit)));
> +                                         AggValueSlot::IsAliased_t(!IsInit),
> +                                         AggValueSlot::MayOverlap));
>      return;
>    }
>
> @@ -432,7 +433,8 @@ EmitMaterializeTemporaryExpr(const Mater
>                                             E->getType().getQualifiers(),
>                                             AggValueSlot::IsDestructed,
>
> AggValueSlot::DoesNotNeedGCBarriers,
> -                                           AggValueSlot::IsNotAliased));
> +                                           AggValueSlot::IsNotAliased,
> +
> + AggValueSlot::DoesNotOverlap));
>        break;
>      }
>      }
>
> Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=329342&r1=329341&r2=329342&vie
> w=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Apr  5 13:52:58 2018
> @@ -337,7 +337,8 @@ void AggExprEmitter::EmitFinalDestCopy(Q
>
>    AggValueSlot srcAgg =
>      AggValueSlot::forLValue(src, AggValueSlot::IsDestructed,
> -                            needsGC(type), AggValueSlot::IsAliased);
> +                            needsGC(type), AggValueSlot::IsAliased,
> +                            AggValueSlot::MayOverlap);
>    EmitCopy(type, Dest, srcAgg);
>  }
>
> @@ -348,7 +349,7 @@ void AggExprEmitter::EmitFinalDestCopy(Q
>  void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest,
>                                const AggValueSlot &src) {
>    if (dest.requiresGCollection()) {
> -    CharUnits sz = CGF.getContext().getTypeSizeInChars(type);
> +    CharUnits sz = dest.getPreferredSize(CGF.getContext(), type);
>      llvm::Value *size = llvm::ConstantInt::get(CGF.SizeTy, sz.getQuantity());
>      CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF,
>                                                        dest.getAddress(), @@ -
> 362,7 +363,7 @@ void AggExprEmitter::EmitCopy(QualType t
>    // the two sides.
>    LValue DestLV = CGF.MakeAddrLValue(dest.getAddress(), type);
>    LValue SrcLV = CGF.MakeAddrLValue(src.getAddress(), type);
> -  CGF.EmitAggregateCopy(DestLV, SrcLV, type,
> +  CGF.EmitAggregateCopy(DestLV, SrcLV, type, dest.mayOverlap(),
>                          dest.isVolatile() || src.isVolatile());  }
>
> @@ -759,6 +760,7 @@ void AggExprEmitter::VisitCastExpr(CastE
>                                            valueDest.isExternallyDestructed(),
>                                            valueDest.requiresGCollection(),
>                                            valueDest.isPotentiallyAliased(),
> +                                          AggValueSlot::DoesNotOverlap,
>                                            AggValueSlot::IsZeroed);
>        }
>
> @@ -986,7 +988,8 @@ void AggExprEmitter::VisitBinAssign(cons
>      EmitCopy(E->getLHS()->getType(),
>               AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed,
>                                       needsGC(E->getLHS()->getType()),
> -                                     AggValueSlot::IsAliased),
> +                                     AggValueSlot::IsAliased,
> +                                     AggValueSlot::MayOverlap),
>               Dest);
>      return;
>    }
> @@ -1007,7 +1010,8 @@ void AggExprEmitter::VisitBinAssign(cons
>    AggValueSlot LHSSlot =
>      AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed,
>                              needsGC(E->getLHS()->getType()),
> -                            AggValueSlot::IsAliased);
> +                            AggValueSlot::IsAliased,
> +                            AggValueSlot::MayOverlap);
>    // A non-volatile aggregate destination might have volatile member.
>    if (!LHSSlot.isVolatile() &&
>        CGF.hasVolatileMember(E->getLHS()->getType()))
> @@ -1185,6 +1189,7 @@ AggExprEmitter::EmitInitializationToLVal
>                                                 AggValueSlot::IsDestructed,
>                                        AggValueSlot::DoesNotNeedGCBarriers,
>                                                 AggValueSlot::IsNotAliased,
> +
> + AggValueSlot::MayOverlap,
>                                                 Dest.isZeroed()));
>      return;
>    case TEK_Scalar:
> @@ -1283,11 +1288,12 @@ void AggExprEmitter::VisitInitListExpr(I
>        Address V = CGF.GetAddressOfDirectBaseInCompleteClass(
>            Dest.getAddress(), CXXRD, BaseRD,
>            /*isBaseVirtual*/ false);
> -      AggValueSlot AggSlot =
> -        AggValueSlot::forAddr(V, Qualifiers(),
> -                              AggValueSlot::IsDestructed,
> -                              AggValueSlot::DoesNotNeedGCBarriers,
> -                              AggValueSlot::IsNotAliased);
> +      AggValueSlot AggSlot = AggValueSlot::forAddr(
> +          V, Qualifiers(),
> +          AggValueSlot::IsDestructed,
> +          AggValueSlot::DoesNotNeedGCBarriers,
> +          AggValueSlot::IsNotAliased,
> +          CGF.overlapForBaseInit(CXXRD, BaseRD, Base.isVirtual()));
>        CGF.EmitAggExpr(E->getInit(curInitIndex++), AggSlot);
>
>        if (QualType::DestructionKind dtorKind = @@ -1468,7 +1474,9 @@ void
> AggExprEmitter::VisitArrayInitLoopE
>        // If the subexpression is an ArrayInitLoopExpr, share its cleanup.
>        auto elementSlot = AggValueSlot::forLValue(
>            elementLV, AggValueSlot::IsDestructed,
> -          AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased);
> +          AggValueSlot::DoesNotNeedGCBarriers,
> +          AggValueSlot::IsNotAliased,
> +          AggValueSlot::DoesNotOverlap);
>        AggExprEmitter(CGF, elementSlot, false)
>            .VisitArrayInitLoopExpr(InnerLoop, outerBegin);
>      } else
> @@ -1584,7 +1592,7 @@ static void CheckAggExprForMemSetUse(Agg
>      }
>
>    // If the type is 16-bytes or smaller, prefer individual stores over
> memset.
> -  CharUnits Size = CGF.getContext().getTypeSizeInChars(E->getType());
> +  CharUnits Size = Slot.getPreferredSize(CGF.getContext(),
> + E->getType());
>    if (Size <= CharUnits::fromQuantity(16))
>      return;
>
> @@ -1630,13 +1638,37 @@ LValue CodeGenFunction::EmitAggExprToLVa
>    LValue LV = MakeAddrLValue(Temp, E->getType());
>    EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsNotDestructed,
>                                           AggValueSlot::DoesNotNeedGCBarriers,
> -                                         AggValueSlot::IsNotAliased));
> +                                         AggValueSlot::IsNotAliased,
> +
> + AggValueSlot::DoesNotOverlap));
>    return LV;
>  }
>
> -void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src,
> -                                        QualType Ty, bool isVolatile,
> -                                        bool isAssignment) {
> +AggValueSlot::Overlap_t CodeGenFunction::overlapForBaseInit(
> +    const CXXRecordDecl *RD, const CXXRecordDecl *BaseRD, bool
> +IsVirtual) {
> +  // Virtual bases are initialized first, in address order, so there's
> +never
> +  // any overlap during their initialization.
> +  //
> +  // FIXME: Under P0840, this is no longer true: the tail padding of a
> +vbase
> +  // of a field could be reused by a vbase of a containing class.
> +  if (IsVirtual)
> +    return AggValueSlot::DoesNotOverlap;
> +
> +  // If the base class is laid out entirely within the nvsize of the
> + derived  // class, its tail padding cannot yet be initialized, so we
> + can issue  // stores at the full width of the base class.
> +  const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
> +  if (Layout.getBaseClassOffset(BaseRD) +
> +          getContext().getASTRecordLayout(BaseRD).getSize() <=
> +      Layout.getNonVirtualSize())
> +    return AggValueSlot::DoesNotOverlap;
> +
> +  // The tail padding may contain values we need to preserve.
> +  return AggValueSlot::MayOverlap;
> +}
> +
> +void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty,
> +                                        AggValueSlot::Overlap_t MayOverlap,
> +                                        bool isVolatile) {
>    assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex");
>
>    Address DestPtr = Dest.getAddress();
> @@ -1669,12 +1701,11 @@ void CodeGenFunction::EmitAggregateCopy(
>    // implementation handles this case safely.  If there is a libc that does
> not
>    // safely handle this, we can add a target hook.
>
> -  // Get data size info for this aggregate. If this is an assignment,
> -  // don't copy the tail padding, because we might be assigning into a
> -  // base subobject where the tail padding is claimed.  Otherwise,
> -  // copying it is fine.
> +  // Get data size info for this aggregate. Don't copy the tail padding
> + if this  // might be a potentially-overlapping subobject, since the
> + tail padding might  // be occupied by a different object. Otherwise, copying
> it is fine.
>    std::pair<CharUnits, CharUnits> TypeInfo;
> -  if (isAssignment)
> +  if (MayOverlap)
>      TypeInfo = getContext().getTypeInfoDataSizeInChars(Ty);
>    else
>      TypeInfo = getContext().getTypeInfoInChars(Ty);
> @@ -1686,22 +1717,11 @@ void CodeGenFunction::EmitAggregateCopy(
>              getContext().getAsArrayType(Ty))) {
>        QualType BaseEltTy;
>        SizeVal = emitArrayLength(VAT, BaseEltTy, DestPtr);
> -      TypeInfo = getContext().getTypeInfoDataSizeInChars(BaseEltTy);
> -      std::pair<CharUnits, CharUnits> LastElementTypeInfo;
> -      if (!isAssignment)
> -        LastElementTypeInfo = getContext().getTypeInfoInChars(BaseEltTy);
> +      TypeInfo = getContext().getTypeInfoInChars(BaseEltTy);
>        assert(!TypeInfo.first.isZero());
>        SizeVal = Builder.CreateNUWMul(
>            SizeVal,
>            llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity()));
> -      if (!isAssignment) {
> -        SizeVal = Builder.CreateNUWSub(
> -            SizeVal,
> -            llvm::ConstantInt::get(SizeTy, TypeInfo.first.getQuantity()));
> -        SizeVal = Builder.CreateNUWAdd(
> -            SizeVal, llvm::ConstantInt::get(
> -                         SizeTy, LastElementTypeInfo.first.getQuantity()));
> -      }
>      }
>    }
>    if (!SizeVal) {
>
> Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=329342&r1=329341&r2=329342&vie
> w=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Thu Apr  5 13:52:58 2018
> @@ -279,7 +279,10 @@ RValue CodeGenFunction::EmitCXXMemberOrO
>          const Expr *Arg = *CE->arg_begin();
>          LValue RHS = EmitLValue(Arg);
>          LValue Dest = MakeAddrLValue(This.getAddress(), Arg->getType());
> -        EmitAggregateCopy(Dest, RHS, Arg->getType());
> +        // This is the MSVC p->Ctor::Ctor(...) extension. We assume that's
> +        // constructing a new complete object of type Ctor.
> +        EmitAggregateCopy(Dest, RHS, Arg->getType(),
> +                          AggValueSlot::DoesNotOverlap);
>          return RValue::get(This.getPointer());
>        }
>        llvm_unreachable("unknown trivial member function"); @@ -631,7 +634,7
> @@ CodeGenFunction::EmitCXXConstructExpr(co
>
>      // Call the constructor.
>      EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating,
> -                           Dest.getAddress(), E);
> +                           Dest.getAddress(), E, Dest.mayOverlap());
>    }
>  }
>
> @@ -933,7 +936,8 @@ static llvm::Value *EmitCXXNewAllocSize(  }
>
>  static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
> -                                    QualType AllocType, Address NewPtr) {
> +                                    QualType AllocType, Address NewPtr,
> +                                    AggValueSlot::Overlap_t MayOverlap)
> + {
>    // FIXME: Refactor with EmitExprAsInit.
>    switch (CGF.getEvaluationKind(AllocType)) {
>    case TEK_Scalar:
> @@ -949,7 +953,8 @@ static void StoreAnyExprIntoOneUnit(Code
>        = AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(),
>                                AggValueSlot::IsDestructed,
>                                AggValueSlot::DoesNotNeedGCBarriers,
> -                              AggValueSlot::IsNotAliased);
> +                              AggValueSlot::IsNotAliased,
> +                              MayOverlap);
>      CGF.EmitAggExpr(Init, Slot);
>      return;
>    }
> @@ -1018,7 +1023,8 @@ void CodeGenFunction::EmitNewArrayInitia
>            AggValueSlot::forAddr(CurPtr, ElementType.getQualifiers(),
>                                  AggValueSlot::IsDestructed,
>                                  AggValueSlot::DoesNotNeedGCBarriers,
> -                                AggValueSlot::IsNotAliased);
> +                                AggValueSlot::IsNotAliased,
> +                                AggValueSlot::DoesNotOverlap);
>        EmitAggExpr(ILE->getInit(0), Slot);
>
>        // Move past these elements.
> @@ -1083,7 +1089,8 @@ void CodeGenFunction::EmitNewArrayInitia
>        // an array, and we have an array filler, we can fold together the two
>        // initialization loops.
>        StoreAnyExprIntoOneUnit(*this, ILE->getInit(i),
> -                              ILE->getInit(i)->getType(), CurPtr);
> +                              ILE->getInit(i)->getType(), CurPtr,
> +                              AggValueSlot::DoesNotOverlap);
>        CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getPointer(),
>                                                   Builder.getSize(1),
>                                                   "array.exp.next"), @@ -
> 1236,7 +1243,8 @@ void CodeGenFunction::EmitNewArrayInitia
>    }
>
>    // Emit the initializer into this element.
> -  StoreAnyExprIntoOneUnit(*this, Init, Init->getType(), CurPtr);
> +  StoreAnyExprIntoOneUnit(*this, Init, Init->getType(), CurPtr,
> +                          AggValueSlot::DoesNotOverlap);
>
>    // Leave the Cleanup if we entered one.
>    if (CleanupDominator) {
> @@ -1267,7 +1275,8 @@ static void EmitNewInitializer(CodeGenFu
>      CGF.EmitNewArrayInitializer(E, ElementType, ElementTy, NewPtr,
> NumElements,
>                                  AllocSizeWithoutCookie);
>    else if (const Expr *Init = E->getInitializer())
> -    StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr);
> +    StoreAnyExprIntoOneUnit(CGF, Init, E->getAllocatedType(), NewPtr,
> +                            AggValueSlot::DoesNotOverlap);
>  }
>
>  /// Emit a call to an operator new or operator delete function, as implicitly
>
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=329342&r1=329341&r2=329342&view=d
> iff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Thu Apr  5 13:52:58 2018
> @@ -1013,8 +1013,9 @@ CodeGenFunction::generateObjCGetterBody(
>        // that's not necessarily the same as "on the stack", so
>        // we still potentially need objc_memmove_collectable.
>        EmitAggregateCopy(/* Dest= */ MakeAddrLValue(ReturnValue, ivarType),
> -                        /* Src= */ LV, ivarType);
> -      return; }
> +                        /* Src= */ LV, ivarType, overlapForReturnValue());
> +      return;
> +    }
>      case TEK_Scalar: {
>        llvm::Value *value;
>        if (propType->isReferenceType()) { @@ -1439,7 +1440,8 @@ void
> CodeGenFunction::GenerateObjCCtorDt
>        EmitAggExpr(IvarInit->getInit(),
>                    AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed,
>
> AggValueSlot::DoesNotNeedGCBarriers,
> -                                          AggValueSlot::IsNotAliased));
> +                                          AggValueSlot::IsNotAliased,
> +
> + AggValueSlot::DoesNotOverlap));
>      }
>      // constructor returns 'self'.
>      CodeGenTypes &Types = CGM.getTypes(); @@ -3381,7 +3383,8 @@
> CodeGenFunction::GenerateObjCAtomicGette
>                                      Qualifiers(),
>                                      AggValueSlot::IsDestructed,
>                                      AggValueSlot::DoesNotNeedGCBarriers,
> -                                    AggValueSlot::IsNotAliased));
> +                                    AggValueSlot::IsNotAliased,
> +                                    AggValueSlot::DoesNotOverlap));
>
>    FinishFunction();
>    HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
>
> Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=329342&r1=329341&r2=3293
> 42&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Thu Apr  5 13:52:58 2018
> @@ -4793,7 +4793,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFun
>                  CGF.getNaturalTypeAlignment(SharedsTy));
>      LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
>      LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
> -    CGF.EmitAggregateCopy(Dest, Src, SharedsTy);
> +    CGF.EmitAggregateCopy(Dest, Src, SharedsTy,
> + AggValueSlot::DoesNotOverlap);
>    }
>    // Emit initial values for private copies (if any).
>    TaskResultTy Result;
>
> Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=329342&r1=329341&r2=329342&view=d
> iff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGStmt.cpp Thu Apr  5 13:52:58 2018
> @@ -1007,7 +1007,7 @@ void CodeGenFunction::EmitReturnOfRValue
>    } else if (RV.isAggregate()) {
>      LValue Dest = MakeAddrLValue(ReturnValue, Ty);
>      LValue Src = MakeAddrLValue(RV.getAggregateAddress(), Ty);
> -    EmitAggregateCopy(Dest, Src, Ty);
> +    EmitAggregateCopy(Dest, Src, Ty, overlapForReturnValue());
>    } else {
>      EmitStoreOfComplex(RV.getComplexVal(), MakeAddrLValue(ReturnValue, Ty),
>                         /*init*/ true);
> @@ -1085,11 +1085,12 @@ void CodeGenFunction::EmitReturnStmt(con
>                                  /*isInit*/ true);
>        break;
>      case TEK_Aggregate:
> -      EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue,
> -                                            Qualifiers(),
> -                                            AggValueSlot::IsDestructed,
> -
> AggValueSlot::DoesNotNeedGCBarriers,
> -                                            AggValueSlot::IsNotAliased));
> +      EmitAggExpr(RV, AggValueSlot::forAddr(
> +                          ReturnValue, Qualifiers(),
> +                          AggValueSlot::IsDestructed,
> +                          AggValueSlot::DoesNotNeedGCBarriers,
> +                          AggValueSlot::IsNotAliased,
> +                          overlapForReturnValue()));
>        break;
>      }
>    }
>
> Modified: cfe/trunk/lib/CodeGen/CGValue.h
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CGValue.h?rev=329342&r1=329341&r2=329342&view=di
> ff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGValue.h (original)
> +++ cfe/trunk/lib/CodeGen/CGValue.h Thu Apr  5 13:52:58 2018
> @@ -472,17 +472,25 @@ class AggValueSlot {
>    /// evaluating an expression which constructs such an object.
>    bool AliasedFlag : 1;
>
> +  /// This is set to true if the tail padding of this slot might
> + overlap  /// another object that may have already been initialized
> + (and whose  /// value must be preserved by this initialization). If
> + so, we may only  /// store up to the dsize of the type. Otherwise we
> + can widen stores to  /// the size of the type.
> +  bool OverlapFlag : 1;
> +
>  public:
>    enum IsAliased_t { IsNotAliased, IsAliased };
>    enum IsDestructed_t { IsNotDestructed, IsDestructed };
>    enum IsZeroed_t { IsNotZeroed, IsZeroed };
> +  enum Overlap_t { DoesNotOverlap, MayOverlap };
>    enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers };
>
>    /// ignored - Returns an aggregate value slot indicating that the
>    /// aggregate value is being ignored.
>    static AggValueSlot ignored() {
>      return forAddr(Address::invalid(), Qualifiers(), IsNotDestructed,
> -                   DoesNotNeedGCBarriers, IsNotAliased);
> +                   DoesNotNeedGCBarriers, IsNotAliased,
> + DoesNotOverlap);
>    }
>
>    /// forAddr - Make a slot for an aggregate value.
> @@ -500,6 +508,7 @@ public:
>                                IsDestructed_t isDestructed,
>                                NeedsGCBarriers_t needsGC,
>                                IsAliased_t isAliased,
> +                              Overlap_t mayOverlap,
>                                IsZeroed_t isZeroed = IsNotZeroed) {
>      AggValueSlot AV;
>      if (addr.isValid()) {
> @@ -514,6 +523,7 @@ public:
>      AV.ObjCGCFlag = needsGC;
>      AV.ZeroedFlag = isZeroed;
>      AV.AliasedFlag = isAliased;
> +    AV.OverlapFlag = mayOverlap;
>      return AV;
>    }
>
> @@ -521,9 +531,10 @@ public:
>                                  IsDestructed_t isDestructed,
>                                  NeedsGCBarriers_t needsGC,
>                                  IsAliased_t isAliased,
> +                                Overlap_t mayOverlap,
>                                  IsZeroed_t isZeroed = IsNotZeroed) {
> -    return forAddr(LV.getAddress(),
> -                   LV.getQuals(), isDestructed, needsGC, isAliased,
> isZeroed);
> +    return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, needsGC,
> +                   isAliased, mayOverlap, isZeroed);
>    }
>
>    IsDestructed_t isExternallyDestructed() const { @@ -571,6 +582,10 @@
> public:
>      return IsAliased_t(AliasedFlag);
>    }
>
> +  Overlap_t mayOverlap() const {
> +    return Overlap_t(OverlapFlag);
> +  }
> +
>    RValue asRValue() const {
>      if (isIgnored()) {
>        return RValue::getIgnored();
> @@ -583,6 +598,14 @@ public:
>    IsZeroed_t isZeroed() const {
>      return IsZeroed_t(ZeroedFlag);
>    }
> +
> +  /// Get the preferred size to use when storing a value to this slot.
> + This  /// is the type size unless that might overlap another object,
> + in which  /// case it's the dsize.
> +  CharUnits getPreferredSize(ASTContext &Ctx, QualType Type) const {
> +    return mayOverlap() ? Ctx.getTypeInfoDataSizeInChars(Type).first
> +                        : Ctx.getTypeSizeInChars(Type);  }
>  };
>
>  }  // end namespace CodeGen
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=329342&r1=329341&r2=329342
> &view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Apr  5 13:52:58 2018
> @@ -2061,7 +2061,8 @@ public:
>                                   T.getQualifiers(),
>                                   AggValueSlot::IsNotDestructed,
>                                   AggValueSlot::DoesNotNeedGCBarriers,
> -                                 AggValueSlot::IsNotAliased);
> +                                 AggValueSlot::IsNotAliased,
> +                                 AggValueSlot::DoesNotOverlap);
>    }
>
>    /// Emit a cast to void* in the appropriate address space.
> @@ -2118,28 +2119,52 @@ public:
>      }
>      return false;
>    }
> -  /// EmitAggregateCopy - Emit an aggregate assignment.
> -  ///
> -  /// The difference to EmitAggregateCopy is that tail padding is not copied.
> -  /// This is required for correctness when assigning non-POD structures in
> C++.
> +
> +  /// Determine whether a return value slot may overlap some other object.
> +  AggValueSlot::Overlap_t overlapForReturnValue() {
> +    // FIXME: Assuming no overlap here breaks guaranteed copy elision for
> base
> +    // class subobjects. These cases may need to be revisited depending on
> the
> +    // resolution of the relevant core issue.
> +    return AggValueSlot::DoesNotOverlap;  }
> +
> +  /// Determine whether a field initialization may overlap some other object.
> +  AggValueSlot::Overlap_t overlapForFieldInit(const FieldDecl *FD) {
> +    // FIXME: These cases can result in overlap as a result of P0840R0's
> +    // [[no_unique_address]] attribute. We can still infer NoOverlap in the
> +    // presence of that attribute if the field is within the nvsize of its
> +    // containing class, because non-virtual subobjects are initialized in
> +    // address order.
> +    return AggValueSlot::DoesNotOverlap;  }
> +
> +  /// Determine whether a base class initialization may overlap some
> + other  /// object.
> +  AggValueSlot::Overlap_t overlapForBaseInit(const CXXRecordDecl *RD,
> +                                             const CXXRecordDecl *BaseRD,
> +                                             bool IsVirtual);
> +
> +  /// Emit an aggregate assignment.
>    void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy) {
>      bool IsVolatile = hasVolatileMember(EltTy);
> -    EmitAggregateCopy(Dest, Src, EltTy, IsVolatile, /* isAssignment= */
> true);
> +    EmitAggregateCopy(Dest, Src, EltTy, AggValueSlot::MayOverlap,
> + IsVolatile);
>    }
>
> -  void EmitAggregateCopyCtor(LValue Dest, LValue Src) {
> -    EmitAggregateCopy(Dest, Src, Src.getType(),
> -                      /* IsVolatile= */ false, /* IsAssignment= */ false);
> +  void EmitAggregateCopyCtor(LValue Dest, LValue Src,
> +                             AggValueSlot::Overlap_t MayOverlap) {
> +    EmitAggregateCopy(Dest, Src, Src.getType(), MayOverlap);
>    }
>
>    /// EmitAggregateCopy - Emit an aggregate copy.
>    ///
> -  /// \param isVolatile - True iff either the source or the destination is
> -  /// volatile.
> -  /// \param isAssignment - If false, allow padding to be copied.  This often
> -  /// yields more efficient.
> +  /// \param isVolatile \c true iff either the source or the destination is
> +  ///        volatile.
> +  /// \param MayOverlap Whether the tail padding of the destination might be
> +  ///        occupied by some other object. More efficient code can often be
> +  ///        generated if not.
>    void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy,
> -                         bool isVolatile = false, bool isAssignment = false);
> +                         AggValueSlot::Overlap_t MayOverlap,
> +                         bool isVolatile = false);
>
>    /// GetAddrOfLocalVar - Return the address of a local variable.
>    Address GetAddrOfLocalVar(const VarDecl *VD) { @@ -2303,11 +2328,13 @@
> public:
>
>    void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
>                                bool ForVirtualBase, bool Delegating,
> -                              Address This, const CXXConstructExpr *E);
> +                              Address This, const CXXConstructExpr *E,
> +                              AggValueSlot::Overlap_t Overlap);
>
>    void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
>                                bool ForVirtualBase, bool Delegating,
> -                              Address This, CallArgList &Args);
> +                              Address This, CallArgList &Args,
> +                              AggValueSlot::Overlap_t Overlap);
>
>    /// Emit assumption load for all bases. Requires to be be called only on
>    /// most-derived class and not under construction of the object.
>
> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=329342&r1=329341&r2=329342
> &view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Thu Apr  5 13:52:58 2018
> @@ -3896,7 +3896,7 @@ static void InitCatchParam(CodeGenFuncti
>                          caughtExnAlignment);
>      LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType);
>      LValue Src = CGF.MakeAddrLValue(adjustedExn, CatchType);
> -    CGF.EmitAggregateCopy(Dest, Src, CatchType);
> +    CGF.EmitAggregateCopy(Dest, Src, CatchType,
> + AggValueSlot::DoesNotOverlap);
>      return;
>    }
>
> @@ -3923,7 +3923,8 @@ static void InitCatchParam(CodeGenFuncti
>                    AggValueSlot::forAddr(ParamAddr, Qualifiers(),
>                                          AggValueSlot::IsNotDestructed,
>                                          AggValueSlot::DoesNotNeedGCBarriers,
> -                                        AggValueSlot::IsNotAliased));
> +                                        AggValueSlot::IsNotAliased,
> +                                        AggValueSlot::DoesNotOverlap));
>
>    // Leave the terminate scope.
>    CGF.EHStack.popTerminate();
>
> Added: cfe/trunk/test/CodeGenCXX/tail-padding.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/tail-
> padding.cpp?rev=329342&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/tail-padding.cpp (added)
> +++ cfe/trunk/test/CodeGenCXX/tail-padding.cpp Thu Apr  5 13:52:58 2018
> @@ -0,0 +1,34 @@
> +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s |
> +FileCheck %s
> +
> +// PR36992
> +namespace Implicit {
> +  struct A { char c; A(const A&); };
> +  struct B { int n; char c[3]; ~B(); };
> +  struct C : B, virtual A {};
> +  static_assert(sizeof(C) == sizeof(void*) + 8);
> +  C f(C c) { return c; }
> +
> +  // CHECK: define {{.*}} @_ZN8Implicit1CC1EOS0_
> +  // CHECK: call void @_ZN8Implicit1AC2ERKS0_(
> +  // Note: this must memcpy 7 bytes, not 8, to avoid trampling over the
> virtual base class.
> +  // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8*
> +{{.*}}, i64 7, i1 false)
> +  // CHECK: store i32 {{.*}} @_ZTVN8Implicit1CE }
> +
> +namespace InitWithinNVSize {
> +  // This is the same as the previous test, except that the A base lies
> +  // entirely within the nvsize of C. This makes it valid to copy at
> +the
> +  // full width.
> +  struct A { char c; A(const A&); };
> +  struct B { int n; char c[3]; ~B(); };
> +  struct C : B, virtual A { char x; };
> +  static_assert(sizeof(C) > sizeof(void*) + 8);
> +  C f(C c) { return c; }
> +
> +  // CHECK: define {{.*}} @_ZN16InitWithinNVSize1CC1EOS0_
> +  // CHECK: call void @_ZN16InitWithinNVSize1AC2ERKS0_(
> +  // This copies over the 'C::x' member, but that's OK because we've not
> initialized it yet.
> +  // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8*
> +{{.*}}, i64 8, i1 false)
> +  // CHECK: store i32 {{.*}} @_ZTVN16InitWithinNVSize1CE
> +  // CHECK: store i8
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org<mailto:cfe-commits at lists.llvm.org>
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
_______________________________________________
cfe-commits mailing list
cfe-commits at lists.llvm.org<mailto: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/20180406/95eaafed/attachment-0001.html>


More information about the cfe-commits mailing list