<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
</head>
<body>
<style type="text/css" style="display:none;"><!-- P {margin-top:0;margin-bottom:0;} --></style>
<div id="divtagdefaultwrapper" style="font-size:12pt;color:#000000;background-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;">
<p>Hi Richard,</p>
<p><br>
</p>
<p>may I suggest to handle the reference binding to unaligned fields in another change rather than trying to get it in the current change (which was originally intended for address taking of such fields)? After your message, it looks to me that references will
 require a different strategy.</p>
<p><br>
</p>
<p>Kind regards,</p>
<p>Roger<br>
</p>
</div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> metafoo@gmail.com <metafoo@gmail.com> on behalf of Richard Smith <richard@metafoo.co.uk><br>
<b>Sent:</b> 15 July 2016 01:28:57<br>
<b>To:</b> Reid Kleckner<br>
<b>Cc:</b> Roger Ferrer Ibanez; cfe-commits<br>
<b>Subject:</b> Re: r275417 - Diagnose taking address and reference binding of packed members</font>
<div> </div>
</div>
<div>
<div dir="ltr">OK, actually, GCC is doing something a lot more clever here.
<div><br>
</div>
<div>Here's what seems to really be going on:</div>
<div><br>
</div>
<div>Packed members are modeled somewhat like bitfield members: a packed member lvalue is a different kind of lvalue to which a reference cannot be bound (like a bitfield). An attempt to bind a const / rvalue reference to such a member will create a temporary,
 copy the packed / bitfield member to the temporary, and then bind the reference to the temporary.</div>
<div><br>
</div>
<div>If we want to follow GCC here (and I think we do -- this seems like a very sensible model), we should handle this case as an ObjectKind and generally apply the same semantic rules that we use for bitfields.</div>
</div>
<div class="gmail_extra"><br>
<div class="gmail_quote">On Thu, Jul 14, 2016 at 5:18 PM, Richard Smith <span dir="ltr">
<<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">It appears that GCC accepts that case. More generally, it looks like GCC suppresses the warning when the reference is a function parameter (any function, not just a copy constructor or similar). I'm not sure if that's an intentional
 feature or a bug, but it should be pretty easy for us to be compatible with, at least...</div>
<div>
<div class="h5">
<div class="gmail_quote"><br>
</div>
<div class="gmail_quote">On Thu, Jul 14, 2016 at 5:03 PM, Reid Kleckner <span dir="ltr">
<<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">I wonder if GCC accepts this:
<div><br>
<div>
<div>In file included from ../../net/tools/quic/quic_epoll_clock_test.cc:7:</div>
<div>In file included from ../../net/tools/quic/test_tools/mock_epoll_server.h:16:</div>
<div>In file included from ../../net/tools/epoll_server/epoll_server.h:41:</div>
<div>../../build/linux/debian_wheezy_amd64-sysroot/usr/include/x86_64-linux-gnu/sys/epoll.h:89:8: error: binding reference to packed member 'data' of class or structure 'epoll_event'</div>
<div>struct epoll_event</div>
<div>       ^~~~~~~~~~~</div>
<div>../../build/linux/debian_wheezy_amd64-sysroot/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/stl_pair.h:267:14: note: in instantiation of function template specialization 'std::pair<long, epoll_event>::pair<long, epoll_event>' requested
 here</div>
<div>      return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));</div>
<div>             ^</div>
<div>../../net/tools/quic/test_tools/mock_epoll_server.h:69:30: note: in instantiation of function template specialization 'std::make_pair<long &, const epoll_event &>' requested here</div>
<div>    event_queue_.insert(std::make_pair(time_in_usec, ee));</div>
</div>
</div>
</div>
<div>
<div>
<div class="gmail_extra"><br>
<div class="gmail_quote">On Thu, Jul 14, 2016 at 4:54 PM, Richard Smith <span dir="ltr">
<<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote"><span>On Thu, Jul 14, 2016 at 3:52 PM, Reid Kleckner via cfe-commits
<span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">Why did we upgrade the unaligned reference binding from a warning to an error? That will make it hard to roll this change out across many codebases.</div>
</blockquote>
<div><br>
</div>
</span>
<div>GCC has given an error on this since version 4.7. If there are cases that GCC accepts and we reject, that sounds like a bug.</div>
<div>
<div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>
<div>
<div class="gmail_extra">
<div class="gmail_quote">On Thu, Jul 14, 2016 at 7:10 AM, Roger Ferrer Ibanez via cfe-commits
<span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: rogfer01<br>
Date: Thu Jul 14 09:10:43 2016<br>
New Revision: 275417<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=275417&view=rev" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project?rev=275417&view=rev</a><br>
Log:<br>
Diagnose taking address and reference binding of packed members<br>
<br>
This patch implements PR#22821.<br>
<br>
Taking the address of a packed member is dangerous since the reduced<br>
alignment of the pointee is lost. This can lead to memory alignment<br>
faults in some architectures if the pointer value is dereferenced.<br>
<br>
This change adds a new warning to clang emitted when taking the address<br>
of a packed member. A packed member is either a field/data member<br>
declared as attribute((packed)) or belonging to a struct/class<br>
declared as such. The associated flag is -Waddress-of-packed-member.<br>
Conversions (either implicit or via a valid casting) to pointer types<br>
with lower or equal alignment requirements (e.g. void* or char*)<br>
silence the warning.<br>
<br>
This change also adds a new error diagnostic when the user attempts to<br>
bind a reference to a packed member, regardless of the alignment.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D20561" rel="noreferrer" target="_blank">
https://reviews.llvm.org/D20561</a><br>
<br>
<br>
<br>
Added:<br>
    cfe/trunk/test/Sema/address-packed-member-memops.c<br>
    cfe/trunk/test/Sema/address-packed.c<br>
    cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp<br>
    cfe/trunk/test/SemaCXX/address-packed.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
    cfe/trunk/include/clang/Sema/Sema.h<br>
    cfe/trunk/lib/Sema/SemaCast.cpp<br>
    cfe/trunk/lib/Sema/SemaChecking.cpp<br>
    cfe/trunk/lib/Sema/SemaExpr.cpp<br>
    cfe/trunk/lib/Sema/SemaInit.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=275417&r1=275416&r2=275417&view=diff" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=275417&r1=275416&r2=275417&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul 14 09:10:43 2016<br>
@@ -5425,6 +5425,11 @@ def warn_pointer_indirection_from_incomp<br>
   "dereference of type %1 that was reinterpret_cast from type %0 has undefined "<br>
   "behavior">,<br>
   InGroup<UndefinedReinterpretCast>, DefaultIgnore;<br>
+def warn_taking_address_of_packed_member : Warning<<br>
+  "taking address of packed member %0 of class or structure %q1 may result in an unaligned pointer value">,<br>
+  InGroup<DiagGroup<"address-of-packed-member">>;<br>
+def err_binding_reference_to_packed_member : Error<<br>
+  "binding reference to packed member %0 of class or structure %q1">;<br>
<br>
 def err_objc_object_assignment : Error<<br>
   "cannot assign to class object (%0 invalid)">;<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=275417&r1=275416&r2=275417&view=diff" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=275417&r1=275416&r2=275417&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jul 14 09:10:43 2016<br>
@@ -9518,6 +9518,10 @@ private:<br>
   void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,<br>
                                 const Expr * const *ExprArgs);<br>
<br>
+  /// \brief Check if we are taking the address of a packed field<br>
+  /// as this may be a problem if the pointer value is dereferenced.<br>
+  void CheckAddressOfPackedMember(Expr *rhs);<br>
+<br>
   /// \brief The parser's current scope.<br>
   ///<br>
   /// The parser maintains this state here.<br>
@@ -9596,6 +9600,51 @@ public:<br>
   // Emitting members of dllexported classes is delayed until the class<br>
   // (including field initializers) is fully parsed.<br>
   SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;<br>
+<br>
+private:<br>
+  /// \brief Helper class that collects misaligned member designations and<br>
+  /// their location info for delayed diagnostics.<br>
+  struct MisalignedMember {<br>
+    Expr *E;<br>
+    RecordDecl *RD;<br>
+    ValueDecl *MD;<br>
+    CharUnits Alignment;<br>
+<br>
+    MisalignedMember() : E(), RD(), MD(), Alignment() {}<br>
+    MisalignedMember(Expr *E, RecordDecl *RD, ValueDecl *MD,<br>
+                     CharUnits Alignment)<br>
+        : E(E), RD(RD), MD(MD), Alignment(Alignment) {}<br>
+    explicit MisalignedMember(Expr *E)<br>
+        : MisalignedMember(E, nullptr, nullptr, CharUnits()) {}<br>
+<br>
+    bool operator==(const MisalignedMember &m) { return this->E == m.E; }<br>
+  };<br>
+  /// \brief Small set of gathered accesses to potentially misaligned members<br>
+  /// due to the packed attribute.<br>
+  SmallVector<MisalignedMember, 4> MisalignedMembers;<br>
+<br>
+  /// \brief Adds an expression to the set of gathered misaligned members.<br>
+  void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,<br>
+                                     CharUnits Alignment);<br>
+<br>
+public:<br>
+  /// \brief Diagnoses the current set of gathered accesses. This typically<br>
+  /// happens at full expression level. The set is cleared after emitting the<br>
+  /// diagnostics.<br>
+  void DiagnoseMisalignedMembers();<br>
+<br>
+  /// \brief This function checks if the expression is in the sef of potentially<br>
+  /// misaligned members and it is converted to some pointer type T with lower<br>
+  /// or equal alignment requirements.  If so it removes it. This is used when<br>
+  /// we do not want to diagnose such misaligned access (e.g. in conversions to void*).<br>
+  void DiscardMisalignedMemberAddress(const Type *T, Expr *E);<br>
+<br>
+  /// \brief This function calls Action when it determines that E designates a<br>
+  /// misaligned member due to the packed attribute. This is used to emit<br>
+  /// local diagnostics like in reference binding.<br>
+  void RefersToMemberWithReducedAlignment(<br>
+      Expr *E,<br>
+      std::function<void(Expr *, RecordDecl *, ValueDecl *, CharUnits)> Action);<br>
 };<br>
<br>
 /// \brief RAII object that enters a new expression evaluation context.<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaCast.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=275417&r1=275416&r2=275417&view=diff" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=275417&r1=275416&r2=275417&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaCast.cpp Thu Jul 14 09:10:43 2016<br>
@@ -256,6 +256,7 @@ Sema::BuildCXXNamedCast(SourceLocation O<br>
       Op.CheckConstCast();<br>
       if (Op.SrcExpr.isInvalid())<br>
         return ExprError();<br>
+      DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);<br>
     }<br>
     return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType,<br>
                                   Op.ValueKind, Op.SrcExpr.get(), DestTInfo,<br>
@@ -279,6 +280,7 @@ Sema::BuildCXXNamedCast(SourceLocation O<br>
       Op.CheckReinterpretCast();<br>
       if (Op.SrcExpr.isInvalid())<br>
         return ExprError();<br>
+      DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);<br>
     }<br>
     return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,<br>
                                     Op.ValueKind, Op.Kind, Op.SrcExpr.get(),<br>
@@ -291,6 +293,7 @@ Sema::BuildCXXNamedCast(SourceLocation O<br>
       Op.CheckStaticCast();<br>
       if (Op.SrcExpr.isInvalid())<br>
         return ExprError();<br>
+      DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);<br>
     }<br>
<br>
     return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=275417&r1=275416&r2=275417&view=diff" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=275417&r1=275416&r2=275417&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jul 14 09:10:43 2016<br>
@@ -8302,6 +8302,8 @@ void CheckImplicitConversion(Sema &S, Ex<br>
<br>
   DiagnoseNullConversion(S, E, T, CC);<br>
<br>
+  S.DiscardMisalignedMemberAddress(Target, E);<br>
+<br>
   if (!Source->isIntegerType() || !Target->isIntegerType())<br>
     return;<br>
<br>
@@ -9371,6 +9373,7 @@ void Sema::CheckCompletedExpr(Expr *E, S<br>
   CheckUnsequencedOperations(E);<br>
   if (!IsConstexpr && !E->isValueDependent())<br>
     CheckForIntOverflow(E);<br>
+  DiagnoseMisalignedMembers();<br>
 }<br>
<br>
 void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,<br>
@@ -10916,3 +10919,67 @@ void Sema::CheckArgumentWithTypeTag(cons<br>
         << ArgumentExpr->getSourceRange()<br>
         << TypeTagExpr->getSourceRange();<br>
 }<br>
+<br>
+void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,<br>
+                                         CharUnits Alignment) {<br>
+  MisalignedMembers.emplace_back(E, RD, MD, Alignment);<br>
+}<br>
+<br>
+void Sema::DiagnoseMisalignedMembers() {<br>
+  for (MisalignedMember &m : MisalignedMembers) {<br>
+    Diag(m.E->getLocStart(), diag::warn_taking_address_of_packed_member)<br>
+        << m.MD << m.RD << m.E->getSourceRange();<br>
+  }<br>
+  MisalignedMembers.clear();<br>
+}<br>
+<br>
+void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {<br>
+  if (!T->isPointerType())<br>
+    return;<br>
+  if (isa<UnaryOperator>(E) &&<br>
+      cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf) {<br>
+    auto *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();<br>
+    if (isa<MemberExpr>(Op)) {<br>
+      auto MA = std::find(MisalignedMembers.begin(), MisalignedMembers.end(),<br>
+                          MisalignedMember(Op));<br>
+      if (MA != MisalignedMembers.end() &&<br>
+          Context.getTypeAlignInChars(T->getPointeeType()) <= MA->Alignment)<br>
+        MisalignedMembers.erase(MA);<br>
+    }<br>
+  }<br>
+}<br>
+<br>
+void Sema::RefersToMemberWithReducedAlignment(<br>
+    Expr *E,<br>
+    std::function<void(Expr *, RecordDecl *, ValueDecl *, CharUnits)> Action) {<br>
+  const auto *ME = dyn_cast<MemberExpr>(E);<br>
+  while (ME && isa<FieldDecl>(ME->getMemberDecl())) {<br>
+    QualType BaseType = ME->getBase()->getType();<br>
+    if (ME->isArrow())<br>
+      BaseType = BaseType->getPointeeType();<br>
+    RecordDecl *RD = BaseType->getAs<RecordType>()->getDecl();<br>
+<br>
+    ValueDecl *MD = ME->getMemberDecl();<br>
+    bool ByteAligned = Context.getTypeAlignInChars(MD->getType()).isOne();<br>
+    if (ByteAligned) // Attribute packed does not have any effect.<br>
+      break;<br>
+<br>
+    if (!ByteAligned &&<br>
+        (RD->hasAttr<PackedAttr>() || (MD->hasAttr<PackedAttr>()))) {<br>
+      CharUnits Alignment = std::min(Context.getTypeAlignInChars(MD->getType()),<br>
+                                     Context.getTypeAlignInChars(BaseType));<br>
+      // Notify that this expression designates a member with reduced alignment<br>
+      Action(E, RD, MD, Alignment);<br>
+      break;<br>
+    }<br>
+    ME = dyn_cast<MemberExpr>(ME->getBase());<br>
+  }<br>
+}<br>
+<br>
+void Sema::CheckAddressOfPackedMember(Expr *rhs) {<br>
+  using namespace std::placeholders;<br>
+  RefersToMemberWithReducedAlignment(<br>
+      rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*this), _1,<br>
+                     _2, _3, _4));<br>
+}<br>
+<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=275417&r1=275416&r2=275417&view=diff" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=275417&r1=275416&r2=275417&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jul 14 09:10:43 2016<br>
@@ -6001,7 +6001,9 @@ Sema::ActOnCastExpr(Scope *S, SourceLoca<br>
   CheckTollFreeBridgeCast(castType, CastExpr);<br>
<br>
   CheckObjCBridgeRelatedCast(castType, CastExpr);<br>
-<br>
+<br>
+  DiscardMisalignedMemberAddress(castType.getTypePtr(), CastExpr);<br>
+<br>
   return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr);<br>
 }<br>
<br>
@@ -10534,6 +10536,8 @@ QualType Sema::CheckAddressOfOperand(Exp<br>
   if (op->getType()->isObjCObjectType())<br>
     return Context.getObjCObjectPointerType(op->getType());<br>
<br>
+  CheckAddressOfPackedMember(op);<br>
+<br>
   return Context.getPointerType(op->getType());<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaInit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=275417&r1=275416&r2=275417&view=diff" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=275417&r1=275416&r2=275417&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jul 14 09:10:43 2016<br>
@@ -6457,6 +6457,15 @@ InitializationSequence::Perform(Sema &S,<br>
                                   ExtendingEntity->getDecl());<br>
<br>
       CheckForNullPointerDereference(S, CurInit.get());<br>
+<br>
+      S.RefersToMemberWithReducedAlignment(CurInit.get(), [&](Expr *E,<br>
+                                                              RecordDecl *RD,<br>
+                                                              ValueDecl *MD,<br>
+                                                              CharUnits) {<br>
+        S.Diag(Kind.getLocation(), diag::err_binding_reference_to_packed_member)<br>
+            << MD << RD << E->getSourceRange();<br>
+      });<br>
+<br>
       break;<br>
<br>
     case SK_BindReferenceToTemporary: {<br>
@@ -6645,12 +6654,16 @@ InitializationSequence::Perform(Sema &S,<br>
                                     getAssignmentAction(Entity), CCK);<br>
       if (CurInitExprRes.isInvalid())<br>
         return ExprError();<br>
+<br>
+      S.DiscardMisalignedMemberAddress(Step->Type.getTypePtr(), CurInit.get());<br>
+<br>
       CurInit = CurInitExprRes;<br>
<br>
       if (Step->Kind == SK_ConversionSequenceNoNarrowing &&<br>
           S.getLangOpts().CPlusPlus && !CurInit.get()->isValueDependent())<br>
         DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(),<br>
                                     CurInit.get());<br>
+<br>
       break;<br>
     }<br>
<br>
<br>
Added: cfe/trunk/test/Sema/address-packed-member-memops.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address-packed-member-memops.c?rev=275417&view=auto" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address-packed-member-memops.c?rev=275417&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/Sema/address-packed-member-memops.c (added)<br>
+++ cfe/trunk/test/Sema/address-packed-member-memops.c Thu Jul 14 09:10:43 2016<br>
@@ -0,0 +1,26 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -verify %s<br>
+// expected-no-diagnostics<br>
+<br>
+struct B {<br>
+  int x, y, z, w;<br>
+} b;<br>
+<br>
+struct __attribute__((packed)) A {<br>
+  struct B b;<br>
+} a;<br>
+<br>
+typedef __typeof__(sizeof(int)) size_t;<br>
+<br>
+void *memcpy(void *dest, const void *src, size_t n);<br>
+int memcmp(const void *s1, const void *s2, size_t n);<br>
+void *memmove(void *dest, const void *src, size_t n);<br>
+void *memset(void *s, int c, size_t n);<br>
+<br>
+int x;<br>
+<br>
+void foo(void) {<br>
+  memcpy(&a.b, &b, sizeof(b));<br>
+  memmove(&a.b, &b, sizeof(b));<br>
+  memset(&a.b, 0, sizeof(b));<br>
+  x = memcmp(&a.b, &b, sizeof(b));<br>
+}<br>
<br>
Added: cfe/trunk/test/Sema/address-packed.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address-packed.c?rev=275417&view=auto" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address-packed.c?rev=275417&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/Sema/address-packed.c (added)<br>
+++ cfe/trunk/test/Sema/address-packed.c Thu Jul 14 09:10:43 2016<br>
@@ -0,0 +1,160 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -verify %s<br>
+extern void f1(int *);<br>
+extern void f2(char *);<br>
+<br>
+struct Ok {<br>
+  char c;<br>
+  int x;<br>
+};<br>
+<br>
+struct __attribute__((packed)) Arguable {<br>
+  char c0;<br>
+  int x;<br>
+  char c1;<br>
+};<br>
+<br>
+union __attribute__((packed)) UnionArguable {<br>
+  char c;<br>
+  int x;<br>
+};<br>
+<br>
+typedef struct Arguable ArguableT;<br>
+<br>
+struct Arguable *get_arguable();<br>
+<br>
+void to_void(void *);<br>
+<br>
+void g0(void) {<br>
+  {<br>
+    struct Ok ok;<br>
+    f1(&ok.x); // no-warning<br>
+    f2(&ok.c); // no-warning<br>
+  }<br>
+  {<br>
+    struct Arguable arguable;<br>
+    f2(&arguable.c0); // no-warning<br>
+    f1(&arguable.x);  // expected-warning {{packed member 'x' of class or structure 'Arguable'}}<br>
+    f2(&arguable.c1); // no-warning<br>
+<br>
+    f1((int *)(void *)&arguable.x); // no-warning<br>
+    to_void(&arguable.x);           // no-warning<br>
+    void *p = &arguable.x;          // no-warning;<br>
+    to_void(p);<br>
+  }<br>
+  {<br>
+    union UnionArguable arguable;<br>
+    f2(&arguable.c); // no-warning<br>
+    f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'UnionArguable'}}<br>
+<br>
+    f1((int *)(void *)&arguable.x); // no-warning<br>
+    to_void(&arguable.x);           // no-warning<br>
+  }<br>
+  {<br>
+    ArguableT arguable;<br>
+    f2(&arguable.c0); // no-warning<br>
+    f1(&arguable.x);  // expected-warning {{packed member 'x' of class or structure 'Arguable'}}<br>
+    f2(&arguable.c1); // no-warning<br>
+<br>
+    f1((int *)(void *)&arguable.x); // no-warning<br>
+    to_void(&arguable.x);           // no-warning<br>
+  }<br>
+  {<br>
+    struct Arguable *arguable = get_arguable();<br>
+    f2(&arguable->c0); // no-warning<br>
+    f1(&arguable->x);  // expected-warning {{packed member 'x' of class or structure 'Arguable'}}<br>
+    f2(&arguable->c1); // no-warning<br>
+<br>
+    f1((int *)(void *)&arguable->x); // no-warning<br>
+    to_void(&arguable->c1);          // no-warning<br>
+  }<br>
+  {<br>
+    ArguableT *arguable = get_arguable();<br>
+    f2(&(arguable->c0)); // no-warning<br>
+    f1(&(arguable->x));  // expected-warning {{packed member 'x' of class or structure 'Arguable'}}<br>
+    f2(&(arguable->c1)); // no-warning<br>
+<br>
+    f1((int *)(void *)&(arguable->x)); // no-warning<br>
+    to_void(&(arguable->c1));          // no-warning<br>
+  }<br>
+}<br>
+<br>
+struct S1 {<br>
+  char c;<br>
+  int i __attribute__((packed));<br>
+};<br>
+<br>
+int *g1(struct S1 *s1) {<br>
+  return &s1->i; // expected-warning {{packed member 'i' of class or structure 'S1'}}<br>
+}<br>
+<br>
+struct S2_i {<br>
+  int i;<br>
+};<br>
+struct __attribute__((packed)) S2 {<br>
+  char c;<br>
+  struct S2_i inner;<br>
+};<br>
+<br>
+int *g2(struct S2 *s2) {<br>
+  return &s2->inner.i; // expected-warning {{packed member 'inner' of class or structure 'S2'}}<br>
+}<br>
+<br>
+struct S2_a {<br>
+  char c;<br>
+  struct S2_i inner __attribute__((packed));<br>
+};<br>
+<br>
+int *g2_a(struct S2_a *s2_a) {<br>
+  return &s2_a->inner.i; // expected-warning {{packed member 'inner' of class or structure 'S2_a'}}<br>
+}<br>
+<br>
+struct __attribute__((packed)) S3 {<br>
+  char c;<br>
+  struct {<br>
+    int i;<br>
+  } inner;<br>
+};<br>
+<br>
+int *g3(struct S3 *s3) {<br>
+  return &s3->inner.i; // expected-warning {{packed member 'inner' of class or structure 'S3'}}<br>
+}<br>
+<br>
+struct S4 {<br>
+  char c;<br>
+  struct __attribute__((packed)) {<br>
+    int i;<br>
+  } inner;<br>
+};<br>
+<br>
+int *g4(struct S4 *s4) {<br>
+  return &s4->inner.i; // expected-warning {{packed member 'i' of class or structure 'S4::(anonymous)'}}<br>
+}<br>
+<br>
+struct S5 {<br>
+  char c;<br>
+  struct {<br>
+    char c1;<br>
+    int i __attribute__((packed));<br>
+  } inner;<br>
+};<br>
+<br>
+int *g5(struct S5 *s5) {<br>
+  return &s5->inner.i; // expected-warning {{packed member 'i' of class or structure 'S5::(anonymous)'}}<br>
+}<br>
+<br>
+struct __attribute__((packed, aligned(2))) AlignedTo2 {<br>
+  int x;<br>
+};<br>
+<br>
+char *g6(struct AlignedTo2 *s) {<br>
+  return (char *)&s->x; // no-warning<br>
+}<br>
+<br>
+struct __attribute__((packed, aligned(2))) AlignedTo2Bis {<br>
+  int x;<br>
+};<br>
+<br>
+struct AlignedTo2Bis* g7(struct AlignedTo2 *s)<br>
+{<br>
+    return (struct AlignedTo2Bis*)&s->x; // no-warning<br>
+}<br>
<br>
Added: cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp?rev=275417&view=auto" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp?rev=275417&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp (added)<br>
+++ cfe/trunk/test/SemaCXX/address-packed-member-memops.cpp Thu Jul 14 09:10:43 2016<br>
@@ -0,0 +1,28 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -verify %s<br>
+// expected-no-diagnostics<br>
+<br>
+struct B {<br>
+  int x, y, z, w;<br>
+} b;<br>
+<br>
+struct __attribute__((packed)) A {<br>
+  struct B b;<br>
+} a;<br>
+<br>
+typedef __typeof__(sizeof(int)) size_t;<br>
+<br>
+extern "C" {<br>
+void *memcpy(void *dest, const void *src, size_t n);<br>
+int memcmp(const void *s1, const void *s2, size_t n);<br>
+void *memmove(void *dest, const void *src, size_t n);<br>
+void *memset(void *s, int c, size_t n);<br>
+}<br>
+<br>
+int x;<br>
+<br>
+void foo() {<br>
+  memcpy(&a.b, &b, sizeof(b));<br>
+  memmove(&a.b, &b, sizeof(b));<br>
+  memset(&a.b, 0, sizeof(b));<br>
+  x = memcmp(&a.b, &b, sizeof(b));<br>
+}<br>
<br>
Added: cfe/trunk/test/SemaCXX/address-packed.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/address-packed.cpp?rev=275417&view=auto" rel="noreferrer" target="_blank">
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/address-packed.cpp?rev=275417&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/address-packed.cpp (added)<br>
+++ cfe/trunk/test/SemaCXX/address-packed.cpp Thu Jul 14 09:10:43 2016<br>
@@ -0,0 +1,118 @@<br>
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s<br>
+extern void f1(int *);<br>
+extern void f2(char *);<br>
+<br>
+struct __attribute__((packed)) Arguable {<br>
+  int x;<br>
+  char c;<br>
+  static void foo();<br>
+};<br>
+<br>
+extern void f3(void());<br>
+<br>
+namespace Foo {<br>
+struct __attribute__((packed)) Arguable {<br>
+  char c;<br>
+  int x;<br>
+  static void foo();<br>
+};<br>
+}<br>
+<br>
+struct Arguable *get_arguable();<br>
+<br>
+void f4(int &);<br>
+<br>
+void to_void(void *);<br>
+<br>
+template <typename... T><br>
+void sink(T...);<br>
+<br>
+void g0() {<br>
+  {<br>
+    Foo::Arguable arguable;<br>
+    f1(&arguable.x);   // expected-warning {{packed member 'x' of class or structure 'Foo::Arguable'}}<br>
+    f2(&arguable.c);   // no-warning<br>
+    f3(&arguable.foo); // no-warning<br>
+<br>
+    int &w = arguable.x; // expected-error {{binding reference to packed member 'x' of class or structure 'Foo::Arguable'}}<br>
+    sink(w);<br>
+    f4(arguable.x); // expected-error {{binding reference to packed member 'x' of class or structure 'Foo::Arguable'}}<br>
+<br>
+    to_void(&arguable.x);                             // no-warning<br>
+    void *p1 = &arguable.x;                           // no-warning<br>
+    void *p2 = static_cast<void *>(&arguable.x);      // no-warning<br>
+    void *p3 = reinterpret_cast<void *>(&arguable.x); // no-warning<br>
+    void *p4 = (void *)&arguable.x;                   // no-warning<br>
+    sink(p1, p2, p3, p4);<br>
+  }<br>
+  {<br>
+    Arguable arguable1;<br>
+    Arguable &arguable(arguable1);<br>
+    f1(&arguable.x);   // expected-warning {{packed member 'x' of class or structure 'Arguable'}}<br>
+    f2(&arguable.c);   // no-warning<br>
+    f3(&arguable.foo); // no-warning<br>
+  }<br>
+  {<br>
+    Arguable *arguable1;<br>
+    Arguable *&arguable(arguable1);<br>
+    f1(&arguable->x);   // expected-warning {{packed member 'x' of class or structure 'Arguable'}}<br>
+    f2(&arguable->c);   // no-warning<br>
+    f3(&arguable->foo); // no-warning<br>
+  }<br>
+}<br>
+<br>
+struct __attribute__((packed)) A {<br>
+  int x;<br>
+  char c;<br>
+<br>
+  int *f0() {<br>
+    return &this->x; // expected-warning {{packed member 'x' of class or structure 'A'}}<br>
+  }<br>
+<br>
+  int *g0() {<br>
+    return &x; // expected-warning {{packed member 'x' of class or structure 'A'}}<br>
+  }<br>
+<br>
+  char *h0() {<br>
+    return &c; // no-warning<br>
+  }<br>
+};<br>
+<br>
+struct B : A {<br>
+  int *f1() {<br>
+    return &this->x; // expected-warning {{packed member 'x' of class or structure 'A'}}<br>
+  }<br>
+<br>
+  int *g1() {<br>
+    return &x; // expected-warning {{packed member 'x' of class or structure 'A'}}<br>
+  }<br>
+<br>
+  char *h1() {<br>
+    return &c; // no-warning<br>
+  }<br>
+};<br>
+<br>
+template <typename Ty><br>
+class __attribute__((packed)) S {<br>
+  Ty X;<br>
+<br>
+public:<br>
+  const Ty *get() const {<br>
+    return &X; // expected-warning {{packed member 'X' of class or structure 'S<int>'}}<br>
+               // expected-warning@-1 {{packed member 'X' of class or structure 'S<float>'}}<br>
+  }<br>
+};<br>
+<br>
+template <typename Ty><br>
+void h(Ty *);<br>
+<br>
+void g1() {<br>
+  S<int> s1;<br>
+  s1.get(); // expected-note {{in instantiation of member function 'S<int>::get'}}<br>
+<br>
+  S<char> s2;<br>
+  s2.get();<br>
+<br>
+  S<float> s3;<br>
+  s3.get(); // expected-note {{in instantiation of member function 'S<float>::get'}}<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote>
</div>
<br>
</div>
</div>
</div>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
<br>
</blockquote>
</div>
</div>
</div>
<br>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</div>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</div>
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose,
 or store or copy the information in any medium. Thank you.
</body>
</html>