2
Copyright 2007 David Nolden <david.nolden.kdevelop@art-master.de>
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.
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.
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.
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>
29
using namespace KDevelop;
31
AbstractType::Ptr realType(const AbstractType::Ptr& _base, const TopDUContext* /*topContext*/, bool* constant) {
35
AbstractType::Ptr base = _base;
36
ReferenceType::Ptr ref = base.cast<ReferenceType>();
37
TypeAliasType::Ptr alias = base.cast<TypeAliasType>();
39
while( ref || alias ) {
40
uint hadModifiers = base->modifiers();
42
base = ref->baseType();
47
base->setModifiers(base->modifiers() | hadModifiers);
49
ref = base.cast<ReferenceType>();
50
alias = base.cast<TypeAliasType>();
56
AbstractType::Ptr realTypeKeepAliases(const AbstractType::Ptr& _base) {
58
AbstractType::Ptr base = _base;
59
ReferenceType::Ptr ref = base.cast<ReferenceType>();
62
uint hadModifiers = base->modifiers();
63
base = ref->baseType();
65
base->setModifiers(base->modifiers() | hadModifiers);
67
ref = base.cast<ReferenceType>();
73
bool isPointerType(const AbstractType::Ptr& type) {
74
return realType(type, 0).cast<PointerType>();
77
bool isReferenceType(const AbstractType::Ptr& type) {
78
return type.cast<ReferenceType>();
81
bool isConstant( const AbstractType::Ptr& t ) {
82
return t && t->modifiers() & AbstractType::ConstModifier;
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 )
93
const int unsignedIntConversionRank = 4;
95
int integerConversionRank( const IntegralType::Ptr& type ) {
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
105
switch( type->dataType() ) {
106
case IntegralType::TypeBoolean:
109
case IntegralType::TypeChar:
112
case IntegralType::TypeWchar_t:
115
case IntegralType::TypeInt:
116
if( type->modifiers() & AbstractType::ShortModifier )
118
if( type->modifiers() & AbstractType::LongModifier )
120
if( type->modifiers() & AbstractType::LongLongModifier )
123
return 4; //default-integer
124
//All other types have no integer-conversion-rank
129
bool isIntegerType( const IntegralType::Ptr& type ) {
130
return integerConversionRank(type) != 0; //integerConversionRank returns 0 for non-integer types
133
bool isFloatingPointType( const IntegralType::Ptr& type ) {
134
return type->dataType() == IntegralType::TypeFloat || type->dataType() == IntegralType::TypeDouble;
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;
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;
149
int functionCount = functions.size();
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;
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() )
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>();
174
getMemberFunctions( baseClass, topContext, functions, functionName, mustBeConstant);
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 )
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";
195
Identifier id(context->owner()->identifier());
196
id.clearTemplateIdentifiers();
198
QList<Declaration*> declarations = context->findLocalDeclarations(id, SimpleCursor::invalid(), topContext, AbstractType::Ptr(), DUContext::OnlyFunctions);
200
for( QList<Declaration*>::iterator it = declarations.begin(); it != declarations.end(); ++it ) {
201
ClassFunctionDeclaration* functionDeclaration = dynamic_cast<ClassFunctionDeclaration*>( *it );
202
if( functionDeclaration && functionDeclaration->isConstructor() )
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);
215
KDevelop::AbstractType::Ptr matchingClassPointer(const KDevelop::AbstractType::Ptr& matchTo, const KDevelop::AbstractType::Ptr& actual, const KDevelop::TopDUContext* topContext) {
216
Cpp::TypeConversion conversion(topContext);
218
StructureType::Ptr actualStructure = realType(actual, topContext).cast<KDevelop::StructureType>();
220
if(actualStructure) {
221
DUContext* internal = actualStructure->internalContext(topContext);
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();
238
Declaration* getDeclaration( const AbstractType::Ptr& type, TopDUContext* top ) {
241
const IdentifiedType* idType = dynamic_cast<const IdentifiedType*>(type.unsafeData());
243
return idType->declaration(top);
249
AbstractType::Ptr decreasePointerDepth(AbstractType::Ptr type, TopDUContext* top, bool useOperator) {
250
type = realType(type, top);
252
if( PointerType::Ptr pt = type.cast<PointerType>() )
255
return pt->baseType();
256
}else if( ArrayType::Ptr pt = type.cast<ArrayType>() ) {
257
return pt->elementType();
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>();
266
return fun->returnType();
271
return AbstractType::Ptr();
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>();
281
AbstractType::Ptr removeConstants(AbstractType::Ptr type, const TopDUContext* source) {
283
if(TypePtr< EnumeratorType > enumerator = type.cast<EnumeratorType>())
285
Declaration* decl = enumerator->declaration(source);
286
if(decl && decl->context()->owner())
288
return decl->context()->owner()->abstractType();
290
}else if(ConstantIntegralType::Ptr integral = type.cast<ConstantIntegralType>())
291
return AbstractType::Ptr(new IntegralType(*integral));