1 //===------- QualTypeNames.cpp - Generate Complete QualType Names ---------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 //===----------------------------------------------------------------------===// 6 // 7 // This file is distributed under the University of Illinois Open Source 8 // License. See LICENSE.TXT for details. 9 // 10 //===----------------------------------------------------------------------===// 11 12 #include "clang/AST/DeclTemplate.h" 13 #include "clang/AST/DeclarationName.h" 14 #include "clang/AST/GlobalDecl.h" 15 #include "clang/AST/Mangle.h" 16 #include "clang/AST/QualTypeNames.h" 17 18 #include <stdio.h> 19 #include <memory> 20 21 namespace clang { 22 23 namespace TypeName { 24 25 /// Create a NestedNameSpecifier for Namesp and its enclosing 26 /// scopes. 27 /// 28 /// \param[in] Ctx - the AST Context to be used. 29 /// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier 30 /// is requested. 31 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace 32 /// specifier "::" should be prepended or not. 33 static NestedNameSpecifier *createNestedNameSpecifier( 34 const ASTContext &Ctx, 35 const NamespaceDecl *Namesp, 36 bool WithGlobalNsPrefix); 37 38 /// Create a NestedNameSpecifier for TagDecl and its enclosing 39 /// scopes. 40 /// 41 /// \param[in] Ctx - the AST Context to be used. 42 /// \param[in] TD - the TagDecl for which a NestedNameSpecifier is 43 /// requested. 44 /// \param[in] FullyQualify - Convert all template arguments into fully 45 /// qualified names. 46 /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace 47 /// specifier "::" should be prepended or not. 48 static NestedNameSpecifier *createNestedNameSpecifier( 49 const ASTContext &Ctx, const TypeDecl *TD, 50 bool FullyQualify, bool WithGlobalNsPrefix); 51 52 static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( 53 const ASTContext &Ctx, const Decl *decl, 54 bool FullyQualified, bool WithGlobalNsPrefix); 55 56 static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier( 57 const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix); 58 59 static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, 60 TemplateName &TName, 61 bool WithGlobalNsPrefix) { 62 bool Changed = false; 63 NestedNameSpecifier *NNS = nullptr; 64 65 TemplateDecl *ArgTDecl = TName.getAsTemplateDecl(); 66 // ArgTDecl won't be NULL because we asserted that this isn't a 67 // dependent context very early in the call chain. 68 assert(ArgTDecl != nullptr); 69 QualifiedTemplateName *QTName = TName.getAsQualifiedTemplateName(); 70 71 if (QTName && !QTName->hasTemplateKeyword()) { 72 NNS = QTName->getQualifier(); 73 NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier( 74 Ctx, NNS, WithGlobalNsPrefix); 75 if (QNNS != NNS) { 76 Changed = true; 77 NNS = QNNS; 78 } else { 79 NNS = nullptr; 80 } 81 } else { 82 NNS = createNestedNameSpecifierForScopeOf( 83 Ctx, ArgTDecl, true, WithGlobalNsPrefix); 84 } 85 if (NNS) { 86 TName = Ctx.getQualifiedTemplateName(NNS, 87 /*TemplateKeyword=*/false, ArgTDecl); 88 Changed = true; 89 } 90 return Changed; 91 } 92 93 static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx, 94 TemplateArgument &Arg, 95 bool WithGlobalNsPrefix) { 96 bool Changed = false; 97 98 // Note: we do not handle TemplateArgument::Expression, to replace it 99 // we need the information for the template instance decl. 100 101 if (Arg.getKind() == TemplateArgument::Template) { 102 TemplateName TName = Arg.getAsTemplate(); 103 Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix); 104 if (Changed) { 105 Arg = TemplateArgument(TName); 106 } 107 } else if (Arg.getKind() == TemplateArgument::Type) { 108 QualType SubTy = Arg.getAsType(); 109 // Check if the type needs more desugaring and recurse. 110 QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix); 111 if (QTFQ != SubTy) { 112 Arg = TemplateArgument(QTFQ); 113 Changed = true; 114 } 115 } 116 return Changed; 117 } 118 119 static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx, 120 const Type *TypePtr, 121 bool WithGlobalNsPrefix) { 122 // DependentTemplateTypes exist within template declarations and 123 // definitions. Therefore we shouldn't encounter them at the end of 124 // a translation unit. If we do, the caller has made an error. 125 assert(!isa<DependentTemplateSpecializationType>(TypePtr)); 126 // In case of template specializations, iterate over the arguments 127 // and fully qualify them as well. 128 if (const auto *TST = dyn_cast<const TemplateSpecializationType>(TypePtr)) { 129 bool MightHaveChanged = false; 130 SmallVector<TemplateArgument, 4> FQArgs; 131 for (TemplateSpecializationType::iterator I = TST->begin(), E = TST->end(); 132 I != E; ++I) { 133 // Cheap to copy and potentially modified by 134 // getFullyQualifedTemplateArgument. 135 TemplateArgument Arg(*I); 136 MightHaveChanged |= getFullyQualifiedTemplateArgument( 137 Ctx, Arg, WithGlobalNsPrefix); 138 FQArgs.push_back(Arg); 139 } 140 141 // If a fully qualified arg is different from the unqualified arg, 142 // allocate new type in the AST. 143 if (MightHaveChanged) { 144 QualType QT = Ctx.getTemplateSpecializationType( 145 TST->getTemplateName(), FQArgs, 146 TST->getCanonicalTypeInternal()); 147 // getTemplateSpecializationType returns a fully qualified 148 // version of the specialization itself, so no need to qualify 149 // it. 150 return QT.getTypePtr(); 151 } 152 } else if (const auto *TSTRecord = dyn_cast<const RecordType>(TypePtr)) { 153 // We are asked to fully qualify and we have a Record Type, 154 // which can point to a template instantiation with no sugar in any of 155 // its template argument, however we still need to fully qualify them. 156 157 if (const auto *TSTDecl = 158 dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) { 159 const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs(); 160 161 bool MightHaveChanged = false; 162 SmallVector<TemplateArgument, 4> FQArgs; 163 for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) { 164 // cheap to copy and potentially modified by 165 // getFullyQualifedTemplateArgument 166 TemplateArgument Arg(TemplateArgs[I]); 167 MightHaveChanged |= getFullyQualifiedTemplateArgument( 168 Ctx, Arg, WithGlobalNsPrefix); 169 FQArgs.push_back(Arg); 170 } 171 172 // If a fully qualified arg is different from the unqualified arg, 173 // allocate new type in the AST. 174 if (MightHaveChanged) { 175 TemplateName TN(TSTDecl->getSpecializedTemplate()); 176 QualType QT = Ctx.getTemplateSpecializationType( 177 TN, FQArgs, 178 TSTRecord->getCanonicalTypeInternal()); 179 // getTemplateSpecializationType returns a fully qualified 180 // version of the specialization itself, so no need to qualify 181 // it. 182 return QT.getTypePtr(); 183 } 184 } 185 } 186 return TypePtr; 187 } 188 189 static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D, 190 bool FullyQualify, 191 bool WithGlobalNsPrefix) { 192 const DeclContext *DC = D->getDeclContext(); 193 if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) { 194 while (NS && NS->isInline()) { 195 // Ignore inline namespace; 196 NS = dyn_cast<NamespaceDecl>(NS->getDeclContext()); 197 } 198 if (NS->getDeclName()) { 199 return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix); 200 } 201 return nullptr; // no starting '::', no anonymous 202 } else if (const auto *TD = dyn_cast<TagDecl>(DC)) { 203 return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix); 204 } else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) { 205 return createNestedNameSpecifier( 206 Ctx, TDD, FullyQualify, WithGlobalNsPrefix); 207 } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) { 208 return NestedNameSpecifier::GlobalSpecifier(Ctx); 209 } 210 return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false 211 } 212 213 /// Return a fully qualified version of this name specifier. 214 static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier( 215 const ASTContext &Ctx, NestedNameSpecifier *Scope, 216 bool WithGlobalNsPrefix) { 217 switch (Scope->getKind()) { 218 case NestedNameSpecifier::Global: 219 // Already fully qualified 220 return Scope; 221 case NestedNameSpecifier::Namespace: 222 return TypeName::createNestedNameSpecifier( 223 Ctx, Scope->getAsNamespace(), WithGlobalNsPrefix); 224 case NestedNameSpecifier::NamespaceAlias: 225 // Namespace aliases are only valid for the duration of the 226 // scope where they were introduced, and therefore are often 227 // invalid at the end of the TU. So use the namespace name more 228 // likely to be valid at the end of the TU. 229 return TypeName::createNestedNameSpecifier( 230 Ctx, 231 Scope->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl(), 232 WithGlobalNsPrefix); 233 case NestedNameSpecifier::Identifier: 234 // A function or some other construct that makes it un-namable 235 // at the end of the TU. Skip the current component of the name, 236 // but use the name of it's prefix. 237 return getFullyQualifiedNestedNameSpecifier( 238 Ctx, Scope->getPrefix(), WithGlobalNsPrefix); 239 case NestedNameSpecifier::Super: 240 case NestedNameSpecifier::TypeSpec: 241 case NestedNameSpecifier::TypeSpecWithTemplate: { 242 const Type *Type = Scope->getAsType(); 243 // Find decl context. 244 const TagDecl *TD = nullptr; 245 if (const TagType *TagDeclType = Type->getAs<TagType>()) { 246 TD = TagDeclType->getDecl(); 247 } else { 248 TD = Type->getAsCXXRecordDecl(); 249 } 250 if (TD) { 251 return TypeName::createNestedNameSpecifier(Ctx, TD, 252 true /*FullyQualified*/, 253 WithGlobalNsPrefix); 254 } else if (const auto *TDD = dyn_cast<TypedefType>(Type)) { 255 return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(), 256 true /*FullyQualified*/, 257 WithGlobalNsPrefix); 258 } 259 return Scope; 260 } 261 } 262 llvm_unreachable("bad NNS kind"); 263 } 264 265 /// Create a nested name specifier for the declaring context of 266 /// the type. 267 static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( 268 const ASTContext &Ctx, const Decl *Decl, 269 bool FullyQualified, bool WithGlobalNsPrefix) { 270 assert(Decl); 271 272 const DeclContext *DC = Decl->getDeclContext()->getRedeclContext(); 273 const auto *Outer = dyn_cast_or_null<NamedDecl>(DC); 274 const auto *OuterNS = dyn_cast_or_null<NamespaceDecl>(DC); 275 if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) { 276 if (const auto *CxxDecl = dyn_cast<CXXRecordDecl>(DC)) { 277 if (ClassTemplateDecl *ClassTempl = 278 CxxDecl->getDescribedClassTemplate()) { 279 // We are in the case of a type(def) that was declared in a 280 // class template but is *not* type dependent. In clang, it 281 // gets attached to the class template declaration rather than 282 // any specific class template instantiation. This result in 283 // 'odd' fully qualified typename: 284 // 285 // vector<_Tp,_Alloc>::size_type 286 // 287 // Make the situation is 'useable' but looking a bit odd by 288 // picking a random instance as the declaring context. 289 if (ClassTempl->spec_begin() != ClassTempl->spec_end()) { 290 Decl = *(ClassTempl->spec_begin()); 291 Outer = dyn_cast<NamedDecl>(Decl); 292 OuterNS = dyn_cast<NamespaceDecl>(Decl); 293 } 294 } 295 } 296 297 if (OuterNS) { 298 return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix); 299 } else if (const auto *TD = dyn_cast<TagDecl>(Outer)) { 300 return createNestedNameSpecifier( 301 Ctx, TD, FullyQualified, WithGlobalNsPrefix); 302 } else if (dyn_cast<TranslationUnitDecl>(Outer)) { 303 // Context is the TU. Nothing needs to be done. 304 return nullptr; 305 } else { 306 // Decl's context was neither the TU, a namespace, nor a 307 // TagDecl, which means it is a type local to a scope, and not 308 // accessible at the end of the TU. 309 return nullptr; 310 } 311 } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) { 312 return NestedNameSpecifier::GlobalSpecifier(Ctx); 313 } 314 return nullptr; 315 } 316 317 /// Create a nested name specifier for the declaring context of 318 /// the type. 319 static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( 320 const ASTContext &Ctx, const Type *TypePtr, 321 bool FullyQualified, bool WithGlobalNsPrefix) { 322 if (!TypePtr) return nullptr; 323 324 Decl *Decl = nullptr; 325 // There are probably other cases ... 326 if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) { 327 Decl = TDT->getDecl(); 328 } else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) { 329 Decl = TagDeclType->getDecl(); 330 } else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) { 331 Decl = TST->getTemplateName().getAsTemplateDecl(); 332 } else { 333 Decl = TypePtr->getAsCXXRecordDecl(); 334 } 335 336 if (!Decl) return nullptr; 337 338 return createNestedNameSpecifierForScopeOf( 339 Ctx, Decl, FullyQualified, WithGlobalNsPrefix); 340 } 341 342 NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx, 343 const NamespaceDecl *Namespace, 344 bool WithGlobalNsPrefix) { 345 while (Namespace && Namespace->isInline()) { 346 // Ignore inline namespace; 347 Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext()); 348 } 349 if (!Namespace) return nullptr; 350 351 bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces 352 return NestedNameSpecifier::Create( 353 Ctx, 354 createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix), 355 Namespace); 356 } 357 358 NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx, 359 const TypeDecl *TD, 360 bool FullyQualify, 361 bool WithGlobalNsPrefix) { 362 return NestedNameSpecifier::Create( 363 Ctx, 364 createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), 365 false /*No TemplateKeyword*/, 366 TD->getTypeForDecl()); 367 } 368 369 /// Return the fully qualified type, including fully-qualified 370 /// versions of any template parameters. 371 QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, 372 bool WithGlobalNsPrefix) { 373 // In case of myType* we need to strip the pointer first, fully 374 // qualify and attach the pointer once again. 375 if (isa<PointerType>(QT.getTypePtr())) { 376 // Get the qualifiers. 377 Qualifiers Quals = QT.getQualifiers(); 378 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix); 379 QT = Ctx.getPointerType(QT); 380 // Add back the qualifiers. 381 QT = Ctx.getQualifiedType(QT, Quals); 382 return QT; 383 } 384 385 // In case of myType& we need to strip the reference first, fully 386 // qualify and attach the reference once again. 387 if (isa<ReferenceType>(QT.getTypePtr())) { 388 // Get the qualifiers. 389 bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr()); 390 Qualifiers Quals = QT.getQualifiers(); 391 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix); 392 // Add the r- or l-value reference type back to the fully 393 // qualified one. 394 if (IsLValueRefTy) 395 QT = Ctx.getLValueReferenceType(QT); 396 else 397 QT = Ctx.getRValueReferenceType(QT); 398 // Add back the qualifiers. 399 QT = Ctx.getQualifiedType(QT, Quals); 400 return QT; 401 } 402 403 // Remove the part of the type related to the type being a template 404 // parameter (we won't report it as part of the 'type name' and it 405 // is actually make the code below to be more complex (to handle 406 // those) 407 while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) { 408 // Get the qualifiers. 409 Qualifiers Quals = QT.getQualifiers(); 410 411 QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar(); 412 413 // Add back the qualifiers. 414 QT = Ctx.getQualifiedType(QT, Quals); 415 } 416 417 NestedNameSpecifier *Prefix = nullptr; 418 // Local qualifiers are attached to the QualType outside of the 419 // elaborated type. Retrieve them before descending into the 420 // elaborated type. 421 Qualifiers PrefixQualifiers = QT.getLocalQualifiers(); 422 QT = QualType(QT.getTypePtr(), 0); 423 ElaboratedTypeKeyword Keyword = ETK_None; 424 if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) { 425 QT = ETypeInput->getNamedType(); 426 assert(!QT.hasLocalQualifiers()); 427 Keyword = ETypeInput->getKeyword(); 428 } 429 // Create a nested name specifier if needed. 430 Prefix = createNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(), 431 true /*FullyQualified*/, 432 WithGlobalNsPrefix); 433 434 // In case of template specializations iterate over the arguments and 435 // fully qualify them as well. 436 if (isa<const TemplateSpecializationType>(QT.getTypePtr()) || 437 isa<const RecordType>(QT.getTypePtr())) { 438 // We are asked to fully qualify and we have a Record Type (which 439 // may point to a template specialization) or Template 440 // Specialization Type. We need to fully qualify their arguments. 441 442 const Type *TypePtr = getFullyQualifiedTemplateType( 443 Ctx, QT.getTypePtr(), WithGlobalNsPrefix); 444 QT = QualType(TypePtr, 0); 445 } 446 if (Prefix || Keyword != ETK_None) { 447 QT = Ctx.getElaboratedType(Keyword, Prefix, QT); 448 } 449 QT = Ctx.getQualifiedType(QT, PrefixQualifiers); 450 return QT; 451 } 452 453 std::string getFullyQualifiedName(QualType QT, 454 const ASTContext &Ctx, 455 const PrintingPolicy &Policy, 456 bool WithGlobalNsPrefix) { 457 QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix); 458 return FQQT.getAsString(Policy); 459 } 460 461 } // end namespace TypeName 462 } // end namespace clang 463