Hello!
I'd like to get comments / reviews for this patch.
clang currently writes warnings if memset is used on a class that contains
virtual methods.
This patch adds warnings when memset is used on a class that contains std class
members. This can cause weird bugs.
I have seen such bugs in a closed source project. And there was also a major
cleanup of such bugs a few years ago in boinc.
Best regards,
Daniel Marjamäki
..................................................................................................................
Daniel Marjamäki
Senior Engineer
Evidente ES East AB
Warfvinges väg 34 SE-112 51 Stockholm Sweden
Mobile:
+46 (0)709 12 42 62
E-mail:
[email protected]
www.evidente.se
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp (revision 194617)
+++ lib/Sema/SemaChecking.cpp (arbetskopia)
@@ -3584,6 +3584,32 @@
return QualType();
}
+static bool hasStdMember(const QualType PointeeTy) {
+ if (!PointeeTy->isRecordType())
+ return false;
+ const CXXRecordDecl *RD = PointeeTy->getAsCXXRecordDecl();
+ if (!RD)
+ return false;
+ const DeclContext *DC = dyn_cast<DeclContext>(RD);
+ if (!DC)
+ return false;
+ for (DeclContext::decl_iterator I = DC->noload_decls_begin(),
+ E = DC->noload_decls_end();
+ I != E; ++I) {
+ const FieldDecl *MemberDecl = dyn_cast<FieldDecl>(*I);
+ if (!MemberDecl)
+ continue;
+ const QualType MemberType = MemberDecl->getType();
+ if (MemberType->isRecordType() && !MemberType->hasPointerRepresentation() &&
+ MemberType->getAsCXXRecordDecl() &&
+ MemberType->getAsCXXRecordDecl()->hasUserDeclaredConstructor() &&
+ QualType::getAsString(MemberType.split()).compare(0, 5, "std::") == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
/// \brief Check for dangerous or invalid arguments to memset().
///
/// This issues warnings on known problematic, dangerous or unspecified
@@ -3721,6 +3747,10 @@
<< FnName << PointeeTy
<< OperationType
<< Call->getCallee()->getSourceRange());
+ } else if (hasStdMember(PointeeTy)) {
+ DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
+ PDiag(diag::warn_std_class_memaccess));
+ continue;
} else if (PointeeTy.hasNonTrivialObjCLifetime() &&
BId != Builtin::BImemset)
DiagRuntimeBehavior(
Index: test/SemaCXX/warn-bad-memaccess.cpp
===================================================================
--- test/SemaCXX/warn-bad-memaccess.cpp (revision 194617)
+++ test/SemaCXX/warn-bad-memaccess.cpp (arbetskopia)
@@ -120,3 +120,23 @@
N::memset(&x1, 0, sizeof x1);
}
}
+
+// test string class in std namespace
+namespace std {
+ class string {
+ private:
+ char *somedata;
+ public:
+ string();
+ string(const char *);
+ };
+};
+
+struct Std1 {
+ std::string str1;
+};
+
+void test_warn_std() {
+ struct Std1 s1;
+ memset(&s1, 0, sizeof s1); // expected-warning{{memset of class that contains std class members}}
+}
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td (revision 194617)
+++ include/clang/Basic/DiagnosticSemaKinds.td (arbetskopia)
@@ -374,6 +374,9 @@
InGroup<DiagGroup<"dynamic-class-memaccess">>;
def note_bad_memaccess_silence : Note<
"explicitly cast the pointer to silence this warning">;
+def warn_std_class_memaccess : Warning<
+ "memset of class that contains std class members">,
+ InGroup<DiagGroup<"std-class-memaccess">>;
def warn_sizeof_pointer_expr_memaccess : Warning<
"'%0' call operates on objects of type %1 while the size is based on a "
"different type %2">,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits