1 //===--- TemplateName.cpp - C++ Template Name Representation---------------===//
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/DeclTemplate.h"
16 #include "clang/AST/NestedNameSpecifier.h"
17 #include "clang/AST/PrettyPrinter.h"
18 #include "clang/AST/TemplateBase.h"
19 #include "clang/Basic/Diagnostic.h"
20 #include "clang/Basic/LangOptions.h"
21 #include "llvm/Support/raw_ostream.h"
22 using namespace clang;
23 using namespace llvm;
24
25 TemplateArgument
getArgumentPack() const26 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
27 return TemplateArgument(Arguments, size());
28 }
29
Profile(llvm::FoldingSetNodeID & ID)30 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
31 Profile(ID, Parameter, Replacement);
32 }
33
Profile(llvm::FoldingSetNodeID & ID,TemplateTemplateParmDecl * parameter,TemplateName replacement)34 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
35 TemplateTemplateParmDecl *parameter,
36 TemplateName replacement) {
37 ID.AddPointer(parameter);
38 ID.AddPointer(replacement.getAsVoidPointer());
39 }
40
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context)41 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
42 ASTContext &Context) {
43 Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
44 }
45
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context,TemplateTemplateParmDecl * Parameter,const TemplateArgument & ArgPack)46 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
47 ASTContext &Context,
48 TemplateTemplateParmDecl *Parameter,
49 const TemplateArgument &ArgPack) {
50 ID.AddPointer(Parameter);
51 ArgPack.Profile(ID, Context);
52 }
53
getKind() const54 TemplateName::NameKind TemplateName::getKind() const {
55 if (Storage.is<TemplateDecl *>())
56 return Template;
57 if (Storage.is<DependentTemplateName *>())
58 return DependentTemplate;
59 if (Storage.is<QualifiedTemplateName *>())
60 return QualifiedTemplate;
61
62 UncommonTemplateNameStorage *uncommon
63 = Storage.get<UncommonTemplateNameStorage*>();
64 if (uncommon->getAsOverloadedStorage())
65 return OverloadedTemplate;
66 if (uncommon->getAsSubstTemplateTemplateParm())
67 return SubstTemplateTemplateParm;
68 return SubstTemplateTemplateParmPack;
69 }
70
getAsTemplateDecl() const71 TemplateDecl *TemplateName::getAsTemplateDecl() const {
72 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
73 return Template;
74
75 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
76 return QTN->getTemplateDecl();
77
78 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
79 return sub->getReplacement().getAsTemplateDecl();
80
81 return 0;
82 }
83
isDependent() const84 bool TemplateName::isDependent() const {
85 if (TemplateDecl *Template = getAsTemplateDecl()) {
86 if (isa<TemplateTemplateParmDecl>(Template))
87 return true;
88 // FIXME: Hack, getDeclContext() can be null if Template is still
89 // initializing due to PCH reading, so we check it before using it.
90 // Should probably modify TemplateSpecializationType to allow constructing
91 // it without the isDependent() checking.
92 return Template->getDeclContext() &&
93 Template->getDeclContext()->isDependentContext();
94 }
95
96 assert(!getAsOverloadedTemplate() &&
97 "overloaded templates shouldn't survive to here");
98
99 return true;
100 }
101
isInstantiationDependent() const102 bool TemplateName::isInstantiationDependent() const {
103 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
104 if (QTN->getQualifier()->isInstantiationDependent())
105 return true;
106 }
107
108 return isDependent();
109 }
110
containsUnexpandedParameterPack() const111 bool TemplateName::containsUnexpandedParameterPack() const {
112 if (TemplateDecl *Template = getAsTemplateDecl()) {
113 if (TemplateTemplateParmDecl *TTP
114 = dyn_cast<TemplateTemplateParmDecl>(Template))
115 return TTP->isParameterPack();
116
117 return false;
118 }
119
120 if (DependentTemplateName *DTN = getAsDependentTemplateName())
121 return DTN->getQualifier() &&
122 DTN->getQualifier()->containsUnexpandedParameterPack();
123
124 return getAsSubstTemplateTemplateParmPack() != 0;
125 }
126
127 void
print(raw_ostream & OS,const PrintingPolicy & Policy,bool SuppressNNS) const128 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
129 bool SuppressNNS) const {
130 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
131 OS << *Template;
132 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
133 if (!SuppressNNS)
134 QTN->getQualifier()->print(OS, Policy);
135 if (QTN->hasTemplateKeyword())
136 OS << "template ";
137 OS << *QTN->getDecl();
138 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
139 if (!SuppressNNS && DTN->getQualifier())
140 DTN->getQualifier()->print(OS, Policy);
141 OS << "template ";
142
143 if (DTN->isIdentifier())
144 OS << DTN->getIdentifier()->getName();
145 else
146 OS << "operator " << getOperatorSpelling(DTN->getOperator());
147 } else if (SubstTemplateTemplateParmStorage *subst
148 = getAsSubstTemplateTemplateParm()) {
149 subst->getReplacement().print(OS, Policy, SuppressNNS);
150 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
151 = getAsSubstTemplateTemplateParmPack())
152 OS << *SubstPack->getParameterPack();
153 else {
154 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
155 (*OTS->begin())->printName(OS);
156 }
157 }
158
operator <<(const DiagnosticBuilder & DB,TemplateName N)159 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
160 TemplateName N) {
161 std::string NameStr;
162 raw_string_ostream OS(NameStr);
163 LangOptions LO;
164 LO.CPlusPlus = true;
165 LO.Bool = true;
166 OS << '\'';
167 N.print(OS, PrintingPolicy(LO));
168 OS << '\'';
169 OS.flush();
170 return DB << NameStr;
171 }
172
dump(raw_ostream & OS) const173 void TemplateName::dump(raw_ostream &OS) const {
174 LangOptions LO; // FIXME!
175 LO.CPlusPlus = true;
176 LO.Bool = true;
177 print(OS, PrintingPolicy(LO));
178 }
179
dump() const180 void TemplateName::dump() const {
181 dump(llvm::errs());
182 }
183