[clang-tidy] Add option "LiteralInitializers" to cppcoreguidelines-pro-type-member-init

Differential Revision: D24892

llvm-svn: 361601
This commit is contained in:
Matthias Gehre 2019-05-24 05:46:57 +00:00
parent 449bfdd1b0
commit b087129b5d
5 changed files with 108 additions and 2 deletions

View File

@ -250,7 +250,8 @@ void fixInitializerList(const ASTContext &Context, DiagnosticBuilder &Diag,
ProTypeMemberInitCheck::ProTypeMemberInitCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IgnoreArrays(Options.get("IgnoreArrays", false)) {}
IgnoreArrays(Options.get("IgnoreArrays", false)),
UseAssignment(Options.getLocalOrGlobal("UseAssignment", false)) {}
void ProTypeMemberInitCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus)
@ -314,6 +315,7 @@ void ProTypeMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
void ProTypeMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IgnoreArrays", IgnoreArrays);
Options.store(Opts, "UseAssignment", UseAssignment);
}
// FIXME: Copied from clang/lib/Sema/SemaDeclCXX.cpp.
@ -338,6 +340,56 @@ static bool isEmpty(ASTContext &Context, const QualType &Type) {
return isIncompleteOrZeroLengthArrayType(Context, Type);
}
static const char *getInitializer(QualType QT, bool UseAssignment) {
const char *DefaultInitializer = "{}";
if (!UseAssignment)
return DefaultInitializer;
if (QT->isPointerType())
return " = nullptr";
const BuiltinType *BT =
dyn_cast<BuiltinType>(QT.getCanonicalType().getTypePtr());
if (!BT)
return DefaultInitializer;
switch (BT->getKind()) {
case BuiltinType::Bool:
return " = false";
case BuiltinType::Float:
return " = 0.0F";
case BuiltinType::Double:
return " = 0.0";
case BuiltinType::LongDouble:
return " = 0.0L";
case BuiltinType::SChar:
case BuiltinType::Char_S:
case BuiltinType::WChar_S:
case BuiltinType::Char16:
case BuiltinType::Char32:
case BuiltinType::Short:
case BuiltinType::Int:
return " = 0";
case BuiltinType::UChar:
case BuiltinType::Char_U:
case BuiltinType::WChar_U:
case BuiltinType::UShort:
case BuiltinType::UInt:
return " = 0U";
case BuiltinType::Long:
return " = 0L";
case BuiltinType::ULong:
return " = 0UL";
case BuiltinType::LongLong:
return " = 0LL";
case BuiltinType::ULongLong:
return " = 0ULL";
default:
return DefaultInitializer;
}
}
void ProTypeMemberInitCheck::checkMissingMemberInitializer(
ASTContext &Context, const CXXRecordDecl &ClassDecl,
const CXXConstructorDecl *Ctor) {
@ -420,7 +472,7 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer(
for (const FieldDecl *Field : FieldsToFix) {
Diag << FixItHint::CreateInsertion(
getLocationForEndOfToken(Context, Field->getSourceRange().getEnd()),
"{}");
getInitializer(Field->getType(), UseAssignment));
}
} else if (Ctor) {
// Otherwise, rewrite the constructor's initializer list.

View File

@ -64,6 +64,11 @@ private:
// Whether arrays need to be initialized or not. Default is false.
bool IgnoreArrays;
// Whether fix-its for initialization of fundamental type use assignment
// instead of brace initalization. Only effective in C++11 mode. Default is
// false.
bool UseAssignment;
};
} // namespace cppcoreguidelines

View File

@ -186,6 +186,11 @@ Improvements to clang-tidy
`WarnOnLargeObject` and `MaxSize` options to warn on any large trivial
object caught by value.
- Added `UseAssignment` option to :doc:`cppcoreguidelines-pro-type-member-init`
If set to true, the check will provide fix-its with literal initializers
(``int i = 0;``) instead of curly braces (``int i{};``).
Improvements to include-fixer
-----------------------------

View File

@ -33,6 +33,10 @@ Options
zero-initialized during construction. For performance critical code, it may
be important to not initialize fixed-size array members. Default is `0`.
.. option:: UseAssignment
If set to non-zero, the check will provide fix-its with literal initializers
(``int i = 0;``) instead of curly braces (``int i{};``).
This rule is part of the "Type safety" profile of the C++ Core
Guidelines, corresponding to rule Type.6. See
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-memberinit.

View File

@ -0,0 +1,40 @@
// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -config="{CheckOptions: [{key: "cppcoreguidelines-pro-type-member-init.UseAssignment", value: 1}]}" -- -std=c++11
struct T {
int i;
};
struct S {
bool b;
// CHECK-FIXES: bool b = false;
char c;
// CHECK-FIXES: char c = 0;
signed char sc;
// CHECK-FIXES: signed char sc = 0;
unsigned char uc;
// CHECK-FIXES: unsigned char uc = 0U;
int i;
// CHECK-FIXES: int i = 0;
unsigned u;
// CHECK-FIXES: unsigned u = 0U;
long l;
// CHECK-FIXES: long l = 0L;
unsigned long ul;
// CHECK-FIXES: unsigned long ul = 0UL;
long long ll;
// CHECK-FIXES: long long ll = 0LL;
unsigned long long ull;
// CHECK-FIXES: unsigned long long ull = 0ULL;
float f;
// CHECK-FIXES: float f = 0.0F;
double d;
// CHECK-FIXES: double d = 0.0;
long double ld;
// CHECK-FIXES: double ld = 0.0L;
int *ptr;
// CHECK-FIXES: int *ptr = nullptr;
T t;
// CHECK-FIXES: T t{};
S() {}
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields:
};