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