File indexing completed on 2024-05-26 04:41:13

0001 /*
0002     SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de>
0003     SPDX-FileCopyrightText: 2014 Sven Brauch <svenbrauch@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 #ifndef KDEVPLATFORM_TYPEUTILS_H
0009 #define KDEVPLATFORM_TYPEUTILS_H
0010 
0011 #include <language/languageexport.h>
0012 #include "abstracttype.h"
0013 #include "unsuretype.h"
0014 #include "integraltype.h"
0015 
0016 #include <type_traits>
0017 
0018 namespace KDevelop {
0019 class TopDUContext;
0020 }
0021 
0022 namespace TypeUtils {
0023 /**
0024  * Returns the completely dereferenced and un-aliased type, pointers are also dereferenced(example: ReferenceType(PointerType(int)) -> int)
0025  * All modifiers are pushed from the aliases into the targets.
0026  *
0027  *  !!DU-Chain must be locked!
0028  * Modifiers of aliases ore references are pushed into the targets.
0029  * @return return-value will only be zero if type is zero
0030  */
0031 KDEVPLATFORMLANGUAGE_EXPORT KDevelop::AbstractType::Ptr targetType(const KDevelop::AbstractType::Ptr& type,
0032                                                                    const KDevelop::TopDUContext* topContext,
0033                                                                    bool* constant = nullptr);
0034 /**
0035  * Same as targetType(..), except that it does not un-aliases TypeAliasTypes
0036  * Modifiers of aliases ore references are pushed into the targets.
0037  */
0038 KDEVPLATFORMLANGUAGE_EXPORT KDevelop::AbstractType::Ptr targetTypeKeepAliases(const KDevelop::AbstractType::Ptr& type,
0039                                                                               const KDevelop::TopDUContext* topContext,
0040                                                                               bool* constant = nullptr);
0041 /**
0042  * Resolves all type-aliases, returning the effective aliased type
0043  * All modifiers are pushed from the aliases into the targets.
0044  */
0045 KDEVPLATFORMLANGUAGE_EXPORT KDevelop::AbstractType::Ptr unAliasedType(const KDevelop::AbstractType::Ptr& type);
0046 
0047 /**
0048  * @brief If @p eventualAlias is an AliasType, return its aliasedType(), otherwise return @p eventualAlias.
0049  */
0050 KDEVPLATFORMLANGUAGE_EXPORT KDevelop::AbstractType::Ptr resolveAliasType(
0051     const KDevelop::AbstractType::Ptr& eventualAlias);
0052 
0053 /**
0054  * @brief Check whether the passed type is a null or mixed type.
0055  * @param type The type to check. Can be null, in which case the function returns false.
0056  */
0057 KDEVPLATFORMLANGUAGE_EXPORT bool isUsefulType(KDevelop::AbstractType::Ptr type);
0058 
0059 /**
0060  * @brief Merge the second type into the first one
0061  *
0062  * If either of @p type or @p newType is null or mixed, return the other one.
0063  * If one or both of the types is an unsure, or if both types are not null, return
0064  * an unsure type representing all possible types from both.
0065  *
0066  * @param type old type
0067  * @param newType the type to be added to @p type
0068  * @return AbstractType::Ptr the merged type, always valid
0069  *
0070  * The first argument might be modified, the second one won't be.
0071  * So if you do something like a = mergeTypes(a, b) make sure you pass "a" as first argument.
0072  *
0073  * @warning: If your language has its own specialized UnsureType, make sure to pass it
0074  * as a template parameter.
0075  **/
0076 template <typename LanguageUnsureType = KDevelop::UnsureType>
0077 KDevelop::AbstractType::Ptr mergeTypes(KDevelop::AbstractType::Ptr type, const KDevelop::AbstractType::Ptr& newType)
0078 {
0079     static_assert(std::is_base_of<KDevelop::UnsureType, LanguageUnsureType>::value,
0080                   "LanguageUnsureType must inherit from KDevelop::UnsureType");
0081 
0082     auto unsure = type.dynamicCast<LanguageUnsureType>();
0083     auto newUnsure = newType.dynamicCast<LanguageUnsureType>();
0084     typename LanguageUnsureType::Ptr ret;
0085 
0086     // both types are unsure, so join the list of possible types.
0087     if (unsure && newUnsure) {
0088         int len = newUnsure->typesSize();
0089         for (int i = 0; i < len; i++) {
0090             unsure->addType(newUnsure->types()[i]);
0091         }
0092 
0093         ret = unsure;
0094     }
0095     // one of them is unsure, use that and add the other one
0096     else if (unsure) {
0097         if (isUsefulType(newType)) {
0098             unsure->addType(newType->indexed());
0099         }
0100         ret = unsure;
0101     } else if (newUnsure) {
0102         auto createdUnsureType = KDevelop::AbstractType::Ptr(newUnsure->clone()).staticCast<LanguageUnsureType>();
0103         if (isUsefulType(type)) {
0104             createdUnsureType->addType(type->indexed());
0105         }
0106         ret = createdUnsureType;
0107     } else {
0108         unsure = typename LanguageUnsureType::Ptr(new LanguageUnsureType());
0109         if (isUsefulType(type)) {
0110             unsure->addType(type->indexed());
0111         }
0112         if (isUsefulType(newType)) {
0113             unsure->addType(newType->indexed());
0114         }
0115         if (!unsure->typesSize()) {
0116             return KDevelop::AbstractType::Ptr(new KDevelop::IntegralType(KDevelop::IntegralType::TypeMixed));
0117         }
0118         ret = unsure;
0119     }
0120     if (ret->typesSize() == 1) {
0121         return ret->types()[0].abstractType();
0122     } else {
0123         return ret;
0124     }
0125 }
0126 }
0127 
0128 #endif