TemplateName.cpp revision 1aee05d08b2184acadeb36de300e216390780d6c
1//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the TemplateName interface and subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/TemplateName.h"
15#include "clang/AST/TemplateBase.h"
16#include "clang/AST/DeclTemplate.h"
17#include "clang/AST/NestedNameSpecifier.h"
18#include "clang/AST/PrettyPrinter.h"
19#include "clang/Basic/Diagnostic.h"
20#include "clang/Basic/LangOptions.h"
21#include "llvm/Support/raw_ostream.h"
22using namespace clang;
23using namespace llvm;
24
25TemplateArgument
26SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
27  return TemplateArgument(Arguments, size());
28}
29
30void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID) {
31  Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
32}
33
34void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
35                                                   ASTContext &Context,
36                                           TemplateTemplateParmDecl *Parameter,
37                                             const TemplateArgument &ArgPack) {
38  ID.AddPointer(Parameter);
39  ArgPack.Profile(ID, Context);
40}
41
42TemplateName::NameKind TemplateName::getKind() const {
43  if (Storage.is<TemplateDecl *>())
44    return Template;
45  if (Storage.is<DependentTemplateName *>())
46    return DependentTemplate;
47  if (Storage.is<QualifiedTemplateName *>())
48    return QualifiedTemplate;
49
50  return getAsOverloadedTemplate()? OverloadedTemplate
51                                  : SubstTemplateTemplateParmPack;
52}
53
54TemplateDecl *TemplateName::getAsTemplateDecl() const {
55  if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
56    return Template;
57
58  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
59    return QTN->getTemplateDecl();
60
61  return 0;
62}
63
64bool TemplateName::isDependent() const {
65  if (TemplateDecl *Template = getAsTemplateDecl()) {
66    if (isa<TemplateTemplateParmDecl>(Template))
67      return true;
68    // FIXME: Hack, getDeclContext() can be null if Template is still
69    // initializing due to PCH reading, so we check it before using it.
70    // Should probably modify TemplateSpecializationType to allow constructing
71    // it without the isDependent() checking.
72    return Template->getDeclContext() &&
73           Template->getDeclContext()->isDependentContext();
74  }
75
76  assert(!getAsOverloadedTemplate() &&
77         "overloaded templates shouldn't survive to here");
78
79  return true;
80}
81
82bool TemplateName::containsUnexpandedParameterPack() const {
83  if (TemplateDecl *Template = getAsTemplateDecl()) {
84    if (TemplateTemplateParmDecl *TTP
85                                  = dyn_cast<TemplateTemplateParmDecl>(Template))
86      return TTP->isParameterPack();
87
88    return false;
89  }
90
91  if (DependentTemplateName *DTN = getAsDependentTemplateName())
92    return DTN->getQualifier() &&
93      DTN->getQualifier()->containsUnexpandedParameterPack();
94
95  return getAsSubstTemplateTemplateParmPack() != 0;
96}
97
98void
99TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
100                    bool SuppressNNS) const {
101  if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
102    OS << Template;
103  else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
104    if (!SuppressNNS)
105      QTN->getQualifier()->print(OS, Policy);
106    if (QTN->hasTemplateKeyword())
107      OS << "template ";
108    OS << QTN->getDecl();
109  } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
110    if (!SuppressNNS && DTN->getQualifier())
111      DTN->getQualifier()->print(OS, Policy);
112    OS << "template ";
113
114    if (DTN->isIdentifier())
115      OS << DTN->getIdentifier()->getName();
116    else
117      OS << "operator " << getOperatorSpelling(DTN->getOperator());
118  } else if (SubstTemplateTemplateParmPackStorage *SubstPack
119                                        = getAsSubstTemplateTemplateParmPack())
120    OS << SubstPack->getParameterPack()->getNameAsString();
121}
122
123const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
124                                           TemplateName N) {
125  std::string NameStr;
126  raw_string_ostream OS(NameStr);
127  LangOptions LO;
128  LO.CPlusPlus = true;
129  LO.Bool = true;
130  N.print(OS, PrintingPolicy(LO));
131  OS.flush();
132  return DB << NameStr;
133}
134
135void TemplateName::dump() const {
136  LangOptions LO;  // FIXME!
137  LO.CPlusPlus = true;
138  LO.Bool = true;
139  print(llvm::errs(), PrintingPolicy(LO));
140}
141