clang 24.0.0git
NestedNameSpecifier.h
Go to the documentation of this file.
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 completes the definition of the NestedNameSpecifier class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
14#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
15
16#include "clang/AST/Decl.h"
18#include "clang/AST/Type.h"
19#include "clang/AST/TypeLoc.h"
20#include "llvm/ADT/DenseMapInfo.h"
21
22namespace clang {
23
25 if (!isStoredKind()) {
26 switch (getFlagKind()) {
27 case FlagKind::Null:
28 return Kind::Null;
29 case FlagKind::Global:
30 return Kind::Global;
31 }
32 llvm_unreachable("unhandled FlagKind");
33 }
34 switch (auto [K, Ptr] = getStored(); K) {
35 case StoredKind::Type:
36 return Kind::Type;
37 case StoredKind::NamespaceWithGlobal:
38 case StoredKind::NamespaceWithNamespace:
39 return Kind::Namespace;
40 case StoredKind::NamespaceOrSuper:
41 switch (static_cast<const Decl *>(Ptr)->getKind()) {
42 case Decl::Namespace:
43 case Decl::NamespaceAlias:
44 return Kind::Namespace;
45 case Decl::CXXRecord:
46 case Decl::ClassTemplateSpecialization:
47 case Decl::ClassTemplatePartialSpecialization:
49 default:
50 llvm_unreachable("unexpected decl kind");
51 }
52 }
53 llvm_unreachable("unknown StoredKind");
54}
55
57 : NestedNameSpecifier({StoredKind::Type, T}) {
58 assert(getKind() == Kind::Type);
59}
60
61auto NestedNameSpecifier::MakeNamespacePtrKind(
62 const ASTContext &Ctx, const NamespaceBaseDecl *Namespace,
63 NestedNameSpecifier Prefix) -> PtrKind {
64 switch (Prefix.getKind()) {
65 case Kind::Null:
66 return {StoredKind::NamespaceOrSuper, Namespace};
67 case Kind::Global:
68 return {StoredKind::NamespaceWithGlobal, Namespace};
69 case Kind::Namespace:
70 return {StoredKind::NamespaceWithNamespace,
71 MakeNamespaceAndPrefixStorage(Ctx, Namespace, Prefix)};
72 case Kind::MicrosoftSuper:
73 case Kind::Type:
74 llvm_unreachable("invalid prefix for namespace");
75 }
76 llvm_unreachable("unhandled kind");
77}
78
79/// Builds a nested name specifier that names a namespace.
82 NestedNameSpecifier Prefix)
83 : NestedNameSpecifier(MakeNamespacePtrKind(Ctx, Namespace, Prefix)) {
84 assert(getKind() == Kind::Namespace);
85}
86
87/// Builds a nested name specifier that names a class through microsoft's
88/// __super specifier.
90 : NestedNameSpecifier({StoredKind::NamespaceOrSuper, RD}) {
91 assert(getKind() == Kind::MicrosoftSuper);
92}
93
95 switch (getKind()) {
97 return getAsMicrosoftSuper();
98 case Kind::Type:
99 return getAsType()->getAsCXXRecordDecl();
100 case Kind::Global:
101 case Kind::Namespace:
102 case Kind::Null:
103 return nullptr;
104 }
105 llvm_unreachable("Invalid NNS Kind!");
106}
107
108NestedNameSpecifier NestedNameSpecifier::getCanonical() const {
109 switch (getKind()) {
113 // These are canonical and unique.
114 return *this;
116 // A namespace is canonical; build a nested-name-specifier with
117 // this namespace and no prefix.
119 return NestedNameSpecifier(
120 {StoredKind::NamespaceOrSuper, ND->getNamespace()->getCanonicalDecl()});
121 }
123 return NestedNameSpecifier(
124 getAsType()->getCanonicalTypeInternal().getTypePtr());
125 }
126 llvm_unreachable("unhandled kind");
127}
128
130 return *this == getCanonical();
131}
132
134 return TypeLoc(Qualifier.getAsType(), LoadPointer(/*Offset=*/0));
135}
136
138 if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type)
139 return TypeLoc();
140 return castAsTypeLoc();
141}
142
143unsigned
144NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier Qualifier) {
145 // Location of the trailing '::'.
146 unsigned Length = sizeof(SourceLocation::UIntTy);
147
148 switch (Qualifier.getKind()) {
150 // Nothing more to add.
151 break;
152
155 // The location of the identifier or namespace name.
156 Length += sizeof(SourceLocation::UIntTy);
157 break;
158
160 // The "void*" that points at the TypeLoc data.
161 // Note: the 'template' keyword is part of the TypeLoc.
162 Length += sizeof(void *);
163 break;
164
166 llvm_unreachable("Expected a non-NULL qualifier");
167 }
168
169 return Length;
170}
171
173 auto [Namespace, Prefix] = Qualifier.getAsNamespaceAndPrefix();
174 return {Namespace, NestedNameSpecifierLoc(Prefix, Data)};
175}
176
182
184 unsigned Length = 0;
185 for (; Qualifier; Qualifier = Qualifier.getAsNamespaceAndPrefix().Prefix) {
186 Length += getLocalDataLength(Qualifier);
187 if (Qualifier.getKind() != NestedNameSpecifier::Kind::Namespace)
188 break;
189 }
190 return Length;
191}
192
194 return getDataLength(Qualifier);
195}
196
198 switch (auto Kind = Qualifier.getKind()) {
200 return SourceRange();
202 return LoadSourceLocation(/*Offset=*/0);
205 unsigned Offset =
207 ? getDataLength(Qualifier.getAsNamespaceAndPrefix().Prefix)
208 : 0;
209 return SourceRange(
210 LoadSourceLocation(Offset),
211 LoadSourceLocation(Offset + sizeof(SourceLocation::UIntTy)));
212 }
214 // The "void*" that points at the TypeLoc data.
215 // Note: the 'template' keyword is part of the TypeLoc.
216 void *TypeData = LoadPointer(/*Offset=*/0);
217 TypeLoc TL(Qualifier.getAsType(), TypeData);
218 return SourceRange(TL.getBeginLoc(), LoadSourceLocation(sizeof(void *)));
219 }
220 }
221
222 llvm_unreachable("Invalid NNS Kind!");
223}
224
228
232
233/// Retrieve the location of the beginning of this
234/// component of the nested-name-specifier.
238
239/// Retrieve the location of the end of this component of the
240/// nested-name-specifier.
244
248
249} // namespace clang
250
251namespace llvm {
252
253template <> struct DenseMapInfo<clang::NestedNameSpecifier> {
254 static unsigned getHashValue(const clang::NestedNameSpecifier &V) {
255 return hash_combine(V.getAsVoidPointer());
256 }
257};
258
259template <> struct DenseMapInfo<clang::NestedNameSpecifierLoc> {
260 using FirstInfo = DenseMapInfo<clang::NestedNameSpecifier>;
261 using SecondInfo = DenseMapInfo<void *>;
262
263 static unsigned getHashValue(const clang::NestedNameSpecifierLoc &PairVal) {
264 return hash_combine(
266 SecondInfo::getHashValue(PairVal.getOpaqueData()));
267 }
268
271 return LHS == RHS;
272 }
273};
274} // namespace llvm
275
276#endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#define V(N, I)
static Decl::Kind getKind(const Decl *D)
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
Represents C++ namespaces and their aliases.
Definition Decl.h:574
NamespaceDecl * getNamespace()
Definition DeclCXX.cpp:3351
NamespaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this namespace.
Definition Decl.h:685
SourceRange getSourceRange() const LLVM_READONLY
Retrieve the source range covered by this nested-name-specifier.
A C++ nested-name-specifier augmented with source location information.
NamespaceAndPrefixLoc getAsNamespaceAndPrefix() const
NestedNameSpecifier getNestedNameSpecifier() const
Retrieve the nested-name-specifier to which this instance refers.
SourceLocation getLocalEndLoc() const
Retrieve the location of the end of this component of the nested-name-specifier.
SourceRange getSourceRange() const LLVM_READONLY
Retrieve the source range covering the entirety of this nested-name-specifier.
NestedNameSpecifierLoc()=default
Construct an empty nested-name-specifier.
NamespaceAndPrefixLoc castAsNamespaceAndPrefix() const
For a nested-name-specifier that refers to a namespace, retrieve the namespace and its prefix.
SourceLocation getEndLoc() const
Retrieve the location of the end of this nested-name-specifier.
SourceLocation getBeginLoc() const
Retrieve the location of the beginning of this nested-name-specifier.
TypeLoc castAsTypeLoc() const
For a nested-name-specifier that refers to a type, retrieve the type with source-location information...
void * getOpaqueData() const
Retrieve the opaque pointer that refers to source-location data.
SourceRange getLocalSourceRange() const
Retrieve the source range covering just the last part of this nested-name-specifier,...
SourceLocation getLocalBeginLoc() const
Retrieve the location of the beginning of this component of the nested-name-specifier.
unsigned getDataLength() const
Determines the data length for the entire nested-name-specifier.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
NestedNameSpecifier getCanonical() const
Retrieves the "canonical" nested name specifier for a given nested name specifier.
CXXRecordDecl * getAsMicrosoftSuper() const
NamespaceAndPrefix getAsNamespaceAndPrefix() const
bool isCanonical() const
Whether this nested name specifier is canonical.
CXXRecordDecl * getAsRecordDecl() const
Retrieve the record declaration stored in this nested name specifier, or null.
Kind
The kind of specifier that completes this nested name specifier.
@ MicrosoftSuper
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Global
The global specifier '::'. There is no stored value.
@ Namespace
A namespace-like entity, stored as a NamespaceBaseDecl*.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Base wrapper for a particular "section" of type source info.
Definition TypeLoc.h:59
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
Top level wrappers for InstallAPI frontend operations.
const FunctionProtoType * T
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
const NamespaceBaseDecl * Namespace
static bool isEqual(const clang::NestedNameSpecifierLoc &LHS, const clang::NestedNameSpecifierLoc &RHS)
static unsigned getHashValue(const clang::NestedNameSpecifierLoc &PairVal)
DenseMapInfo< clang::NestedNameSpecifier > FirstInfo
static unsigned getHashValue(const clang::NestedNameSpecifier &V)