diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.Unreal.h b/clang/include/clang/ASTMatchers/ASTMatchers.Unreal.h index 05cf921a22ad2f..be353d0cea3151 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.Unreal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.Unreal.h @@ -468,4 +468,37 @@ AST_MATCHER(ElaboratedTypeLoc, hasRedundantNamespacing) { return false; } +inline bool classHasTrivialCopyAndDestroy(QualType Type) { + auto *Record = Type->getAsCXXRecordDecl(); + return Record && Record->hasDefinition() && + !Record->hasNonTrivialCopyConstructor() && + !Record->hasNonTrivialDestructor(); +} + +inline bool hasDeletedCopyConstructor(QualType Type) { + auto *Record = Type->getAsCXXRecordDecl(); + if (!Record || !Record->hasDefinition()) + return false; + for (const auto *Constructor : Record->ctors()) { + if (Constructor->isCopyConstructor() && Constructor->isDeleted()) + return true; + } + return false; +} + +inline std::optional isExpensiveToCopyNode(QualType Type, + const ASTContext &Context) { + if (Type->isDependentType() || Type->isIncompleteType()) + return std::nullopt; + return !Type.isTriviallyCopyableType(Context) && + !classHasTrivialCopyAndDestroy(Type) && + !hasDeletedCopyConstructor(Type) && !Type->isObjCLifetimeType(); +} + +AST_MATCHER(QualType, isExpensiveToCopy) { + std::optional IsExpensive = + isExpensiveToCopyNode(Node, Finder->getASTContext()); + return IsExpensive && *IsExpensive; +} + // @unreal: END \ No newline at end of file diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.Unreal.h b/clang/lib/ASTMatchers/Dynamic/Registry.Unreal.h new file mode 100644 index 00000000000000..a1b7a77a85adf1 --- /dev/null +++ b/clang/lib/ASTMatchers/Dynamic/Registry.Unreal.h @@ -0,0 +1,21 @@ +// @unreal: BEGIN +REGISTER_MATCHER(refersToPack); +REGISTER_MATCHER(forNone); +REGISTER_MATCHER(forNoDescendant); +REGISTER_MATCHER(isUClass); +REGISTER_MATCHER(isUStruct); +REGISTER_MATCHER(isUInterface); +REGISTER_MATCHER(isIInterface); +REGISTER_MATCHER(isUFunction); +REGISTER_MATCHER(isUProperty); +REGISTER_MATCHER(hasUSpecifier); +REGISTER_MATCHER(hasUSpecifierValue); +REGISTER_MATCHER(hasUMetadata); +REGISTER_MATCHER(hasUMetadataValue); +REGISTER_MATCHER(withIInterface); +REGISTER_MATCHER(withUInterface); +REGISTER_MATCHER(isMissingDllImportOrExport); +REGISTER_MATCHER(isPODType); +REGISTER_MATCHER(hasRedundantNamespacing); +REGISTER_MATCHER(isExpensiveToCopy); +// @unreal: END \ No newline at end of file diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 91581832017d10..13ef131e1d6557 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -380,22 +380,6 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasUnaryOperand); REGISTER_MATCHER(hasUnarySelector); REGISTER_MATCHER(isPODType); - // @unreal: BEGIN - REGISTER_MATCHER(isUClass); - REGISTER_MATCHER(isUStruct); - REGISTER_MATCHER(isUInterface); - REGISTER_MATCHER(isIInterface); - REGISTER_MATCHER(isUFunction); - REGISTER_MATCHER(isUProperty); - REGISTER_MATCHER(hasUSpecifier); - REGISTER_MATCHER(hasUSpecifierValue); - REGISTER_MATCHER(hasUMetadata); - REGISTER_MATCHER(hasUMetadataValue); - REGISTER_MATCHER(withIInterface); - REGISTER_MATCHER(withUInterface); - REGISTER_MATCHER(isMissingDllImportOrExport); - REGISTER_MATCHER(hasRedundantNamespacing); - // @unreal: END REGISTER_MATCHER(hasUnderlyingDecl); REGISTER_MATCHER(hasUnderlyingType); REGISTER_MATCHER(hasUnqualifiedDesugaredType); @@ -629,6 +613,8 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(voidType); REGISTER_MATCHER(whileStmt); REGISTER_MATCHER(withInitializer); + + #include "Registry.Unreal.h" } RegistryMaps::~RegistryMaps() = default;