1 //===--- TypeTraits.cpp - clang-tidy---------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "TypeTraits.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/DeclCXX.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
18 namespace type_traits {
22 bool classHasTrivialCopyAndDestroy(QualType Type) {
23 auto *Record = Type->getAsCXXRecordDecl();
24 return Record && Record->hasDefinition() &&
25 !Record->hasNonTrivialCopyConstructor() &&
26 !Record->hasNonTrivialDestructor();
29 bool hasDeletedCopyConstructor(QualType Type) {
30 auto *Record = Type->getAsCXXRecordDecl();
31 if (!Record || !Record->hasDefinition())
33 for (const auto *Constructor : Record->ctors()) {
34 if (Constructor->isCopyConstructor() && Constructor->isDeleted())
42 llvm::Optional<bool> isExpensiveToCopy(QualType Type,
43 const ASTContext &Context) {
44 if (Type->isDependentType() || Type->isIncompleteType())
46 return !Type.isTriviallyCopyableType(Context) &&
47 !classHasTrivialCopyAndDestroy(Type) &&
48 !hasDeletedCopyConstructor(Type);
51 bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl,
52 const ASTContext &Context) {
53 const auto *ClassDecl = dyn_cast<CXXRecordDecl>(&RecordDecl);
54 // Non-C++ records are always trivially constructible.
57 // A class with a user-provided default constructor is not trivially
59 if (ClassDecl->hasUserProvidedDefaultConstructor())
61 // A polymorphic class is not trivially constructible
62 if (ClassDecl->isPolymorphic())
64 // A class is trivially constructible if it has a trivial default constructor.
65 if (ClassDecl->hasTrivialDefaultConstructor())
68 // If all its fields are trivially constructible and have no default
70 for (const FieldDecl *Field : ClassDecl->fields()) {
71 if (Field->hasInClassInitializer())
73 if (!isTriviallyDefaultConstructible(Field->getType(), Context))
76 // If all its direct bases are trivially constructible.
77 for (const CXXBaseSpecifier &Base : ClassDecl->bases()) {
78 if (!isTriviallyDefaultConstructible(Base.getType(), Context))
87 // Based on QualType::isTrivial.
88 bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {
92 if (Type->isArrayType())
93 return isTriviallyDefaultConstructible(Context.getBaseElementType(Type),
96 // Return false for incomplete types after skipping any incomplete array
97 // types which are expressly allowed by the standard and thus our API.
98 if (Type->isIncompleteType())
101 if (Context.getLangOpts().ObjCAutoRefCount) {
102 switch (Type.getObjCLifetime()) {
103 case Qualifiers::OCL_ExplicitNone:
106 case Qualifiers::OCL_Strong:
107 case Qualifiers::OCL_Weak:
108 case Qualifiers::OCL_Autoreleasing:
111 case Qualifiers::OCL_None:
112 if (Type->isObjCLifetimeType())
118 QualType CanonicalType = Type.getCanonicalType();
119 if (CanonicalType->isDependentType())
122 // As an extension, Clang treats vector types as Scalar types.
123 if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
126 if (const auto *RT = CanonicalType->getAs<RecordType>()) {
127 return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context);
130 // No other types can match.
134 bool hasNonTrivialMoveConstructor(QualType Type) {
135 auto *Record = Type->getAsCXXRecordDecl();
136 return Record && Record->hasDefinition() &&
137 Record->hasNonTrivialMoveConstructor();
140 bool hasNonTrivialMoveAssignment(QualType Type) {
141 auto *Record = Type->getAsCXXRecordDecl();
142 return Record && Record->hasDefinition() &&
143 Record->hasNonTrivialMoveAssignment();
146 } // namespace type_traits