Symbols.cpp 34.4 KB
Newer Older
con's avatar
con committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

21 22 23
#include "Control.h"
#include "CoreTypes.h"
#include "Literals.h"
24
#include "Matcher.h"
25
#include "Names.h"
con's avatar
con committed
26
#include "Scope.h"
27 28
#include "Symbols.h"
#include "SymbolVisitor.h"
29
#include "Templates.h"
30 31 32
#include "TypeVisitor.h"

#include <cstring>
con's avatar
con committed
33

Roberto Raggi's avatar
Roberto Raggi committed
34
using namespace CPlusPlus;
con's avatar
con committed
35 36

UsingNamespaceDirective::UsingNamespaceDirective(TranslationUnit *translationUnit,
Roberto Raggi's avatar
Roberto Raggi committed
37
                                                 unsigned sourceLocation, const Name *name)
con's avatar
con committed
38 39 40
    : Symbol(translationUnit, sourceLocation, name)
{ }

41 42 43 44
UsingNamespaceDirective::UsingNamespaceDirective(Clone *clone, Subst *subst, UsingNamespaceDirective *original)
    : Symbol(clone, subst, original)
{ }

con's avatar
con committed
45 46 47 48 49 50 51 52 53
UsingNamespaceDirective::~UsingNamespaceDirective()
{ }

FullySpecifiedType UsingNamespaceDirective::type() const
{ return FullySpecifiedType(); }

void UsingNamespaceDirective::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

54 55 56 57 58
NamespaceAlias::NamespaceAlias(TranslationUnit *translationUnit,
                               unsigned sourceLocation, const Name *name)
    : Symbol(translationUnit, sourceLocation, name), _namespaceName(0)
{ }

59 60 61 62 63
NamespaceAlias::NamespaceAlias(Clone *clone, Subst *subst, NamespaceAlias *original)
    : Symbol(clone, subst, original)
    , _namespaceName(clone->name(original->_namespaceName, subst))
{ }

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
NamespaceAlias::~NamespaceAlias()
{ }

const Name *NamespaceAlias::namespaceName() const
{ return _namespaceName; }

void NamespaceAlias::setNamespaceName(const Name *namespaceName)
{ _namespaceName = namespaceName; }

FullySpecifiedType NamespaceAlias::type() const
{ return FullySpecifiedType(); }

void NamespaceAlias::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }


con's avatar
con committed
80
UsingDeclaration::UsingDeclaration(TranslationUnit *translationUnit,
Roberto Raggi's avatar
Roberto Raggi committed
81
                                   unsigned sourceLocation, const Name *name)
con's avatar
con committed
82 83 84
    : Symbol(translationUnit, sourceLocation, name)
{ }

85 86 87 88
UsingDeclaration::UsingDeclaration(Clone *clone, Subst *subst, UsingDeclaration *original)
    : Symbol(clone, subst, original)
{ }

con's avatar
con committed
89 90 91 92 93 94 95 96 97
UsingDeclaration::~UsingDeclaration()
{ }

FullySpecifiedType UsingDeclaration::type() const
{ return FullySpecifiedType(); }

void UsingDeclaration::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

Roberto Raggi's avatar
Roberto Raggi committed
98
Declaration::Declaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
Roberto Raggi's avatar
Roberto Raggi committed
99
    : Symbol(translationUnit, sourceLocation, name)
100
    , _initializer(0)
con's avatar
con committed
101 102
{ }

103 104 105
Declaration::Declaration(Clone *clone, Subst *subst, Declaration *original)
    : Symbol(clone, subst, original)
    , _type(clone->type(original->_type, subst))
106
    , _initializer(clone->stringLiteral(original->_initializer))
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
{
    const char* nameId = nullptr;
    if (const Identifier* identifier = name()->identifier())
        nameId = identifier->chars();
    else
        return;

    Class *enClass = original->enclosingClass();
    const char* enClassNameId = nullptr;
    if (enClass && enClass->name() && enClass->name()->identifier()) {
        enClassNameId = enClass->name()->identifier()->chars();
    } else {
        return;
    }

    if (!enClassNameId)
        return;

    Template *templSpec  = enClass->enclosingTemplate();
    const char* enNamespaceNameId = nullptr;
    if (templSpec) {
        if (Namespace* ns = templSpec->enclosingNamespace()) {
            if (ns->isInline())
                ns = ns->enclosingNamespace();

            if (ns->name() && ns->name()->identifier())
                enNamespaceNameId =ns->name()->identifier()->chars();
        }
    }

    if (!enNamespaceNameId || templSpec->templateParameterCount() < 1)
        return;

    const Name *firstTemplParamName = nullptr;
    if (const TypenameArgument *templParam =
            templSpec->templateParameterAt(0)->asTypenameArgument()) {
        firstTemplParamName = templParam->name();
    }

    if (!firstTemplParamName)
        return;

    FullySpecifiedType newType;
    if (std::strcmp(enNamespaceNameId, "std") == 0 ||
        std::strcmp(enNamespaceNameId, "__cxx11") == 0) {
        if (std::strcmp(enClassNameId, "unique_ptr") == 0) {
            if (std::strcmp(nameId, "pointer") == 0) {
                newType = clone->type(subst->apply(firstTemplParamName), 0);
                newType = FullySpecifiedType(clone->control()->pointerType(newType));
            }
        } else if (std::strcmp(enClassNameId, "list") == 0 ||
                   std::strcmp(enClassNameId, "forward_list") == 0 ||
                   std::strcmp(enClassNameId, "vector") == 0 ||
                   std::strcmp(enClassNameId, "queue") == 0 ||
                   std::strcmp(enClassNameId, "deque") == 0 ||
                   std::strcmp(enClassNameId, "set") == 0 ||
                   std::strcmp(enClassNameId, "unordered_set") == 0 ||
                   std::strcmp(enClassNameId, "multiset") == 0 ||
                   std::strcmp(enClassNameId, "array") == 0) {
            if (std::strcmp(nameId, "reference") == 0 ||
                std::strcmp(nameId, "const_reference") == 0) {
                newType = clone->type(subst->apply(firstTemplParamName), 0);
            } else if (std::strcmp(nameId, "iterator") == 0 ||
                       std::strcmp(nameId, "reverse_iterator") == 0 ||
                       std::strcmp(nameId, "const_reverse_iterator") == 0 ||
                       std::strcmp(nameId, "const_iterator") == 0) {
                newType = clone->type(subst->apply(firstTemplParamName), 0);
                newType = FullySpecifiedType(clone->control()->pointerType(newType));
            }
        } else if (std::strcmp(enClassNameId, "_Hash") == 0 ||
                   std::strcmp(enClassNameId, "_Tree") == 0 ) {
            if (std::strcmp(nameId, "iterator") == 0 ||
                std::strcmp(nameId, "reverse_iterator") == 0 ||
                std::strcmp(nameId, "const_reverse_iterator") == 0 ||
                std::strcmp(nameId, "const_iterator") == 0) {
                FullySpecifiedType clonedType = clone->type(subst->apply(firstTemplParamName), 0);
                if (NamedType *namedType = clonedType.type()->asNamedType()) {
                    if (const TemplateNameId * templateNameId =
                            namedType->name()->asTemplateNameId()) {
                        if (templateNameId->templateArgumentCount()) {
                            newType = clone->type(templateNameId->templateArgumentAt(0), 0);
                            newType = FullySpecifiedType(clone->control()->pointerType(newType));
                        }
                    }
                }
            }
        }
    }

    if (newType.isValid())
        _type = newType;
}
199

con's avatar
con committed
200
Declaration::~Declaration()
Roberto Raggi's avatar
Roberto Raggi committed
201
{ }
con's avatar
con committed
202

203
void Declaration::setType(const FullySpecifiedType &type)
con's avatar
con committed
204 205
{ _type = type; }

206 207 208 209 210
void Declaration::setInitializer(const StringLiteral *initializer)
{
    _initializer = initializer;
}

con's avatar
con committed
211 212 213
FullySpecifiedType Declaration::type() const
{ return _type; }

214 215 216 217 218
const StringLiteral *Declaration::getInitializer() const
{
    return _initializer;
}

con's avatar
con committed
219 220 221
void Declaration::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

222 223 224 225 226 227 228 229 230 231 232 233 234 235
EnumeratorDeclaration::EnumeratorDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
    : Declaration(translationUnit, sourceLocation, name)
    , _constantValue(0)
{}

EnumeratorDeclaration::~EnumeratorDeclaration()
{}

const StringLiteral *EnumeratorDeclaration::constantValue() const
{ return _constantValue; }

void EnumeratorDeclaration::setConstantValue(const StringLiteral *constantValue)
{ _constantValue = constantValue; }

Roberto Raggi's avatar
Roberto Raggi committed
236
Argument::Argument(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
con's avatar
con committed
237
    : Symbol(translationUnit, sourceLocation, name),
238
      _initializer(0)
con's avatar
con committed
239 240
{ }

241 242 243 244 245 246
Argument::Argument(Clone *clone, Subst *subst, Argument *original)
    : Symbol(clone, subst, original)
    , _initializer(clone->stringLiteral(original->_initializer))
    , _type(clone->type(original->_type, subst))
{ }

con's avatar
con committed
247 248 249 250
Argument::~Argument()
{ }

bool Argument::hasInitializer() const
251 252 253
{ return _initializer != 0; }

const StringLiteral *Argument::initializer() const
con's avatar
con committed
254 255
{ return _initializer; }

256 257
void Argument::setInitializer(const StringLiteral *initializer)
{ _initializer = initializer; }
con's avatar
con committed
258

259
void Argument::setType(const FullySpecifiedType &type)
con's avatar
con committed
260 261 262 263 264 265 266 267
{ _type = type; }

FullySpecifiedType Argument::type() const
{ return _type; }

void Argument::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

Roberto Raggi's avatar
Roberto Raggi committed
268 269
TypenameArgument::TypenameArgument(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
    : Symbol(translationUnit, sourceLocation, name)
270
    , _isClassDeclarator(false)
Roberto Raggi's avatar
Roberto Raggi committed
271 272
{ }

273 274 275
TypenameArgument::TypenameArgument(Clone *clone, Subst *subst, TypenameArgument *original)
    : Symbol(clone, subst, original)
    , _type(clone->type(original->_type, subst))
276
    , _isClassDeclarator(original->_isClassDeclarator)
277 278
{ }

Roberto Raggi's avatar
Roberto Raggi committed
279 280 281 282 283 284 285 286 287 288 289 290
TypenameArgument::~TypenameArgument()
{ }

void TypenameArgument::setType(const FullySpecifiedType &type)
{ _type = type; }

FullySpecifiedType TypenameArgument::type() const
{ return _type; }

void TypenameArgument::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

Roberto Raggi's avatar
Roberto Raggi committed
291
Function::Function(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
Roberto Raggi's avatar
Roberto Raggi committed
292
    : Scope(translationUnit, sourceLocation, name),
293 294
      _flags(0)
{ }
con's avatar
con committed
295

296 297 298 299 300 301
Function::Function(Clone *clone, Subst *subst, Function *original)
    : Scope(clone, subst, original)
    , _returnType(clone->type(original->_returnType, subst))
    , _flags(original->_flags)
{ }

con's avatar
con committed
302
Function::~Function()
Roberto Raggi's avatar
Roberto Raggi committed
303
{ }
con's avatar
con committed
304 305

bool Function::isNormal() const
306
{ return f._methodKey == NormalMethod; }
con's avatar
con committed
307 308

bool Function::isSignal() const
309
{ return f._methodKey == SignalMethod; }
con's avatar
con committed
310 311

bool Function::isSlot() const
312
{ return f._methodKey == SlotMethod; }
con's avatar
con committed
313

314 315 316
bool Function::isInvokable() const
{ return f._methodKey == InvokableMethod; }

con's avatar
con committed
317
int Function::methodKey() const
318
{ return f._methodKey; }
con's avatar
con committed
319 320

void Function::setMethodKey(int key)
321
{ f._methodKey = key; }
con's avatar
con committed
322

323
bool Function::isSignatureEqualTo(const Function *other, Matcher *matcher) const
con's avatar
con committed
324
{
325
    if (! other)
con's avatar
con committed
326
        return false;
327
    else if (isConst() != other->isConst())
328
        return false;
329
    else if (isVolatile() != other->isVolatile())
330
        return false;
331 332
    else if (! Matcher::match(unqualifiedName(), other->unqualifiedName(), matcher))
        return false;
333

334 335 336 337 338 339 340
    const unsigned argc = argumentCount();
    if (argc != other->argumentCount())
        return false;
    for (unsigned i = 0; i < argc; ++i) {
        Symbol *l = argumentAt(i);
        Symbol *r = other->argumentAt(i);
        if (! l->type().match(r->type(), matcher))
con's avatar
con committed
341 342
            return false;
    }
343
    return true;
con's avatar
con committed
344 345 346 347 348
}

void Function::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

349
bool Function::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
350 351 352 353 354 355 356
{
    if (const Function *otherTy = otherType->asFunctionType())
        return matcher->match(this, otherTy);

    return false;
}

con's avatar
con committed
357
FullySpecifiedType Function::type() const
358 359 360 361 362 363
{
    FullySpecifiedType ty(const_cast<Function *>(this));
    ty.setConst(isConst());
    ty.setVolatile(isVolatile());
    return ty;
}
con's avatar
con committed
364 365 366 367

FullySpecifiedType Function::returnType() const
{ return _returnType; }

368
void Function::setReturnType(const FullySpecifiedType &returnType)
con's avatar
con committed
369 370
{ _returnType = returnType; }

371 372 373 374 375 376
bool Function::hasReturnType() const
{
    const FullySpecifiedType ty = returnType();
    return ty.isValid() || ty.isSigned() || ty.isUnsigned();
}

con's avatar
con committed
377 378
unsigned Function::argumentCount() const
{
379 380
    const unsigned memCnt = memberCount();
    if (memCnt > 0 && memberAt(0)->type()->isVoidType())
381
        return 0;
382 383 384 385 386 387 388 389

    // Definitions with function-try-blocks will have more than a block, and
    // arguments with a lambda as default argument will also have more blocks.
    unsigned argc = 0;
    for (unsigned it = 0; it < memCnt; ++it)
        if (memberAt(it)->isArgument())
            ++argc;
    return argc;
con's avatar
con committed
390 391 392
}

Symbol *Function::argumentAt(unsigned index) const
393 394 395 396 397 398 399 400 401 402 403 404
{
    for (unsigned it = 0, eit = memberCount(); it < eit; ++it) {
        if (Argument *arg = memberAt(it)->asArgument()) {
            if (index == 0)
                return arg;
            else
                --index;
        }
    }

    return 0;
}
con's avatar
con committed
405

406 407
bool Function::hasArguments() const
{
408 409
    unsigned argc = argumentCount();
    return ! (argc == 0 || (argc == 1 && argumentAt(0)->type()->isVoidType()));
410 411
}

Roberto Raggi's avatar
Roberto Raggi committed
412 413 414 415
unsigned Function::minimumArgumentCount() const
{
    unsigned index = 0;

416
    for (unsigned ei = argumentCount(); index < ei; ++index) {
417
        if (Argument *arg = argumentAt(index)->asArgument()) {
Roberto Raggi's avatar
Roberto Raggi committed
418 419 420 421 422 423 424 425
            if (arg->hasInitializer())
                break;
        }
    }

    return index;
}

426 427 428 429 430 431
bool Function::isVirtual() const
{ return f._isVirtual; }

void Function::setVirtual(bool isVirtual)
{ f._isVirtual = isVirtual; }

432 433 434 435 436 437 438 439 440 441 442 443
bool Function::isOverride() const
{ return f._isOverride; }

void Function::setOverride(bool isOverride)
{ f._isOverride = isOverride; }

bool Function::isFinal() const
{ return f._isFinal; }

void Function::setFinal(bool isFinal)
{ f._isFinal = isFinal; }

con's avatar
con committed
444
bool Function::isVariadic() const
445
{ return f._isVariadic; }
con's avatar
con committed
446 447

void Function::setVariadic(bool isVariadic)
448
{ f._isVariadic = isVariadic; }
con's avatar
con committed
449 450

bool Function::isConst() const
451
{ return f._isConst; }
con's avatar
con committed
452 453

void Function::setConst(bool isConst)
454
{ f._isConst = isConst; }
con's avatar
con committed
455 456

bool Function::isVolatile() const
457
{ return f._isVolatile; }
con's avatar
con committed
458 459

void Function::setVolatile(bool isVolatile)
460
{ f._isVolatile = isVolatile; }
con's avatar
con committed
461 462

bool Function::isPureVirtual() const
463
{ return f._isPureVirtual; }
con's avatar
con committed
464 465

void Function::setPureVirtual(bool isPureVirtual)
466
{ f._isPureVirtual = isPureVirtual; }
con's avatar
con committed
467

468 469 470 471 472 473
Function::RefQualifier Function::refQualifier() const
{ return static_cast<RefQualifier>(f._refQualifier); }

void Function::setRefQualifier(Function::RefQualifier refQualifier)
{ f._refQualifier = refQualifier; }

474
bool Function::isAmbiguous() const
475
{ return f._isAmbiguous; }
476 477

void Function::setAmbiguous(bool isAmbiguous)
478
{ f._isAmbiguous = isAmbiguous; }
479

con's avatar
con committed
480 481 482 483 484 485 486 487 488
void Function::visitSymbol0(SymbolVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (unsigned i = 0; i < memberCount(); ++i) {
            visitSymbol(memberAt(i), visitor);
        }
    }
}

489 490
bool Function::maybeValidPrototype(unsigned actualArgumentCount) const
{
491
    const unsigned argc = argumentCount();
492 493
    unsigned minNumberArguments = 0;

494 495
    for (; minNumberArguments < argc; ++minNumberArguments) {
        Argument *arg = argumentAt(minNumberArguments)->asArgument();
496

497
        if (! arg)
498 499
            return false;

500 501 502 503 504 505 506 507
        if (arg->hasInitializer())
            break;
    }

    if (actualArgumentCount < minNumberArguments) {
        // not enough arguments.
        return false;

508
    } else if (!isVariadic() && actualArgumentCount > argc) {
509 510 511 512 513 514 515 516
        // too many arguments.
        return false;
    }

    return true;
}


con's avatar
con committed
517
Block::Block(TranslationUnit *translationUnit, unsigned sourceLocation)
Roberto Raggi's avatar
Roberto Raggi committed
518
    : Scope(translationUnit, sourceLocation, /*name = */ 0)
con's avatar
con committed
519 520
{ }

521 522 523 524
Block::Block(Clone *clone, Subst *subst, Block *original)
    : Scope(clone, subst, original)
{ }

con's avatar
con committed
525 526 527 528 529 530 531
Block::~Block()
{ }

FullySpecifiedType Block::type() const
{ return FullySpecifiedType(); }

void Block::visitSymbol0(SymbolVisitor *visitor)
532 533 534 535 536 537 538
{
    if (visitor->visit(this)) {
        for (unsigned i = 0; i < memberCount(); ++i) {
            visitSymbol(memberAt(i), visitor);
        }
    }
}
con's avatar
con committed
539

Roberto Raggi's avatar
Roberto Raggi committed
540
Enum::Enum(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
Roberto Raggi's avatar
Roberto Raggi committed
541
    : Scope(translationUnit, sourceLocation, name)
542
    , _isScoped(false)
con's avatar
con committed
543 544
{ }

545 546
Enum::Enum(Clone *clone, Subst *subst, Enum *original)
    : Scope(clone, subst, original)
547
    , _isScoped(original->isScoped())
548 549
{ }

con's avatar
con committed
550 551 552 553 554 555
Enum::~Enum()
{ }

FullySpecifiedType Enum::type() const
{ return FullySpecifiedType(const_cast<Enum *>(this)); }

556 557 558 559 560 561 562 563 564 565
bool Enum::isScoped() const
{
    return _isScoped;
}

void Enum::setScoped(bool scoped)
{
    _isScoped = scoped;
}

con's avatar
con committed
566 567 568
void Enum::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

569
bool Enum::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
570 571 572 573 574 575 576
{
    if (const Enum *otherTy = otherType->asEnumType())
        return matcher->match(this, otherTy);

    return false;
}

con's avatar
con committed
577 578 579 580 581 582 583 584 585
void Enum::visitSymbol0(SymbolVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (unsigned i = 0; i < memberCount(); ++i) {
            visitSymbol(memberAt(i), visitor);
        }
    }
}

586 587 588 589
Template::Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
    : Scope(translationUnit, sourceLocation, name)
{ }

590 591 592 593
Template::Template(Clone *clone, Subst *subst, Template *original)
    : Scope(clone, subst, original)
{ }

594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
Template::~Template()
{ }

unsigned Template::templateParameterCount() const
{
    if (declaration() != 0)
        return memberCount() - 1;

    return 0;
}

Symbol *Template::templateParameterAt(unsigned index) const
{ return memberAt(index); }

Symbol *Template::declaration() const
{
    if (isEmpty())
        return 0;

    if (Symbol *s = memberAt(memberCount() - 1)) {
        if (s->isClass() || s->isForwardClassDeclaration() ||
            s->isTemplate() || s->isFunction() || s->isDeclaration())
            return s;
    }

    return 0;
}

FullySpecifiedType Template::type() const
{ return FullySpecifiedType(const_cast<Template *>(this)); }

void Template::visitSymbol0(SymbolVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (unsigned i = 0; i < memberCount(); ++i) {
            visitSymbol(memberAt(i), visitor);
        }
    }
}

void Template::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

637
bool Template::match0(const Type *otherType, Matcher *matcher) const
638 639 640 641 642 643
{
    if (const Template *otherTy = otherType->asTemplateType())
        return matcher->match(this, otherTy);
    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
644
Namespace::Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
Roberto Raggi's avatar
Roberto Raggi committed
645
    : Scope(translationUnit, sourceLocation, name)
646
    , _isInline(false)
con's avatar
con committed
647 648
{ }

649 650
Namespace::Namespace(Clone *clone, Subst *subst, Namespace *original)
    : Scope(clone, subst, original)
651
    , _isInline(original->_isInline)
652 653
{ }

con's avatar
con committed
654 655 656 657 658 659
Namespace::~Namespace()
{ }

void Namespace::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

660
bool Namespace::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
661 662 663 664 665 666 667
{
    if (const Namespace *otherTy = otherType->asNamespaceType())
        return matcher->match(this, otherTy);

    return false;
}

con's avatar
con committed
668 669 670 671 672 673 674 675 676 677 678 679
void Namespace::visitSymbol0(SymbolVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (unsigned i = 0; i < memberCount(); ++i) {
            visitSymbol(memberAt(i), visitor);
        }
    }
}

FullySpecifiedType Namespace::type() const
{ return FullySpecifiedType(const_cast<Namespace *>(this)); }

Roberto Raggi's avatar
Roberto Raggi committed
680
BaseClass::BaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
con's avatar
con committed
681 682 683 684
    : Symbol(translationUnit, sourceLocation, name),
      _isVirtual(false)
{ }

685 686 687 688 689 690
BaseClass::BaseClass(Clone *clone, Subst *subst, BaseClass *original)
    : Symbol(clone, subst, original)
    , _isVirtual(original->_isVirtual)
    , _type(clone->type(original->_type, subst))
{ }

con's avatar
con committed
691 692 693 694
BaseClass::~BaseClass()
{ }

FullySpecifiedType BaseClass::type() const
Roberto Raggi's avatar
Roberto Raggi committed
695 696 697 698
{ return _type; }

void BaseClass::setType(const FullySpecifiedType &type)
{ _type = type; }
con's avatar
con committed
699 700 701 702 703 704 705

bool BaseClass::isVirtual() const
{ return _isVirtual; }

void BaseClass::setVirtual(bool isVirtual)
{ _isVirtual = isVirtual; }

706 707 708 709 710 711
bool BaseClass::isVariadic() const
{ return _isVariadic; }

void BaseClass::setVariadic(bool isVariadic)
{ _isVariadic = isVariadic; }

con's avatar
con committed
712
void BaseClass::visitSymbol0(SymbolVisitor *visitor)
713 714 715
{ visitor->visit(this); }

ForwardClassDeclaration::ForwardClassDeclaration(TranslationUnit *translationUnit,
Roberto Raggi's avatar
Roberto Raggi committed
716
                                                 unsigned sourceLocation, const Name *name)
Roberto Raggi's avatar
Roberto Raggi committed
717
    : Symbol(translationUnit, sourceLocation, name)
718 719
{ }

720 721 722 723
ForwardClassDeclaration::ForwardClassDeclaration(Clone *clone, Subst *subst, ForwardClassDeclaration *original)
    : Symbol(clone, subst, original)
{ }

724
ForwardClassDeclaration::~ForwardClassDeclaration()
Roberto Raggi's avatar
Roberto Raggi committed
725
{ }
726 727 728 729 730 731 732 733

FullySpecifiedType ForwardClassDeclaration::type() const
{ return FullySpecifiedType(const_cast<ForwardClassDeclaration *>(this)); }

void ForwardClassDeclaration::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

void ForwardClassDeclaration::accept0(TypeVisitor *visitor)
con's avatar
con committed
734 735
{ visitor->visit(this); }

736
bool ForwardClassDeclaration::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
737 738 739 740 741 742 743
{
    if (const ForwardClassDeclaration *otherTy = otherType->asForwardClassDeclarationType())
        return matcher->match(this, otherTy);

    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
744
Class::Class(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
Roberto Raggi's avatar
Roberto Raggi committed
745
    : Scope(translationUnit, sourceLocation, name),
Roberto Raggi's avatar
Roberto Raggi committed
746
      _key(ClassKey)
con's avatar
con committed
747 748
{ }

749 750 751 752 753 754 755 756
Class::Class(Clone *clone, Subst *subst, Class *original)
    : Scope(clone, subst, original)
    , _key(original->_key)
{
    for (size_t i = 0; i < original->_baseClasses.size(); ++i)
        addBaseClass(clone->symbol(original->_baseClasses.at(i), subst)->asBaseClass());
}

con's avatar
con committed
757
Class::~Class()
Roberto Raggi's avatar
Roberto Raggi committed
758
{ }
con's avatar
con committed
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777

bool Class::isClass() const
{ return _key == ClassKey; }

bool Class::isStruct() const
{ return _key == StructKey; }

bool Class::isUnion() const
{ return _key == UnionKey; }

Class::Key Class::classKey() const
{ return _key; }

void Class::setClassKey(Key key)
{ _key = key; }

void Class::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

778
bool Class::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
779 780 781 782 783 784 785
{
    if (const Class *otherTy = otherType->asClassType())
        return matcher->match(this, otherTy);

    return false;
}

con's avatar
con committed
786
unsigned Class::baseClassCount() const
787
{ return unsigned(_baseClasses.size()); }
con's avatar
con committed
788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809

BaseClass *Class::baseClassAt(unsigned index) const
{ return _baseClasses.at(index); }

void Class::addBaseClass(BaseClass *baseClass)
{ _baseClasses.push_back(baseClass); }

FullySpecifiedType Class::type() const
{ return FullySpecifiedType(const_cast<Class *>(this)); }

void Class::visitSymbol0(SymbolVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (unsigned i = 0; i < _baseClasses.size(); ++i) {
            visitSymbol(_baseClasses.at(i), visitor);
        }
        for (unsigned i = 0; i < memberCount(); ++i) {
            visitSymbol(memberAt(i), visitor);
        }
    }
}

810 811 812

QtPropertyDeclaration::QtPropertyDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
    : Symbol(translationUnit, sourceLocation, name)
813
    , _flags(NoFlags)
814 815
{ }

816 817 818 819 820 821
QtPropertyDeclaration::QtPropertyDeclaration(Clone *clone, Subst *subst, QtPropertyDeclaration *original)
    : Symbol(clone, subst, original)
    , _type(clone->type(original->_type, subst))
    , _flags(original->_flags)
{ }

822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
QtPropertyDeclaration::~QtPropertyDeclaration()
{ }

void QtPropertyDeclaration::setType(const FullySpecifiedType &type)
{ _type = type; }

void QtPropertyDeclaration::setFlags(int flags)
{ _flags = flags; }

int QtPropertyDeclaration::flags() const
{ return _flags; }

FullySpecifiedType QtPropertyDeclaration::type() const
{ return _type; }

void QtPropertyDeclaration::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }


841 842 843 844
QtEnum::QtEnum(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
    : Symbol(translationUnit, sourceLocation, name)
{ }

845 846 847 848
QtEnum::QtEnum(Clone *clone, Subst *subst, QtEnum *original)
    : Symbol(clone, subst, original)
{ }

849 850 851 852 853 854 855 856 857 858
QtEnum::~QtEnum()
{ }

FullySpecifiedType QtEnum::type() const
{ return FullySpecifiedType(); }

void QtEnum::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }


Roberto Raggi's avatar
Roberto Raggi committed
859
ObjCBaseClass::ObjCBaseClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
860 861 862
    : Symbol(translationUnit, sourceLocation, name)
{ }

863 864 865 866
ObjCBaseClass::ObjCBaseClass(Clone *clone, Subst *subst, ObjCBaseClass *original)
    : Symbol(clone, subst, original)
{ }

867 868 869 870 871 872 873 874 875
ObjCBaseClass::~ObjCBaseClass()
{ }

FullySpecifiedType ObjCBaseClass::type() const
{ return FullySpecifiedType(); }

void ObjCBaseClass::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

Roberto Raggi's avatar
Roberto Raggi committed
876
ObjCBaseProtocol::ObjCBaseProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
877 878 879
    : Symbol(translationUnit, sourceLocation, name)
{ }

880 881 882 883
ObjCBaseProtocol::ObjCBaseProtocol(Clone *clone, Subst *subst, ObjCBaseProtocol *original)
    : Symbol(clone, subst, original)
{ }

884 885 886 887 888 889 890 891 892
ObjCBaseProtocol::~ObjCBaseProtocol()
{ }

FullySpecifiedType ObjCBaseProtocol::type() const
{ return FullySpecifiedType(); }

void ObjCBaseProtocol::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

Roberto Raggi's avatar
Roberto Raggi committed
893
ObjCClass::ObjCClass(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name):
894 895 896 897
    Scope(translationUnit, sourceLocation, name),
    _categoryName(0),
    _baseClass(0),
    _isInterface(false)
898 899 900 901 902 903 904
{ }

ObjCClass::ObjCClass(Clone *clone, Subst *subst, ObjCClass *original)
    : Scope(clone, subst, original)
    , _categoryName(clone->name(original->_categoryName, subst))
    , _baseClass(0)
    , _isInterface(original->_isInterface)
905
{
906 907 908 909
    if (original->_baseClass)
        _baseClass = clone->symbol(original->_baseClass, subst)->asObjCBaseClass();
    for (size_t i = 0; i < original->_protocols.size(); ++i)
        addProtocol(clone->symbol(original->_protocols.at(i), subst)->asObjCBaseProtocol());
910 911 912 913 914
}

ObjCClass::~ObjCClass()
{}

Roberto Raggi's avatar
Cleanup  
Roberto Raggi committed
915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
bool ObjCClass::isInterface() const
{ return _isInterface; }

void ObjCClass::setInterface(bool isInterface)
{ _isInterface = isInterface; }

bool ObjCClass::isCategory() const
{ return _categoryName != 0; }

const Name *ObjCClass::categoryName() const
{ return _categoryName; }

void ObjCClass::setCategoryName(const Name *categoryName)
{ _categoryName = categoryName; }

ObjCBaseClass *ObjCClass::baseClass() const
{ return _baseClass; }

void ObjCClass::setBaseClass(ObjCBaseClass *baseClass)
{ _baseClass = baseClass; }

unsigned ObjCClass::protocolCount() const
937
{ return unsigned(_protocols.size()); }
Roberto Raggi's avatar
Cleanup  
Roberto Raggi committed
938 939 940 941 942 943 944

ObjCBaseProtocol *ObjCClass::protocolAt(unsigned index) const
{ return _protocols.at(index); }

void ObjCClass::addProtocol(ObjCBaseProtocol *protocol)
{ _protocols.push_back(protocol); }

945 946 947 948 949 950
FullySpecifiedType ObjCClass::type() const
{ return FullySpecifiedType(const_cast<ObjCClass *>(this)); }

void ObjCClass::visitSymbol0(SymbolVisitor *visitor)
{
    if (visitor->visit(this)) {
951 952 953
        if (_baseClass)
            visitSymbol(_baseClass, visitor);

954 955
        for (unsigned i = 0; i < _protocols.size(); ++i)
            visitSymbol(_protocols.at(i), visitor);
956 957 958

        for (unsigned i = 0; i < memberCount(); ++i)
            visitSymbol(memberAt(i), visitor);
959 960 961 962 963 964
    }
}

void ObjCClass::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

965
bool ObjCClass::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
966 967 968 969 970 971 972
{
    if (const ObjCClass *otherTy = otherType->asObjCClassType())
        return matcher->match(this, otherTy);

    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
973
ObjCProtocol::ObjCProtocol(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name):
Roberto Raggi's avatar
Roberto Raggi committed
974
        Scope(translationUnit, sourceLocation, name)
975 976 977
{
}

978 979 980 981 982 983 984
ObjCProtocol::ObjCProtocol(Clone *clone, Subst *subst, ObjCProtocol *original)
    : Scope(clone, subst, original)
{
    for (size_t i = 0; i < original->_protocols.size(); ++i)
        addProtocol(clone->symbol(original->_protocols.at(i), subst)->asObjCBaseProtocol());
}

985 986 987
ObjCProtocol::~ObjCProtocol()
{}

Roberto Raggi's avatar
Cleanup  
Roberto Raggi committed
988
unsigned ObjCProtocol::protocolCount() const
989
{ return unsigned(_protocols.size()); }
Roberto Raggi's avatar
Cleanup  
Roberto Raggi committed
990 991 992 993 994 995 996

ObjCBaseProtocol *ObjCProtocol::protocolAt(unsigned index) const
{ return _protocols.at(index); }

void ObjCProtocol::addProtocol(ObjCBaseProtocol *protocol)
{ _protocols.push_back(protocol); }

997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
FullySpecifiedType ObjCProtocol::type() const
{ return FullySpecifiedType(const_cast<ObjCProtocol *>(this)); }

void ObjCProtocol::visitSymbol0(SymbolVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (unsigned i = 0; i < _protocols.size(); ++i)
            visitSymbol(_protocols.at(i), visitor);
    }
}

void ObjCProtocol::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

1011
bool ObjCProtocol::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
1012 1013 1014 1015 1016 1017 1018
{
    if (const ObjCProtocol *otherTy = otherType->asObjCProtocolType())
        return matcher->match(this, otherTy);

    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
1019 1020
ObjCForwardClassDeclaration::ObjCForwardClassDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation,
                                                         const Name *name):
1021 1022 1023 1024
        Symbol(translationUnit, sourceLocation, name)
{
}

1025 1026 1027 1028
ObjCForwardClassDeclaration::ObjCForwardClassDeclaration(Clone *clone, Subst *subst, ObjCForwardClassDeclaration *original)
    : Symbol(clone, subst, original)
{ }

1029 1030 1031 1032
ObjCForwardClassDeclaration::~ObjCForwardClassDeclaration()
{}

FullySpecifiedType ObjCForwardClassDeclaration::type() const
Erik Verbruggen's avatar
Erik Verbruggen committed
1033
{ return FullySpecifiedType(); }
1034 1035 1036 1037

void ObjCForwardClassDeclaration::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

1038 1039 1040
void ObjCForwardClassDeclaration::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

1041
bool ObjCForwardClassDeclaration::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
1042 1043 1044 1045 1046 1047 1048
{
    if (const ObjCForwardClassDeclaration *otherTy = otherType->asObjCForwardClassDeclarationType())
        return matcher->match(this, otherTy);

    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
1049 1050
ObjCForwardProtocolDeclaration::ObjCForwardProtocolDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation,
                                                               const Name *name):
1051 1052 1053 1054
        Symbol(translationUnit, sourceLocation, name)
{
}

1055 1056 1057 1058
ObjCForwardProtocolDeclaration::ObjCForwardProtocolDeclaration(Clone *clone, Subst *subst, ObjCForwardProtocolDeclaration *original)
    : Symbol(clone, subst, original)
{ }

1059 1060 1061 1062
ObjCForwardProtocolDeclaration::~ObjCForwardProtocolDeclaration()
{}

FullySpecifiedType ObjCForwardProtocolDeclaration::type() const
Erik Verbruggen's avatar
Erik Verbruggen committed
1063
{ return FullySpecifiedType(); }
1064 1065 1066 1067

void ObjCForwardProtocolDeclaration::visitSymbol0(SymbolVisitor *visitor)
{ visitor->visit(this); }

1068 1069 1070
void ObjCForwardProtocolDeclaration::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

1071
bool ObjCForwardProtocolDeclaration::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
1072 1073 1074 1075 1076 1077 1078
{
    if (const ObjCForwardProtocolDeclaration *otherTy = otherType->asObjCForwardProtocolDeclarationType())
        return matcher->match(this, otherTy);

    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
1079
ObjCMethod::ObjCMethod(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
Roberto Raggi's avatar
Roberto Raggi committed
1080
    : Scope(translationUnit, sourceLocation, name),
1081
     _flags(0)
Roberto Raggi's avatar
Roberto Raggi committed
1082
{ }
1083

1084 1085 1086 1087 1088 1089
ObjCMethod::ObjCMethod(Clone *clone, Subst *subst, ObjCMethod *original)
    : Scope(clone, subst, original)
    , _returnType(clone->type(original->_returnType, subst))
    , _flags(original->_flags)
{ }

1090
ObjCMethod::~ObjCMethod()
Roberto Raggi's avatar
Roberto Raggi committed
1091
{ }
1092 1093 1094 1095

void ObjCMethod::accept0(TypeVisitor *visitor)
{ visitor->visit(this); }

1096
bool ObjCMethod::match0(const Type *otherType, Matcher *matcher) const
Roberto Raggi's avatar
Roberto Raggi committed
1097 1098 1099 1100 1101 1102 1103
{
    if (const ObjCMethod *otherTy = otherType->asObjCMethodType())
        return matcher->match(this, otherTy);

    return false;
}

1104 1105 1106 1107 1108 1109
FullySpecifiedType ObjCMethod::type() const
{ return FullySpecifiedType(const_cast<ObjCMethod *>(this)); }

FullySpecifiedType ObjCMethod::returnType() const
{ return _returnType; }

1110
void ObjCMethod::setReturnType(const FullySpecifiedType &returnType)
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
{ _returnType = returnType; }

bool ObjCMethod::hasReturnType() const
{
    const FullySpecifiedType ty = returnType();
    return ty.isValid() || ty.isSigned() || ty.isUnsigned();
}

unsigned ObjCMethod::argumentCount() const
{
1121 1122 1123 1124
    const unsigned c = memberCount();
    if (c > 0 && memberAt(c - 1)->isBlock())
        return c - 1;
    return c;
1125 1126 1127
}

Symbol *ObjCMethod::argumentAt(unsigned index) const
Roberto Raggi's avatar
Roberto Raggi committed
1128 1129 1130
{
    return memberAt(index);
}
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152

bool ObjCMethod::hasArguments() const
{
    return ! (argumentCount() == 0 ||
              (argumentCount() == 1 && argumentAt(0)->type()->isVoidType()));
}

bool ObjCMethod::isVariadic() const
{ return f._isVariadic; }

void ObjCMethod::setVariadic(bool isVariadic)
{ f._isVariadic = isVariadic; }

void ObjCMethod::visitSymbol0(SymbolVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (unsigned i = 0; i < memberCount(); ++i) {
            visitSymbol(memberAt(i), visitor);
        }
    }
}

1153 1154
ObjCPropertyDeclaration::ObjCPropertyDeclaration(TranslationUnit *translationUnit,
                                                 unsigned sourceLocation,
Roberto Raggi's avatar
Roberto Raggi committed
1155
                                                 const Name *name):
1156 1157
    Symbol(translationUnit, sourceLocation, name),
    _getterName(0),
1158 1159
    _setterName(0),
    _propertyAttributes(None)
1160 1161
{}

1162 1163 1164 1165 1166 1167 1168 1169
ObjCPropertyDeclaration::ObjCPropertyDeclaration(Clone *clone, Subst *subst, ObjCPropertyDeclaration *original)
    : Symbol(clone, subst, original)
    , _getterName(clone->name(original->_getterName, subst))
    , _setterName(clone->name(original->_setterName, subst))
    , _type(clone->type(original->_type, subst))
    , _propertyAttributes(original->_propertyAttributes)
{ }

1170 1171 1172
ObjCPropertyDeclaration::~ObjCPropertyDeclaration()
{}

Roberto Raggi's avatar
Cleanup  
Roberto Raggi committed
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
bool ObjCPropertyDeclaration::hasAttribute(int attribute) const
{ return _propertyAttributes & attribute; }

void ObjCPropertyDeclaration::setAttributes(int attributes)
{ _propertyAttributes = attributes; }

bool ObjCPropertyDeclaration::hasGetter() const
{ return hasAttribute(Getter); }

bool ObjCPropertyDeclaration::hasSetter() const
{ return hasAttribute(Setter); }

const Name *ObjCPropertyDeclaration::getterName() const
{ return _getterName; }

void ObjCPropertyDeclaration::setGetterName(const Name *getterName)
{ _getterName = getterName; }

const Name *ObjCPropertyDeclaration::setterName() const
{ return _setterName; }

void ObjCPropertyDeclaration::setSetterName(const Name *setterName)
{ _setterName = setterName; }

void ObjCPropertyDeclaration::setType(const FullySpecifiedType &type)
{ _type = type; }

1200 1201
FullySpecifiedType ObjCPropertyDeclaration::type() const
{ return _type; }
Roberto Raggi's avatar
Roberto Raggi committed
1202

1203 1204 1205 1206 1207
void ObjCPropertyDeclaration::visitSymbol0(SymbolVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
}