clang-tools 8.0.0

TypeTraits.cpp
Go to the documentation of this file.
1 //===--- TypeTraits.cpp - clang-tidy---------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "TypeTraits.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/DeclCXX.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14
15 namespace clang {
16 namespace tidy {
17 namespace utils {
18 namespace type_traits {
19
20 namespace {
21
22 bool classHasTrivialCopyAndDestroy(QualType Type) {
23 auto *Record = Type->getAsCXXRecordDecl();
24 return Record && Record->hasDefinition() &&
25 !Record->hasNonTrivialCopyConstructor() &&
26 !Record->hasNonTrivialDestructor();
27 }
28
29 bool hasDeletedCopyConstructor(QualType Type) {
30 auto *Record = Type->getAsCXXRecordDecl();
31 if (!Record || !Record->hasDefinition())
32 return false;
33 for (const auto *Constructor : Record->ctors()) {
34 if (Constructor->isCopyConstructor() && Constructor->isDeleted())
35 return true;
36 }
37 return false;
38 }
39
40 } // namespace
41
42 llvm::Optional<bool> isExpensiveToCopy(QualType Type,
43 const ASTContext &Context) {
44 if (Type->isDependentType() || Type->isIncompleteType())
45 return llvm::None;
46 return !Type.isTriviallyCopyableType(Context) &&
47 !classHasTrivialCopyAndDestroy(Type) &&
48 !hasDeletedCopyConstructor(Type) &&
49 !Type->isObjCLifetimeType();
50 }
51
52 bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl,
53 const ASTContext &Context) {
54 const auto *ClassDecl = dyn_cast<CXXRecordDecl>(&RecordDecl);
55 // Non-C++ records are always trivially constructible.
56 if (!ClassDecl)
57 return true;
58 // A class with a user-provided default constructor is not trivially
59 // constructible.
60 if (ClassDecl->hasUserProvidedDefaultConstructor())
61 return false;
62 // A polymorphic class is not trivially constructible
63 if (ClassDecl->isPolymorphic())
64 return false;
65 // A class is trivially constructible if it has a trivial default constructor.
66 if (ClassDecl->hasTrivialDefaultConstructor())
67 return true;
68
69 // If all its fields are trivially constructible and have no default
70 // initializers.
71 for (const FieldDecl *Field : ClassDecl->fields()) {
72 if (Field->hasInClassInitializer())
73 return false;
74 if (!isTriviallyDefaultConstructible(Field->getType(), Context))
75 return false;
76 }
77 // If all its direct bases are trivially constructible.
78 for (const CXXBaseSpecifier &Base : ClassDecl->bases()) {
79 if (!isTriviallyDefaultConstructible(Base.getType(), Context))
80 return false;
81 if (Base.isVirtual())
82 return false;
83 }
84
85 return true;
86 }
87
88 // Based on QualType::isTrivial.
89 bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {
90 if (Type.isNull())
91 return false;
92
93 if (Type->isArrayType())
94 return isTriviallyDefaultConstructible(Context.getBaseElementType(Type),
95 Context);
96
97 // Return false for incomplete types after skipping any incomplete array
98 // types which are expressly allowed by the standard and thus our API.
99 if (Type->isIncompleteType())
100 return false;
101
102 if (Context.getLangOpts().ObjCAutoRefCount) {
103 switch (Type.getObjCLifetime()) {
104 case Qualifiers::OCL_ExplicitNone:
105 return true;
106
107 case Qualifiers::OCL_Strong:
108 case Qualifiers::OCL_Weak:
109 case Qualifiers::OCL_Autoreleasing:
110 return false;
111
112 case Qualifiers::OCL_None:
113 if (Type->isObjCLifetimeType())
114 return false;
115 break;
116 }
117 }
118
119 QualType CanonicalType = Type.getCanonicalType();
120 if (CanonicalType->isDependentType())
121 return false;
122
123 // As an extension, Clang treats vector types as Scalar types.
124 if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
125 return true;
126
127 if (const auto *RT = CanonicalType->getAs<RecordType>()) {
128 return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context);
129 }
130
131 // No other types can match.
132 return false;
133 }
134
135 bool hasNonTrivialMoveConstructor(QualType Type) {
136 auto *Record = Type->getAsCXXRecordDecl();
137 return Record && Record->hasDefinition() &&
138 Record->hasNonTrivialMoveConstructor();
139 }
140
141 bool hasNonTrivialMoveAssignment(QualType Type) {
142 auto *Record = Type->getAsCXXRecordDecl();
143 return Record && Record->hasDefinition() &&
144 Record->hasNonTrivialMoveAssignment();
145 }
146
147 } // namespace type_traits
148 } // namespace utils
149 } // namespace tidy
150 } // namespace clang
TypeTraits.h
clang::doc::Record
llvm::SmallVector< uint64_t, 1024 > Record
Definition: BitcodeReader.cpp:19
clang::tidy::utils::type_traits::hasNonTrivialMoveConstructor
bool hasNonTrivialMoveConstructor(QualType Type)
Returns true if Type has a non-trivial move constructor.
Definition: TypeTraits.cpp:135
clang::tidy::utils::type_traits::recordIsTriviallyDefaultConstructible
bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl, const ASTContext &Context)
Returns true if RecordDecl is trivially default constructible.
Definition: TypeTraits.cpp:52
clang::tidy::utils::type_traits::isExpensiveToCopy
llvm::Optional< bool > isExpensiveToCopy(QualType Type, const ASTContext &Context)
Returns true if Type is expensive to copy.
Definition: TypeTraits.cpp:42
clang::tidy::utils::type_traits::isTriviallyDefaultConstructible
bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context)
Returns true if Type is trivially default constructible.
Definition: TypeTraits.cpp:89
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ChangeNamespace.cpp:18
clang::tidy::utils::type_traits::hasNonTrivialMoveAssignment
bool hasNonTrivialMoveAssignment(QualType Type)
Return true if Type has a non-trivial move assignment operator.
Definition: TypeTraits.cpp:141