39#if CLANG_VERSION_MAJOR
>= 22
52inline QualType getFullyQualifiedType(QualType QT,
const ASTContext &Ctx,
53 bool WithGlobalNsPrefix);
55static inline NestedNameSpecifier
56createNestedNameSpecifier(
const ASTContext &Ctx,
const NamespaceDecl *Namesp,
57 bool WithGlobalNsPrefix);
59static inline NestedNameSpecifier
60createNestedNameSpecifier(
const ASTContext &Ctx,
const TypeDecl *TD,
61 bool FullyQualify,
bool WithGlobalNsPrefix);
63static inline NestedNameSpecifier
64createNestedNameSpecifierForScopeOf(
const ASTContext &Ctx,
const Decl *decl,
66 bool WithGlobalNsPrefix);
68static inline NestedNameSpecifier
69getFullyQualifiedNestedNameSpecifier(
const ASTContext &Ctx,
70 NestedNameSpecifier NNS,
71 bool WithGlobalNsPrefix);
73static inline bool getFullyQualifiedTemplateName(
const ASTContext &Ctx,
75 bool WithGlobalNsPrefix) {
77 NestedNameSpecifier NNS =
std::nullopt;
79 TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
83 QualifiedTemplateName *QTName = TName.getAsQualifiedTemplateName();
86 !QTName->hasTemplateKeyword() &&
87 (NNS = QTName->getQualifier())) {
88 NestedNameSpecifier QNNS =
89 getFullyQualifiedNestedNameSpecifier(Ctx, NNS, WithGlobalNsPrefix);
97 NNS = createNestedNameSpecifierForScopeOf(
98 Ctx, ArgTDecl,
true, WithGlobalNsPrefix);
101 TemplateName UnderlyingTN(ArgTDecl);
102 if (UsingShadowDecl *USD = TName.getAsUsingShadowDecl())
103 UnderlyingTN = TemplateName(USD);
105 Ctx.getQualifiedTemplateName(NNS,
106 false, UnderlyingTN);
112static inline bool getFullyQualifiedTemplateArgument(
const ASTContext &Ctx,
113 TemplateArgument &Arg,
114 bool WithGlobalNsPrefix) {
115 bool Changed =
false;
120 if (Arg.getKind() == TemplateArgument::Template) {
121 TemplateName TName = Arg.getAsTemplate();
122 Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
124 Arg = TemplateArgument(TName);
126 }
else if (Arg.getKind() == TemplateArgument::Type) {
127 QualType SubTy = Arg.getAsType();
129 QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix);
131 Arg = TemplateArgument(QTFQ);
138static inline const Type *getFullyQualifiedTemplateType(
139 const ASTContext &Ctx,
140 const TagType *TSTRecord,
141 ElaboratedTypeKeyword Keyword,
142 NestedNameSpecifier Qualifier,
143 bool WithGlobalNsPrefix) {
148 const auto *TD = TSTRecord->getDecl();
149 const auto *TSTDecl = dyn_cast<ClassTemplateSpecializationDecl>(TD);
151 return Ctx.getTagType(Keyword, Qualifier, TD,
false)
154 const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
156 bool MightHaveChanged =
false;
157 SmallVector<TemplateArgument, 4> FQArgs;
158 for (
unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
161 TemplateArgument Arg(TemplateArgs[I]);
163 getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
164 FQArgs.push_back(Arg);
167 if (!MightHaveChanged)
168 return Ctx.getTagType(Keyword, Qualifier, TD,
false)
172 TemplateName TN = Ctx.getQualifiedTemplateName(
174 TemplateName(TSTDecl->getSpecializedTemplate()));
175 QualType QT = Ctx.getTemplateSpecializationType(
177 {}, TSTRecord->getCanonicalTypeInternal());
181 return QT.getTypePtr();
184static inline const Type *
185getFullyQualifiedTemplateType(
const ASTContext &Ctx,
186 const TemplateSpecializationType *TST,
187 bool WithGlobalNsPrefix) {
188 TemplateName TName = TST->getTemplateName();
189 bool MightHaveChanged =
190 getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
191 SmallVector<TemplateArgument, 4> FQArgs;
194 for (TemplateArgument Arg : TST->template_arguments()) {
196 getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix);
197 FQArgs.push_back(Arg);
200 if (!MightHaveChanged)
204 Ctx.getTemplateSpecializationType(TST->getKeyword(), TName, FQArgs,
209 return NewQT.getTypePtr();
212static inline NestedNameSpecifier createOuterNNS(
const ASTContext &Ctx,
215 bool WithGlobalNsPrefix) {
216 const DeclContext *DC = D->getDeclContext();
217 if (
const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
218 while (NS && NS->isInline()) {
220 NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
222 if (NS && NS->getDeclName()) {
223 return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
227 if (
const auto *TD = dyn_cast<TagDecl>(DC))
228 return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
229 if (
const auto *TDD = dyn_cast<TypedefNameDecl>(DC))
230 return createNestedNameSpecifier(Ctx, TDD, FullyQualify,
232 if (WithGlobalNsPrefix && DC->isTranslationUnit())
233 return NestedNameSpecifier::getGlobal();
238static inline NestedNameSpecifier getFullyQualifiedNestedNameSpecifier(
239 const ASTContext &Ctx, NestedNameSpecifier Scope,
240 bool WithGlobalNsPrefix) {
241 switch (Scope.getKind()) {
242 case NestedNameSpecifier::Kind::Null:
243 llvm_unreachable(
"can't fully qualify the empty nested name specifier");
244 case NestedNameSpecifier::Kind::Global:
245 case NestedNameSpecifier::Kind::MicrosoftSuper:
248 case NestedNameSpecifier::Kind::Namespace:
249 return TypeName::createNestedNameSpecifier(
250 Ctx, Scope.getAsNamespaceAndPrefix().Namespace->getNamespace(),
252 case NestedNameSpecifier::Kind::Type: {
253 const Type *Type = Scope.getAsType();
256 if (
const TagType *TagDeclType = Type->getAs<TagType>())
257 TD = TagDeclType->getDecl();
258 else if (
const auto *D = dyn_cast<TypedefType>(Type))
262 return TypeName::createNestedNameSpecifier(Ctx, TD,
true,
266 llvm_unreachable(
"bad NNS kind");
271static inline NestedNameSpecifier
272createNestedNameSpecifierForScopeOf(
const ASTContext &Ctx,
const Decl *Decl,
274 bool WithGlobalNsPrefix) {
278 if (Decl->isTemplateParameter())
280 const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
281 const auto *Outer = dyn_cast<NamedDecl>(DC);
282 const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);
283 if (OuterNS && OuterNS->isAnonymousNamespace())
284 OuterNS = dyn_cast<NamespaceDecl>(OuterNS->getParent());
293 if (
const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) {
294 if (ClassTemplateDecl *ClassTempl =
295 CxxDecl->getDescribedClassTemplate()) {
296 if (!ClassTempl->specializations().empty()) {
297 Decl = *(ClassTempl->spec_begin());
298 Outer = dyn_cast<NamedDecl>(Decl);
299 OuterNS = dyn_cast<NamespaceDecl>(Decl);
306 return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
307 }
else if (
const auto *TD = dyn_cast<TagDecl>(Outer)) {
308 return createNestedNameSpecifier(
309 Ctx, TD, FullyQualified, WithGlobalNsPrefix);
310 }
else if (isa<TranslationUnitDecl>(Outer)) {
319 }
else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
320 return NestedNameSpecifier::getGlobal();
327static inline NestedNameSpecifier
328createNestedNameSpecifierForScopeOf(
const ASTContext &Ctx,
const Type *TypePtr,
330 bool WithGlobalNsPrefix) {
334 Decl *Decl =
nullptr;
336 if (
const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
337 Decl = TDT->getDecl();
338 }
else if (
const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
339 Decl = TagDeclType->getDecl();
340 }
else if (
const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
341 Decl = TST->getTemplateName().getAsTemplateDecl();
343 Decl = TypePtr->getAsCXXRecordDecl();
349 return createNestedNameSpecifierForScopeOf(
350 Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
353inline NestedNameSpecifier
354createNestedNameSpecifier(
const ASTContext &Ctx,
const NamespaceDecl *Namespace,
355 bool WithGlobalNsPrefix) {
356 while (Namespace && Namespace->isInline()) {
358 Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
363 bool FullyQualify =
true;
364 return NestedNameSpecifier(
366 createOuterNNS(Ctx, Namespace, FullyQualify, WithGlobalNsPrefix));
369inline NestedNameSpecifier
370createNestedNameSpecifier(
const ASTContext &Ctx,
const TypeDecl *TD,
371 bool FullyQualify,
bool WithGlobalNsPrefix) {
372 const Type *TypePtr = Ctx.getTypeDeclType(TD).getTypePtr();
373 if (
auto *RD = dyn_cast<TagType>(TypePtr)) {
377 TypePtr = getFullyQualifiedTemplateType(
378 Ctx, RD, ElaboratedTypeKeyword::None,
379 createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
381 }
else if (
auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
382 TypePtr = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix);
384 return NestedNameSpecifier(TypePtr);
389inline QualType getFullyQualifiedType(QualType QT,
const ASTContext &Ctx,
390 bool WithGlobalNsPrefix =
false) {
393 if (isa<PointerType>(QT.getTypePtr())) {
395 Qualifiers Quals = QT.getQualifiers();
396 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
397 QT = Ctx.getPointerType(QT);
399 QT = Ctx.getQualifiedType(QT, Quals);
403 if (
auto *MPT = dyn_cast<MemberPointerType>(QT.getTypePtr())) {
405 Qualifiers Quals = QT.getQualifiers();
407 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
408 NestedNameSpecifier Qualifier = getFullyQualifiedNestedNameSpecifier(
409 Ctx, MPT->getQualifier(), WithGlobalNsPrefix);
410 QT = Ctx.getMemberPointerType(QT, Qualifier,
411 MPT->getMostRecentCXXRecordDecl());
413 QT = Ctx.getQualifiedType(QT, Quals);
419 if (isa<ReferenceType>(QT.getTypePtr())) {
421 bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
422 Qualifiers Quals = QT.getQualifiers();
423 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
427 QT = Ctx.getLValueReferenceType(QT);
429 QT = Ctx.getRValueReferenceType(QT);
431 QT = Ctx.getQualifiedType(QT, Quals);
436 if (
auto *AT = dyn_cast<AttributedType>(QT.getTypePtr())) {
437 QualType NewModified =
438 getFullyQualifiedType(AT->getModifiedType(), Ctx, WithGlobalNsPrefix);
439 QualType NewEquivalent =
440 getFullyQualifiedType(AT->getEquivalentType(), Ctx, WithGlobalNsPrefix);
441 Qualifiers Qualifiers = QT.getLocalQualifiers();
442 return Ctx.getQualifiedType(
443 Ctx.getAttributedType(AT->getAttrKind(), NewModified, NewEquivalent),
451 while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) {
453 Qualifiers Quals = QT.getQualifiers();
455 QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
458 QT = Ctx.getQualifiedType(QT, Quals);
461 if (
const auto *TST =
462 dyn_cast<
const TemplateSpecializationType>(QT.getTypePtr())) {
464 const Type *T = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix);
467 return Ctx.getQualifiedType(T, QT.getQualifiers());
473 Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
474 QT = QualType(QT.getTypePtr(), 0);
478 if (
const auto *UT = QT->getAs<UsingType>()) {
479 QT = Ctx.getQualifiedType(UT->desugar(), PrefixQualifiers);
480 return getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
484 NestedNameSpecifier Prefix = createNestedNameSpecifierForScopeOf(
485 Ctx, QT.getTypePtr(),
true , WithGlobalNsPrefix);
489 if (
const auto *TT = dyn_cast<TagType>(QT.getTypePtr())) {
494 const Type *TypePtr = getFullyQualifiedTemplateType(
495 Ctx, TT, TT->getKeyword(), Prefix, WithGlobalNsPrefix);
496 QT = QualType(TypePtr, 0);
497 }
else if (
const auto *TT = dyn_cast<TypedefType>(QT.getTypePtr())) {
503 NestedNameSpecifier TypedefPrefix = TT->getQualifier();
504 QT = Ctx.getTypedefType(
505 TT->getKeyword(), TypedefPrefix ? TypedefPrefix : Prefix,
507 getFullyQualifiedType(TT->desugar(), Ctx, WithGlobalNsPrefix));
514 QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
652#if CLANG_VERSION_MAJOR >= 21
690#if CLANG_VERSION_MAJOR >= 21
761#if CLANG_VERSION_MAJOR < 21
838 if (!
Decl)
return nullptr;
876#if CLANG_VERSION_MAJOR < 21
903#if CLANG_VERSION_MAJOR >= 21
953#if LIBCLANG_VERSION_MAJOR >= 18
997 const ASTContext &Ctx,
998 const PrintingPolicy &Policy,
999 bool WithGlobalNsPrefix =
false) {
1000 QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
1001 return FQQT.getAsString(Policy);