| //===- TemplateName.cpp - C++ Template Name Representation ----------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | //  This file defines the TemplateName interface and subclasses. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "clang/AST/TemplateName.h" | 
 | #include "clang/AST/DeclBase.h" | 
 | #include "clang/AST/DeclTemplate.h" | 
 | #include "clang/AST/NestedNameSpecifier.h" | 
 | #include "clang/AST/PrettyPrinter.h" | 
 | #include "clang/AST/TemplateBase.h" | 
 | #include "clang/Basic/Diagnostic.h" | 
 | #include "clang/Basic/LLVM.h" | 
 | #include "clang/Basic/LangOptions.h" | 
 | #include "clang/Basic/OperatorKinds.h" | 
 | #include "llvm/ADT/ArrayRef.h" | 
 | #include "llvm/ADT/FoldingSet.h" | 
 | #include "llvm/Support/Casting.h" | 
 | #include "llvm/Support/Compiler.h" | 
 | #include "llvm/Support/raw_ostream.h" | 
 | #include <cassert> | 
 | #include <string> | 
 |  | 
 | using namespace clang; | 
 |  | 
 | TemplateArgument  | 
 | SubstTemplateTemplateParmPackStorage::getArgumentPack() const { | 
 |   return TemplateArgument(llvm::makeArrayRef(Arguments, size())); | 
 | } | 
 |  | 
 | void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { | 
 |   Profile(ID, Parameter, Replacement); | 
 | } | 
 |  | 
 | void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,  | 
 |                                            TemplateTemplateParmDecl *parameter, | 
 |                                                TemplateName replacement) { | 
 |   ID.AddPointer(parameter); | 
 |   ID.AddPointer(replacement.getAsVoidPointer()); | 
 | } | 
 |  | 
 | void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, | 
 |                                                    ASTContext &Context) { | 
 |   Profile(ID, Context, Parameter, getArgumentPack()); | 
 | } | 
 |  | 
 | void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,  | 
 |                                                    ASTContext &Context, | 
 |                                            TemplateTemplateParmDecl *Parameter, | 
 |                                              const TemplateArgument &ArgPack) { | 
 |   ID.AddPointer(Parameter); | 
 |   ArgPack.Profile(ID, Context); | 
 | } | 
 |  | 
 | TemplateName::TemplateName(void *Ptr) { | 
 |   Storage = StorageType::getFromOpaqueValue(Ptr); | 
 | } | 
 |  | 
 | TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {} | 
 | TemplateName::TemplateName(OverloadedTemplateStorage *Storage) | 
 |     : Storage(Storage) {} | 
 | TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) | 
 |     : Storage(Storage) {} | 
 | TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) | 
 |     : Storage(Storage) {} | 
 | TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {} | 
 | TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {} | 
 |  | 
 | bool TemplateName::isNull() const { return Storage.isNull(); } | 
 |  | 
 | TemplateName::NameKind TemplateName::getKind() const { | 
 |   if (Storage.is<TemplateDecl *>()) | 
 |     return Template; | 
 |   if (Storage.is<DependentTemplateName *>()) | 
 |     return DependentTemplate; | 
 |   if (Storage.is<QualifiedTemplateName *>()) | 
 |     return QualifiedTemplate; | 
 |  | 
 |   UncommonTemplateNameStorage *uncommon | 
 |     = Storage.get<UncommonTemplateNameStorage*>(); | 
 |   if (uncommon->getAsOverloadedStorage()) | 
 |     return OverloadedTemplate; | 
 |   if (uncommon->getAsSubstTemplateTemplateParm()) | 
 |     return SubstTemplateTemplateParm; | 
 |   return SubstTemplateTemplateParmPack; | 
 | } | 
 |  | 
 | TemplateDecl *TemplateName::getAsTemplateDecl() const { | 
 |   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) | 
 |     return Template; | 
 |  | 
 |   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) | 
 |     return QTN->getTemplateDecl(); | 
 |  | 
 |   if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) | 
 |     return sub->getReplacement().getAsTemplateDecl(); | 
 |  | 
 |   return nullptr; | 
 | } | 
 |  | 
 | OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { | 
 |   if (UncommonTemplateNameStorage *Uncommon = | 
 |           Storage.dyn_cast<UncommonTemplateNameStorage *>()) | 
 |     return Uncommon->getAsOverloadedStorage(); | 
 |  | 
 |   return nullptr; | 
 | } | 
 |  | 
 | SubstTemplateTemplateParmStorage * | 
 | TemplateName::getAsSubstTemplateTemplateParm() const { | 
 |   if (UncommonTemplateNameStorage *uncommon = | 
 |           Storage.dyn_cast<UncommonTemplateNameStorage *>()) | 
 |     return uncommon->getAsSubstTemplateTemplateParm(); | 
 |  | 
 |   return nullptr; | 
 | } | 
 |  | 
 | SubstTemplateTemplateParmPackStorage * | 
 | TemplateName::getAsSubstTemplateTemplateParmPack() const { | 
 |   if (UncommonTemplateNameStorage *Uncommon = | 
 |           Storage.dyn_cast<UncommonTemplateNameStorage *>()) | 
 |     return Uncommon->getAsSubstTemplateTemplateParmPack(); | 
 |  | 
 |   return nullptr; | 
 | } | 
 |  | 
 | QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { | 
 |   return Storage.dyn_cast<QualifiedTemplateName *>(); | 
 | } | 
 |  | 
 | DependentTemplateName *TemplateName::getAsDependentTemplateName() const { | 
 |   return Storage.dyn_cast<DependentTemplateName *>(); | 
 | } | 
 |  | 
 | TemplateName TemplateName::getNameToSubstitute() const { | 
 |   TemplateDecl *Decl = getAsTemplateDecl(); | 
 |  | 
 |   // Substituting a dependent template name: preserve it as written. | 
 |   if (!Decl) | 
 |     return *this; | 
 |  | 
 |   // If we have a template declaration, use the most recent non-friend | 
 |   // declaration of that template. | 
 |   Decl = cast<TemplateDecl>(Decl->getMostRecentDecl()); | 
 |   while (Decl->getFriendObjectKind()) { | 
 |     Decl = cast<TemplateDecl>(Decl->getPreviousDecl()); | 
 |     assert(Decl && "all declarations of template are friends"); | 
 |   } | 
 |   return TemplateName(Decl); | 
 | } | 
 |  | 
 | bool TemplateName::isDependent() const { | 
 |   if (TemplateDecl *Template = getAsTemplateDecl()) { | 
 |     if (isa<TemplateTemplateParmDecl>(Template)) | 
 |       return true; | 
 |     // FIXME: Hack, getDeclContext() can be null if Template is still | 
 |     // initializing due to PCH reading, so we check it before using it. | 
 |     // Should probably modify TemplateSpecializationType to allow constructing | 
 |     // it without the isDependent() checking. | 
 |     return Template->getDeclContext() && | 
 |            Template->getDeclContext()->isDependentContext(); | 
 |   } | 
 |  | 
 |   assert(!getAsOverloadedTemplate() && | 
 |          "overloaded templates shouldn't survive to here"); | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool TemplateName::isInstantiationDependent() const { | 
 |   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { | 
 |     if (QTN->getQualifier()->isInstantiationDependent()) | 
 |       return true; | 
 |   } | 
 |    | 
 |   return isDependent(); | 
 | } | 
 |  | 
 | bool TemplateName::containsUnexpandedParameterPack() const { | 
 |   if (TemplateDecl *Template = getAsTemplateDecl()) { | 
 |     if (TemplateTemplateParmDecl *TTP  | 
 |                                   = dyn_cast<TemplateTemplateParmDecl>(Template)) | 
 |       return TTP->isParameterPack(); | 
 |  | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (DependentTemplateName *DTN = getAsDependentTemplateName()) | 
 |     return DTN->getQualifier() &&  | 
 |       DTN->getQualifier()->containsUnexpandedParameterPack(); | 
 |  | 
 |   return getAsSubstTemplateTemplateParmPack() != nullptr; | 
 | } | 
 |  | 
 | void | 
 | TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, | 
 |                     bool SuppressNNS) const { | 
 |   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) | 
 |     OS << *Template; | 
 |   else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { | 
 |     if (!SuppressNNS) | 
 |       QTN->getQualifier()->print(OS, Policy); | 
 |     if (QTN->hasTemplateKeyword()) | 
 |       OS << "template "; | 
 |     OS << *QTN->getDecl(); | 
 |   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { | 
 |     if (!SuppressNNS && DTN->getQualifier()) | 
 |       DTN->getQualifier()->print(OS, Policy); | 
 |     OS << "template "; | 
 |      | 
 |     if (DTN->isIdentifier()) | 
 |       OS << DTN->getIdentifier()->getName(); | 
 |     else | 
 |       OS << "operator " << getOperatorSpelling(DTN->getOperator()); | 
 |   } else if (SubstTemplateTemplateParmStorage *subst | 
 |                = getAsSubstTemplateTemplateParm()) { | 
 |     subst->getReplacement().print(OS, Policy, SuppressNNS); | 
 |   } else if (SubstTemplateTemplateParmPackStorage *SubstPack | 
 |                                         = getAsSubstTemplateTemplateParmPack()) | 
 |     OS << *SubstPack->getParameterPack(); | 
 |   else { | 
 |     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); | 
 |     (*OTS->begin())->printName(OS); | 
 |   } | 
 | } | 
 |  | 
 | const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, | 
 |                                            TemplateName N) { | 
 |   std::string NameStr; | 
 |   llvm::raw_string_ostream OS(NameStr); | 
 |   LangOptions LO; | 
 |   LO.CPlusPlus = true; | 
 |   LO.Bool = true; | 
 |   OS << '\''; | 
 |   N.print(OS, PrintingPolicy(LO)); | 
 |   OS << '\''; | 
 |   OS.flush(); | 
 |   return DB << NameStr; | 
 | } | 
 |  | 
 | void TemplateName::dump(raw_ostream &OS) const { | 
 |   LangOptions LO;  // FIXME! | 
 |   LO.CPlusPlus = true; | 
 |   LO.Bool = true; | 
 |   print(OS, PrintingPolicy(LO)); | 
 | } | 
 |  | 
 | LLVM_DUMP_METHOD void TemplateName::dump() const { | 
 |   dump(llvm::errs()); | 
 | } |