ahatanak updated this revision to Diff 142691.
ahatanak marked an inline comment as done.
ahatanak added a comment.

Move method visitArray to the derived classes and pass the array type to the 
method instead of the QualType.


Repository:
  rC Clang

https://reviews.llvm.org/D45310

Files:
  include/clang/AST/NonTrivialTypeVisitor.h
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/CodeGen/CGNonTrivialStruct.cpp
  lib/Sema/SemaChecking.cpp
  test/SemaObjC/warn-nontrivial-struct-memaccess.m

Index: test/SemaObjC/warn-nontrivial-struct-memaccess.m
===================================================================
--- /dev/null
+++ test/SemaObjC/warn-nontrivial-struct-memaccess.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime-has-weak -x objective-c -fobjc-arc -verify %s
+
+void *memset(void *, int, __SIZE_TYPE__);
+void bzero(void *, __SIZE_TYPE__);
+void *memcpy(void *, const void *, __SIZE_TYPE__);
+void *memmove(void *, const void *, __SIZE_TYPE__);
+
+struct Trivial {
+  int f0;
+  volatile int f1;
+};
+
+struct NonTrivial0 {
+  int f0;
+  __weak id f1; // expected-note 2 {{non-trivial to default-initialize}} expected-note 2 {{non-trivial to copy}}
+  volatile int f2;
+  id f3[10]; // expected-note 2 {{non-trivial to default-initialize}} expected-note 2 {{non-trivial to copy}}
+};
+
+struct NonTrivial1 {
+  id f0; // expected-note 2 {{non-trivial to default-initialize}} expected-note 2 {{non-trivial to copy}}
+  int f1;
+  struct NonTrivial0 f2;
+};
+
+void testTrivial(struct Trivial *d, struct Trivial *s) {
+  memset(d, 0, sizeof(struct Trivial));
+  bzero(d, sizeof(struct Trivial));
+  memcpy(d, s, sizeof(struct Trivial));
+  memmove(d, s, sizeof(struct Trivial));
+}
+
+void testNonTrivial1(struct NonTrivial1 *d, struct NonTrivial1 *s) {
+  memset(d, 0, sizeof(struct NonTrivial1)); // expected-warning {{that is not trivial to primitive-default-initialize}} expected-note {{explicitly cast the pointer to silence}}
+  memset((void *)d, 0, sizeof(struct NonTrivial1));
+  bzero(d, sizeof(struct NonTrivial1)); // expected-warning {{that is not trivial to primitive-default-initialize}} expected-note {{explicitly cast the pointer to silence}}
+  memcpy(d, s, sizeof(struct NonTrivial1)); // expected-warning {{that is not trivial to primitive-copy}} expected-note {{explicitly cast the pointer to silence}}
+  memmove(d, s, sizeof(struct NonTrivial1)); // expected-warning {{that is not trivial to primitive-copy}} expected-note {{explicitly cast the pointer to silence}}
+}
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -28,6 +28,7 @@
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExprOpenMP.h"
 #include "clang/AST/NSAPI.h"
+#include "clang/AST/NonTrivialTypeVisitor.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/TemplateBase.h"
@@ -7378,6 +7379,98 @@
   return QualType();
 }
 
+namespace {
+
+struct SearchNonTrivialToInitializeField
+    : DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField> {
+  using Super =
+      DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField>;
+
+  SearchNonTrivialToInitializeField(const Expr *E, Sema &S) : E(E), S(S) {}
+
+  void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
+                     SourceLocation SL) {
+    if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
+      asDerived().visitArray(PDIK, AT, SL);
+      return;
+    }
+
+    Super::visitWithKind(PDIK, FT, SL);
+  }
+
+  void visitARCStrong(QualType FT, SourceLocation SL) {
+    S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1);
+  }
+  void visitARCWeak(QualType FT, SourceLocation SL) {
+    S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1);
+  }
+  void visitStruct(QualType FT, SourceLocation SL) {
+    for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
+      visit(FD->getType(), FD->getLocation());
+  }
+  void visitArray(QualType::PrimitiveDefaultInitializeKind PDIK,
+                  const ArrayType *AT, SourceLocation SL) {
+    visit(getContext().getBaseElementType(AT), SL);
+  }
+  void visitTrivial(QualType FT, SourceLocation SL) {}
+
+  static void diag(QualType RT, const Expr *E, Sema &S) {
+    SearchNonTrivialToInitializeField(E, S).visitStruct(RT, SourceLocation());
+  }
+
+  ASTContext &getContext() { return S.getASTContext(); }
+
+  const Expr *E;
+  Sema &S;
+};
+
+struct SearchNonTrivialToCopyField
+    : CopiedTypeVisitor<SearchNonTrivialToCopyField, false> {
+  using Super = CopiedTypeVisitor<SearchNonTrivialToCopyField, false>;
+
+  SearchNonTrivialToCopyField(const Expr *E, Sema &S) : E(E), S(S) {}
+
+  void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
+                     SourceLocation SL) {
+    if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
+      asDerived().visitArray(PCK, AT, SL);
+      return;
+    }
+
+    Super::visitWithKind(PCK, FT, SL);
+  }
+
+  void visitARCStrong(QualType FT, SourceLocation SL) {
+    S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
+  }
+  void visitARCWeak(QualType FT, SourceLocation SL) {
+    S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
+  }
+  void visitStruct(QualType FT, SourceLocation SL) {
+    for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
+      visit(FD->getType(), FD->getLocation());
+  }
+  void visitArray(QualType::PrimitiveCopyKind PCK, const ArrayType *AT,
+                  SourceLocation SL) {
+    visit(getContext().getBaseElementType(AT), SL);
+  }
+  void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
+                SourceLocation SL) {}
+  void visitTrivial(QualType FT, SourceLocation SL) {}
+  void visitVolatileTrivial(QualType FT, SourceLocation SL) {}
+
+  static void diag(QualType RT, const Expr *E, Sema &S) {
+    SearchNonTrivialToCopyField(E, S).visitStruct(RT, SourceLocation());
+  }
+
+  ASTContext &getContext() { return S.getASTContext(); }
+
+  const Expr *E;
+  Sema &S;
+};
+
+}
+
 /// \brief Check for dangerous or invalid arguments to memset().
 ///
 /// This issues warnings on known problematic, dangerous or unspecified
@@ -7543,7 +7636,23 @@
         PDiag(diag::warn_arc_object_memaccess)
           << ArgIdx << FnName << PointeeTy
           << Call->getCallee()->getSourceRange());
-    else
+    else if (const auto *RT = PointeeTy->getAs<RecordType>()) {
+      if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
+          RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) {
+          DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
+                              PDiag(diag::warn_cstruct_memaccess) << ArgIdx << FnName
+                                  << PointeeTy << 0);
+          SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this);
+      } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
+                 RT->getDecl()->isNonTrivialToPrimitiveCopy()) {
+          DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
+                              PDiag(diag::warn_cstruct_memaccess) << ArgIdx << FnName
+                                  << PointeeTy << 1);
+          SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this);
+      } else {
+        continue;
+      }
+    } else
       continue;
 
     DiagRuntimeBehavior(
Index: lib/CodeGen/CGNonTrivialStruct.cpp
===================================================================
--- lib/CodeGen/CGNonTrivialStruct.cpp
+++ lib/CodeGen/CGNonTrivialStruct.cpp
@@ -14,6 +14,7 @@
 
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "clang/AST/NonTrivialTypeVisitor.h"
 #include "llvm/Support/ScopedPrinter.h"
 #include <array>
 
@@ -32,101 +33,6 @@
 enum { DstIdx = 0, SrcIdx = 1 };
 const char *ValNameStr[2] = {"dst", "src"};
 
-template <class Derived, class RetTy = void> struct DestructedTypeVisitor {
-  template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
-    return asDerived().visit(FT.isDestructedType(), FT,
-                             std::forward<Ts>(Args)...);
-  }
-
-  template <class... Ts>
-  RetTy visit(QualType::DestructionKind DK, QualType FT, Ts &&... Args) {
-    if (asDerived().getContext().getAsArrayType(FT))
-      return asDerived().visitArray(DK, FT, std::forward<Ts>(Args)...);
-
-    switch (DK) {
-    case QualType::DK_objc_strong_lifetime:
-      return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
-    case QualType::DK_nontrivial_c_struct:
-      return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
-    case QualType::DK_none:
-      return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
-    case QualType::DK_cxx_destructor:
-      return asDerived().visitCXXDestructor(FT, std::forward<Ts>(Args)...);
-    case QualType::DK_objc_weak_lifetime:
-      return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
-    }
-
-    llvm_unreachable("unknown destruction kind");
-  }
-
-  Derived &asDerived() { return static_cast<Derived &>(*this); }
-};
-
-template <class Derived, class RetTy = void>
-struct DefaultInitializedTypeVisitor {
-  template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
-    return asDerived().visit(FT.isNonTrivialToPrimitiveDefaultInitialize(), FT,
-                             std::forward<Ts>(Args)...);
-  }
-
-  template <class... Ts>
-  RetTy visit(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
-              Ts &&... Args) {
-    if (asDerived().getContext().getAsArrayType(FT))
-      return asDerived().visitArray(PDIK, FT, std::forward<Ts>(Args)...);
-
-    switch (PDIK) {
-    case QualType::PDIK_ARCStrong:
-      return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
-    case QualType::PDIK_ARCWeak:
-      return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
-    case QualType::PDIK_Struct:
-      return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
-    case QualType::PDIK_Trivial:
-      return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
-    }
-
-    llvm_unreachable("unknown default-initialize kind");
-  }
-
-  Derived &asDerived() { return static_cast<Derived &>(*this); }
-};
-
-template <class Derived, bool IsMove, class RetTy = void>
-struct CopiedTypeVisitor {
-  template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
-    QualType::PrimitiveCopyKind PCK =
-        IsMove ? FT.isNonTrivialToPrimitiveDestructiveMove()
-               : FT.isNonTrivialToPrimitiveCopy();
-    return asDerived().visit(PCK, FT, std::forward<Ts>(Args)...);
-  }
-
-  template <class... Ts>
-  RetTy visit(QualType::PrimitiveCopyKind PCK, QualType FT, Ts &&... Args) {
-    asDerived().preVisit(PCK, FT, std::forward<Ts>(Args)...);
-
-    if (asDerived().getContext().getAsArrayType(FT))
-      return asDerived().visitArray(PCK, FT, std::forward<Ts>(Args)...);
-
-    switch (PCK) {
-    case QualType::PCK_ARCStrong:
-      return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
-    case QualType::PCK_ARCWeak:
-      return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
-    case QualType::PCK_Struct:
-      return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
-    case QualType::PCK_Trivial:
-      return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
-    case QualType::PCK_VolatileTrivial:
-      return asDerived().visitVolatileTrivial(FT, std::forward<Ts>(Args)...);
-    }
-
-    llvm_unreachable("unknown primitive copy kind");
-  }
-
-  Derived &asDerived() { return static_cast<Derived &>(*this); }
-};
-
 template <class Derived> struct StructVisitor {
   StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
 
@@ -172,6 +78,7 @@
 struct CopyStructVisitor : StructVisitor<Derived>,
                            CopiedTypeVisitor<Derived, IsMove> {
   using StructVisitor<Derived>::asDerived;
+  using Super = CopiedTypeVisitor<Derived, IsMove>;
 
   CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
 
@@ -183,6 +90,20 @@
       asDerived().flushTrivialFields(std::forward<Ts>(Args)...);
   }
 
+  template <class... Ts>
+  void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
+                     const FieldDecl *FD, CharUnits CurStructOffsset,
+                     Ts &&... Args) {
+    if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
+      asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD,
+                             CurStructOffsset, std::forward<Ts>(Args)...);
+      return;
+    }
+
+    Super::visitWithKind(PCK, FT, FD, CurStructOffsset,
+                         std::forward<Ts>(Args)...);
+  }
+
   template <class... Ts>
   void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
                     Ts... Args) {
@@ -259,24 +180,24 @@
   }
 
   template <class FieldKind>
-  void visitArray(FieldKind FK, QualType QT, const FieldDecl *FD,
-                  CharUnits CurStructOffset) {
+  void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
+                  const FieldDecl *FD, CharUnits CurStructOffset) {
     // String for non-volatile trivial fields is emitted when
     // flushTrivialFields is called.
     if (!FK)
-      return asDerived().visitTrivial(QT, FD, CurStructOffset);
+      return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
 
     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
     ASTContext &Ctx = asDerived().getContext();
-    const auto *AT = Ctx.getAsConstantArrayType(QT);
-    unsigned NumElts = Ctx.getConstantArrayElementCount(AT);
-    QualType EltTy = Ctx.getBaseElementType(AT);
+    const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
+    unsigned NumElts = Ctx.getConstantArrayElementCount(CAT);
+    QualType EltTy = Ctx.getBaseElementType(CAT);
     CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy);
     appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" +
               llvm::to_string(EltSize.getQuantity()) + "n" +
               llvm::to_string(NumElts));
-    EltTy = QT.isVolatileQualified() ? EltTy.withVolatile() : EltTy;
-    asDerived().visit(FK, EltTy, nullptr, FieldOffset);
+    EltTy = IsVolatile ? EltTy.withVolatile() : EltTy;
+    asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset);
     appendStr("_AE");
   }
 
@@ -344,16 +265,36 @@
 struct GenDefaultInitializeFuncName
     : GenUnaryFuncName<GenDefaultInitializeFuncName>,
       DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> {
+  using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
   GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
       : GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
                                                        DstAlignment, Ctx) {}
+  void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
+                     const FieldDecl *FD, CharUnits CurStructOffset) {
+    if (const auto *AT = getContext().getAsArrayType(FT)) {
+      visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
+      return;
+    }
+
+    Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
+  }
 };
 
 struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
                                DestructedTypeVisitor<GenDestructorFuncName> {
+  using Super = DestructedTypeVisitor<GenDestructorFuncName>;
   GenDestructorFuncName(CharUnits DstAlignment, ASTContext &Ctx)
       : GenUnaryFuncName<GenDestructorFuncName>("__destructor_", DstAlignment,
                                                 Ctx) {}
+  void visitWithKind(QualType::DestructionKind DK, QualType FT,
+                     const FieldDecl *FD, CharUnits CurStructOffset) {
+    if (const auto *AT = getContext().getAsArrayType(FT)) {
+      visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
+      return;
+    }
+
+    Super::visitWithKind(DK, FT, FD, CurStructOffset);
+  }
 };
 
 // Helper function that creates CGFunctionInfo for an N-ary special function.
@@ -386,11 +327,13 @@
   }
 
   template <class FieldKind, size_t N>
-  void visitArray(FieldKind FK, QualType QT, const FieldDecl *FD,
-                  CharUnits CurStackOffset, std::array<Address, N> Addrs) {
+  void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
+                  const FieldDecl *FD, CharUnits CurStackOffset,
+                  std::array<Address, N> Addrs) {
     // Non-volatile trivial fields are copied when flushTrivialFields is called.
     if (!FK)
-      return asDerived().visitTrivial(QT, FD, CurStackOffset, Addrs);
+      return asDerived().visitTrivial(QualType(AT, 0), FD, CurStackOffset,
+                                      Addrs);
 
     CodeGenFunction &CGF = *this->CGF;
     ASTContext &Ctx = CGF.getContext();
@@ -401,8 +344,7 @@
     for (unsigned I = 0; I < N; ++I)
       StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStackOffset, FD);
     Address DstAddr = StartAddrs[DstIdx];
-    llvm::Value *NumElts =
-        CGF.emitArrayLength(Ctx.getAsArrayType(QT), BaseEltQT, DstAddr);
+    llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
     unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
     llvm::Value *BaseEltSizeVal =
         llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
@@ -437,16 +379,17 @@
 
     // Visit the element of the array in the loop body.
     CGF.EmitBlock(LoopBB);
-    QualType EltQT = Ctx.getAsArrayType(QT)->getElementType();
+    QualType EltQT = AT->getElementType();
     CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
     std::array<Address, N> NewAddrs = Addrs;
 
     for (unsigned I = 0; I < N; ++I)
       NewAddrs[I] = Address(
           PHIs[I], StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
 
-    EltQT = QT.isVolatileQualified() ? EltQT.withVolatile() : EltQT;
-    this->asDerived().visit(EltQT, nullptr, CharUnits::Zero(), NewAddrs);
+    EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
+    this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
+                                    NewAddrs);
 
     LoopBB = CGF.Builder.GetInsertBlock();
 
@@ -624,7 +567,20 @@
 struct GenDestructor : StructVisitor<GenDestructor>,
                        GenFuncBase<GenDestructor>,
                        DestructedTypeVisitor<GenDestructor> {
+  using Super = DestructedTypeVisitor<GenDestructor>;
   GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
+
+  void visitWithKind(QualType::DestructionKind DK, QualType FT,
+                     const FieldDecl *FD, CharUnits CurStructOffset,
+                     std::array<Address, 1> Addrs) {
+    if (const auto *AT = getContext().getAsArrayType(FT)) {
+      visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
+      return;
+    }
+
+    Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
+  }
+
   void visitARCStrong(QualType QT, const FieldDecl *FD,
                       CharUnits CurStackOffset, std::array<Address, 1> Addrs) {
     CGF->destroyARCStrongImprecise(
@@ -648,10 +604,24 @@
     : StructVisitor<GenDefaultInitialize>,
       GenFuncBase<GenDefaultInitialize>,
       DefaultInitializedTypeVisitor<GenDefaultInitialize> {
+  using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
   typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
+
   GenDefaultInitialize(ASTContext &Ctx)
       : StructVisitor<GenDefaultInitialize>(Ctx) {}
 
+  void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
+                     const FieldDecl *FD, CharUnits CurStructOffset,
+                     std::array<Address, 1> Addrs) {
+    if (const auto *AT = getContext().getAsArrayType(FT)) {
+      visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
+                 Addrs);
+      return;
+    }
+
+    Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
+  }
+
   void visitARCStrong(QualType QT, const FieldDecl *FD,
                       CharUnits CurStackOffset, std::array<Address, 1> Addrs) {
     CGF->EmitNullInitialization(
@@ -665,25 +635,26 @@
   }
 
   template <class FieldKind, size_t... Is>
-  void visitArray(FieldKind FK, QualType QT, const FieldDecl *FD,
-                  CharUnits CurStackOffset, std::array<Address, 1> Addrs) {
+  void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
+                  const FieldDecl *FD, CharUnits CurStackOffset,
+                  std::array<Address, 1> Addrs) {
     if (!FK)
-      return visitTrivial(QT, FD, CurStackOffset, Addrs);
+      return visitTrivial(QualType(AT, 0), FD, CurStackOffset, Addrs);
 
     ASTContext &Ctx = getContext();
-    CharUnits Size = Ctx.getTypeSizeInChars(QT);
-    QualType EltTy = Ctx.getBaseElementType(QT);
+    CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
+    QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
 
     if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
-      GenFuncBaseTy::visitArray(FK, QT, FD, CurStackOffset, Addrs);
+      GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStackOffset, Addrs);
       return;
     }
 
     llvm::Constant *SizeVal = CGF->Builder.getInt64(Size.getQuantity());
     Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
     Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
     CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
-                              QT.isVolatileQualified());
+                              IsVolatile);
   }
 
   void callSpecialFunction(QualType FT, CharUnits Offset,
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -612,6 +612,13 @@
             "'%2'">;
 def warn_builtin_unknown : Warning<"use of unknown builtin %0">,
   InGroup<ImplicitFunctionDeclare>, DefaultError;
+def warn_cstruct_memaccess : Warning<
+  "%select{destination for|source of|first operand of|second operand of}0 this "
+  "%1 call is a pointer to record %2 that is not trivial to "
+  "%select{primitive-default-initialize|primitive-copy}3">,
+  InGroup<DiagGroup<"nontrivial-memaccess">>;
+def note_nontrivial_field : Note<
+  "field is non-trivial to %select{copy|default-initialize}0">;
 def warn_dyn_class_memaccess : Warning<
   "%select{destination for|source of|first operand of|second operand of}0 this "
   "%1 call is a pointer to %select{|class containing a }2dynamic class %3; "
Index: include/clang/AST/NonTrivialTypeVisitor.h
===================================================================
--- /dev/null
+++ include/clang/AST/NonTrivialTypeVisitor.h
@@ -0,0 +1,113 @@
+//===-- NonTrivialTypeVisitor.h - Visitor for non-trivial Types *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the visitor classes that are used to traverse non-trivial
+//  structs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H
+#define LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+template <class Derived, class RetTy = void> struct DestructedTypeVisitor {
+  template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
+    return asDerived().visitWithKind(FT.isDestructedType(), FT,
+                                     std::forward<Ts>(Args)...);
+  }
+
+  template <class... Ts>
+  RetTy visitWithKind(QualType::DestructionKind DK, QualType FT,
+                      Ts &&... Args) {
+    switch (DK) {
+    case QualType::DK_objc_strong_lifetime:
+      return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+    case QualType::DK_nontrivial_c_struct:
+      return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
+    case QualType::DK_none:
+      return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
+    case QualType::DK_cxx_destructor:
+      return asDerived().visitCXXDestructor(FT, std::forward<Ts>(Args)...);
+    case QualType::DK_objc_weak_lifetime:
+      return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
+    }
+
+    llvm_unreachable("unknown destruction kind");
+  }
+
+  Derived &asDerived() { return static_cast<Derived &>(*this); }
+};
+
+template <class Derived, class RetTy = void>
+struct DefaultInitializedTypeVisitor {
+  template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
+    return asDerived().visitWithKind(
+        FT.isNonTrivialToPrimitiveDefaultInitialize(), FT,
+        std::forward<Ts>(Args)...);
+  }
+
+  template <class... Ts>
+  RetTy visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK,
+                      QualType FT, Ts &&... Args) {
+    switch (PDIK) {
+    case QualType::PDIK_ARCStrong:
+      return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+    case QualType::PDIK_ARCWeak:
+      return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
+    case QualType::PDIK_Struct:
+      return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
+    case QualType::PDIK_Trivial:
+      return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
+    }
+
+    llvm_unreachable("unknown default-initialize kind");
+  }
+
+  Derived &asDerived() { return static_cast<Derived &>(*this); }
+};
+
+template <class Derived, bool IsMove, class RetTy = void>
+struct CopiedTypeVisitor {
+  template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
+    QualType::PrimitiveCopyKind PCK =
+        IsMove ? FT.isNonTrivialToPrimitiveDestructiveMove()
+               : FT.isNonTrivialToPrimitiveCopy();
+    return asDerived().visitWithKind(PCK, FT, std::forward<Ts>(Args)...);
+  }
+
+  template <class... Ts>
+  RetTy visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
+                      Ts &&... Args) {
+    asDerived().preVisit(PCK, FT, std::forward<Ts>(Args)...);
+
+    switch (PCK) {
+    case QualType::PCK_ARCStrong:
+      return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+    case QualType::PCK_ARCWeak:
+      return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
+    case QualType::PCK_Struct:
+      return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
+    case QualType::PCK_Trivial:
+      return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
+    case QualType::PCK_VolatileTrivial:
+      return asDerived().visitVolatileTrivial(FT, std::forward<Ts>(Args)...);
+    }
+
+    llvm_unreachable("unknown primitive copy kind");
+  }
+
+  Derived &asDerived() { return static_cast<Derived &>(*this); }
+};
+
+} // end namespace clang
+
+#endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to