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