1 //===- NestedNameSpecifier.h - C++ nested name specifiers -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the NestedNameSpecifier class, which represents 10 // a C++ nested-name-specifier. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H 15 #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H 16 17 #include "clang/AST/DependenceFlags.h" 18 #include "clang/Basic/Diagnostic.h" 19 #include "clang/Basic/SourceLocation.h" 20 #include "llvm/ADT/DenseMapInfo.h" 21 #include "llvm/ADT/FoldingSet.h" 22 #include "llvm/ADT/PointerIntPair.h" 23 #include "llvm/Support/Compiler.h" 24 #include <cstdint> 25 #include <cstdlib> 26 #include <utility> 27 28 namespace clang { 29 30 class ASTContext; 31 class CXXRecordDecl; 32 class IdentifierInfo; 33 class LangOptions; 34 class NamespaceAliasDecl; 35 class NamespaceDecl; 36 struct PrintingPolicy; 37 class Type; 38 class TypeLoc; 39 40 /// Represents a C++ nested name specifier, such as 41 /// "\::std::vector<int>::". 42 /// 43 /// C++ nested name specifiers are the prefixes to qualified 44 /// names. For example, "foo::" in "foo::x" is a nested name 45 /// specifier. Nested name specifiers are made up of a sequence of 46 /// specifiers, each of which can be a namespace, type, identifier 47 /// (for dependent names), decltype specifier, or the global specifier ('::'). 48 /// The last two specifiers can only appear at the start of a 49 /// nested-namespace-specifier. 50 class NestedNameSpecifier : public llvm::FoldingSetNode { 51 /// Enumeration describing 52 enum StoredSpecifierKind { 53 StoredIdentifier = 0, 54 StoredDecl = 1, 55 StoredTypeSpec = 2 56 }; 57 58 /// The nested name specifier that precedes this nested name 59 /// specifier. 60 /// 61 /// The pointer is the nested-name-specifier that precedes this 62 /// one. The integer stores one of the first four values of type 63 /// SpecifierKind. 64 llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix; 65 66 /// The last component in the nested name specifier, which 67 /// can be an identifier, a declaration, or a type. 68 /// 69 /// When the pointer is NULL, this specifier represents the global 70 /// specifier '::'. Otherwise, the pointer is one of 71 /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of 72 /// specifier as encoded within the prefix. 73 void* Specifier = nullptr; 74 75 public: 76 /// The kind of specifier that completes this nested name 77 /// specifier. 78 enum SpecifierKind { 79 /// An identifier, stored as an IdentifierInfo*. 80 Identifier, 81 82 /// A namespace, stored as a NamespaceDecl*. 83 Namespace, 84 85 /// A namespace alias, stored as a NamespaceAliasDecl*. 86 NamespaceAlias, 87 88 /// A type, stored as a Type*. 89 TypeSpec, 90 91 /// The global specifier '::'. There is no stored value. 92 Global, 93 94 /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of 95 /// the class it appeared in. 96 Super 97 }; 98 99 private: 100 /// Builds the global specifier. NestedNameSpecifier()101 NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {} 102 103 /// Copy constructor used internally to clone nested name 104 /// specifiers. 105 NestedNameSpecifier(const NestedNameSpecifier &Other) = default; 106 107 /// Either find or insert the given nested name specifier 108 /// mockup in the given context. 109 static NestedNameSpecifier *FindOrInsert(const ASTContext &Context, 110 const NestedNameSpecifier &Mockup); 111 112 public: 113 NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete; 114 115 /// Builds a specifier combining a prefix and an identifier. 116 /// 117 /// The prefix must be dependent, since nested name specifiers 118 /// referencing an identifier are only permitted when the identifier 119 /// cannot be resolved. 120 static NestedNameSpecifier *Create(const ASTContext &Context, 121 NestedNameSpecifier *Prefix, 122 const IdentifierInfo *II); 123 124 /// Builds a nested name specifier that names a namespace. 125 static NestedNameSpecifier *Create(const ASTContext &Context, 126 NestedNameSpecifier *Prefix, 127 const NamespaceDecl *NS); 128 129 /// Builds a nested name specifier that names a namespace alias. 130 static NestedNameSpecifier *Create(const ASTContext &Context, 131 NestedNameSpecifier *Prefix, 132 const NamespaceAliasDecl *Alias); 133 134 /// Builds a nested name specifier that names a type. 135 static NestedNameSpecifier * 136 Create(const ASTContext &Context, NestedNameSpecifier *Prefix, const Type *T); 137 138 /// Builds a specifier that consists of just an identifier. 139 /// 140 /// The nested-name-specifier is assumed to be dependent, but has no 141 /// prefix because the prefix is implied by something outside of the 142 /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent 143 /// type. 144 static NestedNameSpecifier *Create(const ASTContext &Context, 145 const IdentifierInfo *II); 146 147 /// Returns the nested name specifier representing the global 148 /// scope. 149 static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); 150 151 /// Returns the nested name specifier representing the __super scope 152 /// for the given CXXRecordDecl. 153 static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context, 154 CXXRecordDecl *RD); 155 156 /// Return the prefix of this nested name specifier. 157 /// 158 /// The prefix contains all of the parts of the nested name 159 /// specifier that precede this current specifier. For example, for a 160 /// nested name specifier that represents "foo::bar::", the current 161 /// specifier will contain "bar::" and the prefix will contain 162 /// "foo::". getPrefix()163 NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } 164 165 /// Determine what kind of nested name specifier is stored. 166 SpecifierKind getKind() const; 167 168 /// Retrieve the identifier stored in this nested name 169 /// specifier. getAsIdentifier()170 IdentifierInfo *getAsIdentifier() const { 171 if (Prefix.getInt() == StoredIdentifier) 172 return (IdentifierInfo *)Specifier; 173 174 return nullptr; 175 } 176 177 /// Retrieve the namespace stored in this nested name 178 /// specifier. 179 NamespaceDecl *getAsNamespace() const; 180 181 /// Retrieve the namespace alias stored in this nested name 182 /// specifier. 183 NamespaceAliasDecl *getAsNamespaceAlias() const; 184 185 /// Retrieve the record declaration stored in this nested name 186 /// specifier. 187 CXXRecordDecl *getAsRecordDecl() const; 188 189 /// Retrieve the type stored in this nested name specifier. getAsType()190 const Type *getAsType() const { 191 if (Prefix.getInt() == StoredTypeSpec) 192 return (const Type *)Specifier; 193 194 return nullptr; 195 } 196 197 /// Fully translate this nested name specifier to a type. 198 /// Unlike getAsType, this will convert this entire nested 199 /// name specifier chain into its equivalent type. 200 const Type *translateToType(const ASTContext &Context) const; 201 202 NestedNameSpecifierDependence getDependence() const; 203 204 /// Whether this nested name specifier refers to a dependent 205 /// type or not. 206 bool isDependent() const; 207 208 /// Whether this nested name specifier involves a template 209 /// parameter. 210 bool isInstantiationDependent() const; 211 212 /// Whether this nested-name-specifier contains an unexpanded 213 /// parameter pack (for C++11 variadic templates). 214 bool containsUnexpandedParameterPack() const; 215 216 /// Whether this nested name specifier contains an error. 217 bool containsErrors() const; 218 219 /// Print this nested name specifier to the given output stream. If 220 /// `ResolveTemplateArguments` is true, we'll print actual types, e.g. 221 /// `ns::SomeTemplate<int, MyClass>` instead of 222 /// `ns::SomeTemplate<Container::value_type, T>`. 223 void print(raw_ostream &OS, const PrintingPolicy &Policy, 224 bool ResolveTemplateArguments = false, 225 bool PrintFinalScopeResOp = true) const; 226 Profile(llvm::FoldingSetNodeID & ID)227 void Profile(llvm::FoldingSetNodeID &ID) const { 228 ID.AddPointer(Prefix.getOpaqueValue()); 229 ID.AddPointer(Specifier); 230 } 231 232 /// Dump the nested name specifier to standard output to aid 233 /// in debugging. 234 void dump(const LangOptions &LO) const; 235 void dump() const; 236 void dump(llvm::raw_ostream &OS) const; 237 void dump(llvm::raw_ostream &OS, const LangOptions &LO) const; 238 }; 239 240 /// A C++ nested-name-specifier augmented with source location 241 /// information. 242 class NestedNameSpecifierLoc { 243 NestedNameSpecifier *Qualifier = nullptr; 244 void *Data = nullptr; 245 246 /// Determines the data length for the last component in the 247 /// given nested-name-specifier. 248 static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier); 249 250 /// Determines the data length for the entire 251 /// nested-name-specifier. 252 static unsigned getDataLength(NestedNameSpecifier *Qualifier); 253 254 public: 255 /// Construct an empty nested-name-specifier. 256 NestedNameSpecifierLoc() = default; 257 258 /// Construct a nested-name-specifier with source location information 259 /// from NestedNameSpecifierLoc(NestedNameSpecifier * Qualifier,void * Data)260 NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data) 261 : Qualifier(Qualifier), Data(Data) {} 262 263 /// Evaluates true when this nested-name-specifier location is 264 /// non-empty. 265 explicit operator bool() const { return Qualifier; } 266 267 /// Evaluates true when this nested-name-specifier location is 268 /// non-empty. hasQualifier()269 bool hasQualifier() const { return Qualifier; } 270 271 /// Retrieve the nested-name-specifier to which this instance 272 /// refers. getNestedNameSpecifier()273 NestedNameSpecifier *getNestedNameSpecifier() const { 274 return Qualifier; 275 } 276 277 /// Retrieve the opaque pointer that refers to source-location data. getOpaqueData()278 void *getOpaqueData() const { return Data; } 279 280 /// Retrieve the source range covering the entirety of this 281 /// nested-name-specifier. 282 /// 283 /// For example, if this instance refers to a nested-name-specifier 284 /// \c \::std::vector<int>::, the returned source range would cover 285 /// from the initial '::' to the last '::'. getSourceRange()286 SourceRange getSourceRange() const LLVM_READONLY { 287 return SourceRange(getBeginLoc(), getEndLoc()); 288 } 289 290 /// Retrieve the source range covering just the last part of 291 /// this nested-name-specifier, not including the prefix. 292 /// 293 /// For example, if this instance refers to a nested-name-specifier 294 /// \c \::std::vector<int>::, the returned source range would cover 295 /// from "vector" to the last '::'. 296 SourceRange getLocalSourceRange() const; 297 298 /// Retrieve the location of the beginning of this 299 /// nested-name-specifier. getBeginLoc()300 SourceLocation getBeginLoc() const { 301 if (!Qualifier) 302 return SourceLocation(); 303 304 NestedNameSpecifierLoc First = *this; 305 while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 306 First = Prefix; 307 return First.getLocalSourceRange().getBegin(); 308 } 309 310 /// Retrieve the location of the end of this 311 /// nested-name-specifier. getEndLoc()312 SourceLocation getEndLoc() const { return getLocalSourceRange().getEnd(); } 313 314 /// Retrieve the location of the beginning of this 315 /// component of the nested-name-specifier. getLocalBeginLoc()316 SourceLocation getLocalBeginLoc() const { 317 return getLocalSourceRange().getBegin(); 318 } 319 320 /// Retrieve the location of the end of this component of the 321 /// nested-name-specifier. getLocalEndLoc()322 SourceLocation getLocalEndLoc() const { 323 return getLocalSourceRange().getEnd(); 324 } 325 326 /// Return the prefix of this nested-name-specifier. 327 /// 328 /// For example, if this instance refers to a nested-name-specifier 329 /// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the 330 /// returned prefix may be empty, if this is the first component of 331 /// the nested-name-specifier. getPrefix()332 NestedNameSpecifierLoc getPrefix() const { 333 if (!Qualifier) 334 return *this; 335 336 return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data); 337 } 338 339 /// For a nested-name-specifier that refers to a type, 340 /// retrieve the type with source-location information. 341 TypeLoc getTypeLoc() const; 342 343 /// Determines the data length for the entire 344 /// nested-name-specifier. getDataLength()345 unsigned getDataLength() const { return getDataLength(Qualifier); } 346 347 friend bool operator==(NestedNameSpecifierLoc X, 348 NestedNameSpecifierLoc Y) { 349 return X.Qualifier == Y.Qualifier && X.Data == Y.Data; 350 } 351 352 friend bool operator!=(NestedNameSpecifierLoc X, 353 NestedNameSpecifierLoc Y) { 354 return !(X == Y); 355 } 356 }; 357 358 /// Class that aids in the construction of nested-name-specifiers along 359 /// with source-location information for all of the components of the 360 /// nested-name-specifier. 361 class NestedNameSpecifierLocBuilder { 362 /// The current representation of the nested-name-specifier we're 363 /// building. 364 NestedNameSpecifier *Representation = nullptr; 365 366 /// Buffer used to store source-location information for the 367 /// nested-name-specifier. 368 /// 369 /// Note that we explicitly manage the buffer (rather than using a 370 /// SmallVector) because \c Declarator expects it to be possible to memcpy() 371 /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. 372 char *Buffer = nullptr; 373 374 /// The size of the buffer used to store source-location information 375 /// for the nested-name-specifier. 376 unsigned BufferSize = 0; 377 378 /// The capacity of the buffer used to store source-location 379 /// information for the nested-name-specifier. 380 unsigned BufferCapacity = 0; 381 382 public: 383 NestedNameSpecifierLocBuilder() = default; 384 NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); 385 386 NestedNameSpecifierLocBuilder & 387 operator=(const NestedNameSpecifierLocBuilder &Other); 388 ~NestedNameSpecifierLocBuilder()389 ~NestedNameSpecifierLocBuilder() { 390 if (BufferCapacity) 391 free(Buffer); 392 } 393 394 /// Retrieve the representation of the nested-name-specifier. getRepresentation()395 NestedNameSpecifier *getRepresentation() const { return Representation; } 396 397 /// Extend the current nested-name-specifier by another 398 /// nested-name-specifier component of the form 'type::'. 399 /// 400 /// \param Context The AST context in which this nested-name-specifier 401 /// resides. 402 /// 403 /// \param TL The TypeLoc that describes the type preceding the '::'. 404 /// 405 /// \param ColonColonLoc The location of the trailing '::'. 406 void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc); 407 408 /// Extend the current nested-name-specifier by another 409 /// nested-name-specifier component of the form 'identifier::'. 410 /// 411 /// \param Context The AST context in which this nested-name-specifier 412 /// resides. 413 /// 414 /// \param Identifier The identifier. 415 /// 416 /// \param IdentifierLoc The location of the identifier. 417 /// 418 /// \param ColonColonLoc The location of the trailing '::'. 419 void Extend(ASTContext &Context, IdentifierInfo *Identifier, 420 SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); 421 422 /// Extend the current nested-name-specifier by another 423 /// nested-name-specifier component of the form 'namespace::'. 424 /// 425 /// \param Context The AST context in which this nested-name-specifier 426 /// resides. 427 /// 428 /// \param Namespace The namespace. 429 /// 430 /// \param NamespaceLoc The location of the namespace name. 431 /// 432 /// \param ColonColonLoc The location of the trailing '::'. 433 void Extend(ASTContext &Context, NamespaceDecl *Namespace, 434 SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); 435 436 /// Extend the current nested-name-specifier by another 437 /// nested-name-specifier component of the form 'namespace-alias::'. 438 /// 439 /// \param Context The AST context in which this nested-name-specifier 440 /// resides. 441 /// 442 /// \param Alias The namespace alias. 443 /// 444 /// \param AliasLoc The location of the namespace alias 445 /// name. 446 /// 447 /// \param ColonColonLoc The location of the trailing '::'. 448 void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, 449 SourceLocation AliasLoc, SourceLocation ColonColonLoc); 450 451 /// Turn this (empty) nested-name-specifier into the global 452 /// nested-name-specifier '::'. 453 void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); 454 455 /// Turns this (empty) nested-name-specifier into '__super' 456 /// nested-name-specifier. 457 /// 458 /// \param Context The AST context in which this nested-name-specifier 459 /// resides. 460 /// 461 /// \param RD The declaration of the class in which nested-name-specifier 462 /// appeared. 463 /// 464 /// \param SuperLoc The location of the '__super' keyword. 465 /// name. 466 /// 467 /// \param ColonColonLoc The location of the trailing '::'. 468 void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, 469 SourceLocation SuperLoc, SourceLocation ColonColonLoc); 470 471 /// Make a new nested-name-specifier from incomplete source-location 472 /// information. 473 /// 474 /// This routine should be used very, very rarely, in cases where we 475 /// need to synthesize a nested-name-specifier. Most code should instead use 476 /// \c Adopt() with a proper \c NestedNameSpecifierLoc. 477 void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, 478 SourceRange R); 479 480 /// Adopt an existing nested-name-specifier (with source-range 481 /// information). 482 void Adopt(NestedNameSpecifierLoc Other); 483 484 /// Retrieve the source range covered by this nested-name-specifier. getSourceRange()485 SourceRange getSourceRange() const LLVM_READONLY { 486 return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); 487 } 488 489 /// Retrieve a nested-name-specifier with location information, 490 /// copied into the given AST context. 491 /// 492 /// \param Context The context into which this nested-name-specifier will be 493 /// copied. 494 NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; 495 496 /// Retrieve a nested-name-specifier with location 497 /// information based on the information in this builder. 498 /// 499 /// This loc will contain references to the builder's internal data and may 500 /// be invalidated by any change to the builder. getTemporary()501 NestedNameSpecifierLoc getTemporary() const { 502 return NestedNameSpecifierLoc(Representation, Buffer); 503 } 504 505 /// Clear out this builder, and prepare it to build another 506 /// nested-name-specifier with source-location information. Clear()507 void Clear() { 508 Representation = nullptr; 509 BufferSize = 0; 510 } 511 512 /// Retrieve the underlying buffer. 513 /// 514 /// \returns A pair containing a pointer to the buffer of source-location 515 /// data and the size of the source-location data that resides in that 516 /// buffer. getBuffer()517 std::pair<char *, unsigned> getBuffer() const { 518 return std::make_pair(Buffer, BufferSize); 519 } 520 }; 521 522 /// Insertion operator for diagnostics. This allows sending 523 /// NestedNameSpecifiers into a diagnostic with <<. 524 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, 525 NestedNameSpecifier *NNS) { 526 DB.AddTaggedVal(reinterpret_cast<uint64_t>(NNS), 527 DiagnosticsEngine::ak_nestednamespec); 528 return DB; 529 } 530 531 } // namespace clang 532 533 namespace llvm { 534 535 template <> struct DenseMapInfo<clang::NestedNameSpecifierLoc> { 536 using FirstInfo = DenseMapInfo<clang::NestedNameSpecifier *>; 537 using SecondInfo = DenseMapInfo<void *>; 538 539 static clang::NestedNameSpecifierLoc getEmptyKey() { 540 return clang::NestedNameSpecifierLoc(FirstInfo::getEmptyKey(), 541 SecondInfo::getEmptyKey()); 542 } 543 544 static clang::NestedNameSpecifierLoc getTombstoneKey() { 545 return clang::NestedNameSpecifierLoc(FirstInfo::getTombstoneKey(), 546 SecondInfo::getTombstoneKey()); 547 } 548 549 static unsigned getHashValue(const clang::NestedNameSpecifierLoc &PairVal) { 550 return hash_combine( 551 FirstInfo::getHashValue(PairVal.getNestedNameSpecifier()), 552 SecondInfo::getHashValue(PairVal.getOpaqueData())); 553 } 554 555 static bool isEqual(const clang::NestedNameSpecifierLoc &LHS, 556 const clang::NestedNameSpecifierLoc &RHS) { 557 return LHS == RHS; 558 } 559 }; 560 } // namespace llvm 561 562 #endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H 563