clang-tools  14.0.0git
TypeTraits.cpp
Go to the documentation of this file.
1 //===--- TypeTraits.cpp - clang-tidy---------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "TypeTraits.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/DeclCXX.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 
14 namespace clang {
15 namespace tidy {
16 namespace utils {
17 namespace type_traits {
18 
19 namespace {
20 
21 bool classHasTrivialCopyAndDestroy(QualType Type) {
22  auto *Record = Type->getAsCXXRecordDecl();
23  return Record && Record->hasDefinition() &&
24  !Record->hasNonTrivialCopyConstructor() &&
25  !Record->hasNonTrivialDestructor();
26 }
27 
28 bool hasDeletedCopyConstructor(QualType Type) {
29  auto *Record = Type->getAsCXXRecordDecl();
30  if (!Record || !Record->hasDefinition())
31  return false;
32  for (const auto *Constructor : Record->ctors()) {
33  if (Constructor->isCopyConstructor() && Constructor->isDeleted())
34  return true;
35  }
36  return false;
37 }
38 
39 } // namespace
40 
41 llvm::Optional<bool> isExpensiveToCopy(QualType Type,
42  const ASTContext &Context) {
43  if (Type->isDependentType() || Type->isIncompleteType())
44  return llvm::None;
45  return !Type.isTriviallyCopyableType(Context) &&
46  !classHasTrivialCopyAndDestroy(Type) &&
47  !hasDeletedCopyConstructor(Type) &&
48  !Type->isObjCLifetimeType();
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  // It is impossible to determine whether an ill-formed decl is trivially
58  // constructible.
59  if (RecordDecl.isInvalidDecl())
60  return false;
61  // A class with a user-provided default constructor is not trivially
62  // constructible.
63  if (ClassDecl->hasUserProvidedDefaultConstructor())
64  return false;
65  // A polymorphic class is not trivially constructible
66  if (ClassDecl->isPolymorphic())
67  return false;
68  // A class is trivially constructible if it has a trivial default constructor.
69  if (ClassDecl->hasTrivialDefaultConstructor())
70  return true;
71 
72  // If all its fields are trivially constructible and have no default
73  // initializers.
74  for (const FieldDecl *Field : ClassDecl->fields()) {
75  if (Field->hasInClassInitializer())
76  return false;
77  if (!isTriviallyDefaultConstructible(Field->getType(), Context))
78  return false;
79  }
80  // If all its direct bases are trivially constructible.
81  for (const CXXBaseSpecifier &Base : ClassDecl->bases()) {
82  if (!isTriviallyDefaultConstructible(Base.getType(), Context))
83  return false;
84  if (Base.isVirtual())
85  return false;
86  }
87 
88  return true;
89 }
90 
91 // Based on QualType::isTrivial.
92 bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {
93  if (Type.isNull())
94  return false;
95 
96  if (Type->isArrayType())
97  return isTriviallyDefaultConstructible(Context.getBaseElementType(Type),
98  Context);
99 
100  // Return false for incomplete types after skipping any incomplete array
101  // types which are expressly allowed by the standard and thus our API.
102  if (Type->isIncompleteType())
103  return false;
104 
105  if (Context.getLangOpts().ObjCAutoRefCount) {
106  switch (Type.getObjCLifetime()) {
107  case Qualifiers::OCL_ExplicitNone:
108  return true;
109 
110  case Qualifiers::OCL_Strong:
111  case Qualifiers::OCL_Weak:
112  case Qualifiers::OCL_Autoreleasing:
113  return false;
114 
115  case Qualifiers::OCL_None:
116  if (Type->isObjCLifetimeType())
117  return false;
118  break;
119  }
120  }
121 
122  QualType CanonicalType = Type.getCanonicalType();
123  if (CanonicalType->isDependentType())
124  return false;
125 
126  // As an extension, Clang treats vector types as Scalar types.
127  if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
128  return true;
129 
130  if (const auto *RT = CanonicalType->getAs<RecordType>()) {
131  return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context);
132  }
133 
134  // No other types can match.
135  return false;
136 }
137 
138 // Based on QualType::isDestructedType.
139 bool isTriviallyDestructible(QualType Type) {
140  if (Type.isNull())
141  return false;
142 
143  if (Type->isIncompleteType())
144  return false;
145 
146  if (Type.getCanonicalType()->isDependentType())
147  return false;
148 
149  return Type.isDestructedType() == QualType::DK_none;
150 }
151 
152 bool hasNonTrivialMoveConstructor(QualType Type) {
153  auto *Record = Type->getAsCXXRecordDecl();
154  return Record && Record->hasDefinition() &&
155  Record->hasNonTrivialMoveConstructor();
156 }
157 
158 bool hasNonTrivialMoveAssignment(QualType Type) {
159  auto *Record = Type->getAsCXXRecordDecl();
160  return Record && Record->hasDefinition() &&
161  Record->hasNonTrivialMoveAssignment();
162 }
163 
164 } // namespace type_traits
165 } // namespace utils
166 } // namespace tidy
167 } // namespace clang
Base
std::unique_ptr< GlobalCompilationDatabase > Base
Definition: GlobalCompilationDatabaseTests.cpp:90
Type
NodeType Type
Definition: HTMLGenerator.cpp:73
clang::tidy::utils::type_traits::isTriviallyDestructible
bool isTriviallyDestructible(QualType Type)
Returns true if Type is trivially destructible.
Definition: TypeTraits.cpp:139
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:41
clang::tidy::utils::type_traits::isTriviallyDefaultConstructible
bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context)
Returns true if Type is trivially default constructible.
Definition: TypeTraits.cpp:92
TypeTraits.h
clang::tidy::utils::type_traits::hasNonTrivialMoveConstructor
bool hasNonTrivialMoveConstructor(QualType Type)
Returns true if Type has a non-trivial move constructor.
Definition: TypeTraits.cpp:152
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:51
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::doc::Record
llvm::SmallVector< uint64_t, 1024 > Record
Definition: BitcodeReader.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:158