~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to languages/cpp/cppduchain/typeutils.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2010-05-05 07:21:55 UTC
  • mfrom: (1.2.3 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100505072155-h78lx19pu04sbhtn
Tags: 4:4.0.0-2
* Upload to unstable (Closes: #579947, #481832).
* Acknowledge obsolete NMU fixes (Closes: #562410, #546961).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright 2007 David Nolden <david.nolden.kdevelop@art-master.de>
 
3
 
 
4
   This library is free software; you can redistribute it and/or
 
5
   modify it under the terms of the GNU Library General Public
 
6
   License version 2 as published by the Free Software Foundation.
 
7
 
 
8
   This library is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
   Library General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU Library General Public License
 
14
   along with this library; see the file COPYING.LIB.  If not, write to
 
15
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
16
   Boston, MA 02110-1301, USA.
 
17
*/
 
18
 
 
19
#include "typeutils.h"
 
20
#include "cppduchain/cpptypes.h"
 
21
#include <language/duchain/ducontext.h>
 
22
#include <language/duchain/forwarddeclaration.h>
 
23
#include <language/duchain/classfunctiondeclaration.h>
 
24
#include <language/duchain/classdeclaration.h>
 
25
#include "typeconversion.h"
 
26
#include <declarationbuilder.h>
 
27
 
 
28
namespace TypeUtils {
 
29
using namespace KDevelop;
 
30
 
 
31
  AbstractType::Ptr realType(const AbstractType::Ptr& _base, const TopDUContext* /*topContext*/, bool* constant) {
 
32
 
 
33
    if(constant)
 
34
      *constant = false;
 
35
    AbstractType::Ptr base = _base;
 
36
    ReferenceType::Ptr ref = base.cast<ReferenceType>();
 
37
    TypeAliasType::Ptr alias = base.cast<TypeAliasType>();
 
38
 
 
39
    while( ref || alias ) {
 
40
      uint hadModifiers = base->modifiers();
 
41
      if(ref) {
 
42
        base = ref->baseType();
 
43
      }else{
 
44
        base = alias->type();
 
45
      }
 
46
      if(base)
 
47
        base->setModifiers(base->modifiers() | hadModifiers);
 
48
      
 
49
      ref = base.cast<ReferenceType>();
 
50
      alias = base.cast<TypeAliasType>();
 
51
    }
 
52
 
 
53
    return base;
 
54
  }
 
55
 
 
56
  AbstractType::Ptr realTypeKeepAliases(const AbstractType::Ptr& _base) {
 
57
 
 
58
    AbstractType::Ptr base = _base;
 
59
    ReferenceType::Ptr ref = base.cast<ReferenceType>();
 
60
 
 
61
    while( ref ) {
 
62
      uint hadModifiers = base->modifiers();
 
63
      base = ref->baseType();
 
64
      if(base)
 
65
        base->setModifiers(base->modifiers() | hadModifiers);
 
66
      
 
67
      ref = base.cast<ReferenceType>();
 
68
    }
 
69
 
 
70
    return base;
 
71
  }
 
72
 
 
73
  bool isPointerType(const AbstractType::Ptr& type) {
 
74
    return realType(type, 0).cast<PointerType>();
 
75
  }
 
76
 
 
77
  bool isReferenceType(const AbstractType::Ptr& type) {
 
78
    return type.cast<ReferenceType>();
 
79
  }
 
80
 
 
81
  bool isConstant( const AbstractType::Ptr& t ) {
 
82
    return t && t->modifiers() & AbstractType::ConstModifier;
 
83
  }
 
84
 
 
85
  bool isNullType( const AbstractType::Ptr& t ) {
 
86
    ConstantIntegralType::Ptr integral = t.cast<ConstantIntegralType>();
 
87
    if( integral && integral->dataType() == IntegralType::TypeInt && integral->value<qint64>() == 0 )
 
88
      return true;
 
89
    else
 
90
      return false;
 
91
  }
 
92
 
 
93
    const int unsignedIntConversionRank = 4;
 
94
 
 
95
  int integerConversionRank( const IntegralType::Ptr& type ) {
 
96
    /**
 
97
     * Ranks:
 
98
     * 1 - bool
 
99
     * 2 - 1 byte, char
 
100
     * 3 - 2 byte,  short int, wchar_t, unsigned short int
 
101
     * 4 - 4 byte,  int, unsigned int
 
102
     * 5 - 4 byte,  long int
 
103
     * 6 - 4 byte, long long int
 
104
     **/
 
105
    switch( type->dataType() ) {
 
106
      case IntegralType::TypeBoolean:
 
107
        return 1;
 
108
      break;
 
109
      case IntegralType::TypeChar:
 
110
        return 2;
 
111
      break;
 
112
      case IntegralType::TypeWchar_t:
 
113
        return 3;
 
114
      break;
 
115
      case IntegralType::TypeInt:
 
116
        if( type->modifiers() & AbstractType::ShortModifier )
 
117
          return 3;
 
118
        if( type->modifiers() & AbstractType::LongModifier )
 
119
          return 5;
 
120
        if( type->modifiers() & AbstractType::LongLongModifier )
 
121
          return 6;
 
122
 
 
123
        return 4; //default-integer
 
124
      //All other types have no integer-conversion-rank
 
125
      default:
 
126
        return 0;
 
127
    };
 
128
  }
 
129
  bool isIntegerType( const IntegralType::Ptr& type ) {
 
130
    return integerConversionRank(type) != 0; //integerConversionRank returns 0 for non-integer types
 
131
  }
 
132
 
 
133
  bool isFloatingPointType( const IntegralType::Ptr& type ) {
 
134
    return type->dataType() == IntegralType::TypeFloat || type->dataType() == IntegralType::TypeDouble;
 
135
  }
 
136
 
 
137
  bool isVoidType( const AbstractType::Ptr& type ) {
 
138
    IntegralType::Ptr integral = type.cast<IntegralType>();
 
139
    if( !integral ) return false;
 
140
    return integral->dataType() == IntegralType::TypeVoid;
 
141
  }
 
142
 
 
143
  ///Returns whether base is a base-class of c
 
144
  void getMemberFunctions(const CppClassType::Ptr& klass, const TopDUContext* topContext, QHash<KDevelop::FunctionType::Ptr, ClassFunctionDeclaration*>& functions, const QString& functionName, bool mustBeConstant)  {
 
145
    Declaration* klassDecl = klass->declaration(topContext);
 
146
    ClassDeclaration* cppClassDecl = dynamic_cast<ClassDeclaration*>(klassDecl);
 
147
    DUContext* context = klassDecl ? klassDecl->internalContext() : 0;
 
148
 
 
149
    int functionCount = functions.size();
 
150
 
 
151
    if( context ) {
 
152
      QList<Declaration*> declarations = context->findLocalDeclarations(Identifier(functionName), SimpleCursor::invalid(), topContext);
 
153
      for( QList<Declaration*>::iterator it = declarations.begin(); it != declarations.end(); ++it ) {
 
154
        KDevelop::FunctionType::Ptr function = (*it)->abstractType().cast<KDevelop::FunctionType>();
 
155
        ClassFunctionDeclaration* functionDeclaration = dynamic_cast<ClassFunctionDeclaration*>( *it );
 
156
        if( function && functionDeclaration ) {
 
157
          if( !functions.contains(function) && (!mustBeConstant || (function->modifiers() & AbstractType::ConstModifier)) ) {
 
158
            functions[function] =  functionDeclaration;
 
159
          }
 
160
        }
 
161
      }
 
162
    }
 
163
 
 
164
    ///One overloaded function of a specific name overloads all inherited with the same name. Think about it in the context where getMemberFunctions is used.
 
165
    if( functionCount != functions.size() )
 
166
      return;
 
167
 
 
168
    if(cppClassDecl) {
 
169
      //equivalent to using the imported parent-contexts
 
170
      FOREACH_FUNCTION(const KDevelop::BaseClassInstance& base, cppClassDecl->baseClasses) {
 
171
        if( base.access != KDevelop::Declaration::Private ) { //we need const-cast here because the constant list makes also the pointers constant, which is not intended
 
172
          CppClassType::Ptr baseClass = base.baseClass.type<CppClassType>();
 
173
          if( baseClass )
 
174
            getMemberFunctions( baseClass, topContext, functions, functionName,   mustBeConstant);
 
175
        }
 
176
      }
 
177
    }
 
178
  }
 
179
 
 
180
  void getMemberFunctions(const CppClassType::Ptr& klass, const TopDUContext* topContext, QList<Declaration*>& functions, const QString& functionName, bool mustBeConstant)  {
 
181
    QHash<KDevelop::FunctionType::Ptr, ClassFunctionDeclaration*> tempFunctions;
 
182
    getMemberFunctions( klass, topContext, tempFunctions, functionName, mustBeConstant );
 
183
    for( QHash<KDevelop::FunctionType::Ptr, ClassFunctionDeclaration*>::const_iterator it = tempFunctions.constBegin(); it != tempFunctions.constEnd(); ++it )
 
184
      functions << (*it);
 
185
  }
 
186
 
 
187
  void getConstructors(const CppClassType::Ptr& klass, const TopDUContext* topContext, QList<Declaration*>& functions) {
 
188
    Declaration* klassDecl = klass->declaration(topContext);
 
189
    DUContext* context = klassDecl ? klassDecl->internalContext() : 0;
 
190
    if( !context || !context->owner() || !context->owner() ) {
 
191
//       kDebug(9007) << "Tried to get constructors of a class without context";
 
192
      return;
 
193
    }
 
194
    
 
195
    Identifier id(context->owner()->identifier());
 
196
    id.clearTemplateIdentifiers();
 
197
 
 
198
    QList<Declaration*> declarations = context->findLocalDeclarations(id, SimpleCursor::invalid(), topContext, AbstractType::Ptr(), DUContext::OnlyFunctions);
 
199
 
 
200
    for( QList<Declaration*>::iterator it = declarations.begin(); it != declarations.end(); ++it ) {
 
201
      ClassFunctionDeclaration* functionDeclaration = dynamic_cast<ClassFunctionDeclaration*>( *it );
 
202
      if( functionDeclaration && functionDeclaration->isConstructor() )
 
203
        functions <<  *it;
 
204
    }
 
205
  }
 
206
  bool isPublicBaseClass( const CppClassType::Ptr& c, const CppClassType::Ptr& base, const KDevelop::TopDUContext* topContext, int* baseConversionLevels ) {
 
207
    ClassDeclaration* fromDecl = dynamic_cast<ClassDeclaration*>(c->declaration(topContext));
 
208
    ClassDeclaration* toDecl = dynamic_cast<ClassDeclaration*>(base->declaration(topContext));
 
209
    if(fromDecl && toDecl)
 
210
      return fromDecl->isPublicBaseClass(toDecl, topContext, baseConversionLevels);
 
211
    else
 
212
      return false;
 
213
  }
 
214
 
 
215
KDevelop::AbstractType::Ptr matchingClassPointer(const KDevelop::AbstractType::Ptr& matchTo, const KDevelop::AbstractType::Ptr& actual, const KDevelop::TopDUContext* topContext) {
 
216
  Cpp::TypeConversion conversion(topContext);
 
217
  
 
218
  StructureType::Ptr actualStructure = realType(actual, topContext).cast<KDevelop::StructureType>();
 
219
  
 
220
  if(actualStructure) {
 
221
    DUContext* internal = actualStructure->internalContext(topContext);
 
222
    if(internal) {
 
223
      typedef QPair<Declaration*, int> DeclarationDepthPair;
 
224
      foreach(Declaration* decl, internal->findDeclarations(Cpp::castIdentifier.identifier(), SimpleCursor::invalid(), topContext, (DUContext::SearchFlags)(DUContext::DontSearchInParent | DUContext::NoFiltering))) {
 
225
        FunctionType::Ptr funType = decl->type<FunctionType>();
 
226
        if(funType && funType->returnType()) {
 
227
          if(conversion.implicitConversion(funType->returnType()->indexed(), matchTo->indexed(), true)) {
 
228
            return funType->returnType();
 
229
          }
 
230
        }
 
231
      }
 
232
    }
 
233
  }
 
234
  
 
235
  return actual;
 
236
}
 
237
 
 
238
Declaration* getDeclaration( const AbstractType::Ptr& type, TopDUContext* top ) {
 
239
  if( !type) return 0;
 
240
 
 
241
  const IdentifiedType* idType = dynamic_cast<const IdentifiedType*>(type.unsafeData());
 
242
  if( idType ) {
 
243
    return idType->declaration(top);
 
244
  } else {
 
245
    return 0;
 
246
  }
 
247
}
 
248
 
 
249
AbstractType::Ptr decreasePointerDepth(AbstractType::Ptr type, TopDUContext* top, bool useOperator) {
 
250
  type = realType(type, top);
 
251
  
 
252
  if( PointerType::Ptr pt = type.cast<PointerType>() )
 
253
  {
 
254
    //Dereference
 
255
    return pt->baseType();
 
256
  }else if( ArrayType::Ptr pt = type.cast<ArrayType>() ) {
 
257
    return pt->elementType();
 
258
  }else{
 
259
    if(useOperator) {
 
260
      Declaration* decl = getDeclaration(type, top);
 
261
      if(decl && decl->internalContext()) {
 
262
        QList<Declaration*> decls = decl->internalContext()->findDeclarations(Identifier("operator*"), SimpleCursor::invalid(), top, DUContext::DontSearchInParent);
 
263
        if(!decls.isEmpty()) {
 
264
          FunctionType::Ptr fun = decls.first()->type<FunctionType>();
 
265
          if(fun)
 
266
            return fun->returnType();
 
267
        }
 
268
      }
 
269
    }
 
270
  }
 
271
  return AbstractType::Ptr();
 
272
}
 
273
 
 
274
AbstractType::Ptr increasePointerDepth(AbstractType::Ptr type) {
 
275
    AbstractType::Ptr oldType = realType(type, 0); ///Dereference references
 
276
    PointerType::Ptr newPointer(new PointerType());
 
277
    newPointer->setBaseType( oldType );
 
278
    return newPointer.cast<AbstractType>();
 
279
}
 
280
 
 
281
AbstractType::Ptr removeConstants(AbstractType::Ptr type, const TopDUContext* source) {
 
282
  
 
283
    if(TypePtr< EnumeratorType > enumerator = type.cast<EnumeratorType>())
 
284
    {
 
285
      Declaration* decl = enumerator->declaration(source);
 
286
      if(decl && decl->context()->owner())
 
287
      {
 
288
        return decl->context()->owner()->abstractType();
 
289
      }
 
290
    }else if(ConstantIntegralType::Ptr integral = type.cast<ConstantIntegralType>())
 
291
      return AbstractType::Ptr(new IntegralType(*integral));
 
292
    
 
293
    return type;
 
294
}
 
295
}