File indexing completed on 2024-06-16 04:23:17

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 #include "typeutils.h"
0009 #include "referencetype.h"
0010 #include "pointertype.h"
0011 #include "typealiastype.h"
0012 #include "unsuretype.h"
0013 #include "integraltype.h"
0014 
0015 namespace TypeUtils {
0016 using namespace KDevelop;
0017 
0018 AbstractType::Ptr unAliasedType(const AbstractType::Ptr& _type)
0019 {
0020     auto type = _type;
0021     auto alias = type.dynamicCast<KDevelop::TypeAliasType>();
0022 
0023     int depth = 0; //Prevent endless recursion
0024     while (alias && depth < 20) {
0025         uint hadModifiers = alias->modifiers();
0026 
0027         type = alias->type();
0028 
0029         if (hadModifiers && type)
0030             type->setModifiers(type->modifiers() | hadModifiers);
0031 
0032         alias = type.dynamicCast<KDevelop::TypeAliasType>();
0033         ++depth;
0034     }
0035 
0036     return type;
0037 }
0038 
0039 ///@todo remove constant and topContext
0040 AbstractType::Ptr targetType(const AbstractType::Ptr& _base, const TopDUContext* /*topContext*/, bool* /*constant*/)
0041 {
0042     auto base = _base;
0043 
0044     auto ref = base.dynamicCast<ReferenceType>();
0045     auto pnt = base.dynamicCast<PointerType>();
0046     auto alias = base.dynamicCast<TypeAliasType>();
0047 
0048     while (ref || pnt || alias) {
0049         uint hadModifiers = base->modifiers();
0050 
0051         if (ref) {
0052             base = ref->baseType();
0053         } else if (pnt) {
0054             base = pnt->baseType();
0055         } else {
0056             base = alias->type();
0057         }
0058         if ((alias || ref) && hadModifiers && base)
0059             base->setModifiers(base->modifiers() | hadModifiers);
0060 
0061         ref = base.dynamicCast<ReferenceType>();
0062         pnt = base.dynamicCast<PointerType>();
0063         alias = base.dynamicCast<TypeAliasType>();
0064     }
0065 
0066     return base;
0067 }
0068 
0069 AbstractType::Ptr targetTypeKeepAliases(const AbstractType::Ptr& _base, const TopDUContext* /*topContext*/,
0070                                         bool* /*constant*/)
0071 {
0072     auto base = _base;
0073 
0074     auto ref = base.dynamicCast<ReferenceType>();
0075     auto pnt = base.dynamicCast<PointerType>();
0076 
0077     while (ref || pnt) {
0078         if (ref) {
0079             uint hadModifiers = ref->modifiers();
0080             base = ref->baseType();
0081             if (hadModifiers && base)
0082                 base->setModifiers(base->modifiers() | hadModifiers);
0083         } else if (pnt) {
0084             base = pnt->baseType();
0085         }
0086         ref = base.dynamicCast<ReferenceType>();
0087         pnt = base.dynamicCast<PointerType>();
0088     }
0089 
0090     return base;
0091 }
0092 
0093 AbstractType::Ptr resolveAliasType(const AbstractType::Ptr& eventualAlias)
0094 {
0095     if (eventualAlias && eventualAlias->whichType() == KDevelop::AbstractType::TypeAlias) {
0096         return eventualAlias.staticCast<TypeAliasType>()->type();
0097     }
0098     return eventualAlias;
0099 }
0100 
0101 bool isUsefulType(AbstractType::Ptr type)
0102 {
0103     type = resolveAliasType(type);
0104     if (!type) {
0105         return false;
0106     }
0107     if (type->whichType() != AbstractType::TypeIntegral) {
0108         return true;
0109     }
0110     auto dtype = type.staticCast<IntegralType>()->dataType();
0111     if (dtype != IntegralType::TypeMixed && dtype != IntegralType::TypeNull) {
0112         return true;
0113     }
0114     return false;
0115 }
0116 } // namespace TypeUtils