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