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