diff options
Diffstat (limited to 'clang-tools-extra/clang-tidy/utils')
-rw-r--r-- | clang-tools-extra/clang-tidy/utils/Matchers.h | 5 | ||||
-rw-r--r-- | clang-tools-extra/clang-tidy/utils/TypeTraits.cpp | 75 | ||||
-rw-r--r-- | clang-tools-extra/clang-tidy/utils/TypeTraits.h | 7 |
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 |