clang-tools  3.9.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())
45  return llvm::None;
46  return !Type.isTriviallyCopyableType(Context) &&
47  !classHasTrivialCopyAndDestroy(Type) &&
48  !hasDeletedCopyConstructor(Type);
49 }
50 
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.
55  if (!ClassDecl)
56  return true;
57  // A class with a user-provided default constructor is not trivially
58  // constructible.
59  if (ClassDecl->hasUserProvidedDefaultConstructor())
60  return false;
61  // A class is trivially constructible if it has a trivial default constructor.
62  if (ClassDecl->hasTrivialDefaultConstructor())
63  return true;
64 
65  // If all its fields are trivially constructible.
66  for (const FieldDecl *Field : ClassDecl->fields()) {
67  if (!isTriviallyDefaultConstructible(Field->getType(), Context))
68  return false;
69  }
70  // If all its direct bases are trivially constructible.
71  for (const CXXBaseSpecifier &Base : ClassDecl->bases()) {
72  if (!isTriviallyDefaultConstructible(Base.getType(), Context))
73  return false;
74  }
75 
76  return true;
77 }
78 
79 // Based on QualType::isTrivial.
81  const ASTContext &Context) {
82  if (Type.isNull())
83  return false;
84 
85  if (Type->isArrayType())
86  return isTriviallyDefaultConstructible(Context.getBaseElementType(Type),
87  Context);
88 
89  // Return false for incomplete types after skipping any incomplete array
90  // types which are expressly allowed by the standard and thus our API.
91  if (Type->isIncompleteType())
92  return false;
93 
94  if (Context.getLangOpts().ObjCAutoRefCount) {
95  switch (Type.getObjCLifetime()) {
96  case Qualifiers::OCL_ExplicitNone:
97  return true;
98 
99  case Qualifiers::OCL_Strong:
100  case Qualifiers::OCL_Weak:
101  case Qualifiers::OCL_Autoreleasing:
102  return false;
103 
104  case Qualifiers::OCL_None:
105  if (Type->isObjCLifetimeType())
106  return false;
107  break;
108  }
109  }
110 
111  QualType CanonicalType = Type.getCanonicalType();
112  if (CanonicalType->isDependentType())
113  return false;
114 
115  // As an extension, Clang treats vector types as Scalar types.
116  if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
117  return true;
118 
119  if (const auto *RT = CanonicalType->getAs<RecordType>()) {
120  return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context);
121  }
122 
123  // No other types can match.
124  return false;
125 }
126 
127 bool hasNonTrivialMoveConstructor(QualType Type) {
128  auto *Record = Type->getAsCXXRecordDecl();
129  return Record && Record->hasDefinition() &&
130  Record->hasNonTrivialMoveConstructor();
131 }
132 
133 bool hasNonTrivialMoveAssignment(QualType Type) {
134  auto *Record = Type->getAsCXXRecordDecl();
135  return Record && Record->hasDefinition() &&
136  Record->hasNonTrivialMoveAssignment();
137 }
138 
139 } // namespace type_traits
140 } // namespace utils
141 } // namespace tidy
142 } // namespace clang
bool hasNonTrivialMoveConstructor(QualType Type)
Returns true if Type has a non-trivial move constructor.
Definition: TypeTraits.cpp:127
bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl, const ASTContext &Context)
Returns true if RecordDecl is trivially default constructible.
Definition: TypeTraits.cpp:51
llvm::Optional< bool > isExpensiveToCopy(QualType Type, const ASTContext &Context)
Returns true if Type is expensive to copy.
Definition: TypeTraits.cpp:42
bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context)
Returns true if Type is trivially default constructible.
Definition: TypeTraits.cpp:80
ClangTidyContext & Context
Definition: ClangTidy.cpp:93
bool hasNonTrivialMoveAssignment(QualType Type)
Return true if Type has a non-trivial move assignment operator.
Definition: TypeTraits.cpp:133