| //===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===// |
| // |
| // 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/DeclTemplate.h" |
| #include "clang/AST/NestedNameSpecifier.h" |
| #include "clang/AST/PrettyPrinter.h" |
| #include "clang/Basic/Diagnostic.h" |
| #include "clang/Basic/LangOptions.h" |
| #include "llvm/Support/raw_ostream.h" |
| using namespace clang; |
| using namespace llvm; |
| |
| TemplateName::NameKind TemplateName::getKind() const { |
| if (Storage.is<TemplateDecl *>()) |
| return Template; |
| if (Storage.is<OverloadedTemplateStorage *>()) |
| return OverloadedTemplate; |
| if (Storage.is<QualifiedTemplateName *>()) |
| return QualifiedTemplate; |
| assert(Storage.is<DependentTemplateName *>() && "There's a case unhandled!"); |
| return DependentTemplate; |
| } |
| |
| TemplateDecl *TemplateName::getAsTemplateDecl() const { |
| if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) |
| return Template; |
| |
| if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) |
| return QTN->getTemplateDecl(); |
| |
| return 0; |
| } |
| |
| 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; |
| } |
| |
| void |
| TemplateName::print(llvm::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()); |
| } |
| } |
| |
| const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, |
| TemplateName N) { |
| std::string NameStr; |
| raw_string_ostream OS(NameStr); |
| LangOptions LO; |
| LO.CPlusPlus = true; |
| LO.Bool = true; |
| N.print(OS, PrintingPolicy(LO)); |
| OS.flush(); |
| return DB << NameStr; |
| } |
| |
| void TemplateName::dump() const { |
| LangOptions LO; // FIXME! |
| LO.CPlusPlus = true; |
| LO.Bool = true; |
| print(llvm::errs(), PrintingPolicy(LO)); |
| } |