typebuilder.cpp 28 KB
Newer Older
1
/* This file is part of KDevelop
2
    Copyright 2006 Hamish Rodda <rodda@kde.org>
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

19 20
#include "typebuilder.h"

21 22 23
#include <language/duchain/identifier.h>
#include <language/duchain/duchain.h>
#include <language/duchain/forwarddeclaration.h>
24
#include <templateparameterdeclaration.h>
25
#include <language/duchain/duchainlock.h>
26 27
#include "cppeditorintegrator.h"
#include "name_compiler.h"
28
#include <language/duchain/ducontext.h>
29
#include "cpptypes.h"
Hamish Rodda's avatar
Hamish Rodda committed
30
#include <language/duchain/types/alltypes.h>
31 32
#include "parsesession.h"
#include "tokens.h"
33
#include "cppduchain.h"
34
#include <language/duchain/declaration.h>
35
#include "declarationbuilder.h"
36
#include "expressionparser.h"
37
#include "parser/rpp/chartools.h"
38
#include "cppdebughelper.h"
39
#include "debugbuilders.h"
40 41
#include <language/duchain/types/typealiastype.h>
#include <util/pushvalue.h>
42 43
#include "typeutils.h"
#include <functional>
44

45
using namespace KDevelop;
46 47
using namespace Cpp;

48 49 50
QString stringFromSessionTokens( ParseSession* session, int start_token, int end_token ) {
    int startPosition = session->token_stream->position(start_token);
    int endPosition = session->token_stream->position(end_token);
51
    return QString::fromUtf8( stringFromContents(session->contentsVector(), startPosition, endPosition - startPosition) );
52 53
}

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
bool isConstexpr(ParseSession* session, const ListNode<uint> *storageSpec)
{
  if (storageSpec) {
    const ListNode<uint> *it = storageSpec->toFront();
    const ListNode<uint> *end = it;
    do {
      int kind = session->token_stream->kind(it->element);
      if (kind == Token_constexpr)
        return true;

      it = it->next;
    } while (it != end);
  }

  return false;
}

David nolden's avatar
David nolden committed
71
TypeBuilder::TypeBuilder(ParseSession* session)
72
  : ContextBuilder(session), m_inTypedef(false), m_lastTypeWasInstance(false), m_lastTypeWasAuto(false)
73 74 75
{
}

76 77
void TypeBuilder::visitClassSpecifier(ClassSpecifierAST *node)
{
78
  if(m_onlyComputeSimplified) {
David nolden's avatar
David nolden committed
79
    ContextBuilder::visitClassSpecifier(node);
80 81
    return;
  }
82
  PushValue<bool> setNotInTypedef(m_inTypedef, false);
83
  
84
  /*int kind = */editor()->parseSession()->token_stream->kind(node->class_key);
85
  CppClassType::Ptr classType = CppClassType::Ptr(new CppClassType());
Hamish Rodda's avatar
Hamish Rodda committed
86

Hamish Rodda's avatar
Hamish Rodda committed
87
  openType(classType);
88

89
  classTypeOpened( currentAbstractType() ); //This callback is needed, because the type of the class-declaration needs to be set early so the class can be referenced from within itself
90

David nolden's avatar
David nolden committed
91
  ContextBuilder::visitClassSpecifier(node);
92 93

  closeType();
94 95
}

96 97
void TypeBuilder::visitBaseSpecifier(BaseSpecifierAST *node)
{
98 99 100 101
  if(m_onlyComputeSimplified) {
    return;
  }
  
102
  if (node->name) {
103
    DUChainReadLocker lock(DUChain::lock());
Hamish Rodda's avatar
Hamish Rodda committed
104 105

    bool openedType = openTypeFromName(node->name, AbstractType::NoModifiers, true);
106 107 108 109

    if( openedType ) {
      closeType();
    } else { //A case for the problem-reporter
110 111 112
      QualifiedIdentifier id;
      identifierForNode(node->name, id);
      kDebug(9007) << "Could not find base declaration for" << id;
113
    }
114 115
  }

David nolden's avatar
David nolden committed
116
  ContextBuilder::visitBaseSpecifier(node);
117 118
}

119
void TypeBuilder::visitEnumSpecifier(EnumSpecifierAST *node)
120
{
121
  if(m_onlyComputeSimplified) {
David nolden's avatar
David nolden committed
122
    ContextBuilder::visitEnumSpecifier(node);
123 124 125
    return;
  }
  
David Nolden's avatar
David Nolden committed
126
  m_currentEnumeratorValue = 0;
Hamish Rodda's avatar
Hamish Rodda committed
127 128

  openType(EnumerationType::Ptr(new EnumerationType()));
129

David nolden's avatar
David nolden committed
130
  ContextBuilder::visitEnumSpecifier(node);
Hamish Rodda's avatar
Hamish Rodda committed
131

Hamish Rodda's avatar
Hamish Rodda committed
132
  closeType();
133 134 135 136
}

void TypeBuilder::visitEnumerator(EnumeratorAST* node)
{
137
  if(m_onlyComputeSimplified) {
David nolden's avatar
David nolden committed
138
    ContextBuilder::visitEnumerator(node);
139 140 141
    return;
  }
  
142
  bool openedType = false;
Hamish Rodda's avatar
Hamish Rodda committed
143

David Nolden's avatar
David Nolden committed
144 145
  if(node->expression) {
    Cpp::ExpressionParser parser;
146

David Nolden's avatar
David Nolden committed
147
    Cpp::ExpressionEvaluationResult res;
Hamish Rodda's avatar
Hamish Rodda committed
148

149
    bool delay = false;
150 151 152
    if(!delay) {
      DUChainReadLocker lock(DUChain::lock());
      node->expression->ducontext = currentContext();
153
      res = parser.evaluateType( node->expression, editor()->parseSession() );
154 155

      //Delay the type-resolution of template-parameters
156 157
      if( res.allDeclarations.size() ) {
        Declaration* decl = res.allDeclarations[0].getDeclaration(currentContext()->topContext());
158
        ///@todo Do a proper check on all involved types, also template parameters, by giving correct parameters to evaluateType
159
        if( dynamic_cast<TemplateParameterDeclaration*>(decl) || isTemplateDependent(decl)) {
160
          delay = true;
161
        }
162
      }
163

164
      if ( !delay && res.isValid() && res.isInstance ) {
165
        AbstractType::Ptr resType = res.type.abstractType();
Hamish Rodda's avatar
Hamish Rodda committed
166
        if( ConstantIntegralType::Ptr iType = resType.cast<ConstantIntegralType>() ) {
167
          m_currentEnumeratorValue = (int)iType->value<qint64>();
168 169 170 171
          EnumeratorType::Ptr enumerator(new EnumeratorType());
          enumerator->setValue<qint64>(m_currentEnumeratorValue);
          openedType = true;
          openType(enumerator);
172 173
        } else if( DelayedType::Ptr dType = resType.cast<DelayedType>() ) {
          openType(dType.cast<AbstractType>()); ///@todo Make this an enumerator-type that holds the same information
174 175
          openedType = true;
        }
176
      }
177 178 179 180
    }
    if( delay || (!openedType && templateDeclarationDepth() != 0) ) {
      QString str;
      ///Only record the strings, because these expressions may depend on template-parameters and thus must be evaluated later
181
      str += stringFromSessionTokens( editor()->parseSession(), node->expression->start_token, node->expression->end_token );
182

183
      openDelayedType(IndexedTypeIdentifier(str.trimmed(), true), node, DelayedType::Delayed);
184
      openedType = true;
David Nolden's avatar
David Nolden committed
185 186
    }
  }
Hamish Rodda's avatar
Hamish Rodda committed
187 188 189

//   if (EnumerationType::Ptr parent = currentType<EnumerationType>()) {
//     EnumeratorType::Ptr enumerator(new EnumeratorType());
David Nolden's avatar
David Nolden committed
190 191 192 193
//     openType(enumerator, node);
//     ok = true;
//   }

194 195
  if(!openedType) {
    openedType = true;
Hamish Rodda's avatar
Hamish Rodda committed
196
    EnumeratorType::Ptr enumerator(new EnumeratorType());
Hamish Rodda's avatar
Hamish Rodda committed
197
    openType(enumerator);
198 199
    enumerator->setValue<qint64>(m_currentEnumeratorValue);
  }
Hamish Rodda's avatar
Hamish Rodda committed
200

David nolden's avatar
David nolden committed
201
  ContextBuilder::visitEnumerator(node);
202

David Nolden's avatar
David Nolden committed
203 204 205
  closeType();

  ++m_currentEnumeratorValue;
206 207
}

208 209 210 211 212
bool TypeBuilder::lastTypeWasInstance() const
{
  return m_lastTypeWasInstance;
}

213 214 215 216 217
void TypeBuilder::setLastTypeWasInstance(bool wasInstance)
{
  m_lastTypeWasInstance = wasInstance;
}

218 219 220 221 222
bool TypeBuilder::lastTypeWasAuto() const
{
  return m_lastTypeWasAuto;
}

223 224 225 226 227
void TypeBuilder::setLastTypeWasAuto(bool wasAuto)
{
  m_lastTypeWasAuto = wasAuto;
}

228
void TypeBuilder::visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node)
229
{
230 231 232 233
  if(m_onlyComputeSimplified) {
    return;
  }
  
234 235
  PushValue<bool> setInTypedef(m_inTypedef, false);

236
  m_lastTypeWasInstance = false;
237 238
  AbstractType::Ptr type;

239
  int kind = editor()->parseSession()->token_stream->kind(node->type);
240 241 242

  if( kind == Token_typename ) {
    //For typename, just find the type and return
243
    bool openedType = openTypeFromName(node->name, parseConstVolatile(editor()->parseSession(), node->cv));
Hamish Rodda's avatar
Hamish Rodda committed
244

David nolden's avatar
David nolden committed
245
    ContextBuilder::visitElaboratedTypeSpecifier(node);
246 247 248

    if(openedType)
      closeType();
249
    
250 251
    return;
  }
Hamish Rodda's avatar
Hamish Rodda committed
252

Hamish Rodda's avatar
Hamish Rodda committed
253
  if (node->name) {
254
/*    {
255
      DUChainReadLocker lock(DUChain::lock());
Hamish Rodda's avatar
Hamish Rodda committed
256

257
      ///If possible, find another fitting declaration/forward-declaration and re-use it's type
Hamish Rodda's avatar
Hamish Rodda committed
258

259
      SimpleCursor pos = editor()->findPosition(node->start_token, KDevelop::EditorIntegrator::FrontEdge);
260

261
      QList<Declaration*> declarations = Cpp::findDeclarationsSameLevel(currentContext(), identifierForNode(node->name), pos);
262
      if( !declarations.isEmpty() && declarations.first()->abstractType()) {
Hamish Rodda's avatar
Hamish Rodda committed
263
        openType(declarations.first()->abstractType());
264 265 266
        closeType();
        return;
      }
267
    }*/
Hamish Rodda's avatar
Hamish Rodda committed
268

269 270 271 272
    switch (kind) {
      case Token_class:
      case Token_struct:
      case Token_union:
273
        type = AbstractType::Ptr(new CppClassType());
274 275
        break;
      case Token_enum:
Hamish Rodda's avatar
Hamish Rodda committed
276
        type = AbstractType::Ptr(new EnumerationType());
277 278 279 280 281 282 283
        break;
      case Token_typename:
        // TODO what goes here...?
        //type = def->abstractType();
        break;
    }

Hamish Rodda's avatar
Hamish Rodda committed
284
    openType(type);
Hamish Rodda's avatar
Hamish Rodda committed
285 286
  }

Hamish Rodda's avatar
Hamish Rodda committed
287 288
  // TODO.. figure out what to do with this now... parseConstVolatile(node->cv);

David nolden's avatar
David nolden committed
289
  ContextBuilder::visitElaboratedTypeSpecifier(node);
Hamish Rodda's avatar
Hamish Rodda committed
290

291
  if (type)
Hamish Rodda's avatar
Hamish Rodda committed
292
    closeType();
293 294
}

295
///TODO: share code with TypeASTVisitor
296
void TypeBuilder::visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node)
297
{
298 299 300 301
  if(m_onlyComputeSimplified) {
    return;
  }
  
302
  bool openedType = false;
303
  m_lastTypeWasInstance = false;
Milian Wolff's avatar
Milian Wolff committed
304
  m_lastTypeWasAuto = false;
305

306
  if ((node->isTypeof || node->isDecltype) && node->expression) {
307
    bool isDecltypeInParen = false;
308 309 310 311 312
        if (node->isDecltype && node->expression->kind == AST::Kind_PrimaryExpression) {
          int startPosition = editor()->parseSession()->token_stream->position(node->expression->start_token);
          static IndexedString paren("(");
          isDecltypeInParen = editor()->parseSession()->contentsVector()[startPosition] == paren.index();
        }
313

314
    node->expression->ducontext = currentContext();
315
    ExpressionParser parser(false, false, isDecltypeInParen, m_mapAst);
316
    ExpressionEvaluationResult result = parser.evaluateType(node->expression, editor()->parseSession(), topContext());
317
    AbstractType::Ptr type = result.type.abstractType();
318 319 320
    // make reference for decltype in additional parens - but only if it's not already a reference
    // see spec 7.1.6/4
    if (isDecltypeInParen && type && !TypeUtils::isReferenceType(type))
321
    {
322 323 324 325
      // type might already be a ref type
      ReferenceType::Ptr refType = ReferenceType::Ptr(new ReferenceType);
      refType->setBaseType(type);
      type = refType.cast<AbstractType>();
326 327
    }

328 329 330 331 332 333
    if(!type)
    {
      DUChainReadLocker lock(DUChain::lock());
      DelayedType::Ptr delayed( new DelayedType() );
      delayed->setIdentifier( IndexedTypeIdentifier( stringFromSessionTokens(editor()->parseSession(),
                                                     node->expression->start_token,
334
                                                     node->expression->end_token).trimmed(), true ) );
335 336 337
      delayed->setKind( templateDeclarationDepth() ? DelayedType::Delayed : DelayedType::Unresolved );
      type = delayed.cast<AbstractType>();
    }
338

339
    openType(type);
340 341
    openedType = true;
  } else if (node->integrals) {
Hamish Rodda's avatar
Hamish Rodda committed
342 343
    uint type = IntegralType::TypeNone;
    uint modifiers = AbstractType::NoModifiers;
Hamish Rodda's avatar
Hamish Rodda committed
344

345 346
    const ListNode<uint> *it = node->integrals->toFront();
    const ListNode<uint> *end = it;
Hamish Rodda's avatar
Hamish Rodda committed
347
    do {
348
      int kind = editor()->parseSession()->token_stream->kind(it->element);
Hamish Rodda's avatar
Hamish Rodda committed
349 350
      switch (kind) {
        case Token_char:
Hamish Rodda's avatar
Hamish Rodda committed
351
          type = IntegralType::TypeChar;
352
          break;
353
        case Token_char16_t:
Milian Wolff's avatar
Milian Wolff committed
354
          type = IntegralType::TypeChar16_t;
355 356
          break;
        case Token_char32_t:
Milian Wolff's avatar
Milian Wolff committed
357
          type = IntegralType::TypeChar32_t;
358
          break;
Hamish Rodda's avatar
Hamish Rodda committed
359
        case Token_wchar_t:
Hamish Rodda's avatar
Hamish Rodda committed
360
          type = IntegralType::TypeWchar_t;
361
          break;
Hamish Rodda's avatar
Hamish Rodda committed
362
        case Token_bool:
Hamish Rodda's avatar
Hamish Rodda committed
363
          type = IntegralType::TypeBoolean;
364
          break;
Hamish Rodda's avatar
Hamish Rodda committed
365
        case Token_short:
Hamish Rodda's avatar
Hamish Rodda committed
366
          modifiers |= AbstractType::ShortModifier;
367
          break;
Hamish Rodda's avatar
Hamish Rodda committed
368
        case Token_int:
Hamish Rodda's avatar
Hamish Rodda committed
369
          type = IntegralType::TypeInt;
370
          break;
Hamish Rodda's avatar
Hamish Rodda committed
371
        case Token_long:
Hamish Rodda's avatar
Hamish Rodda committed
372 373
          if (modifiers & AbstractType::LongModifier)
            modifiers |= AbstractType::LongLongModifier;
Hamish Rodda's avatar
Hamish Rodda committed
374
          else
Hamish Rodda's avatar
Hamish Rodda committed
375
            modifiers |= AbstractType::LongModifier;
376
          break;
Hamish Rodda's avatar
Hamish Rodda committed
377
        case Token_signed:
Hamish Rodda's avatar
Hamish Rodda committed
378
          modifiers |= AbstractType::SignedModifier;
379
          break;
Hamish Rodda's avatar
Hamish Rodda committed
380
        case Token_unsigned:
Hamish Rodda's avatar
Hamish Rodda committed
381
          modifiers |= AbstractType::UnsignedModifier;
382
          break;
Hamish Rodda's avatar
Hamish Rodda committed
383
        case Token_float:
Hamish Rodda's avatar
Hamish Rodda committed
384
          type = IntegralType::TypeFloat;
385
          break;
Hamish Rodda's avatar
Hamish Rodda committed
386
        case Token_double:
Hamish Rodda's avatar
Hamish Rodda committed
387
          type = IntegralType::TypeDouble;
388
          break;
Hamish Rodda's avatar
Hamish Rodda committed
389
        case Token_void:
Hamish Rodda's avatar
Hamish Rodda committed
390
          type = IntegralType::TypeVoid;
Hamish Rodda's avatar
Hamish Rodda committed
391
          break;
Milian Wolff's avatar
Milian Wolff committed
392 393 394
        case Token_auto:
          m_lastTypeWasAuto = true;
          break;
Hamish Rodda's avatar
Hamish Rodda committed
395 396 397 398
      }

      it = it->next;
    } while (it != end);
399

Hamish Rodda's avatar
Hamish Rodda committed
400 401 402
    if(type == IntegralType::TypeNone)
      type = IntegralType::TypeInt; //Happens, example: "unsigned short"

403
    modifiers |= parseConstVolatile(editor()->parseSession(), node->cv);
Hamish Rodda's avatar
Hamish Rodda committed
404 405 406 407 408

    IntegralType::Ptr integral(new IntegralType(type));
    integral->setModifiers(modifiers);
    openedType = true;
    openType(integral);
409
    
410
  } else if (node->name) {
411
    openedType = openTypeFromName(node->name, parseConstVolatile(editor()->parseSession(), node->cv));
Hamish Rodda's avatar
Hamish Rodda committed
412
  }
413

David nolden's avatar
David nolden committed
414
  ContextBuilder::visitSimpleTypeSpecifier(node);
415

416
  if (openedType)
Hamish Rodda's avatar
Hamish Rodda committed
417
    closeType();
418 419
}

420 421 422
void TypeBuilder::createIntegralTypeForExpression(ExpressionAST* expression)
{
  if (!expression) {
423 424
    return;
  }
425

426
  IntegralType::Ptr integral = lastType().cast<IntegralType>();
427 428 429 430 431 432 433
  if (!integral && m_lastTypeWasAuto) {
    ReferenceType::Ptr ref = lastType().cast<ReferenceType>();
    if (ref) {
      integral = ref->baseType().cast<IntegralType>();
    }
  }

434 435 436 437 438 439
  if (!integral) {
    return;
  }

  if (!(integral->modifiers() & AbstractType::ConstModifier) && !m_lastTypeWasAuto) {
    return;
440 441
  }

442 443 444
  bool openedType = false;
  bool delay = false;
  ///@todo This is nearly a copy of visitEnumerator and parts of visitSimpleTypeSpecifier, merge it
445
  {
446 447
    //Parse the expression, and create a CppConstantIntegralType, since we know the value
    Cpp::ExpressionParser parser;
448 449 450 451 452 453 454 455 456 457 458
    DUChainReadLocker lock(DUChain::lock());
    expression->ducontext = currentContext();
    Cpp::ExpressionEvaluationResult res = parser.evaluateType( expression, editor()->parseSession() );

    //Delay the type-resolution of template-parameters
    if( res.allDeclarations.size() ) {
      Declaration* decl = res.allDeclarations[0].getDeclaration(currentContext()->topContext());
      ///@todo Do a check on all involved types, also template parameters, by giving the parameter to evaluateType
      if( dynamic_cast<TemplateParameterDeclaration*>(decl) || isTemplateDependent(decl))
        delay = true;
    }
459

460
    if ( !delay && res.isValid() && res.isInstance ) {
461
      const AbstractType::Ptr& type = prepareTypeForExpression(res.type.abstractType(), integral->modifiers());
462 463 464 465
      if (type) {
        openType( type );
        openedType = true;
      }
466 467
    }
  }
468 469 470 471 472 473 474 475 476 477 478 479
  if( delay || !openedType ) {
    ///Only record the strings, because these expressions may depend on template-parameters and thus must be evaluated later
    QString str = stringFromSessionTokens( editor()->parseSession(), expression->start_token, expression->end_token ).trimmed();

    QualifiedIdentifier id( str, true );

    openDelayedType(IndexedTypeIdentifier(id), expression, DelayedType::Delayed);
    openedType = true;
  }

  if(openedType)
    closeType();
480 481
}

482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
AbstractType::Ptr TypeBuilder::prepareTypeForExpression(AbstractType::Ptr type, quint64 modifiers)
{
  if (!m_lastTypeWasAuto) {
    return type;
  }

  // remove references or aliases
  type = TypeUtils::realType( type, topContext() );
  // Turn "5" into "int"
  type = TypeUtils::removeConstants( type, topContext() );

  if (!type) {
    // NOTE: the type might not be valid anymore, see https://bugs.kde.org/show_bug.cgi?id=318972
    return type;
  }

  // ensure proper const modifier is set
  type->setModifiers( modifiers );

  if (ReferenceType::Ptr ref = lastType().cast<ReferenceType>()) {
    ref->setBaseType( type );
    type = ref.cast<AbstractType>();
  }

  return type;
}

509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
void TypeBuilder::createTypeForInitializer(InitializerAST *node) {
  if(m_onlyComputeSimplified) {
    return;
  }

  ExpressionAST* expression = 0;
  if (node->initializer_clause && node->initializer_clause->expression) {
    // auto foo = ...;
    expression = node->initializer_clause->expression;
  } else {
    // auto foo(...);
    expression = node->expression;
  }

  createIntegralTypeForExpression(expression);
}

void TypeBuilder::createTypeForCondition(ConditionAST* node)
{
  if (m_onlyComputeSimplified) {
    return;
  }

  createIntegralTypeForExpression(node->expression);
533 534
}

Hamish Rodda's avatar
Hamish Rodda committed
535
bool TypeBuilder::openTypeFromName(NameAST* name, uint modifiers, bool needClass) {
536 537
  QualifiedIdentifier id;
  identifierForNode(name, id);
538 539

  bool openedType = false;
Hamish Rodda's avatar
Hamish Rodda committed
540

541 542 543
  bool delay = false;

  if(!delay) {
544
    CursorInRevision pos = editor()->findPosition(name->start_token, CppEditorIntegrator::FrontEdge);
545
    DUChainReadLocker lock(DUChain::lock());
546 547
    ifDebug( kDebug() << "searching" << id.toString(); )
    ifDebugCurrentFile( kDebug() << "searching" << id.toString(); )
Hamish Rodda's avatar
Hamish Rodda committed
548

549
    QList<Declaration*> dec = searchContext()->findDeclarations(id, pos, AbstractType::Ptr(), 0, DUContext::NoUndefinedTemplateParams);
550 551
    ifDebug( kDebug() << "found" << dec.count() <<  (dec.count() ? dec[0]->toString() : QString()); )
    ifDebugCurrentFile( kDebug() << "found" << dec.count() <<  (dec.count() ? dec[0]->toString() : QString()); )
552 553
    if ( dec.isEmpty() ) {
      ifDebug( kDebug(9007) << "opening delayed:"<< id.toString() ; )
554
      delay = true;
555
    }
556 557

    if(!delay) {
558 559
      
      ifDebug( if( dec.count() > 1 ) kDebug(9007) << id.toString() << "was found" << dec.count() << "times"; )
560 561 562 563 564 565

      // see section 3.4.1-7 in the cpp spec on unqualified name lookup
      // and https://bugs.kde.org/show_bug.cgi?id=273658 for a bug report
      AbstractType::Ptr type;
      int matchQuality = 0; // we just pick the size of the qualified identifier as match quality
      bool wasInstance = false;
566
      foreach( Declaration* decl, dec ) {
567 568
        AbstractType::Ptr unAliased = TypeUtils::unAliasedType(decl->abstractType());
        if( needClass && !unAliased.cast<CppClassType>() )
569
          continue;
Hamish Rodda's avatar
Hamish Rodda committed
570

571 572
        if(unAliased.cast<DelayedType>())
          continue;
Hamish Rodda's avatar
Hamish Rodda committed
573

574
        if (decl->abstractType()) {
575
          //kDebug(9007) << "found for" << id.toString() << ":" << decl->toString() << "type:" << decl->abstractType()->toString() << "context:" << decl->context();
Hamish Rodda's avatar
Hamish Rodda committed
576

577 578 579 580 581 582
          const int quality = decl->qualifiedIdentifier().count();
          if (matchQuality < quality) {
            // better quality, prefer over old match
            type = decl->abstractType();
            matchQuality = quality;
            wasInstance = decl->kind() == KDevelop::Declaration::Instance;
583
          }
584 585
        }
      }
586

587 588 589 590
      if (type) {
        m_lastTypeWasInstance = wasInstance;
        applyModifiers(type, modifiers);
        openType(type);
Hamish Rodda's avatar
Hamish Rodda committed
591

592
        openedType = true;
593
      }
594
    }
Hamish Rodda's avatar
Hamish Rodda committed
595

596 597
    if(!openedType)
      delay = true;
598
  }
599 600
    ///@todo What about position?

601
  if(delay) {
602 603
    //Either delay the resolution for template-dependent types, or create an unresolved type that stores the name.
   openedType = true;
604
   IndexedTypeIdentifier typeId(id);
Hamish Rodda's avatar
Hamish Rodda committed
605
   typeId.setIsConstant(modifiers & AbstractType::ConstModifier);
606
   typeId.setIsVolatile(modifiers & AbstractType::VolatileModifier);
607
   
608
   openDelayedType(typeId, name, templateDeclarationDepth() ? DelayedType::Delayed : DelayedType::Unresolved );
Hamish Rodda's avatar
Hamish Rodda committed
609

610
   ifDebug( DUChainReadLocker lock(DUChain::lock()); if(templateDeclarationDepth() == 0) kDebug(9007) << "no declaration found for" << id.toString() << "in context \"" << searchContext()->scopeIdentifier(true).toString() << "\"" << "" << searchContext(); )
611
   ifDebugCurrentFile( DUChainReadLocker lock(DUChain::lock()); if(templateDeclarationDepth() == 0) kDebug(9007) << "no declaration found for" << id.toString() << "in context \"" << searchContext()->scopeIdentifier(true).toString() << "\"" << "" << searchContext(); )
612
  }
Hamish Rodda's avatar
Hamish Rodda committed
613

614
  ifDebugCurrentFile( DUChainReadLocker lock(DUChain::lock()); kDebug() << "opened type" << (currentAbstractType() ? currentAbstractType()->toString() : QString("(no type)")); )
Hamish Rodda's avatar
Hamish Rodda committed
615

616 617 618
  return openedType;
}

619 620 621 622
void TypeBuilder::applyModifiers(KDevelop::AbstractType::Ptr type, uint modifiers) {
  type->setModifiers(modifiers | type->modifiers());
}

623

Hamish Rodda's avatar
Hamish Rodda committed
624
DUContext* TypeBuilder::searchContext() const {
625
  DUChainReadLocker lock(DUChain::lock());
626 627 628 629 630 631 632
  if( !m_importedParentContexts.isEmpty() ) {
    if( DUContext* ctx = m_importedParentContexts.last().context(topContext()) )
      if(ctx->type() == DUContext::Template)
        return m_importedParentContexts.last().context(topContext());
  } 
    
  return currentContext();
633 634
}

635 636
void TypeBuilder::visitTypedef(TypedefAST* node)
{
637
  PushValue<bool> setInTypedef(m_inTypedef, true);
638
  
639
//   openType(KDevelop::TypeAliasType::Ptr(new KDevelop::TypeAliasType()));
640

David nolden's avatar
David nolden committed
641
  ContextBuilder::visitTypedef(node);
642

643
//   closeType();
644 645
}

646 647
AbstractType::Ptr TypeBuilder::typeForCurrentDeclaration()
{
648 649 650
  if(m_onlyComputeSimplified)
    return AbstractType::Ptr();
  
651 652 653 654 655 656 657 658 659
  if(m_inTypedef) {
    KDevelop::TypeAliasType::Ptr alias(new KDevelop::TypeAliasType());
    alias->setType(lastType());
    return alias.cast<AbstractType>();
  }else{
    return lastType();
  }
}

Hamish Rodda's avatar
Hamish Rodda committed
660
void TypeBuilder::visitFunctionDeclaration(FunctionDefinitionAST* node)
661
{
Hamish Rodda's avatar
Hamish Rodda committed
662
  clearLastType();
Hamish Rodda's avatar
Hamish Rodda committed
663

664
  if(!node->declarator && node->type_specifier)
665
    m_typeSpecifierWithoutInitDeclarators = node->type_specifier->start_token;
Hamish Rodda's avatar
Hamish Rodda committed
666

David nolden's avatar
David nolden committed
667
  ContextBuilder::visitFunctionDeclaration(node);
668 669
}

Hamish Rodda's avatar
Hamish Rodda committed
670 671
void TypeBuilder::visitSimpleDeclaration(SimpleDeclarationAST* node)
{
Hamish Rodda's avatar
Hamish Rodda committed
672
  clearLastType();
673 674
  
  preVisitSimpleDeclaration(node);
Hamish Rodda's avatar
Hamish Rodda committed
675

676 677 678
  // Reimplement default visitor
  visit(node->type_specifier);

Hamish Rodda's avatar
Hamish Rodda committed
679
  AbstractType::Ptr baseType = lastType();
680

681 682 683 684
  if (baseType && isConstexpr(editor()->parseSession(), node->storage_specifiers)) {
    baseType->setModifiers(baseType->modifiers() | AbstractType::ConstModifier);
  }

685 686 687 688 689
  if (node->init_declarators) {
    const ListNode<InitDeclaratorAST*> *it = node->init_declarators->toFront(), *end = it;
    do {
      visit(it->element);
      // Reset last type to be the base type
Hamish Rodda's avatar
Hamish Rodda committed
690
      setLastType(baseType);
691 692 693 694 695 696 697 698 699

      it = it->next;
    } while (it != end);
  }

  visit(node->win_decl_specifiers);

  visitPostSimpleDeclaration(node);
}
Hamish Rodda's avatar
Hamish Rodda committed
700

701 702
void TypeBuilder::visitPtrOperator(PtrOperatorAST* node)
{
703 704 705 706
  if(m_onlyComputeSimplified) {
    return;
  }
  
707
  bool typeOpened = false;
708
  if (node->op) {
709
    const QString op = editor()->tokenToString(node->op);
710
    if (!op.isEmpty()) {
711
      if (op[0] == '&') {
Hamish Rodda's avatar
Hamish Rodda committed
712
        ReferenceType::Ptr pointer(new ReferenceType());
713
        pointer->setModifiers(parseConstVolatile(editor()->parseSession(), node->cv));
714
        pointer->setBaseType(lastType());
715 716 717
        if (op.size() == 2 && op[1] == '&')
          pointer->setIsRValue(true);

Hamish Rodda's avatar
Hamish Rodda committed
718
        openType(pointer);
719 720 721
        typeOpened = true;

      } else if (op[0] == '*') {
Hamish Rodda's avatar
Hamish Rodda committed
722
        PointerType::Ptr pointer(new PointerType());
723
        pointer->setModifiers(parseConstVolatile(editor()->parseSession(), node->cv));
724
        pointer->setBaseType(lastType());
Hamish Rodda's avatar
Hamish Rodda committed
725
        openType(pointer);
726 727
        typeOpened = true;
      }
728
    }
729
  }
730

David nolden's avatar
David nolden committed
731
  ContextBuilder::visitPtrOperator(node);
732

733 734
  if (typeOpened)
    closeType();
735
}
736

737 738 739 740 741 742 743 744 745 746
void TypeBuilder::visitPtrToMember(PtrToMemberAST *node)
{
  PtrToMemberType::Ptr pointer(new PtrToMemberType);
  pointer->setBaseType(lastType());
  ContextBuilder::visitPtrToMember(node);
  pointer->setClassType(lastType());
  openType(pointer);
  closeType();
}

Hamish Rodda's avatar
Hamish Rodda committed
747
FunctionType* TypeBuilder::openFunction(DeclaratorAST *node)
748
{
Hamish Rodda's avatar
Hamish Rodda committed
749
  FunctionType* functionType = new FunctionType();
750 751

  if (node->fun_cv)
752
    functionType->setModifiers(parseConstVolatile(editor()->parseSession(), node->fun_cv));
753 754 755 756 757 758 759

  if (lastType())
    functionType->setReturnType(lastType());

  return functionType;
}

760 761 762 763 764 765 766 767 768
void TypeBuilder::visitTrailingReturnType(TrailingReturnTypeAST* node)
{
  DefaultVisitor::visitTrailingReturnType(node);

  FunctionType::Ptr funcType = currentType<FunctionType>();
  if (lastType() && funcType)
    funcType->setReturnType(lastType());
}

769
void TypeBuilder::createTypeForDeclarator(DeclaratorAST *node) {
770
  // Custom code - create array types
771 772 773 774
  if (node->array_dimensions) {
    const ListNode<ExpressionAST*> *it = node->array_dimensions->toFront(), *end = it;

    do {
775
      visitArrayExpression(it->element);
776 777 778 779
      it = it->next;
    } while (it != end);
  }

780
  if (node->parameter_declaration_clause) {
781
    // New function type
Hamish Rodda's avatar
Hamish Rodda committed
782
    openType(FunctionType::Ptr(openFunction(node)));
783
  }
784
}
785

786
void TypeBuilder::closeTypeForDeclarator(DeclaratorAST *node) {
787
  if (node->parameter_declaration_clause) {
788
    closeType();
789
  }
790 791 792 793
}

void TypeBuilder::visitArrayExpression(ExpressionAST* expression)
{
794 795 796 797
  if(m_onlyComputeSimplified) {
    return;
  }
  
798 799
  bool typeOpened = false;

800 801 802
  Cpp::ExpressionParser parser;

  Cpp::ExpressionEvaluationResult res;
Hamish Rodda's avatar
Hamish Rodda committed
803

804 805
  {
    DUChainReadLocker lock(DUChain::lock());
806 807
    if(expression) {
      expression->ducontext = currentContext();
808
      res = parser.evaluateType( expression, editor()->parseSession() );
809
    }
Hamish Rodda's avatar
Hamish Rodda committed
810

811
    ArrayType::Ptr array(new ArrayType());
812 813
    array->setElementType(lastType());

814
    ConstantIntegralType::Ptr integral = res.type.type<ConstantIntegralType>();
815 816
    if( res.isValid() && integral ) {
      array->setDimension(integral->value<qint64>());
817 818
    } else {
      array->setDimension(0);
819
    }
Hamish Rodda's avatar
Hamish Rodda committed
820

Hamish Rodda's avatar
Hamish Rodda committed
821
    openType(array);
822
    typeOpened = true;
823 824 825 826 827 828
  }

  if (typeOpened)
    closeType();
}

829
uint TypeBuilder::parseConstVolatile(ParseSession* session, const ListNode<uint> *cv)
Hamish Rodda's avatar
Hamish Rodda committed
830
{
Hamish Rodda's avatar
Hamish Rodda committed
831
  uint ret = AbstractType::NoModifiers;