1 /*
2     SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de>
3     SPDX-FileCopyrightText: 2014 Sven Brauch <svenbrauch@gmail.com>
4 
5     SPDX-License-Identifier: LGPL-2.0-only
6 */
7 
8 #include "typeutils.h"
9 #include "referencetype.h"
10 #include "pointertype.h"
11 #include "typealiastype.h"
12 #include "unsuretype.h"
13 #include "integraltype.h"
14 
15 namespace TypeUtils {
16 using namespace KDevelop;
17 
unAliasedType(const TypePtr<KDevelop::AbstractType> & _type)18 TypePtr<KDevelop::AbstractType> unAliasedType(const TypePtr<KDevelop::AbstractType>& _type)
19 {
20     TypePtr<KDevelop::AbstractType> type = _type;
21 
22     TypePtr<KDevelop::TypeAliasType> alias = type.cast<KDevelop::TypeAliasType>();
23 
24     int depth = 0; //Prevent endless recursion
25     while (alias && depth < 20) {
26         uint hadModifiers = alias->modifiers();
27 
28         type = alias->type();
29 
30         if (hadModifiers && type)
31             type->setModifiers(type->modifiers() | hadModifiers);
32 
33         alias = type.cast<KDevelop::TypeAliasType>();
34         ++depth;
35     }
36 
37     return type;
38 }
39 
40 ///@todo remove constant and topContext
targetType(const AbstractType::Ptr & _base,const TopDUContext *,bool *)41 AbstractType::Ptr targetType(const AbstractType::Ptr& _base, const TopDUContext* /*topContext*/, bool* /*constant*/)
42 {
43     AbstractType::Ptr base(_base);
44 
45     ReferenceType::Ptr ref = base.cast<ReferenceType>();
46     PointerType::Ptr pnt = base.cast<PointerType>();
47     TypeAliasType::Ptr alias = base.cast<TypeAliasType>();
48 
49     while (ref || pnt || alias) {
50         uint hadModifiers = base->modifiers();
51 
52         if (ref) {
53             base = ref->baseType();
54         } else if (pnt) {
55             base = pnt->baseType();
56         } else {
57             base = alias->type();
58         }
59         if ((alias || ref) && hadModifiers && base)
60             base->setModifiers(base->modifiers() | hadModifiers);
61 
62         ref = base.cast<ReferenceType>();
63         pnt = base.cast<PointerType>();
64         alias = base.cast<TypeAliasType>();
65     }
66 
67     return base;
68 }
69 
targetTypeKeepAliases(const AbstractType::Ptr & _base,const TopDUContext *,bool *)70 AbstractType::Ptr targetTypeKeepAliases(const AbstractType::Ptr& _base, const TopDUContext* /*topContext*/,
71                                         bool* /*constant*/)
72 {
73     AbstractType::Ptr base(_base);
74 
75     ReferenceType::Ptr ref = base.cast<ReferenceType>();
76     PointerType::Ptr pnt = base.cast<PointerType>();
77 
78     while (ref || pnt) {
79         if (ref) {
80             uint hadModifiers = ref->modifiers();
81             base = ref->baseType();
82             if (hadModifiers && base)
83                 base->setModifiers(base->modifiers() | hadModifiers);
84         } else if (pnt) {
85             base = pnt->baseType();
86         }
87         ref = base.cast<ReferenceType>();
88         pnt = base.cast<PointerType>();
89     }
90 
91     return base;
92 }
93 
resolveAliasType(const AbstractType::Ptr & eventualAlias)94 AbstractType::Ptr resolveAliasType(const AbstractType::Ptr& eventualAlias)
95 {
96     if (eventualAlias && eventualAlias->whichType() == KDevelop::AbstractType::TypeAlias) {
97         return eventualAlias.cast<TypeAliasType>()->type();
98     }
99     return eventualAlias;
100 }
101 
isUsefulType(AbstractType::Ptr type)102 bool isUsefulType(AbstractType::Ptr type)
103 {
104     type = resolveAliasType(type);
105     if (!type) {
106         return false;
107     }
108     if (type->whichType() != AbstractType::TypeIntegral) {
109         return true;
110     }
111     auto dtype = type.cast<IntegralType>()->dataType();
112     if (dtype != IntegralType::TypeMixed && dtype != IntegralType::TypeNull) {
113         return true;
114     }
115     return false;
116 }
117 } // namespace TypeUtils
118