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