[cfe-commits] r130492 - in /cfe/trunk: include/clang/AST/Type.h lib/AST/Type.cpp lib/Sema/SemaChecking.cpp test/SemaCXX/warn-non-pod-memset.cpp

Chandler Carruth chandlerc at gmail.com
Fri Apr 29 02:46:08 PDT 2011


Author: chandlerc
Date: Fri Apr 29 04:46:08 2011
New Revision: 130492

URL: http://llvm.org/viewvc/llvm-project?rev=130492&view=rev
Log:
Relax the non-POD memset warning to use the less restrictive C++11
definition of POD. Specifically, this allows certain non-aggregate
types due to their data members being private.

The representation of C++11 POD testing is pretty gross. Any suggestions
for improvements there are welcome. Especially the name
'isCXX11PODType()' seems truly unfortunate.

Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=130492&r1=130491&r2=130492&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Apr 29 04:46:08 2011
@@ -1179,6 +1179,12 @@
   /// (C++0x [basic.types]p9)
   bool isTrivialType() const;
 
+  /// isCXX11PODType() - Return true if this is a POD type according to the
+  /// more relaxed rules of the C++11 standard, regardless of the current
+  /// compilation's language.
+  /// (C++0x [basic.types]p9)
+  bool isCXX11PODType() const;
+
   /// Helper methods to distinguish type categories. All type predicates
   /// operate on the canonical type, ignoring typedefs and qualifiers.
 

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=130492&r1=130491&r2=130492&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri Apr 29 04:46:08 2011
@@ -943,6 +943,52 @@
   return false;
 }
 
+// This is effectively the intersection of isTrivialType and hasStandardLayout.
+// We implement it dircetly to avoid redundant conversions from a type to
+// a CXXRecordDecl.
+bool Type::isCXX11PODType() const {
+  if (isIncompleteType())
+    return false;
+
+  // C++11 [basic.types]p9:
+  //   Scalar types, POD classes, arrays of such types, and cv-qualified
+  //   versions of these types are collectively called trivial types.
+  const Type *BaseTy = getBaseElementTypeUnsafe();
+  assert(BaseTy && "NULL element type");
+  if (BaseTy->isScalarType()) return true;
+  if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
+    if (const CXXRecordDecl *ClassDecl =
+        dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+      // C++11 [class]p10:
+      //   A POD struct is a non-union class that is both a trivial class [...]
+      // C++11 [class]p5:
+      //   A trivial class is a class that has a trivial default constructor
+      if (!ClassDecl->hasTrivialConstructor()) return false;
+      //   and is trivially copyable.
+      if (!ClassDecl->isTriviallyCopyable()) return false;
+
+      // C++11 [class]p10:
+      //   A POD struct is a non-union class that is both a trivial class and
+      //   a standard-layout class [...]
+      if (!ClassDecl->hasStandardLayout()) return false;
+
+      // C++11 [class]p10:
+      //   A POD struct is a non-union class that is both a trivial class and
+      //   a standard-layout class, and has no non-static data members of type
+      //   non-POD struct, non-POD union (or array of such types). [...]
+      //
+      // We don't directly query the recursive aspect as the requiremets for
+      // both standard-layout classes and trivial classes apply recursively
+      // already.
+    }
+
+    return true;
+  }
+
+  // No other types can match.
+  return false;
+}
+
 bool Type::isPromotableIntegerType() const {
   if (const BuiltinType *BT = getAs<BuiltinType>())
     switch (BT->getKind()) {

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=130492&r1=130491&r2=130492&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Apr 29 04:46:08 2011
@@ -1812,21 +1812,34 @@
 
   const Expr *Dest = Call->getArg(0)->IgnoreParenImpCasts();
 
+  // The type checking for this warning is moderately expensive, only do it
+  // when enabled.
+  if (getDiagnostics().getDiagnosticLevel(diag::warn_non_pod_memset,
+                                          Dest->getExprLoc()) ==
+      Diagnostic::Ignored)
+    return;
+
   QualType DestTy = Dest->getType();
   if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
     QualType PointeeTy = DestPtrTy->getPointeeType();
-    if (!PointeeTy->isPODType() && !PointeeTy->isVoidType()) {
-      DiagRuntimeBehavior(
-        Dest->getExprLoc(), Dest,
-        PDiag(diag::warn_non_pod_memset)
-          << PointeeTy << Call->getCallee()->getSourceRange());
-
-      SourceRange ArgRange = Call->getArg(0)->getSourceRange();
-      DiagRuntimeBehavior(
-        Dest->getExprLoc(), Dest,
-        PDiag(diag::note_non_pod_memset_silence)
-          << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
-    }
+    if (PointeeTy->isVoidType())
+      return;
+
+    // Check the C++11 POD definition regardless of language mode; it is more
+    // relaxed than earlier definitions and we don't want spurrious warnings.
+    if (PointeeTy->isCXX11PODType())
+      return;
+
+    DiagRuntimeBehavior(
+      Dest->getExprLoc(), Dest,
+      PDiag(diag::warn_non_pod_memset)
+        << PointeeTy << Call->getCallee()->getSourceRange());
+
+    SourceRange ArgRange = Call->getArg(0)->getSourceRange();
+    DiagRuntimeBehavior(
+      Dest->getExprLoc(), Dest,
+      PDiag(diag::note_non_pod_memset_silence)
+        << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
   }
 }
 

Modified: cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp?rev=130492&r1=130491&r2=130492&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-non-pod-memset.cpp Fri Apr 29 04:46:08 2011
@@ -7,6 +7,14 @@
 struct S2 { int x; } s2;
 struct S3 { float x, y; S1 s[4]; void (*f)(S1**); } s3;
 
+// We use the C++11 concept of POD for this warning, so ensure a non-aggregate
+// still warns.
+class C1 {
+  int x, y, z;
+public:
+  void foo() {}
+} c1;
+
 // Non-POD types that should warn.
 struct X1 { X1(); } x1;
 struct X2 { ~X2(); } x2;
@@ -45,6 +53,7 @@
   memset(&s1, 0, sizeof s1);
   memset(&s2, 0, sizeof s2);
   memset(&s3, 0, sizeof s3);
+  memset(&c1, 0, sizeof c1);
 
   // Unevaluated code shouldn't warn.
   (void)sizeof memset(&x1, 0, sizeof x1);





More information about the cfe-commits mailing list