1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "DeprecatedGenTemplateInstance.h"
27 #include "Overview.h"
28
29 #include <cplusplus/Control.h>
30 #include <cplusplus/Scope.h>
31 #include <cplusplus/Names.h>
32 #include <cplusplus/Symbols.h>
33 #include <cplusplus/CoreTypes.h>
34 #include <cplusplus/Literals.h>
35
36 #include <QVarLengthArray>
37 #include <QDebug>
38
39 using namespace CPlusPlus;
40
41 namespace {
42
43 class ApplySubstitution
44 {
45 public:
46 ApplySubstitution(Control *control, Symbol *symbol, const DeprecatedGenTemplateInstance::Substitution &substitution);
47 ~ApplySubstitution();
48
control() const49 inline Control *control() const { return _control; }
50
51 FullySpecifiedType apply(const Name *name);
52 FullySpecifiedType apply(const FullySpecifiedType &type);
53
54 int findSubstitution(const Identifier *id) const;
55 FullySpecifiedType applySubstitution(int index) const;
56
57 private:
58 class ApplyToType: protected TypeVisitor
59 {
60 public:
ApplyToType(ApplySubstitution * q)61 ApplyToType(ApplySubstitution *q)
62 : q(q) {}
63
operator ()(const FullySpecifiedType & ty)64 FullySpecifiedType operator()(const FullySpecifiedType &ty)
65 {
66 FullySpecifiedType previousType = switchType(ty);
67 accept(ty.type());
68 return switchType(previousType);
69 }
70
71 protected:
72 using TypeVisitor::visit;
73
control() const74 Control *control() const
75 { return q->control(); }
76
switchType(const FullySpecifiedType & type)77 FullySpecifiedType switchType(const FullySpecifiedType &type)
78 {
79 FullySpecifiedType previousType = _type;
80 _type = type;
81 return previousType;
82 }
83
visit(VoidType *)84 void visit(VoidType *) override
85 {
86 // nothing to do
87 }
88
visit(IntegerType *)89 void visit(IntegerType *) override
90 {
91 // nothing to do
92 }
93
visit(FloatType *)94 void visit(FloatType *) override
95 {
96 // nothing to do
97 }
98
visit(PointerToMemberType *)99 void visit(PointerToMemberType *) override
100 {
101 qDebug() << Q_FUNC_INFO; // ### TODO
102 }
103
visit(PointerType * ptrTy)104 void visit(PointerType *ptrTy) override
105 {
106 _type.setType(control()->pointerType(q->apply(ptrTy->elementType())));
107 }
108
visit(ReferenceType * refTy)109 void visit(ReferenceType *refTy) override
110 {
111 _type.setType(control()->referenceType(q->apply(refTy->elementType()), refTy->isRvalueReference()));
112 }
113
visit(ArrayType * arrayTy)114 void visit(ArrayType *arrayTy) override
115 {
116 _type.setType(control()->arrayType(q->apply(arrayTy->elementType()), arrayTy->size()));
117 }
118
visit(NamedType * ty)119 void visit(NamedType *ty) override
120 {
121 FullySpecifiedType n = q->apply(ty->name());
122 _type.setType(n.type());
123 }
124
visit(Function * funTy)125 void visit(Function *funTy) override
126 {
127 Function *fun = control()->newFunction(/*sourceLocation=*/ 0, funTy->name());
128 fun->setEnclosingScope(funTy->enclosingScope());
129 fun->setConst(funTy->isConst());
130 fun->setVolatile(funTy->isVolatile());
131 fun->setVirtual(funTy->isVirtual());
132 fun->setOverride(funTy->isOverride());
133 fun->setFinal(funTy->isFinal());
134 fun->setAmbiguous(funTy->isAmbiguous());
135 fun->setVariadic(funTy->isVariadic());
136
137 fun->setReturnType(q->apply(funTy->returnType()));
138
139 for (int i = 0, argc = funTy->argumentCount(); i < argc; ++i) {
140 Argument *originalArgument = funTy->argumentAt(i)->asArgument();
141 Argument *arg = control()->newArgument(/*sourceLocation*/ 0,
142 originalArgument->name());
143
144 arg->setType(q->apply(originalArgument->type()));
145 arg->setInitializer(originalArgument->initializer());
146 fun->addMember(arg);
147 }
148
149 _type.setType(fun);
150 }
151
visit(Namespace *)152 void visit(Namespace *) override
153 {
154 qDebug() << Q_FUNC_INFO;
155 }
156
visit(Class *)157 void visit(Class *) override
158 {
159 qDebug() << Q_FUNC_INFO;
160 }
161
visit(Enum *)162 void visit(Enum *) override
163 {
164 qDebug() << Q_FUNC_INFO;
165 }
166
visit(ForwardClassDeclaration *)167 void visit(ForwardClassDeclaration *) override
168 {
169 qDebug() << Q_FUNC_INFO;
170 }
171
visit(ObjCClass *)172 void visit(ObjCClass *) override
173 {
174 qDebug() << Q_FUNC_INFO;
175 }
176
visit(ObjCProtocol *)177 void visit(ObjCProtocol *) override
178 {
179 qDebug() << Q_FUNC_INFO;
180 }
181
visit(ObjCMethod *)182 void visit(ObjCMethod *) override
183 {
184 qDebug() << Q_FUNC_INFO;
185 }
186
visit(ObjCForwardClassDeclaration *)187 void visit(ObjCForwardClassDeclaration *) override
188 {
189 qDebug() << Q_FUNC_INFO;
190 }
191
visit(ObjCForwardProtocolDeclaration *)192 void visit(ObjCForwardProtocolDeclaration *) override
193 {
194 qDebug() << Q_FUNC_INFO;
195 }
196
197 private:
198 ApplySubstitution *q;
199 FullySpecifiedType _type;
200 QHash<Symbol *, FullySpecifiedType> _processed;
201 };
202
203 class ApplyToName: protected NameVisitor
204 {
205 public:
ApplyToName(ApplySubstitution * q)206 ApplyToName(ApplySubstitution *q): q(q) {}
207
operator ()(const Name * name)208 FullySpecifiedType operator()(const Name *name)
209 {
210 FullySpecifiedType previousType = switchType(FullySpecifiedType());
211 accept(name);
212 return switchType(previousType);
213 }
214
215 protected:
control() const216 Control *control() const
217 { return q->control(); }
218
findSubstitution(const Identifier * id) const219 int findSubstitution(const Identifier *id) const
220 { return q->findSubstitution(id); }
221
applySubstitution(int index) const222 FullySpecifiedType applySubstitution(int index) const
223 { return q->applySubstitution(index); }
224
switchType(const FullySpecifiedType & type)225 FullySpecifiedType switchType(const FullySpecifiedType &type)
226 {
227 FullySpecifiedType previousType = _type;
228 _type = type;
229 return previousType;
230 }
231
visit(const Identifier * name)232 void visit(const Identifier *name) override
233 {
234 int index = findSubstitution(name->identifier());
235
236 if (index != -1)
237 _type = applySubstitution(index);
238
239 else
240 _type = control()->namedType(name);
241 }
242
visit(const TemplateNameId * name)243 void visit(const TemplateNameId *name) override
244 {
245 QVarLengthArray<TemplateArgument, 8> arguments(name->templateArgumentCount());
246 for (int i = 0; i < name->templateArgumentCount(); ++i) {
247 FullySpecifiedType argTy = name->templateArgumentAt(i).type();
248 arguments[i] = q->apply(argTy);
249 }
250
251 const TemplateNameId *templId = control()->templateNameId(name->identifier(),
252 name->isSpecialization(),
253 arguments.data(),
254 arguments.size());
255 _type = control()->namedType(templId);
256 }
257
instantiate(const Name * name)258 const Name *instantiate(const Name *name)
259 {
260 if (! name)
261 return name;
262
263 if (const Identifier *nameId = name->asNameId()) {
264 const Identifier *id = control()->identifier(nameId->chars(), nameId->size());
265 return id;
266
267 } else if (const TemplateNameId *templId = name->asTemplateNameId()) {
268 QVarLengthArray<TemplateArgument, 8> arguments(templId->templateArgumentCount());
269 for (int templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount();
270 ++templateArgIndex) {
271 FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex).type();
272 arguments[templateArgIndex] = q->apply(argTy);
273 }
274 const Identifier *id = control()->identifier(templId->identifier()->chars(),
275 templId->identifier()->size());
276 return control()->templateNameId(id, templId->isSpecialization(), arguments.data(),
277 arguments.size());
278
279 } else if (const QualifiedNameId *qq = name->asQualifiedNameId()) {
280 const Name *base = instantiate(qq->base());
281 const Name *name = instantiate(qq->name());
282
283 return control()->qualifiedNameId(base, name);
284
285 } else if (const OperatorNameId *op = name->asOperatorNameId()) {
286 return control()->operatorNameId(op->kind());
287
288 } else if (const ConversionNameId *c = name->asConversionNameId()) {
289 FullySpecifiedType ty = q->apply(c->type());
290 return control()->conversionNameId(ty);
291
292 }
293
294 return nullptr;
295 }
296
visit(const QualifiedNameId * name)297 void visit(const QualifiedNameId *name) override
298 {
299 if (const Name *n = instantiate(name))
300 _type = control()->namedType(n);
301 }
302
visit(const DestructorNameId * name)303 void visit(const DestructorNameId *name) override
304 {
305 Overview oo;
306 qWarning() << "ignored name:" << oo.prettyName(name);
307 }
308
visit(const OperatorNameId * name)309 void visit(const OperatorNameId *name) override
310 {
311 Overview oo;
312 qWarning() << "ignored name:" << oo.prettyName(name);
313 }
314
visit(const ConversionNameId * name)315 void visit(const ConversionNameId *name) override
316 {
317 Overview oo;
318 qWarning() << "ignored name:" << oo.prettyName(name);
319 }
320
visit(const SelectorNameId * name)321 void visit(const SelectorNameId *name) override
322 {
323 Overview oo;
324 qWarning() << "ignored name:" << oo.prettyName(name);
325 }
326
327 private:
328 ApplySubstitution *q;
329 FullySpecifiedType _type;
330 };
331
332 public: // attributes
333 Control *_control;
334 Symbol *symbol;
335 DeprecatedGenTemplateInstance::Substitution substitution;
336 ApplyToType applyToType;
337 ApplyToName applyToName;
338 };
339
ApplySubstitution(Control * control,Symbol * symbol,const DeprecatedGenTemplateInstance::Substitution & substitution)340 ApplySubstitution::ApplySubstitution(Control *control, Symbol *symbol,
341 const DeprecatedGenTemplateInstance::Substitution &substitution)
342 : _control(control), symbol(symbol),
343 substitution(substitution),
344 applyToType(this), applyToName(this)
345 { }
346
~ApplySubstitution()347 ApplySubstitution::~ApplySubstitution()
348 {
349 }
350
apply(const Name * name)351 FullySpecifiedType ApplySubstitution::apply(const Name *name)
352 {
353 FullySpecifiedType ty = applyToName(name);
354 return ty;
355 }
356
apply(const FullySpecifiedType & type)357 FullySpecifiedType ApplySubstitution::apply(const FullySpecifiedType &type)
358 {
359 FullySpecifiedType ty = applyToType(type);
360 return ty;
361 }
362
findSubstitution(const Identifier * id) const363 int ApplySubstitution::findSubstitution(const Identifier *id) const
364 {
365 Q_ASSERT(id != nullptr);
366
367 for (int index = 0; index < substitution.size(); ++index) {
368 QPair<const Identifier *, FullySpecifiedType> s = substitution.at(index);
369
370 if (id->match(s.first))
371 return index;
372 }
373
374 return -1;
375 }
376
applySubstitution(int index) const377 FullySpecifiedType ApplySubstitution::applySubstitution(int index) const
378 {
379 Q_ASSERT(index != -1);
380 Q_ASSERT(index < substitution.size());
381
382 return substitution.at(index).second;
383 }
384
385 } // end of anonymous namespace
386
DeprecatedGenTemplateInstance(QSharedPointer<Control> control,const Substitution & substitution)387 DeprecatedGenTemplateInstance::DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution)
388 : _control(control),
389 _substitution(substitution)
390 { }
391
gen(Symbol * symbol)392 FullySpecifiedType DeprecatedGenTemplateInstance::gen(Symbol *symbol)
393 {
394 ApplySubstitution o(_control.data(), symbol, _substitution);
395 return o.apply(symbol->type());
396 }
397
instantiate(const Name * className,Symbol * candidate,QSharedPointer<Control> control)398 FullySpecifiedType DeprecatedGenTemplateInstance::instantiate(const Name *className, Symbol *candidate,
399 QSharedPointer<Control> control)
400 {
401 if (className) {
402 if (const TemplateNameId *templId = className->asTemplateNameId()) {
403 if (Template *templ = candidate->enclosingTemplate()) {
404 DeprecatedGenTemplateInstance::Substitution subst;
405
406 for (int i = 0; i < templId->templateArgumentCount(); ++i) {
407 FullySpecifiedType templArgTy = templId->templateArgumentAt(i).type();
408
409 if (i < templ->templateParameterCount()) {
410 const Name *templArgName = templ->templateParameterAt(i)->name();
411
412 if (templArgName && templArgName->identifier()) {
413 const Identifier *templArgId = templArgName->identifier();
414 subst.append(qMakePair(templArgId, templArgTy));
415 }
416 }
417 }
418
419 DeprecatedGenTemplateInstance inst(control, subst);
420 return inst.gen(candidate);
421 }
422 }
423 }
424 return candidate->type();
425 }
426