/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/clang/lib/AST/TemplateName.cpp
Line | Count | Source (jump to first uncovered line) |
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 |
26 | 11 | SubstTemplateTemplateParmPackStorage::getArgumentPack() const { |
27 | 11 | return TemplateArgument(llvm::makeArrayRef(Arguments, size())); |
28 | 11 | } |
29 | | |
30 | 3.42k | void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { |
31 | 3.42k | Profile(ID, Parameter, Replacement); |
32 | 3.42k | } |
33 | | |
34 | | void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, |
35 | | TemplateTemplateParmDecl *parameter, |
36 | 6.31k | TemplateName replacement) { |
37 | 6.31k | ID.AddPointer(parameter); |
38 | 6.31k | ID.AddPointer(replacement.getAsVoidPointer()); |
39 | 6.31k | } |
40 | | |
41 | | void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, |
42 | 2 | ASTContext &Context) { |
43 | 2 | Profile(ID, Context, Parameter, getArgumentPack()); |
44 | 2 | } |
45 | | |
46 | | void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, |
47 | | ASTContext &Context, |
48 | | TemplateTemplateParmDecl *Parameter, |
49 | 12 | const TemplateArgument &ArgPack) { |
50 | 12 | ID.AddPointer(Parameter); |
51 | 12 | ArgPack.Profile(ID, Context); |
52 | 12 | } |
53 | | |
54 | 248k | TemplateName::TemplateName(void *Ptr) { |
55 | 248k | Storage = StorageType::getFromOpaqueValue(Ptr); |
56 | 248k | } |
57 | | |
58 | 312k | TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {} |
59 | | TemplateName::TemplateName(OverloadedTemplateStorage *Storage) |
60 | 3.70k | : Storage(Storage) {} |
61 | | TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage) |
62 | 2.89k | : Storage(Storage) {} |
63 | | TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage) |
64 | 10 | : Storage(Storage) {} |
65 | 5.69k | TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {} |
66 | 1.26k | TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {} |
67 | | |
68 | 31.4k | bool TemplateName::isNull() const { return Storage.isNull(); } |
69 | | |
70 | 161k | TemplateName::NameKind TemplateName::getKind() const { |
71 | 161k | if (Storage.is<TemplateDecl *>()) |
72 | 154k | return Template; |
73 | 6.74k | if (6.74k Storage.is<DependentTemplateName *>()6.74k ) |
74 | 209 | return DependentTemplate; |
75 | 6.53k | if (6.53k Storage.is<QualifiedTemplateName *>()6.53k ) |
76 | 2.50k | return QualifiedTemplate; |
77 | 4.03k | |
78 | 4.03k | UncommonTemplateNameStorage *uncommon |
79 | 4.03k | = Storage.get<UncommonTemplateNameStorage*>(); |
80 | 4.03k | if (uncommon->getAsOverloadedStorage()) |
81 | 3.72k | return OverloadedTemplate; |
82 | 308 | if (308 uncommon->getAsSubstTemplateTemplateParm()308 ) |
83 | 304 | return SubstTemplateTemplateParm; |
84 | 4 | return SubstTemplateTemplateParmPack; |
85 | 4 | } |
86 | | |
87 | 1.27M | TemplateDecl *TemplateName::getAsTemplateDecl() const { |
88 | 1.27M | if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) |
89 | 1.24M | return Template; |
90 | 27.1k | |
91 | 27.1k | if (QualifiedTemplateName *27.1k QTN27.1k = getAsQualifiedTemplateName()) |
92 | 12.3k | return QTN->getTemplateDecl(); |
93 | 14.8k | |
94 | 14.8k | if (SubstTemplateTemplateParmStorage *14.8k sub14.8k = getAsSubstTemplateTemplateParm()) |
95 | 14.1k | return sub->getReplacement().getAsTemplateDecl(); |
96 | 612 | |
97 | 612 | return nullptr; |
98 | 612 | } |
99 | | |
100 | 30.8k | OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const { |
101 | 30.8k | if (UncommonTemplateNameStorage *Uncommon = |
102 | 30.8k | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
103 | 3.73k | return Uncommon->getAsOverloadedStorage(); |
104 | 27.0k | |
105 | 27.0k | return nullptr; |
106 | 27.0k | } |
107 | | |
108 | | SubstTemplateTemplateParmStorage * |
109 | 157k | TemplateName::getAsSubstTemplateTemplateParm() const { |
110 | 157k | if (UncommonTemplateNameStorage *uncommon = |
111 | 157k | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
112 | 16.2k | return uncommon->getAsSubstTemplateTemplateParm(); |
113 | 141k | |
114 | 141k | return nullptr; |
115 | 141k | } |
116 | | |
117 | | SubstTemplateTemplateParmPackStorage * |
118 | 24.1k | TemplateName::getAsSubstTemplateTemplateParmPack() const { |
119 | 24.1k | if (UncommonTemplateNameStorage *Uncommon = |
120 | 24.1k | Storage.dyn_cast<UncommonTemplateNameStorage *>()) |
121 | 275 | return Uncommon->getAsSubstTemplateTemplateParmPack(); |
122 | 23.9k | |
123 | 23.9k | return nullptr; |
124 | 23.9k | } |
125 | | |
126 | 358k | QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { |
127 | 358k | return Storage.dyn_cast<QualifiedTemplateName *>(); |
128 | 358k | } |
129 | | |
130 | 288k | DependentTemplateName *TemplateName::getAsDependentTemplateName() const { |
131 | 288k | return Storage.dyn_cast<DependentTemplateName *>(); |
132 | 288k | } |
133 | | |
134 | 2.88k | TemplateName TemplateName::getNameToSubstitute() const { |
135 | 2.88k | TemplateDecl *Decl = getAsTemplateDecl(); |
136 | 2.88k | |
137 | 2.88k | // Substituting a dependent template name: preserve it as written. |
138 | 2.88k | if (!Decl) |
139 | 34 | return *this; |
140 | 2.85k | |
141 | 2.85k | // If we have a template declaration, use the most recent non-friend |
142 | 2.85k | // declaration of that template. |
143 | 2.85k | Decl = cast<TemplateDecl>(Decl->getMostRecentDecl()); |
144 | 2.85k | while (Decl->getFriendObjectKind()2.85k ) { |
145 | 0 | Decl = cast<TemplateDecl>(Decl->getPreviousDecl()); |
146 | 0 | assert(Decl && "all declarations of template are friends"); |
147 | 0 | } |
148 | 2.88k | return TemplateName(Decl); |
149 | 2.88k | } |
150 | | |
151 | 146k | bool TemplateName::isDependent() const { |
152 | 146k | if (TemplateDecl *Template146k = getAsTemplateDecl()) { |
153 | 146k | if (isa<TemplateTemplateParmDecl>(Template)) |
154 | 1.57k | return true; |
155 | 145k | // FIXME: Hack, getDeclContext() can be null if Template is still |
156 | 145k | // initializing due to PCH reading, so we check it before using it. |
157 | 145k | // Should probably modify TemplateSpecializationType to allow constructing |
158 | 145k | // it without the isDependent() checking. |
159 | 145k | return Template->getDeclContext() && |
160 | 145k | Template->getDeclContext()->isDependentContext(); |
161 | 146k | } |
162 | 83 | |
163 | 146k | assert(!getAsOverloadedTemplate() && |
164 | 83 | "overloaded templates shouldn't survive to here"); |
165 | 83 | |
166 | 83 | return true; |
167 | 83 | } |
168 | | |
169 | 5.04k | bool TemplateName::isInstantiationDependent() const { |
170 | 5.04k | if (QualifiedTemplateName *QTN5.04k = getAsQualifiedTemplateName()) { |
171 | 237 | if (QTN->getQualifier()->isInstantiationDependent()) |
172 | 0 | return true; |
173 | 5.04k | } |
174 | 5.04k | |
175 | 5.04k | return isDependent(); |
176 | 5.04k | } |
177 | | |
178 | 230k | bool TemplateName::containsUnexpandedParameterPack() const { |
179 | 230k | if (TemplateDecl *Template230k = getAsTemplateDecl()) { |
180 | 230k | if (TemplateTemplateParmDecl *TTP |
181 | 230k | = dyn_cast<TemplateTemplateParmDecl>(Template)) |
182 | 1.86k | return TTP->isParameterPack(); |
183 | 229k | |
184 | 229k | return false; |
185 | 229k | } |
186 | 86 | |
187 | 86 | if (DependentTemplateName *86 DTN86 = getAsDependentTemplateName()) |
188 | 55 | return DTN->getQualifier() && |
189 | 55 | DTN->getQualifier()->containsUnexpandedParameterPack(); |
190 | 31 | |
191 | 31 | return getAsSubstTemplateTemplateParmPack() != nullptr; |
192 | 31 | } |
193 | | |
194 | | void |
195 | | TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, |
196 | 5.84k | bool SuppressNNS) const { |
197 | 5.84k | if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>()) |
198 | 5.71k | OS << *Template; |
199 | 131 | else if (QualifiedTemplateName *131 QTN131 = getAsQualifiedTemplateName()) { |
200 | 39 | if (!SuppressNNS) |
201 | 39 | QTN->getQualifier()->print(OS, Policy); |
202 | 39 | if (QTN->hasTemplateKeyword()) |
203 | 0 | OS << "template "; |
204 | 39 | OS << *QTN->getDecl(); |
205 | 131 | } else if (DependentTemplateName *92 DTN92 = getAsDependentTemplateName()) { |
206 | 8 | if (!SuppressNNS && 8 DTN->getQualifier()8 ) |
207 | 8 | DTN->getQualifier()->print(OS, Policy); |
208 | 8 | OS << "template "; |
209 | 8 | |
210 | 8 | if (DTN->isIdentifier()) |
211 | 0 | OS << DTN->getIdentifier()->getName(); |
212 | 8 | else |
213 | 8 | OS << "operator " << getOperatorSpelling(DTN->getOperator()); |
214 | 92 | } else if (SubstTemplateTemplateParmStorage *84 subst84 |
215 | 81 | = getAsSubstTemplateTemplateParm()) { |
216 | 81 | subst->getReplacement().print(OS, Policy, SuppressNNS); |
217 | 84 | } else if (SubstTemplateTemplateParmPackStorage *3 SubstPack3 |
218 | 3 | = getAsSubstTemplateTemplateParmPack()) |
219 | 0 | OS << *SubstPack->getParameterPack(); |
220 | 3 | else { |
221 | 3 | OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); |
222 | 3 | (*OTS->begin())->printName(OS); |
223 | 3 | } |
224 | 5.84k | } |
225 | | |
226 | | const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, |
227 | 138 | TemplateName N) { |
228 | 138 | std::string NameStr; |
229 | 138 | raw_string_ostream OS(NameStr); |
230 | 138 | LangOptions LO; |
231 | 138 | LO.CPlusPlus = true; |
232 | 138 | LO.Bool = true; |
233 | 138 | OS << '\''; |
234 | 138 | N.print(OS, PrintingPolicy(LO)); |
235 | 138 | OS << '\''; |
236 | 138 | OS.flush(); |
237 | 138 | return DB << NameStr; |
238 | 138 | } |
239 | | |
240 | 15 | void TemplateName::dump(raw_ostream &OS) const { |
241 | 15 | LangOptions LO; // FIXME! |
242 | 15 | LO.CPlusPlus = true; |
243 | 15 | LO.Bool = true; |
244 | 15 | print(OS, PrintingPolicy(LO)); |
245 | 15 | } |
246 | | |
247 | 0 | LLVM_DUMP_METHOD void TemplateName::dump() const { |
248 | 0 | dump(llvm::errs()); |
249 | 0 | } |