Example #1
0
///TODO: share code with TypeBuilder
void TypeASTVisitor::visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node)
{
  if(m_stopSearch)
    return;

  Cpp::FindDeclaration find( m_context, m_source, m_flags, m_context->range().end );
  find.openQualifiedIdentifier(false);

  // Don't forget the modifiers!
  uint modifiers = AbstractType::NoModifiers;
  if (node->cv) {
    const ListNode<uint> *it = node->cv->toFront();
    const ListNode<uint> *end = it;
    do {
      int kind = m_session->token_stream->kind(it->element);
      switch (kind) {
        case Token_const:
          modifiers |= AbstractType::ConstModifier;
          break;
        case Token_volatile:
          modifiers |= AbstractType::VolatileModifier;
          break;
        default:
          //qCDebug(CPPDUCHAIN) << "Unknown modifier token" << kind;
          break;
      }
      it = it->next;
    } while (it != end);
  }

  if (node->integrals)
    {
      uint type = IntegralType::TypeNone;

      const ListNode<uint> *it2 = node->integrals->toFront();
      const ListNode<uint> *end = it2;
      do {
        int kind = m_session->token_stream->kind(it2->element);
        switch (kind) {
          case Token_char:
            type = IntegralType::TypeChar;
            break;
          case Token_char16_t:
            type = IntegralType::TypeChar16_t;
            break;
          case Token_char32_t:
            type = IntegralType::TypeChar32_t;
            break;
          case Token_wchar_t:
            type = IntegralType::TypeWchar_t;
            break;
          case Token_bool:
            type = IntegralType::TypeBoolean;
            break;
          case Token_short:
            modifiers |= AbstractType::ShortModifier;
            break;
          case Token_int:
            type = IntegralType::TypeInt;
            break;
          case Token_long:
            if (modifiers & AbstractType::LongModifier)
              modifiers |= AbstractType::LongLongModifier;
            else
              modifiers |= AbstractType::LongModifier;
            break;
          case Token_signed:
            modifiers |= AbstractType::SignedModifier;
            break;
          case Token_unsigned:
            modifiers |= AbstractType::UnsignedModifier;
            break;
          case Token_float:
            type = IntegralType::TypeFloat;
            break;
          case Token_double:
            type = IntegralType::TypeDouble;
            break;
          case Token_void:
            type = IntegralType::TypeVoid;
            break;
        }

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

      if(type == IntegralType::TypeNone)
        type = IntegralType::TypeInt; //Happens, example: "unsigned short"

      KDevelop::IntegralType::Ptr integral ( new KDevelop::IntegralType(type) );
      integral->setModifiers(modifiers);

      m_type = integral.cast<AbstractType>();

      m_typeId = QualifiedIdentifier(integral->toString());
    }
  else if (node->isTypeof || node->isDecltype)
    {
      if (node->expression)
      {
         bool isDecltypeInParen = false;
        if (node->isDecltype && node->expression->kind == AST::Kind_PrimaryExpression) {
          int startPosition = m_session->token_stream->position(node->expression->start_token);
          static IndexedString paren("(");
          isDecltypeInParen = m_session->contentsVector()[startPosition] == paren.index();
        }

        ExpressionParser parser(false, false, isDecltypeInParen);
        node->expression->ducontext = const_cast<DUContext*>(m_context);
        ExpressionEvaluationResult result = parser.evaluateType(node->expression, m_session);
        m_type = result.type.abstractType();
        m_typeId = QualifiedIdentifier(result.toString());

        {
          LOCKDUCHAIN;
          // Transform specific constants like '5' into their type 'int'
          m_type = TypeUtils::removeConstants(m_type, m_source);
        }
        // make reference for decltype in additional parens - but only if it's not already a reference
        // see spec 7.1.6/4
        if (isDecltypeInParen && m_type && !TypeUtils::isReferenceType(m_type))
        {
          // type might already be a ref type
          ReferenceType::Ptr refType = ReferenceType::Ptr(new ReferenceType);
          refType->setBaseType(m_type);
          m_type = refType.cast<AbstractType>();
          ///TODO: anything todo with m_typeId ?
        }

        if(m_visitor)
          m_visitor->parse(node->expression); // Give the visitor a chance to build uses
      }
    }

  {
    LOCKDUCHAIN;
    find.closeQualifiedIdentifier();
    m_declarations = find.lastDeclarations();
    if(!m_declarations.isEmpty() && m_declarations[0])
      m_type = m_declarations[0]->abstractType();
  }

  visit(node->name);
}