clang: lib/AST/NestedNameSpecifier.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

27#include "llvm/ADT/FoldingSet.h"

28#include "llvm/Support/Compiler.h"

29#include "llvm/Support/ErrorHandling.h"

30#include "llvm/Support/raw_ostream.h"

31#include

32#include

33#include

34#include

35

36using namespace clang;

37

39NestedNameSpecifier::FindOrInsert(const ASTContext &Context,

41 llvm::FoldingSetNodeID ID;

43

44 void *InsertPos = nullptr;

46 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);

47 if (!NNS) {

48 NNS =

50 Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);

51 }

52

53 return NNS;

54}

55

59 assert(II && "Identifier cannot be NULL");

60 assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");

61

63 Mockup.Prefix.setPointer(Prefix);

64 Mockup.Prefix.setInt(StoredIdentifier);

66 return FindOrInsert(Context, Mockup);

67}

68

73 assert(NS && "Namespace cannot be NULL");

74 assert((!Prefix ||

75 (Prefix->getAsType() == nullptr &&

77 "Broken nested name specifier");

79 Mockup.Prefix.setPointer(Prefix);

80 Mockup.Prefix.setInt(StoredDecl);

81 Mockup.Specifier = const_cast<NamespaceDecl *>(NS);

82 return FindOrInsert(Context, Mockup);

83}

84

89 assert(Alias && "Namespace alias cannot be NULL");

90 assert((!Prefix ||

91 (Prefix->getAsType() == nullptr &&

93 "Broken nested name specifier");

95 Mockup.Prefix.setPointer(Prefix);

96 Mockup.Prefix.setInt(StoredDecl);

98 return FindOrInsert(Context, Mockup);

99}

100

104 bool Template, const Type *T) {

105 assert(T && "Type cannot be NULL");

107 Mockup.Prefix.setPointer(Prefix);

108 Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);

109 Mockup.Specifier = const_cast<Type*>(T);

110 return FindOrInsert(Context, Mockup);

111}

112

115 assert(II && "Identifier cannot be NULL");

117 Mockup.Prefix.setPointer(nullptr);

118 Mockup.Prefix.setInt(StoredIdentifier);

120 return FindOrInsert(Context, Mockup);

121}

122

125 if (!Context.GlobalNestedNameSpecifier)

126 Context.GlobalNestedNameSpecifier =

128 return Context.GlobalNestedNameSpecifier;

129}

130

135 Mockup.Prefix.setPointer(nullptr);

136 Mockup.Prefix.setInt(StoredDecl);

137 Mockup.Specifier = RD;

138 return FindOrInsert(Context, Mockup);

139}

140

142 if (!Specifier)

144

145 switch (Prefix.getInt()) {

146 case StoredIdentifier:

148

149 case StoredDecl: {

151 if (isa(ND))

154 }

155

156 case StoredTypeSpec:

158

159 case StoredTypeSpecWithTemplate:

161 }

162

163 llvm_unreachable("Invalid NNS Kind!");

164}

165

166

168 if (Prefix.getInt() == StoredDecl)

169 return dyn_cast(static_cast<NamedDecl *>(Specifier));

170

171 return nullptr;

172}

173

174

176 if (Prefix.getInt() == StoredDecl)

177 return dyn_cast(static_cast<NamedDecl *>(Specifier));

178

179 return nullptr;

180}

181

182

184 switch (Prefix.getInt()) {

185 case StoredIdentifier:

186 return nullptr;

187

188 case StoredDecl:

189 return dyn_cast(static_cast<NamedDecl *>(Specifier));

190

191 case StoredTypeSpec:

192 case StoredTypeSpecWithTemplate:

194 }

195

196 llvm_unreachable("Invalid NNS Kind!");

197}

198

202

203 auto F = NestedNameSpecifierDependence::Dependent |

204 NestedNameSpecifierDependence::Instantiation;

205

208 return F;

209 }

210

214 return NestedNameSpecifierDependence::None;

215

218 for (const auto &Base : RD->bases())

219 if (Base.getType()->isDependentType())

220

221 return NestedNameSpecifierDependence::Dependent;

222 return NestedNameSpecifierDependence::None;

223 }

224

228 }

229 llvm_unreachable("Invalid NNS Kind!");

230}

231

233 return getDependence() & NestedNameSpecifierDependence::Dependent;

234}

235

237 return getDependence() & NestedNameSpecifierDependence::Instantiation;

238}

239

241 return getDependence() & NestedNameSpecifierDependence::UnexpandedPack;

242}

243

245 return getDependence() & NestedNameSpecifierDependence::Error;

246}

247

248

249

251 bool ResolveTemplateArguments) const {

254

258 break;

259

262 return;

263

265 break;

266

269 break;

270

272 break;

273

275 OS << "__super";

276 break;

277

279 OS << "template ";

280

281 [[fallthrough]];

282

285 dyn_cast_or_null(getAsRecordDecl());

286 if (ResolveTemplateArguments && Record) {

287

288 Record->printName(OS, Policy);

290 OS, Record->getTemplateArgs().asArray(), Policy,

291 Record->getSpecializedTemplate()->getTemplateParameters());

292 break;

293 }

295

298

299

300

301

302

303

304

305

306 assert(!isa(T) &&

307 "Elaborated type in nested-name-specifier");

309 = dyn_cast(T)) {

310

311

312 SpecType->getTemplateName().print(OS, InnerPolicy,

314

315

317 InnerPolicy);

318 } else if (const auto *DepSpecType =

319 dyn_cast(T)) {

320

321

322 OS << DepSpecType->getIdentifier()->getName();

323

325 InnerPolicy);

326 } else {

327

329 }

330 break;

331 }

332 }

333

334 OS << "::";

335}

336

338 dump(llvm::errs(), LO);

339}

340

342

345 dump(OS, LO);

346}

347

351}

352

353unsigned

354NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {

355 assert(Qualifier && "Expected a non-NULL qualifier");

356

357

359

360 switch (Qualifier->getKind()) {

362

363 break;

364

369

371 break;

372

375

376

377 Length += sizeof(void *);

378 break;

379 }

380

381 return Length;

382}

383

384unsigned

386 unsigned Length = 0;

388 Length += getLocalDataLength(Qualifier);

389 return Length;

390}

391

392

393

396 memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(Raw));

398}

399

400

401

404 memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));

406}

407

409 if (!Qualifier)

411

415

418}

419

421 if (!Qualifier)

423

424 unsigned Offset = getDataLength(Qualifier->getPrefix());

425 switch (Qualifier->getKind()) {

428

436

439

440

441 void *TypeData = LoadPointer(Data, Offset);

442 TypeLoc TL(Qualifier->getAsType(), TypeData);

445 }

446 }

447

448 llvm_unreachable("Invalid NNS Kind!");

449}

450

455

456

457 unsigned Offset = getDataLength(Qualifier->getPrefix());

458 void *TypeData = LoadPointer(Data, Offset);

459 return TypeLoc(Qualifier->getAsType(), TypeData);

460}

461

462static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,

463 unsigned &BufferCapacity) {

464 if (Start == End)

465 return;

466

467 if (BufferSize + (End - Start) > BufferCapacity) {

468

469 unsigned NewCapacity = std::max(

470 (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),

471 (unsigned)(BufferSize + (End - Start)));

472 if (!BufferCapacity) {

473 char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));

474 if (Buffer)

475 memcpy(NewBuffer, Buffer, BufferSize);

476 Buffer = NewBuffer;

477 } else {

478 Buffer = static_cast<char *>(llvm::safe_realloc(Buffer, NewCapacity));

479 }

480 BufferCapacity = NewCapacity;

481 }

482 assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy");

483 memcpy(Buffer + BufferSize, Start, End - Start);

484 BufferSize += End - Start;

485}

486

487

489 unsigned &BufferSize, unsigned &BufferCapacity) {

491 Append(reinterpret_cast<char *>(&Raw),

492 reinterpret_cast<char *>(&Raw) + sizeof(Raw), Buffer, BufferSize,

493 BufferCapacity);

494}

495

496

497static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,

498 unsigned &BufferCapacity) {

499 Append(reinterpret_cast<char *>(&Ptr),

500 reinterpret_cast<char *>(&Ptr) + sizeof(void *),

501 Buffer, BufferSize, BufferCapacity);

502}

503

506 : Representation(Other.Representation) {

507 if (Other.Buffer)

508 return;

509

510 if (Other.BufferCapacity == 0) {

511

512 Buffer = Other.Buffer;

513 BufferSize = Other.BufferSize;

514 return;

515 }

516

517

519 BufferCapacity);

520}

521

525 Representation = Other.Representation;

526

527 if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {

528

529 BufferSize = Other.BufferSize;

530 memcpy(Buffer, Other.Buffer, BufferSize);

531 return *this;

532 }

533

534

535 if (BufferCapacity) {

536 free(Buffer);

537 BufferCapacity = 0;

538 }

539

540 if (Other.Buffer) {

541

542 Buffer = nullptr;

543 BufferSize = 0;

544 return *this;

545 }

546

547 if (Other.BufferCapacity == 0) {

548

549 Buffer = Other.Buffer;

550 BufferSize = Other.BufferSize;

551 return *this;

552 }

553

554

555 BufferSize = 0;

557 BufferCapacity);

558 return *this;

559}

560

568

569

571 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);

572}

573

580

581

583 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);

584}

585

591 Namespace);

592

593

594 SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);

595 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);

596}

597

603

604

606 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);

607}

608

611 assert(!Representation && "Already have a nested-name-specifier!?");

613

614

615 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);

616}

617

623

624

626 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);

627}

628

632 Representation = Qualifier;

633

634

635

636 BufferSize = 0;

639 Stack.push_back(NNS);

640 while (!Stack.empty()) {

642 switch (NNS->getKind()) {

647 break;

648

655 BufferCapacity);

656 break;

657 }

658

661 break;

662 }

663

664

666 Buffer, BufferSize, BufferCapacity);

667 }

668}

669

671 if (BufferCapacity)

672 free(Buffer);

673

675 Representation = nullptr;

676 BufferSize = 0;

677 return;

678 }

679

680

681

682

683 Representation = Other.getNestedNameSpecifier();

684 Buffer = static_cast<char *>(Other.getOpaqueData());

685 BufferSize = Other.getDataLength();

686 BufferCapacity = 0;

687}

688

691 if (!Representation)

693

694

695

696 if (BufferCapacity == 0)

698

699

700

701

702 void *Mem = Context.Allocate(BufferSize, alignof(void *));

703 memcpy(Mem, Buffer, BufferSize);

705}

Defines the clang::ASTContext interface.

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the C++ template declaration subclasses.

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the clang::LangOptions interface.

llvm::MachO::Record Record

static void * LoadPointer(void *Data, unsigned Offset)

Load a (possibly unaligned) pointer from a given address and offset.

static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity)

static void SaveSourceLocation(SourceLocation Loc, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity)

Save a source location to the given buffer.

static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity)

Save a pointer to the given buffer.

static SourceLocation LoadSourceLocation(void *Data, unsigned Offset)

Load a (possibly unaligned) source location from a given address and offset.

Defines the clang::SourceLocation class and associated facilities.

Defines the clang::TypeLoc interface and its subclasses.

C Language Family Type Representation.

__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const

Allocate a TypeSourceInfo where all locations have been initialized to a given location,...

void * Allocate(size_t Size, unsigned Align=8) const

Represents a C++ struct/union/class.

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

This represents a decl that may have a name.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

Represents a C++ namespace alias.

Represent a C++ namespace.

Class that aids in the construction of nested-name-specifiers along with source-location information ...

void Adopt(NestedNameSpecifierLoc Other)

Adopt an existing nested-name-specifier (with source-range information).

NestedNameSpecifierLocBuilder & operator=(const NestedNameSpecifierLocBuilder &Other)

void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R)

Make a new nested-name-specifier from incomplete source-location information.

NestedNameSpecifierLocBuilder()=default

void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, SourceLocation SuperLoc, SourceLocation ColonColonLoc)

Turns this (empty) nested-name-specifier into '__super' nested-name-specifier.

void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, SourceLocation ColonColonLoc)

Extend the current nested-name-specifier by another nested-name-specifier component of the form 'type...

void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc)

Turn this (empty) nested-name-specifier into the global nested-name-specifier '::'.

NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const

Retrieve a nested-name-specifier with location information, copied into the given AST context.

A C++ nested-name-specifier augmented with source location information.

TypeLoc getTypeLoc() const

For a nested-name-specifier that refers to a type, retrieve the type with source-location information...

SourceRange getLocalSourceRange() const

Retrieve the source range covering just the last part of this nested-name-specifier,...

SourceRange getSourceRange() const LLVM_READONLY

Retrieve the source range covering the entirety of this nested-name-specifier.

unsigned getDataLength() const

Determines the data length for the entire nested-name-specifier.

Represents a C++ nested name specifier, such as "\::std::vector::".

bool containsErrors() const

Whether this nested name specifier contains an error.

CXXRecordDecl * getAsRecordDecl() const

Retrieve the record declaration stored in this nested name specifier.

bool isDependent() const

Whether this nested name specifier refers to a dependent type or not.

SpecifierKind getKind() const

Determine what kind of nested name specifier is stored.

static NestedNameSpecifier * Create(const ASTContext &Context, NestedNameSpecifier *Prefix, const IdentifierInfo *II)

Builds a specifier combining a prefix and an identifier.

void Profile(llvm::FoldingSetNodeID &ID) const

NamespaceAliasDecl * getAsNamespaceAlias() const

Retrieve the namespace alias stored in this nested name specifier.

IdentifierInfo * getAsIdentifier() const

Retrieve the identifier stored in this nested name specifier.

static NestedNameSpecifier * GlobalSpecifier(const ASTContext &Context)

Returns the nested name specifier representing the global scope.

bool isInstantiationDependent() const

Whether this nested name specifier involves a template parameter.

NestedNameSpecifier * getPrefix() const

Return the prefix of this nested name specifier.

SpecifierKind

The kind of specifier that completes this nested name specifier.

@ NamespaceAlias

A namespace alias, stored as a NamespaceAliasDecl*.

@ TypeSpec

A type, stored as a Type*.

@ TypeSpecWithTemplate

A type that was preceded by the 'template' keyword, stored as a Type*.

@ Super

Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.

@ Identifier

An identifier, stored as an IdentifierInfo*.

@ Global

The global specifier '::'. There is no stored value.

@ Namespace

A namespace, stored as a NamespaceDecl*.

NestedNameSpecifierDependence getDependence() const

bool containsUnexpandedParameterPack() const

Whether this nested-name-specifier contains an unexpanded parameter pack (for C++11 variadic template...

NamespaceDecl * getAsNamespace() const

Retrieve the namespace stored in this nested name specifier.

void print(raw_ostream &OS, const PrintingPolicy &Policy, bool ResolveTemplateArguments=false) const

Print this nested name specifier to the given output stream.

static NestedNameSpecifier * SuperSpecifier(const ASTContext &Context, CXXRecordDecl *RD)

Returns the nested name specifier representing the __super scope for the given CXXRecordDecl.

const Type * getAsType() const

Retrieve the type stored in this nested name specifier.

A (possibly-)qualified type.

void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const

Encodes a location in the source.

static SourceLocation getFromRawEncoding(UIntTy Encoding)

Turn a raw encoding of a SourceLocation object into a real SourceLocation.

bool isValid() const

Return true if this is a valid SourceLocation object.

UIntTy getRawEncoding() const

When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getBegin() const

Represents a type template specialization; the template must be a class template, a type alias templa...

Base wrapper for a particular "section" of type source info.

void * getOpaqueData() const

Get the pointer where source information is stored.

SourceLocation getBeginLoc() const

Get the begin source location.

const Type * getTypePtr() const

A container of type source information.

TypeLoc getTypeLoc() const

Return the TypeLoc wrapper for the type source info.

The base class of the type hierarchy.

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

The JSON file list parser is used to communicate input to InstallAPI.

@ Result

The result type of a method or function.

const FunctionProtoType * T

void printTemplateArgumentList(raw_ostream &OS, ArrayRef< TemplateArgument > Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL=nullptr)

Print a template argument list, including the '<' and '>' enclosing the template arguments.

NestedNameSpecifierDependence toNestedNameSpecifierDependendence(TypeDependence D)

@ Other

Other implicit parameter.

Wraps an identifier and optional source location for the identifier.

Describes how types, statements, expressions, and declarations should be printed.

unsigned SuppressScope

Suppresses printing of scope specifiers.