#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include "revng/ADT/CompilationTime.h" #include "revng/ADT/Concepts.h" #include "revng/Model/DynamicFunction.h" #include "revng/Model/Function.h" #include "revng/Model/Identifier.h" #include "revng/Model/Segment.h" // // The following helpers are designed to help with handling metadata. // // Metadata are some common fields appearing in different (sometime unrelated) // types within the model. These allow to work with those in a generic manner. namespace model { // Every supported metadata field should have an `EntityWithXXX` concept // declared for it. template concept EntityWithKey = requires(const Type &Value) { { Value.key() } -> std::convertible_to; }; template concept EntityWithCustomName = requires(const Type &Value) { { Value.CustomName() } -> std::convertible_to; }; template concept EntityWithOriginalName = requires(const Type &Value) { { Value.OriginalName() } -> std::convertible_to; }; template concept EntityWithComment = requires(const Type &Value) { { Value.Comment() } -> std::convertible_to; }; template concept EntityWithReturnValueComment = requires(const Type &Value) { { Value.ReturnValueComment() } -> std::convertible_to; }; template void ensureCompatibility() { static_assert(EntityWithCustomName || EntityWithOriginalName || EntityWithComment || EntityWithReturnValueComment, "This would be a no-op."); } template LHS ©Metadata(LHS &To, const RHS &From) { ensureCompatibility(); ensureCompatibility(); if constexpr (EntityWithCustomName && EntityWithCustomName) To.CustomName() = From.CustomName(); if constexpr (EntityWithOriginalName && EntityWithOriginalName) To.OriginalName() = From.OriginalName(); if constexpr (EntityWithComment && EntityWithComment) To.Comment() = From.Comment(); if constexpr (EntityWithReturnValueComment && EntityWithReturnValueComment) { To.ReturnValueComment() = From.ReturnValueComment(); } return To; } template LHS &moveMetadata(LHS &To, const RHS &From) { ensureCompatibility(); ensureCompatibility(); if constexpr (EntityWithCustomName && EntityWithCustomName) To.CustomName() = std::move(From.CustomName()); if constexpr (EntityWithOriginalName && EntityWithOriginalName) To.OriginalName() = std::move(From.OriginalName()); if constexpr (EntityWithComment && EntityWithComment) To.Comment() = std::move(From.Comment()); if constexpr (EntityWithReturnValueComment && EntityWithReturnValueComment) { To.ReturnValueComment() = std::move(From.ReturnValueComment()); } return To; } template bool hasMetadata(const Type &Value) { ensureCompatibility(); if constexpr (EntityWithCustomName) if (!Value.CustomName().empty()) return true; if constexpr (EntityWithOriginalName) if (!Value.OriginalName().empty()) return true; if constexpr (EntityWithComment) if (!Value.Comment().empty()) return true; if constexpr (EntityWithReturnValueComment) if (!Value.ReturnValueComment().empty()) return true; return false; } } // namespace model