|
|
|||
File indexing completed on 2026-05-10 08:36:38
0001 //===- NestedNameSpecifier.h - C++ nested name specifiers -------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 // 0009 // This file defines the NestedNameSpecifier class, which represents 0010 // a C++ nested-name-specifier. 0011 // 0012 //===----------------------------------------------------------------------===// 0013 0014 #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H 0015 #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H 0016 0017 #include "clang/AST/DependenceFlags.h" 0018 #include "clang/Basic/Diagnostic.h" 0019 #include "clang/Basic/SourceLocation.h" 0020 #include "llvm/ADT/DenseMapInfo.h" 0021 #include "llvm/ADT/FoldingSet.h" 0022 #include "llvm/ADT/PointerIntPair.h" 0023 #include "llvm/Support/Compiler.h" 0024 #include <cstdint> 0025 #include <cstdlib> 0026 #include <utility> 0027 0028 namespace clang { 0029 0030 class ASTContext; 0031 class CXXRecordDecl; 0032 class IdentifierInfo; 0033 class LangOptions; 0034 class NamespaceAliasDecl; 0035 class NamespaceDecl; 0036 struct PrintingPolicy; 0037 class Type; 0038 class TypeLoc; 0039 0040 /// Represents a C++ nested name specifier, such as 0041 /// "\::std::vector<int>::". 0042 /// 0043 /// C++ nested name specifiers are the prefixes to qualified 0044 /// names. For example, "foo::" in "foo::x" is a nested name 0045 /// specifier. Nested name specifiers are made up of a sequence of 0046 /// specifiers, each of which can be a namespace, type, identifier 0047 /// (for dependent names), decltype specifier, or the global specifier ('::'). 0048 /// The last two specifiers can only appear at the start of a 0049 /// nested-namespace-specifier. 0050 class NestedNameSpecifier : public llvm::FoldingSetNode { 0051 /// Enumeration describing 0052 enum StoredSpecifierKind { 0053 StoredIdentifier = 0, 0054 StoredDecl = 1, 0055 StoredTypeSpec = 2, 0056 StoredTypeSpecWithTemplate = 3 0057 }; 0058 0059 /// The nested name specifier that precedes this nested name 0060 /// specifier. 0061 /// 0062 /// The pointer is the nested-name-specifier that precedes this 0063 /// one. The integer stores one of the first four values of type 0064 /// SpecifierKind. 0065 llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix; 0066 0067 /// The last component in the nested name specifier, which 0068 /// can be an identifier, a declaration, or a type. 0069 /// 0070 /// When the pointer is NULL, this specifier represents the global 0071 /// specifier '::'. Otherwise, the pointer is one of 0072 /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of 0073 /// specifier as encoded within the prefix. 0074 void* Specifier = nullptr; 0075 0076 public: 0077 /// The kind of specifier that completes this nested name 0078 /// specifier. 0079 enum SpecifierKind { 0080 /// An identifier, stored as an IdentifierInfo*. 0081 Identifier, 0082 0083 /// A namespace, stored as a NamespaceDecl*. 0084 Namespace, 0085 0086 /// A namespace alias, stored as a NamespaceAliasDecl*. 0087 NamespaceAlias, 0088 0089 /// A type, stored as a Type*. 0090 TypeSpec, 0091 0092 /// A type that was preceded by the 'template' keyword, 0093 /// stored as a Type*. 0094 TypeSpecWithTemplate, 0095 0096 /// The global specifier '::'. There is no stored value. 0097 Global, 0098 0099 /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of 0100 /// the class it appeared in. 0101 Super 0102 }; 0103 0104 private: 0105 /// Builds the global specifier. 0106 NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {} 0107 0108 /// Copy constructor used internally to clone nested name 0109 /// specifiers. 0110 NestedNameSpecifier(const NestedNameSpecifier &Other) = default; 0111 0112 /// Either find or insert the given nested name specifier 0113 /// mockup in the given context. 0114 static NestedNameSpecifier *FindOrInsert(const ASTContext &Context, 0115 const NestedNameSpecifier &Mockup); 0116 0117 public: 0118 NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete; 0119 0120 /// Builds a specifier combining a prefix and an identifier. 0121 /// 0122 /// The prefix must be dependent, since nested name specifiers 0123 /// referencing an identifier are only permitted when the identifier 0124 /// cannot be resolved. 0125 static NestedNameSpecifier *Create(const ASTContext &Context, 0126 NestedNameSpecifier *Prefix, 0127 const IdentifierInfo *II); 0128 0129 /// Builds a nested name specifier that names a namespace. 0130 static NestedNameSpecifier *Create(const ASTContext &Context, 0131 NestedNameSpecifier *Prefix, 0132 const NamespaceDecl *NS); 0133 0134 /// Builds a nested name specifier that names a namespace alias. 0135 static NestedNameSpecifier *Create(const ASTContext &Context, 0136 NestedNameSpecifier *Prefix, 0137 const NamespaceAliasDecl *Alias); 0138 0139 /// Builds a nested name specifier that names a type. 0140 static NestedNameSpecifier *Create(const ASTContext &Context, 0141 NestedNameSpecifier *Prefix, 0142 bool Template, const Type *T); 0143 0144 /// Builds a specifier that consists of just an identifier. 0145 /// 0146 /// The nested-name-specifier is assumed to be dependent, but has no 0147 /// prefix because the prefix is implied by something outside of the 0148 /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent 0149 /// type. 0150 static NestedNameSpecifier *Create(const ASTContext &Context, 0151 const IdentifierInfo *II); 0152 0153 /// Returns the nested name specifier representing the global 0154 /// scope. 0155 static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); 0156 0157 /// Returns the nested name specifier representing the __super scope 0158 /// for the given CXXRecordDecl. 0159 static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context, 0160 CXXRecordDecl *RD); 0161 0162 /// Return the prefix of this nested name specifier. 0163 /// 0164 /// The prefix contains all of the parts of the nested name 0165 /// specifier that precede this current specifier. For example, for a 0166 /// nested name specifier that represents "foo::bar::", the current 0167 /// specifier will contain "bar::" and the prefix will contain 0168 /// "foo::". 0169 NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } 0170 0171 /// Determine what kind of nested name specifier is stored. 0172 SpecifierKind getKind() const; 0173 0174 /// Retrieve the identifier stored in this nested name 0175 /// specifier. 0176 IdentifierInfo *getAsIdentifier() const { 0177 if (Prefix.getInt() == StoredIdentifier) 0178 return (IdentifierInfo *)Specifier; 0179 0180 return nullptr; 0181 } 0182 0183 /// Retrieve the namespace stored in this nested name 0184 /// specifier. 0185 NamespaceDecl *getAsNamespace() const; 0186 0187 /// Retrieve the namespace alias stored in this nested name 0188 /// specifier. 0189 NamespaceAliasDecl *getAsNamespaceAlias() const; 0190 0191 /// Retrieve the record declaration stored in this nested name 0192 /// specifier. 0193 CXXRecordDecl *getAsRecordDecl() const; 0194 0195 /// Retrieve the type stored in this nested name specifier. 0196 const Type *getAsType() const { 0197 if (Prefix.getInt() == StoredTypeSpec || 0198 Prefix.getInt() == StoredTypeSpecWithTemplate) 0199 return (const Type *)Specifier; 0200 0201 return nullptr; 0202 } 0203 0204 NestedNameSpecifierDependence getDependence() const; 0205 0206 /// Whether this nested name specifier refers to a dependent 0207 /// type or not. 0208 bool isDependent() const; 0209 0210 /// Whether this nested name specifier involves a template 0211 /// parameter. 0212 bool isInstantiationDependent() const; 0213 0214 /// Whether this nested-name-specifier contains an unexpanded 0215 /// parameter pack (for C++11 variadic templates). 0216 bool containsUnexpandedParameterPack() const; 0217 0218 /// Whether this nested name specifier contains an error. 0219 bool containsErrors() const; 0220 0221 /// Print this nested name specifier to the given output stream. If 0222 /// `ResolveTemplateArguments` is true, we'll print actual types, e.g. 0223 /// `ns::SomeTemplate<int, MyClass>` instead of 0224 /// `ns::SomeTemplate<Container::value_type, T>`. 0225 void print(raw_ostream &OS, const PrintingPolicy &Policy, 0226 bool ResolveTemplateArguments = false) const; 0227 0228 void Profile(llvm::FoldingSetNodeID &ID) const { 0229 ID.AddPointer(Prefix.getOpaqueValue()); 0230 ID.AddPointer(Specifier); 0231 } 0232 0233 /// Dump the nested name specifier to standard output to aid 0234 /// in debugging. 0235 void dump(const LangOptions &LO) const; 0236 void dump() const; 0237 void dump(llvm::raw_ostream &OS) const; 0238 void dump(llvm::raw_ostream &OS, const LangOptions &LO) const; 0239 }; 0240 0241 /// A C++ nested-name-specifier augmented with source location 0242 /// information. 0243 class NestedNameSpecifierLoc { 0244 NestedNameSpecifier *Qualifier = nullptr; 0245 void *Data = nullptr; 0246 0247 /// Determines the data length for the last component in the 0248 /// given nested-name-specifier. 0249 static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier); 0250 0251 /// Determines the data length for the entire 0252 /// nested-name-specifier. 0253 static unsigned getDataLength(NestedNameSpecifier *Qualifier); 0254 0255 public: 0256 /// Construct an empty nested-name-specifier. 0257 NestedNameSpecifierLoc() = default; 0258 0259 /// Construct a nested-name-specifier with source location information 0260 /// from 0261 NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data) 0262 : Qualifier(Qualifier), Data(Data) {} 0263 0264 /// Evaluates true when this nested-name-specifier location is 0265 /// non-empty. 0266 explicit operator bool() const { return Qualifier; } 0267 0268 /// Evaluates true when this nested-name-specifier location is 0269 /// non-empty. 0270 bool hasQualifier() const { return Qualifier; } 0271 0272 /// Retrieve the nested-name-specifier to which this instance 0273 /// refers. 0274 NestedNameSpecifier *getNestedNameSpecifier() const { 0275 return Qualifier; 0276 } 0277 0278 /// Retrieve the opaque pointer that refers to source-location data. 0279 void *getOpaqueData() const { return Data; } 0280 0281 /// Retrieve the source range covering the entirety of this 0282 /// nested-name-specifier. 0283 /// 0284 /// For example, if this instance refers to a nested-name-specifier 0285 /// \c \::std::vector<int>::, the returned source range would cover 0286 /// from the initial '::' to the last '::'. 0287 SourceRange getSourceRange() const LLVM_READONLY; 0288 0289 /// Retrieve the source range covering just the last part of 0290 /// this nested-name-specifier, not including the prefix. 0291 /// 0292 /// For example, if this instance refers to a nested-name-specifier 0293 /// \c \::std::vector<int>::, the returned source range would cover 0294 /// from "vector" to the last '::'. 0295 SourceRange getLocalSourceRange() const; 0296 0297 /// Retrieve the location of the beginning of this 0298 /// nested-name-specifier. 0299 SourceLocation getBeginLoc() const { 0300 return getSourceRange().getBegin(); 0301 } 0302 0303 /// Retrieve the location of the end of this 0304 /// nested-name-specifier. 0305 SourceLocation getEndLoc() const { 0306 return getSourceRange().getEnd(); 0307 } 0308 0309 /// Retrieve the location of the beginning of this 0310 /// component of the nested-name-specifier. 0311 SourceLocation getLocalBeginLoc() const { 0312 return getLocalSourceRange().getBegin(); 0313 } 0314 0315 /// Retrieve the location of the end of this component of the 0316 /// nested-name-specifier. 0317 SourceLocation getLocalEndLoc() const { 0318 return getLocalSourceRange().getEnd(); 0319 } 0320 0321 /// Return the prefix of this nested-name-specifier. 0322 /// 0323 /// For example, if this instance refers to a nested-name-specifier 0324 /// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the 0325 /// returned prefix may be empty, if this is the first component of 0326 /// the nested-name-specifier. 0327 NestedNameSpecifierLoc getPrefix() const { 0328 if (!Qualifier) 0329 return *this; 0330 0331 return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data); 0332 } 0333 0334 /// For a nested-name-specifier that refers to a type, 0335 /// retrieve the type with source-location information. 0336 TypeLoc getTypeLoc() const; 0337 0338 /// Determines the data length for the entire 0339 /// nested-name-specifier. 0340 unsigned getDataLength() const { return getDataLength(Qualifier); } 0341 0342 friend bool operator==(NestedNameSpecifierLoc X, 0343 NestedNameSpecifierLoc Y) { 0344 return X.Qualifier == Y.Qualifier && X.Data == Y.Data; 0345 } 0346 0347 friend bool operator!=(NestedNameSpecifierLoc X, 0348 NestedNameSpecifierLoc Y) { 0349 return !(X == Y); 0350 } 0351 }; 0352 0353 /// Class that aids in the construction of nested-name-specifiers along 0354 /// with source-location information for all of the components of the 0355 /// nested-name-specifier. 0356 class NestedNameSpecifierLocBuilder { 0357 /// The current representation of the nested-name-specifier we're 0358 /// building. 0359 NestedNameSpecifier *Representation = nullptr; 0360 0361 /// Buffer used to store source-location information for the 0362 /// nested-name-specifier. 0363 /// 0364 /// Note that we explicitly manage the buffer (rather than using a 0365 /// SmallVector) because \c Declarator expects it to be possible to memcpy() 0366 /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. 0367 char *Buffer = nullptr; 0368 0369 /// The size of the buffer used to store source-location information 0370 /// for the nested-name-specifier. 0371 unsigned BufferSize = 0; 0372 0373 /// The capacity of the buffer used to store source-location 0374 /// information for the nested-name-specifier. 0375 unsigned BufferCapacity = 0; 0376 0377 public: 0378 NestedNameSpecifierLocBuilder() = default; 0379 NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); 0380 0381 NestedNameSpecifierLocBuilder & 0382 operator=(const NestedNameSpecifierLocBuilder &Other); 0383 0384 ~NestedNameSpecifierLocBuilder() { 0385 if (BufferCapacity) 0386 free(Buffer); 0387 } 0388 0389 /// Retrieve the representation of the nested-name-specifier. 0390 NestedNameSpecifier *getRepresentation() const { return Representation; } 0391 0392 /// Extend the current nested-name-specifier by another 0393 /// nested-name-specifier component of the form 'type::'. 0394 /// 0395 /// \param Context The AST context in which this nested-name-specifier 0396 /// resides. 0397 /// 0398 /// \param TemplateKWLoc The location of the 'template' keyword, if present. 0399 /// 0400 /// \param TL The TypeLoc that describes the type preceding the '::'. 0401 /// 0402 /// \param ColonColonLoc The location of the trailing '::'. 0403 void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, 0404 SourceLocation ColonColonLoc); 0405 0406 /// Extend the current nested-name-specifier by another 0407 /// nested-name-specifier component of the form 'identifier::'. 0408 /// 0409 /// \param Context The AST context in which this nested-name-specifier 0410 /// resides. 0411 /// 0412 /// \param Identifier The identifier. 0413 /// 0414 /// \param IdentifierLoc The location of the identifier. 0415 /// 0416 /// \param ColonColonLoc The location of the trailing '::'. 0417 void Extend(ASTContext &Context, IdentifierInfo *Identifier, 0418 SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); 0419 0420 /// Extend the current nested-name-specifier by another 0421 /// nested-name-specifier component of the form 'namespace::'. 0422 /// 0423 /// \param Context The AST context in which this nested-name-specifier 0424 /// resides. 0425 /// 0426 /// \param Namespace The namespace. 0427 /// 0428 /// \param NamespaceLoc The location of the namespace name. 0429 /// 0430 /// \param ColonColonLoc The location of the trailing '::'. 0431 void Extend(ASTContext &Context, NamespaceDecl *Namespace, 0432 SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); 0433 0434 /// Extend the current nested-name-specifier by another 0435 /// nested-name-specifier component of the form 'namespace-alias::'. 0436 /// 0437 /// \param Context The AST context in which this nested-name-specifier 0438 /// resides. 0439 /// 0440 /// \param Alias The namespace alias. 0441 /// 0442 /// \param AliasLoc The location of the namespace alias 0443 /// name. 0444 /// 0445 /// \param ColonColonLoc The location of the trailing '::'. 0446 void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, 0447 SourceLocation AliasLoc, SourceLocation ColonColonLoc); 0448 0449 /// Turn this (empty) nested-name-specifier into the global 0450 /// nested-name-specifier '::'. 0451 void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); 0452 0453 /// Turns this (empty) nested-name-specifier into '__super' 0454 /// nested-name-specifier. 0455 /// 0456 /// \param Context The AST context in which this nested-name-specifier 0457 /// resides. 0458 /// 0459 /// \param RD The declaration of the class in which nested-name-specifier 0460 /// appeared. 0461 /// 0462 /// \param SuperLoc The location of the '__super' keyword. 0463 /// name. 0464 /// 0465 /// \param ColonColonLoc The location of the trailing '::'. 0466 void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, 0467 SourceLocation SuperLoc, SourceLocation ColonColonLoc); 0468 0469 /// Make a new nested-name-specifier from incomplete source-location 0470 /// information. 0471 /// 0472 /// This routine should be used very, very rarely, in cases where we 0473 /// need to synthesize a nested-name-specifier. Most code should instead use 0474 /// \c Adopt() with a proper \c NestedNameSpecifierLoc. 0475 void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, 0476 SourceRange R); 0477 0478 /// Adopt an existing nested-name-specifier (with source-range 0479 /// information). 0480 void Adopt(NestedNameSpecifierLoc Other); 0481 0482 /// Retrieve the source range covered by this nested-name-specifier. 0483 SourceRange getSourceRange() const LLVM_READONLY { 0484 return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); 0485 } 0486 0487 /// Retrieve a nested-name-specifier with location information, 0488 /// copied into the given AST context. 0489 /// 0490 /// \param Context The context into which this nested-name-specifier will be 0491 /// copied. 0492 NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; 0493 0494 /// Retrieve a nested-name-specifier with location 0495 /// information based on the information in this builder. 0496 /// 0497 /// This loc will contain references to the builder's internal data and may 0498 /// be invalidated by any change to the builder. 0499 NestedNameSpecifierLoc getTemporary() const { 0500 return NestedNameSpecifierLoc(Representation, Buffer); 0501 } 0502 0503 /// Clear out this builder, and prepare it to build another 0504 /// nested-name-specifier with source-location information. 0505 void Clear() { 0506 Representation = nullptr; 0507 BufferSize = 0; 0508 } 0509 0510 /// Retrieve the underlying buffer. 0511 /// 0512 /// \returns A pair containing a pointer to the buffer of source-location 0513 /// data and the size of the source-location data that resides in that 0514 /// buffer. 0515 std::pair<char *, unsigned> getBuffer() const { 0516 return std::make_pair(Buffer, BufferSize); 0517 } 0518 }; 0519 0520 /// Insertion operator for diagnostics. This allows sending 0521 /// NestedNameSpecifiers into a diagnostic with <<. 0522 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, 0523 NestedNameSpecifier *NNS) { 0524 DB.AddTaggedVal(reinterpret_cast<uint64_t>(NNS), 0525 DiagnosticsEngine::ak_nestednamespec); 0526 return DB; 0527 } 0528 0529 } // namespace clang 0530 0531 namespace llvm { 0532 0533 template <> struct DenseMapInfo<clang::NestedNameSpecifierLoc> { 0534 using FirstInfo = DenseMapInfo<clang::NestedNameSpecifier *>; 0535 using SecondInfo = DenseMapInfo<void *>; 0536 0537 static clang::NestedNameSpecifierLoc getEmptyKey() { 0538 return clang::NestedNameSpecifierLoc(FirstInfo::getEmptyKey(), 0539 SecondInfo::getEmptyKey()); 0540 } 0541 0542 static clang::NestedNameSpecifierLoc getTombstoneKey() { 0543 return clang::NestedNameSpecifierLoc(FirstInfo::getTombstoneKey(), 0544 SecondInfo::getTombstoneKey()); 0545 } 0546 0547 static unsigned getHashValue(const clang::NestedNameSpecifierLoc &PairVal) { 0548 return hash_combine( 0549 FirstInfo::getHashValue(PairVal.getNestedNameSpecifier()), 0550 SecondInfo::getHashValue(PairVal.getOpaqueData())); 0551 } 0552 0553 static bool isEqual(const clang::NestedNameSpecifierLoc &LHS, 0554 const clang::NestedNameSpecifierLoc &RHS) { 0555 return LHS == RHS; 0556 } 0557 }; 0558 } // namespace llvm 0559 0560 #endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|