clang-tools  9.0.0
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  // A class with a user-provided default constructor is not trivially
58  // constructible.
59  if (ClassDecl->hasUserProvidedDefaultConstructor())
60  return false;
61  // A polymorphic class is not trivially constructible
62  if (ClassDecl->isPolymorphic())
63  return false;
64  // A class is trivially constructible if it has a trivial default constructor.
65  if (ClassDecl->hasTrivialDefaultConstructor())
66  return true;
67 
68  // If all its fields are trivially constructible and have no default
69  // initializers.
70  for (const FieldDecl *Field : ClassDecl->fields()) {
71  if (Field->hasInClassInitializer())
72  return false;
73  if (!isTriviallyDefaultConstructible(Field->getType(), Context))
74  return false;
75  }
76  // If all its direct bases are trivially constructible.
77  for (const CXXBaseSpecifier &Base : ClassDecl->bases()) {
78  if (!isTriviallyDefaultConstructible(Base.getType(), Context))
79  return false;
80  if (Base.isVirtual())
81  return false;
82  }
83 
84  return true;
85 }
86 
87 // Based on QualType::isTrivial.
88 bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {
89  if (Type.isNull())
90  return false;
91 
92  if (Type->isArrayType())
93  return isTriviallyDefaultConstructible(Context.getBaseElementType(Type),
94  Context);
95 
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())
99  return false;
100 
101  if (Context.getLangOpts().ObjCAutoRefCount) {
102  switch (Type.getObjCLifetime()) {
103  case Qualifiers::OCL_ExplicitNone:
104  return true;
105 
106  case Qualifiers::OCL_Strong:
107  case Qualifiers::OCL_Weak:
108  case Qualifiers::OCL_Autoreleasing:
109  return false;
110 
111  case Qualifiers::OCL_None:
112  if (Type->isObjCLifetimeType())
113  return false;
114  break;
115  }
116  }
117 
118  QualType CanonicalType = Type.getCanonicalType();
119  if (CanonicalType->isDependentType())
120  return false;
121 
122  // As an extension, Clang treats vector types as Scalar types.
123  if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
124  return true;
125 
126  if (const auto *RT = CanonicalType->getAs<RecordType>()) {
127  return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context);
128  }
129 
130  // No other types can match.
131  return false;
132 }
133 
135  auto *Record = Type->getAsCXXRecordDecl();
136  return Record && Record->hasDefinition() &&
137  Record->hasNonTrivialMoveConstructor();
138 }
139 
141  auto *Record = Type->getAsCXXRecordDecl();
142  return Record && Record->hasDefinition() &&
143  Record->hasNonTrivialMoveAssignment();
144 }
145 
146 } // namespace type_traits
147 } // namespace utils
148 } // namespace tidy
149 } // namespace clang
llvm::SmallVector< uint64_t, 1024 > Record
bool hasNonTrivialMoveConstructor(QualType Type)
Returns true if Type has a non-trivial move constructor.
Definition: TypeTraits.cpp:134
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:41
bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context)
Returns true if Type is trivially default constructible.
Definition: TypeTraits.cpp:88
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::unique_ptr< GlobalCompilationDatabase > Base
NodeType Type
bool hasNonTrivialMoveAssignment(QualType Type)
Return true if Type has a non-trivial move assignment operator.
Definition: TypeTraits.cpp:140