summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/utils
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/utils')
-rw-r--r--clang-tools-extra/clang-tidy/utils/Matchers.h5
-rw-r--r--clang-tools-extra/clang-tidy/utils/TypeTraits.cpp75
-rw-r--r--clang-tools-extra/clang-tidy/utils/TypeTraits.h7
3 files changed, 87 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.h b/clang-tools-extra/clang-tidy/utils/Matchers.h
index 834c06b2861..94ed53a5089 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.h
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -23,6 +23,11 @@ AST_MATCHER(QualType, isExpensiveToCopy) {
return IsExpensive && *IsExpensive;
}
+AST_MATCHER(RecordDecl, isTriviallyDefaultConstructible) {
+ return type_traits::recordIsTriviallyDefaultConstructible(
+ Node, Finder->getASTContext());
+}
+
} // namespace matchers
} // namespace tidy
} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
index 6c17ee356a0..8e63f0a22d0 100644
--- a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
+++ b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp
@@ -31,6 +31,81 @@ llvm::Optional<bool> isExpensiveToCopy(QualType Type, ASTContext &Context) {
!classHasTrivialCopyAndDestroy(Type);
}
+bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl,
+ const ASTContext &Context) {
+ const auto *ClassDecl = dyn_cast<CXXRecordDecl>(&RecordDecl);
+ // Non-C++ records are always trivially constructible.
+ if (!ClassDecl)
+ return true;
+ // A class with a user-provided default constructor is not trivially
+ // constructible.
+ if (ClassDecl->hasUserProvidedDefaultConstructor())
+ return false;
+ // A class is trivially constructible if it has a trivial default constructor.
+ if (ClassDecl->hasTrivialDefaultConstructor())
+ return true;
+
+ // If all its fields are trivially constructible.
+ for (const FieldDecl *Field : ClassDecl->fields()) {
+ if (!isTriviallyDefaultConstructible(Field->getType(), Context))
+ return false;
+ }
+ // If all its direct bases are trivially constructible.
+ for (const CXXBaseSpecifier &Base : ClassDecl->bases()) {
+ if (!isTriviallyDefaultConstructible(Base.getType(), Context))
+ return false;
+ }
+
+ return true;
+}
+
+// Based on QualType::isTrivial.
+bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {
+ if (Type.isNull())
+ return false;
+
+ if (Type->isArrayType())
+ return isTriviallyDefaultConstructible(Context.getBaseElementType(Type),
+ Context);
+
+ // Return false for incomplete types after skipping any incomplete array
+ // types which are expressly allowed by the standard and thus our API.
+ if (Type->isIncompleteType())
+ return false;
+
+ if (Context.getLangOpts().ObjCAutoRefCount) {
+ switch (Type.getObjCLifetime()) {
+ case Qualifiers::OCL_ExplicitNone:
+ return true;
+
+ case Qualifiers::OCL_Strong:
+ case Qualifiers::OCL_Weak:
+ case Qualifiers::OCL_Autoreleasing:
+ return false;
+
+ case Qualifiers::OCL_None:
+ if (Type->isObjCLifetimeType())
+ return false;
+ break;
+ }
+ }
+
+ QualType CanonicalType = Type.getCanonicalType();
+ if (CanonicalType->isDependentType())
+ return false;
+
+ // As an extension, Clang treats vector types as Scalar types.
+ if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
+ return true;
+
+ if (const auto *RT = CanonicalType->getAs<RecordType>()) {
+ return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context);
+ }
+
+ // No other types can match.
+ return false;
+}
+
} // type_traits
} // namespace tidy
} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/utils/TypeTraits.h b/clang-tools-extra/clang-tidy/utils/TypeTraits.h
index 573e61f2f5e..c612e5613d5 100644
--- a/clang-tools-extra/clang-tidy/utils/TypeTraits.h
+++ b/clang-tools-extra/clang-tidy/utils/TypeTraits.h
@@ -20,6 +20,13 @@ namespace type_traits {
// \brief Returns true If \c Type is expensive to copy.
llvm::Optional<bool> isExpensiveToCopy(QualType Type, ASTContext &Context);
+// \brief Returns true If \c Type is trivially default constructible.
+bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context);
+
+// \brief Returns true If \c RecordDecl is trivially default constructible.
+bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl,
+ const ASTContext &Context);
+
} // type_traits
} // namespace tidy
} // namespace clang
OpenPOWER on IntegriCloud