[clang-tools-extra] r269024 - Fixed cppcoreguidelines-pro-type-member-init when checking records with indirect fields
Haojian Wu via cfe-commits
cfe-commits at lists.llvm.org
Tue May 10 00:42:20 PDT 2016
Author: hokein
Date: Tue May 10 02:42:19 2016
New Revision: 269024
URL: http://llvm.org/viewvc/llvm-project?rev=269024&view=rev
Log:
Fixed cppcoreguidelines-pro-type-member-init when checking records with indirect fields
Summary:
Fixed a crash in cppcoreguidelines-pro-type-member-init when checking record types with indirect fields pre-C++11.
Fixed handling of indirect fields so they are properly checked and suggested fixes are proposed.
Patch by Michael Miller!
Reviewers: aaron.ballman, alexfh, hokein
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D19993
Modified:
clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp?rev=269024&r1=269023&r2=269024&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp Tue May 10 02:42:19 2016
@@ -27,16 +27,23 @@ namespace cppcoreguidelines {
namespace {
-void fieldsRequiringInit(const RecordDecl::field_range &Fields,
- ASTContext &Context,
- SmallPtrSetImpl<const FieldDecl *> &FieldsToInit) {
+// Iterate over all the fields in a record type, both direct and indirect (e.g.
+// if the record contains an anonmyous struct). If OneFieldPerUnion is true and
+// the record type (or indirect field) is a union, forEachField will stop after
+// the first field.
+template <typename T, typename Func>
+void forEachField(const RecordDecl *Record, const T &Fields,
+ bool OneFieldPerUnion, Func &&Fn) {
for (const FieldDecl *F : Fields) {
- if (F->hasInClassInitializer())
- continue;
- QualType Type = F->getType();
- if (!F->hasInClassInitializer() &&
- utils::type_traits::isTriviallyDefaultConstructible(Type, Context))
- FieldsToInit.insert(F);
+ if (F->isAnonymousStructOrUnion()) {
+ if (const CXXRecordDecl *R = F->getType()->getAsCXXRecordDecl())
+ forEachField(R, R->fields(), OneFieldPerUnion, Fn);
+ } else {
+ Fn(F);
+ }
+
+ if (OneFieldPerUnion && Record->isUnion())
+ break;
}
}
@@ -179,8 +186,8 @@ computeInsertions(const CXXConstructorDe
// Gets either the field or base class being initialized by the provided
// initializer.
const auto *InitDecl =
- Init->isMemberInitializer()
- ? static_cast<const NamedDecl *>(Init->getMember())
+ Init->isAnyMemberInitializer()
+ ? static_cast<const NamedDecl *>(Init->getAnyMember())
: Init->getBaseClass()->getAsCXXRecordDecl();
// Add all fields between current field up until the next intializer.
@@ -216,7 +223,8 @@ void getInitializationsInOrder(const CXX
Decls.emplace_back(Decl);
}
}
- Decls.append(ClassDecl->fields().begin(), ClassDecl->fields().end());
+ forEachField(ClassDecl, ClassDecl->fields(), false,
+ [&](const FieldDecl *F) { Decls.push_back(F); });
}
template <typename T>
@@ -238,22 +246,6 @@ void fixInitializerList(const ASTContext
}
}
-template <typename T, typename Func>
-void forEachField(const RecordDecl *Record, const T &Fields,
- bool OneFieldPerUnion, Func &&Fn) {
- for (const FieldDecl *F : Fields) {
- if (F->isAnonymousStructOrUnion()) {
- if (const RecordDecl *R = getCanonicalRecordDecl(F->getType()))
- forEachField(R, R->fields(), OneFieldPerUnion, Fn);
- } else {
- Fn(F);
- }
-
- if (OneFieldPerUnion && Record->isUnion())
- break;
- }
-}
-
} // anonymous namespace
ProTypeMemberInitCheck::ProTypeMemberInitCheck(StringRef Name,
@@ -314,8 +306,14 @@ void ProTypeMemberInitCheck::checkMissin
if (IsUnion && ClassDecl->hasInClassInitializer())
return;
+ // Gather all fields (direct and indirect) that need to be initialized.
SmallPtrSet<const FieldDecl *, 16> FieldsToInit;
- fieldsRequiringInit(ClassDecl->fields(), Context, FieldsToInit);
+ forEachField(ClassDecl, ClassDecl->fields(), false, [&](const FieldDecl *F) {
+ if (!F->hasInClassInitializer() &&
+ utils::type_traits::isTriviallyDefaultConstructible(F->getType(),
+ Context))
+ FieldsToInit.insert(F);
+ });
if (FieldsToInit.empty())
return;
@@ -325,7 +323,7 @@ void ProTypeMemberInitCheck::checkMissin
if (Init->isAnyMemberInitializer() && Init->isWritten()) {
if (IsUnion)
return; // We can only initialize one member of a union.
- FieldsToInit.erase(Init->getMember());
+ FieldsToInit.erase(Init->getAnyMember());
}
}
removeFieldsInitializedInBody(*Ctor->getBody(), Context, FieldsToInit);
@@ -389,8 +387,8 @@ void ProTypeMemberInitCheck::checkMissin
if (const auto *BaseClassDecl = getCanonicalRecordDecl(Base.getType())) {
AllBases.emplace_back(BaseClassDecl);
if (!BaseClassDecl->field_empty() &&
- utils::type_traits::isTriviallyDefaultConstructible(
- Base.getType(), Context))
+ utils::type_traits::isTriviallyDefaultConstructible(Base.getType(),
+ Context))
BasesToInit.insert(BaseClassDecl);
}
}
Modified: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp?rev=269024&r1=269023&r2=269024&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init-cxx98.cpp Tue May 10 02:42:19 2016
@@ -103,3 +103,14 @@ public:
int X;
};
+
+class PositiveIndirectMember {
+ struct {
+ int *A;
+ };
+
+ PositiveIndirectMember() : A() {}
+ PositiveIndirectMember(int) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A
+ // CHECK-FIXES: PositiveIndirectMember(int) : A() {}
+};
Modified: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp?rev=269024&r1=269023&r2=269024&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-pro-type-member-init.cpp Tue May 10 02:42:19 2016
@@ -357,3 +357,13 @@ class PositiveSelfInitialization : Negat
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType
// CHECK-FIXES: PositiveSelfInitialization() : NegativeAggregateType(), PositiveSelfInitialization() {}
};
+
+class PositiveIndirectMember {
+ struct {
+ int *A;
+ // CHECK-FIXES: int *A{};
+ };
+
+ PositiveIndirectMember() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A
+};
More information about the cfe-commits
mailing list