brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · 98a5d40 Raw
157 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "TypeTraits.h"10#include "clang/AST/ASTContext.h"11#include "clang/AST/DeclCXX.h"12#include <optional>13 14namespace clang::tidy::utils::type_traits {15 16static bool classHasTrivialCopyAndDestroy(QualType Type) {17  auto *Record = Type->getAsCXXRecordDecl();18  return Record && Record->hasDefinition() &&19         !Record->hasNonTrivialCopyConstructor() &&20         !Record->hasNonTrivialDestructor();21}22 23static bool hasDeletedCopyConstructor(QualType Type) {24  auto *Record = Type->getAsCXXRecordDecl();25  if (!Record || !Record->hasDefinition())26    return false;27  for (const auto *Constructor : Record->ctors()) {28    if (Constructor->isCopyConstructor() && Constructor->isDeleted())29      return true;30  }31  return false;32}33 34std::optional<bool> isExpensiveToCopy(QualType Type,35                                      const ASTContext &Context) {36  if (Type->isDependentType() || Type->isIncompleteType())37    return std::nullopt;38  return !Type.isTriviallyCopyableType(Context) &&39         !classHasTrivialCopyAndDestroy(Type) &&40         !hasDeletedCopyConstructor(Type) && !Type->isObjCLifetimeType();41}42 43bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl,44                                           const ASTContext &Context) {45  const auto *ClassDecl = dyn_cast<CXXRecordDecl>(&RecordDecl);46  // Non-C++ records are always trivially constructible.47  if (!ClassDecl)48    return true;49  // It is impossible to determine whether an ill-formed decl is trivially50  // constructible.51  if (RecordDecl.isInvalidDecl())52    return false;53  // A class with a user-provided default constructor is not trivially54  // constructible.55  if (ClassDecl->hasUserProvidedDefaultConstructor())56    return false;57  // A polymorphic class is not trivially constructible58  if (ClassDecl->isPolymorphic())59    return false;60  // A class is trivially constructible if it has a trivial default constructor.61  if (ClassDecl->hasTrivialDefaultConstructor())62    return true;63 64  // If all its fields are trivially constructible and have no default65  // initializers.66  for (const FieldDecl *Field : ClassDecl->fields()) {67    if (Field->hasInClassInitializer())68      return false;69    if (!isTriviallyDefaultConstructible(Field->getType(), Context))70      return false;71  }72  // If all its direct bases are trivially constructible.73  for (const CXXBaseSpecifier &Base : ClassDecl->bases()) {74    if (!isTriviallyDefaultConstructible(Base.getType(), Context))75      return false;76    if (Base.isVirtual())77      return false;78  }79 80  return true;81}82 83// Based on QualType::isTrivial.84bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) {85  if (Type.isNull())86    return false;87 88  if (Type->isArrayType())89    return isTriviallyDefaultConstructible(Context.getBaseElementType(Type),90                                           Context);91 92  // Return false for incomplete types after skipping any incomplete array93  // types which are expressly allowed by the standard and thus our API.94  if (Type->isIncompleteType())95    return false;96 97  if (Context.getLangOpts().ObjCAutoRefCount) {98    switch (Type.getObjCLifetime()) {99    case Qualifiers::OCL_ExplicitNone:100      return true;101 102    case Qualifiers::OCL_Strong:103    case Qualifiers::OCL_Weak:104    case Qualifiers::OCL_Autoreleasing:105      return false;106 107    case Qualifiers::OCL_None:108      if (Type->isObjCLifetimeType())109        return false;110      break;111    }112  }113 114  const QualType CanonicalType = Type.getCanonicalType();115  if (CanonicalType->isDependentType())116    return false;117 118  // As an extension, Clang treats vector types as Scalar types.119  if (CanonicalType->isScalarType() || CanonicalType->isVectorType())120    return true;121 122  if (const auto *RD = CanonicalType->getAsRecordDecl()) {123    return recordIsTriviallyDefaultConstructible(*RD, Context);124  }125 126  // No other types can match.127  return false;128}129 130// Based on QualType::isDestructedType.131bool isTriviallyDestructible(QualType Type) {132  if (Type.isNull())133    return false;134 135  if (Type->isIncompleteType())136    return false;137 138  if (Type.getCanonicalType()->isDependentType())139    return false;140 141  return Type.isDestructedType() == QualType::DK_none;142}143 144bool hasNonTrivialMoveConstructor(QualType Type) {145  auto *Record = Type->getAsCXXRecordDecl();146  return Record && Record->hasDefinition() &&147         Record->hasNonTrivialMoveConstructor();148}149 150bool hasNonTrivialMoveAssignment(QualType Type) {151  auto *Record = Type->getAsCXXRecordDecl();152  return Record && Record->hasDefinition() &&153         Record->hasNonTrivialMoveAssignment();154}155 156} // namespace clang::tidy::utils::type_traits157