blob: 622f7b44cd92e2ff53e97ef4da2ba55a7922d5d4 [file] [log] [blame]
Douglas Gregor841324a2009-08-04 16:50:30 +00001//===------- TreeTransform.h - Semantic Tree Transformation ---------------===/
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// This file implements a semantic tree transformation that takes a given
10// AST and rebuilds it, possibly transforming some nodes in the process.
11//
12//===----------------------------------------------------------------------===/
13#ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H
14#define LLVM_CLANG_SEMA_TREETRANSFORM_H
15
16#include "Sema.h"
17#include <algorithm>
18
19namespace clang {
20
21/// \brief A semantic tree transformation that allows one to transform one
22/// abstract syntax tree into another.
23///
24/// A new tree transformation is defined by creating a new subclass \c X of
25/// \c TreeTransform<X> and then overriding certain operations to provide
26/// behavior specific to that transformation. For example, template
27/// instantiation is implemented as a tree transformation where the
28/// transformation of TemplateTypeParmType nodes involves substituting the
29/// template arguments for their corresponding template parameters; a similar
30/// transformation is performed for non-type template parameters and
31/// template template parameters.
32///
33/// This tree-transformation template uses static polymorphism to allow
34/// subclasses to customize any of its operations. Thus, a subclass can
35/// override any of the transformation or rebuild operators by providing an
36/// operation with the same signature as the default implementation. The
37/// overridding function should not be virtual.
38///
39/// Semantic tree transformations are split into two stages, either of which
40/// can be replaced by a subclass. The "transform" step transforms an AST node
41/// or the parts of an AST node using the various transformation functions,
42/// then passes the pieces on to the "rebuild" step, which constructs a new AST
43/// node of the appropriate kind from the pieces. The default transformation
44/// routines recursively transform the operands to composite AST nodes (e.g.,
45/// the pointee type of a PointerType node) and, if any of those operand nodes
46/// were changed by the transformation, invokes the rebuild operation to create
47/// a new AST node.
48///
49/// Subclasses can customize the transformation at various levels. The
50/// most course-grained transformations involve replacing TransformType(),
51/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifier(),
52/// TransformTemplateName(), or TransformTemplateArgument() with entirely
53/// new implementations.
54///
55/// For more fine-grained transformations, subclasses can replace any of the
56/// \c TransformXXX functions (where XXX is the name of an AST node, e.g.,
57/// PointerType) to alter the transformation. As mentioned previously,
58/// replacing TransformTemplateTypeParmType() allows template instantiation
59/// to substitute template arguments for their corresponding template
60/// parameters. Additionally, subclasses can override the \c RebuildXXX
61/// functions to control how AST nodes are rebuilt when their operands change.
62/// By default, \c TreeTransform will invoke semantic analysis to rebuild
63/// AST nodes. However, certain other tree transformations (e.g, cloning) may
64/// be able to use more efficient rebuild steps.
65///
66/// There are a handful of other functions that can be overridden, allowing one
67/// to avoid traversing nodes that don't need any transformation
68/// (\c AlreadyTransformed()), force rebuilding AST nodes even when their
69/// operands have not changed (\c AlwaysRebuild()), and customize the
70/// default locations and entity names used for type-checking
71/// (\c getBaseLocation(), \c getBaseEntity()).
72///
73/// FIXME: In the future, TreeTransform will support transformation of
74/// statements and expressions as well as types.
75template<typename Derived>
76class TreeTransform {
77protected:
78 Sema &SemaRef;
79
80public:
81 /// \brief Initializes a new tree transformer.
82 TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
83
84 /// \brief Retrieves a reference to the derived class.
85 Derived &getDerived() { return static_cast<Derived&>(*this); }
86
87 /// \brief Retrieves a reference to the derived class.
88 const Derived &getDerived() const {
89 return static_cast<const Derived&>(*this);
90 }
91
92 /// \brief Retrieves a reference to the semantic analysis object used for
93 /// this tree transform.
94 Sema &getSema() const { return SemaRef; }
95
96 /// \brief Whether the transformation should always rebuild AST nodes, even
97 /// if none of the children have changed.
98 ///
99 /// Subclasses may override this function to specify when the transformation
100 /// should rebuild all AST nodes.
101 bool AlwaysRebuild() { return false; }
102
103 /// \brief Returns the location of the entity being transformed, if that
104 /// information was not available elsewhere in the AST.
105 ///
106 /// By default, returns no source-location information. Subclasses can
107 /// provide an alternative implementation that provides better location
108 /// information.
109 SourceLocation getBaseLocation() { return SourceLocation(); }
110
111 /// \brief Returns the name of the entity being transformed, if that
112 /// information was not available elsewhere in the AST.
113 ///
114 /// By default, returns an empty name. Subclasses can provide an alternative
115 /// implementation with a more precise name.
116 DeclarationName getBaseEntity() { return DeclarationName(); }
117
118 /// \brief Determine whether the given type \p T has already been
119 /// transformed.
120 ///
121 /// Subclasses can provide an alternative implementation of this routine
122 /// to short-circuit evaluation when it is known that a given type will
123 /// not change. For example, template instantiation need not traverse
124 /// non-dependent types.
125 bool AlreadyTransformed(QualType T) {
126 return T.isNull();
127 }
128
129 /// \brief Transforms the given type into another type.
130 ///
131 /// By default, this routine transforms a type by delegating to the
132 /// appropriate TransformXXXType to build a new type, then applying
133 /// the qualifiers on \p T to the resulting type with AddTypeQualifiers.
134 /// Subclasses may override this function (to take over all type
135 /// transformations), some set of the TransformXXXType functions, or
136 /// the AddTypeQualifiers function to alter the transformation.
137 ///
138 /// \returns the transformed type.
139 QualType TransformType(QualType T);
140
141 /// \brief Transform the given type by adding the given set of qualifiers
142 /// and returning the result.
143 ///
144 /// FIXME: By default, this routine adds type qualifiers only to types that
145 /// can have qualifiers, and silently suppresses those qualifiers that are
146 /// not permitted (e.g., qualifiers on reference or function types). This
147 /// is the right thing for template instantiation, but probably not for
148 /// other clients.
149 QualType AddTypeQualifiers(QualType T, unsigned CVRQualifiers);
150
151 /// \brief Transform the given expression.
152 ///
153 /// FIXME: At the moment, subclasses must override this.
154 Sema::OwningExprResult TransformExpr(Expr *E);
155
156 /// \brief Transform the given declaration, which is referenced from a type
157 /// or expression.
158 ///
159 /// Subclasses must override this.
160 Decl *TransformDecl(Decl *D);
161
162 /// \brief Transform the given nested-name-specifier.
163 ///
164 /// Subclasses must override this.
165 NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
166 SourceRange Range);
167
168 /// \brief Transform the given template name.
169 ///
170 /// FIXME: At the moment, subclasses must override this.
171 TemplateName TransformTemplateName(TemplateName Template);
172
173 /// \brief Transform the given template argument.
174 ///
175 /// FIXME: At the moment, subclasses must override this.
176 TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
177
178#define ABSTRACT_TYPE(CLASS, PARENT)
179#define TYPE(CLASS, PARENT) \
180 QualType Transform##CLASS##Type(const CLASS##Type *T);
181#include "clang/AST/TypeNodes.def"
182
183 /// \brief Build a new pointer type given its pointee type.
184 ///
185 /// By default, performs semantic analysis when building the pointer type.
186 /// Subclasses may override this routine to provide different behavior.
187 QualType RebuildPointerType(QualType PointeeType);
188
189 /// \brief Build a new block pointer type given its pointee type.
190 ///
191 /// By default, performs semantic analysis when building the block pointer
192 /// type. Subclasses may override this routine to provide different behavior.
193 QualType RebuildBlockPointerType(QualType PointeeType);
194
195 /// \brief Build a new lvalue reference type given the type it references.
196 ///
197 /// By default, performs semantic analysis when building the lvalue reference
198 /// type. Subclasses may override this routine to provide different behavior.
199 QualType RebuildLValueReferenceType(QualType ReferentType);
200
201 /// \brief Build a new rvalue reference type given the type it references.
202 ///
203 /// By default, performs semantic analysis when building the rvalue reference
204 /// type. Subclasses may override this routine to provide different behavior.
205 QualType RebuildRValueReferenceType(QualType ReferentType);
206
207 /// \brief Build a new member pointer type given the pointee type and the
208 /// class type it refers into.
209 ///
210 /// By default, performs semantic analysis when building the member pointer
211 /// type. Subclasses may override this routine to provide different behavior.
212 QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType);
213
214 /// \brief Build a new array type given the element type, size
215 /// modifier, size of the array (if known), size expression, and index type
216 /// qualifiers.
217 ///
218 /// By default, performs semantic analysis when building the array type.
219 /// Subclasses may override this routine to provide different behavior.
220 /// Also by default, all of the other Rebuild*Array
221 QualType RebuildArrayType(QualType ElementType,
222 ArrayType::ArraySizeModifier SizeMod,
223 const llvm::APInt *Size,
224 Expr *SizeExpr,
225 unsigned IndexTypeQuals,
226 SourceRange BracketsRange);
227
228 /// \brief Build a new constant array type given the element type, size
229 /// modifier, (known) size of the array, and index type qualifiers.
230 ///
231 /// By default, performs semantic analysis when building the array type.
232 /// Subclasses may override this routine to provide different behavior.
233 QualType RebuildConstantArrayType(QualType ElementType,
234 ArrayType::ArraySizeModifier SizeMod,
235 const llvm::APInt &Size,
236 unsigned IndexTypeQuals);
237
238 /// \brief Build a new constant array type given the element type, size
239 /// modifier, (known) size of the array, size expression, and index type
240 /// qualifiers.
241 ///
242 /// By default, performs semantic analysis when building the array type.
243 /// Subclasses may override this routine to provide different behavior.
244 QualType RebuildConstantArrayWithExprType(QualType ElementType,
245 ArrayType::ArraySizeModifier SizeMod,
246 const llvm::APInt &Size,
247 Expr *SizeExpr,
248 unsigned IndexTypeQuals,
249 SourceRange BracketsRange);
250
251 /// \brief Build a new constant array type given the element type, size
252 /// modifier, (known) size of the array, and index type qualifiers.
253 ///
254 /// By default, performs semantic analysis when building the array type.
255 /// Subclasses may override this routine to provide different behavior.
256 QualType RebuildConstantArrayWithoutExprType(QualType ElementType,
257 ArrayType::ArraySizeModifier SizeMod,
258 const llvm::APInt &Size,
259 unsigned IndexTypeQuals);
260
261 /// \brief Build a new incomplete array type given the element type, size
262 /// modifier, and index type qualifiers.
263 ///
264 /// By default, performs semantic analysis when building the array type.
265 /// Subclasses may override this routine to provide different behavior.
266 QualType RebuildIncompleteArrayType(QualType ElementType,
267 ArrayType::ArraySizeModifier SizeMod,
268 unsigned IndexTypeQuals);
269
270 /// \brief Build a new variable-length array type given the element type,
271 /// size modifier, size expression, and index type qualifiers.
272 ///
273 /// By default, performs semantic analysis when building the array type.
274 /// Subclasses may override this routine to provide different behavior.
275 QualType RebuildVariableArrayType(QualType ElementType,
276 ArrayType::ArraySizeModifier SizeMod,
277 Sema::ExprArg SizeExpr,
278 unsigned IndexTypeQuals,
279 SourceRange BracketsRange);
280
281 /// \brief Build a new dependent-sized array type given the element type,
282 /// size modifier, size expression, and index type qualifiers.
283 ///
284 /// By default, performs semantic analysis when building the array type.
285 /// Subclasses may override this routine to provide different behavior.
286 QualType RebuildDependentSizedArrayType(QualType ElementType,
287 ArrayType::ArraySizeModifier SizeMod,
288 Sema::ExprArg SizeExpr,
289 unsigned IndexTypeQuals,
290 SourceRange BracketsRange);
291
292 /// \brief Build a new vector type given the element type and
293 /// number of elements.
294 ///
295 /// By default, performs semantic analysis when building the vector type.
296 /// Subclasses may override this routine to provide different behavior.
297 QualType RebuildVectorType(QualType ElementType, unsigned NumElements);
298
299 /// \brief Build a new extended vector type given the element type and
300 /// number of elements.
301 ///
302 /// By default, performs semantic analysis when building the vector type.
303 /// Subclasses may override this routine to provide different behavior.
304 QualType RebuildExtVectorType(QualType ElementType, unsigned NumElements,
305 SourceLocation AttributeLoc);
306
307 /// \brief Build a new potentially dependently-sized extended vector type
308 /// given the element type and number of elements.
309 ///
310 /// By default, performs semantic analysis when building the vector type.
311 /// Subclasses may override this routine to provide different behavior.
312 QualType RebuildDependentSizedExtVectorType(QualType ElementType,
313 Sema::ExprArg SizeExpr,
314 SourceLocation AttributeLoc);
315
316 /// \brief Build a new function type.
317 ///
318 /// By default, performs semantic analysis when building the function type.
319 /// Subclasses may override this routine to provide different behavior.
320 QualType RebuildFunctionProtoType(QualType T,
321 QualType *ParamTypes,
322 unsigned NumParamTypes,
323 bool Variadic, unsigned Quals);
324
325 /// \brief Build a new typedef type.
326 QualType RebuildTypedefType(TypedefDecl *Typedef) {
327 return SemaRef.Context.getTypeDeclType(Typedef);
328 }
329
330 /// \brief Build a new class/struct/union type.
331 QualType RebuildRecordType(RecordDecl *Record) {
332 return SemaRef.Context.getTypeDeclType(Record);
333 }
334
335 /// \brief Build a new Enum type.
336 QualType RebuildEnumType(EnumDecl *Enum) {
337 return SemaRef.Context.getTypeDeclType(Enum);
338 }
339
340 /// \brief Build a new typeof(expr) type.
341 ///
342 /// By default, performs semantic analysis when building the typeof type.
343 /// Subclasses may override this routine to provide different behavior.
344 QualType RebuildTypeOfExprType(Sema::ExprArg Underlying);
345
346 /// \brief Build a new typeof(type) type.
347 ///
348 /// By default, builds a new TypeOfType with the given underlying type.
349 QualType RebuildTypeOfType(QualType Underlying);
350
351 /// \brief Build a new C++0x decltype type.
352 ///
353 /// By default, performs semantic analysis when building the decltype type.
354 /// Subclasses may override this routine to provide different behavior.
355 QualType RebuildDecltypeType(Sema::ExprArg Underlying);
356
357 /// \brief Build a new template specialization type.
358 ///
359 /// By default, performs semantic analysis when building the template
360 /// specialization type. Subclasses may override this routine to provide
361 /// different behavior.
362 QualType RebuildTemplateSpecializationType(TemplateName Template,
363 const TemplateArgument *Args,
364 unsigned NumArgs);
365
366 /// \brief Build a new qualified name type.
367 ///
368 /// By default, builds a new QualifiedNameType type from the
369 /// nested-name-specifier and the named type. Subclasses may override
370 /// this routine to provide different behavior.
371 QualType RebuildQualifiedNameType(NestedNameSpecifier *NNS, QualType Named) {
372 return SemaRef.Context.getQualifiedNameType(NNS, Named);
373 }
374
375 /// \brief Build a new typename type that refers to a template-id.
376 ///
377 /// By default, builds a new TypenameType type from the nested-name-specifier
378 /// and the given type. Subclasses may override this routine to provide
379 /// different behavior.
380 QualType RebuildTypenameType(NestedNameSpecifier *NNS, QualType T) {
381 if (NNS->isDependent())
382 return SemaRef.Context.getTypenameType(NNS,
383 cast<TemplateSpecializationType>(T));
384
385 return SemaRef.Context.getQualifiedNameType(NNS, T);
386 }
387
388 /// \brief Build a new typename type that refers to an identifier.
389 ///
390 /// By default, performs semantic analysis when building the typename type
391 /// (or qualified name type). Subclasses may override this routine to provide
392 /// different behavior.
393 QualType RebuildTypenameType(NestedNameSpecifier *NNS,
394 const IdentifierInfo *Id) {
395 return SemaRef.CheckTypenameType(NNS, *Id,
396 SourceRange(getDerived().getBaseLocation()));
397 }
398};
399
400//===----------------------------------------------------------------------===//
401// Type transformation
402//===----------------------------------------------------------------------===//
403
404template<typename Derived>
405QualType TreeTransform<Derived>::TransformType(QualType T) {
406 if (getDerived().AlreadyTransformed(T))
407 return T;
408
409 QualType Result;
410 switch (T->getTypeClass()) {
411#define ABSTRACT_TYPE(CLASS, PARENT)
412#define TYPE(CLASS, PARENT) \
413 case Type::CLASS: \
414 Result = getDerived().Transform##CLASS##Type( \
415 static_cast<CLASS##Type*>(T.getTypePtr())); \
416 break;
417#include "clang/AST/TypeNodes.def"
418 }
419
420 if (Result.isNull() || T == Result)
421 return Result;
422
423 return getDerived().AddTypeQualifiers(Result, T.getCVRQualifiers());
424}
425
426template<typename Derived>
427QualType
428TreeTransform<Derived>::AddTypeQualifiers(QualType T, unsigned CVRQualifiers) {
429 if (CVRQualifiers && !T->isFunctionType() && !T->isReferenceType())
430 return T.getWithAdditionalQualifiers(CVRQualifiers);
431
432 return T;
433}
434
435template<typename Derived>
436QualType TreeTransform<Derived>::TransformExtQualType(const ExtQualType *T) {
437 // FIXME: Implement
438 return QualType(T, 0);
439}
440
441template<typename Derived>
442QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) {
443 // Nothing to do
444 return QualType(T, 0);
445}
446
447template<typename Derived>
448QualType TreeTransform<Derived>::TransformFixedWidthIntType(
449 const FixedWidthIntType *T) {
450 // FIXME: Implement
451 return QualType(T, 0);
452}
453
454template<typename Derived>
455QualType TreeTransform<Derived>::TransformComplexType(const ComplexType *T) {
456 // FIXME: Implement
457 return QualType(T, 0);
458}
459
460template<typename Derived>
461QualType TreeTransform<Derived>::TransformPointerType(const PointerType *T) {
462 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
463 if (PointeeType.isNull())
464 return QualType();
465
466 if (!getDerived().AlwaysRebuild() &&
467 PointeeType == T->getPointeeType())
468 return QualType(T, 0);
469
470 return getDerived().RebuildPointerType(PointeeType);
471}
472
473template<typename Derived>
474QualType
475TreeTransform<Derived>::TransformBlockPointerType(const BlockPointerType *T) {
476 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
477 if (PointeeType.isNull())
478 return QualType();
479
480 if (!getDerived().AlwaysRebuild() &&
481 PointeeType == T->getPointeeType())
482 return QualType(T, 0);
483
484 return getDerived().RebuildBlockPointerType(PointeeType);
485}
486
487template<typename Derived>
488QualType
489TreeTransform<Derived>::TransformLValueReferenceType(
490 const LValueReferenceType *T) {
491 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
492 if (PointeeType.isNull())
493 return QualType();
494
495 if (!getDerived().AlwaysRebuild() &&
496 PointeeType == T->getPointeeType())
497 return QualType(T, 0);
498
499 return getDerived().RebuildLValueReferenceType(PointeeType);
500}
501
502template<typename Derived>
503QualType
504TreeTransform<Derived>::TransformRValueReferenceType(
505 const RValueReferenceType *T) {
506 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
507 if (PointeeType.isNull())
508 return QualType();
509
510 if (!getDerived().AlwaysRebuild() &&
511 PointeeType == T->getPointeeType())
512 return QualType(T, 0);
513
514 return getDerived().RebuildRValueReferenceType(PointeeType);
515}
516
517template<typename Derived>
518QualType
519TreeTransform<Derived>::TransformMemberPointerType(const MemberPointerType *T) {
520 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
521 if (PointeeType.isNull())
522 return QualType();
523
524 QualType ClassType = getDerived().TransformType(QualType(T->getClass(), 0));
525 if (ClassType.isNull())
526 return QualType();
527
528 if (!getDerived().AlwaysRebuild() &&
529 PointeeType == T->getPointeeType() &&
530 ClassType == QualType(T->getClass(), 0))
531 return QualType(T, 0);
532
533 return getDerived().RebuildMemberPointerType(PointeeType, ClassType);
534}
535
536template<typename Derived>
537QualType
538TreeTransform<Derived>::TransformConstantArrayType(const ConstantArrayType *T) {
539 QualType ElementType = getDerived().TransformType(T->getElementType());
540 if (ElementType.isNull())
541 return QualType();
542
543 if (!getDerived().AlwaysRebuild() &&
544 ElementType == T->getElementType())
545 return QualType(T, 0);
546
547 return getDerived().RebuildConstantArrayType(ElementType,
548 T->getSizeModifier(),
549 T->getSize(),
550 T->getIndexTypeQualifier());
551}
552
553template<typename Derived>
554QualType
555TreeTransform<Derived>::TransformConstantArrayWithExprType(
556 const ConstantArrayWithExprType *T) {
557 QualType ElementType = getDerived().TransformType(T->getElementType());
558 if (ElementType.isNull())
559 return QualType();
560
561 if (!getDerived().AlwaysRebuild() &&
562 ElementType == T->getElementType())
563 return QualType(T, 0);
564
565 return getDerived().RebuildConstantArrayWithExprType(ElementType,
566 T->getSizeModifier(),
567 T->getSize(),
568 /*FIXME: Transform?*/T->getSizeExpr(),
569 T->getIndexTypeQualifier(),
570 T->getBracketsRange());
571}
572
573template<typename Derived>
574QualType
575TreeTransform<Derived>::TransformConstantArrayWithoutExprType(
576 const ConstantArrayWithoutExprType *T) {
577 QualType ElementType = getDerived().TransformType(T->getElementType());
578 if (ElementType.isNull())
579 return QualType();
580
581 if (!getDerived().AlwaysRebuild() &&
582 ElementType == T->getElementType())
583 return QualType(T, 0);
584
585 return getDerived().RebuildConstantArrayWithoutExprType(ElementType,
586 T->getSizeModifier(),
587 T->getSize(),
588 T->getIndexTypeQualifier());
589}
590
591template<typename Derived>
592QualType TreeTransform<Derived>::TransformIncompleteArrayType(
593 const IncompleteArrayType *T) {
594 QualType ElementType = getDerived().TransformType(T->getElementType());
595 if (ElementType.isNull())
596 return QualType();
597
598 if (!getDerived().AlwaysRebuild() &&
599 ElementType == T->getElementType())
600 return QualType(T, 0);
601
602 return getDerived().RebuildIncompleteArrayType(ElementType,
603 T->getSizeModifier(),
604 T->getIndexTypeQualifier());
605}
606
607template<typename Derived>
608QualType TreeTransform<Derived>::TransformVariableArrayType(
609 const VariableArrayType *T) {
610 QualType ElementType = getDerived().TransformType(T->getElementType());
611 if (ElementType.isNull())
612 return QualType();
613
614 Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
615 if (Size.isInvalid())
616 return QualType();
617
618 if (!getDerived().AlwaysRebuild() &&
619 ElementType == T->getElementType() &&
620 Size.get() == T->getSizeExpr()) {
621 Size.take();
622 return QualType(T, 0);
623 }
624
625 return getDerived().RebuildVariableArrayType(ElementType,
626 T->getSizeModifier(),
627 move(Size),
628 T->getIndexTypeQualifier(),
629 T->getBracketsRange());
630}
631
632template<typename Derived>
633QualType TreeTransform<Derived>::TransformDependentSizedArrayType(
634 const DependentSizedArrayType *T) {
635 QualType ElementType = getDerived().TransformType(T->getElementType());
636 if (ElementType.isNull())
637 return QualType();
638
639 Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
640 if (Size.isInvalid())
641 return QualType();
642
643 if (!getDerived().AlwaysRebuild() &&
644 ElementType == T->getElementType() &&
645 Size.get() == T->getSizeExpr()) {
646 Size.take();
647 return QualType(T, 0);
648 }
649
650 return getDerived().RebuildDependentSizedArrayType(ElementType,
651 T->getSizeModifier(),
652 move(Size),
653 T->getIndexTypeQualifier(),
654 T->getBracketsRange());
655}
656
657template<typename Derived>
658QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
659 const DependentSizedExtVectorType *T) {
660 QualType ElementType = getDerived().TransformType(T->getElementType());
661 if (ElementType.isNull())
662 return QualType();
663
664 Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
665 if (Size.isInvalid())
666 return QualType();
667
668 if (!getDerived().AlwaysRebuild() &&
669 ElementType == T->getElementType() &&
670 Size.get() == T->getSizeExpr()) {
671 Size.take();
672 return QualType(T, 0);
673 }
674
675 return getDerived().RebuildDependentSizedExtVectorType(ElementType,
676 move(Size),
677 T->getAttributeLoc());
678}
679
680template<typename Derived>
681QualType TreeTransform<Derived>::TransformVectorType(const VectorType *T) {
682 QualType ElementType = getDerived().TransformType(T->getElementType());
683 if (ElementType.isNull())
684 return QualType();
685
686 if (!getDerived().AlwaysRebuild() &&
687 ElementType == T->getElementType())
688 return QualType(T, 0);
689
690 return getDerived().RebuildVectorType(ElementType, T->getNumElements());
691}
692
693template<typename Derived>
694QualType
695TreeTransform<Derived>::TransformExtVectorType(const ExtVectorType *T) {
696 QualType ElementType = getDerived().TransformType(T->getElementType());
697 if (ElementType.isNull())
698 return QualType();
699
700 if (!getDerived().AlwaysRebuild() &&
701 ElementType == T->getElementType())
702 return QualType(T, 0);
703
704 return getDerived().RebuildExtVectorType(ElementType, T->getNumElements(),
705 /*FIXME*/SourceLocation());
706}
707
708template<typename Derived>
709QualType TreeTransform<Derived>::TransformFunctionProtoType(
710 const FunctionProtoType *T) {
711 QualType ResultType = getDerived().TransformType(T->getResultType());
712 if (ResultType.isNull())
713 return QualType();
714
715 llvm::SmallVector<QualType, 4> ParamTypes;
716 for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(),
717 ParamEnd = T->arg_type_end();
718 Param != ParamEnd; ++Param) {
719 QualType P = getDerived().TransformType(*Param);
720 if (P.isNull())
721 return QualType();
722
723 ParamTypes.push_back(P);
724 }
725
726 if (!getDerived().AlwaysRebuild() &&
727 ResultType == T->getResultType() &&
728 std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin()))
729 return QualType(T, 0);
730
731 return getDerived().RebuildFunctionProtoType(ResultType, ParamTypes.data(),
732 ParamTypes.size(), T->isVariadic(),
733 T->getTypeQuals());
734}
735
736template<typename Derived>
737QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
738 const FunctionNoProtoType *T) {
739 // FIXME: Implement
740 return QualType(T, 0);
741}
742
743template<typename Derived>
744QualType TreeTransform<Derived>::TransformTypedefType(const TypedefType *T) {
745 TypedefDecl *Typedef
746 = cast_or_null<TypedefDecl>(getDerived().TransformDecl(T->getDecl()));
747 if (!Typedef)
748 return QualType();
749
750 if (!getDerived().AlwaysRebuild() &&
751 Typedef == T->getDecl())
752 return QualType(T, 0);
753
754 return getDerived().RebuildTypedefType(Typedef);
755}
756
757template<typename Derived>
758QualType TreeTransform<Derived>::TransformTypeOfExprType(
759 const TypeOfExprType *T) {
760 Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
761 if (E.isInvalid())
762 return QualType();
763
764 if (!getDerived().AlwaysRebuild() &&
765 E.get() == T->getUnderlyingExpr()) {
766 E.take();
767 return QualType(T, 0);
768 }
769
770 return getDerived().RebuildTypeOfExprType(move(E));
771}
772
773template<typename Derived>
774QualType TreeTransform<Derived>::TransformTypeOfType(const TypeOfType *T) {
775 QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
776 if (Underlying.isNull())
777 return QualType();
778
779 if (!getDerived().AlwaysRebuild() &&
780 Underlying == T->getUnderlyingType())
781 return QualType(T, 0);
782
783 return getDerived().RebuildTypeOfType(Underlying);
784}
785
786template<typename Derived>
787QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) {
788 Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
789 if (E.isInvalid())
790 return QualType();
791
792 if (!getDerived().AlwaysRebuild() &&
793 E.get() == T->getUnderlyingExpr()) {
794 E.take();
795 return QualType(T, 0);
796 }
797
798 return getDerived().RebuildDecltypeType(move(E));
799}
800
801template<typename Derived>
802QualType TreeTransform<Derived>::TransformRecordType(const RecordType *T) {
803 RecordDecl *Record
804 = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
805 if (!Record)
806 return QualType();
807
808 if (!getDerived().AlwaysRebuild() &&
809 Record == T->getDecl())
810 return QualType(T, 0);
811
812 return getDerived().RebuildRecordType(Record);
813}
814
815template<typename Derived>
816QualType TreeTransform<Derived>::TransformEnumType(const EnumType *T) {
817 EnumDecl *Enum
818 = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
819 if (!Enum)
820 return QualType();
821
822 if (!getDerived().AlwaysRebuild() &&
823 Enum == T->getDecl())
824 return QualType(T, 0);
825
826 return getDerived().RebuildEnumType(Enum);
827}
828
829template<typename Derived>
830QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
831 const TemplateTypeParmType *T) {
832 // Nothing to do
833 return QualType(T, 0);
834}
835
836template<typename Derived>
837QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
838 const TemplateSpecializationType *T) {
839 TemplateName Template
840 = getDerived().TransformTemplateName(T->getTemplateName());
841 if (Template.isNull())
842 return QualType();
843
844 llvm::SmallVector<TemplateArgument, 4> NewTemplateArgs;
845 NewTemplateArgs.reserve(T->getNumArgs());
846 for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
847 Arg != ArgEnd; ++Arg) {
848 TemplateArgument NewArg = getDerived().TransformTemplateArgument(*Arg);
849 if (NewArg.isNull())
850 return QualType();
851
852 NewTemplateArgs.push_back(NewArg);
853 }
854
855 // FIXME: early abort if all of the template arguments and such are the
856 // same.
857
858 // FIXME: We're missing the locations of the template name, '<', and '>'.
859 return getDerived().RebuildTemplateSpecializationType(Template,
860 NewTemplateArgs.data(),
861 NewTemplateArgs.size());
862}
863
864template<typename Derived>
865QualType TreeTransform<Derived>::TransformQualifiedNameType(
866 const QualifiedNameType *T) {
867 NestedNameSpecifier *NNS
868 = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
869 SourceRange());
870 if (!NNS)
871 return QualType();
872
873 QualType Named = getDerived().TransformType(T->getNamedType());
874 if (Named.isNull())
875 return QualType();
876
877 if (!getDerived().AlwaysRebuild() &&
878 NNS == T->getQualifier() &&
879 Named == T->getNamedType())
880 return QualType(T, 0);
881
882 return getDerived().RebuildQualifiedNameType(NNS, Named);
883}
884
885template<typename Derived>
886QualType TreeTransform<Derived>::TransformTypenameType(const TypenameType *T) {
887 NestedNameSpecifier *NNS
888 = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
889 SourceRange(getDerived().getBaseLocation()));
890 if (!NNS)
891 return QualType();
892
893 if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
894 QualType NewTemplateId
895 = getDerived().TransformType(QualType(TemplateId, 0));
896 if (NewTemplateId.isNull())
897 return QualType();
898
899 if (!getDerived().AlwaysRebuild() &&
900 NNS == T->getQualifier() &&
901 NewTemplateId == QualType(TemplateId, 0))
902 return QualType(T, 0);
903
904 return getDerived().RebuildTypenameType(NNS, NewTemplateId);
905 }
906
907 return getDerived().RebuildTypenameType(NNS, T->getIdentifier());
908}
909
910template<typename Derived>
911QualType TreeTransform<Derived>::TransformObjCInterfaceType(
912 const ObjCInterfaceType *T) {
913 // FIXME: Implement
914 return QualType(T, 0);
915}
916
917template<typename Derived>
918QualType TreeTransform<Derived>::TransformObjCObjectPointerType(
919 const ObjCObjectPointerType *T) {
920 // FIXME: Implement
921 return QualType(T, 0);
922}
923
924//===----------------------------------------------------------------------===//
925// Type reconstruction
926//===----------------------------------------------------------------------===//
927
928template<typename Derived>
929QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
930 return SemaRef.BuildPointerType(PointeeType, 0,
931 getDerived().getBaseLocation(),
932 getDerived().getBaseEntity());
933}
934
935template<typename Derived>
936QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
937 return SemaRef.BuildBlockPointerType(PointeeType, 0,
938 getDerived().getBaseLocation(),
939 getDerived().getBaseEntity());
940}
941
942template<typename Derived>
943QualType
944TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
945 return SemaRef.BuildReferenceType(ReferentType, true, 0,
946 getDerived().getBaseLocation(),
947 getDerived().getBaseEntity());
948}
949
950template<typename Derived>
951QualType
952TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) {
953 return SemaRef.BuildReferenceType(ReferentType, false, 0,
954 getDerived().getBaseLocation(),
955 getDerived().getBaseEntity());
956}
957
958template<typename Derived>
959QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
960 QualType ClassType) {
961 return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0,
962 getDerived().getBaseLocation(),
963 getDerived().getBaseEntity());
964}
965
966template<typename Derived>
967QualType
968TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
969 ArrayType::ArraySizeModifier SizeMod,
970 const llvm::APInt *Size,
971 Expr *SizeExpr,
972 unsigned IndexTypeQuals,
973 SourceRange BracketsRange) {
974 if (SizeExpr || !Size)
975 return SemaRef.BuildArrayType(ElementType, SizeMod, SizeExpr,
976 IndexTypeQuals, BracketsRange,
977 getDerived().getBaseEntity());
978
979 QualType Types[] = {
980 SemaRef.Context.UnsignedCharTy, SemaRef.Context.UnsignedShortTy,
981 SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy,
982 SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty
983 };
984 const unsigned NumTypes = sizeof(Types) / sizeof(QualType);
985 QualType SizeType;
986 for (unsigned I = 0; I != NumTypes; ++I)
987 if (Size->getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) {
988 SizeType = Types[I];
989 break;
990 }
991
992 if (SizeType.isNull())
993 SizeType = SemaRef.Context.getFixedWidthIntType(Size->getBitWidth(), false);
994
995 IntegerLiteral ArraySize(*Size, SizeType, /*FIXME*/BracketsRange.getBegin());
996 return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize,
997 IndexTypeQuals, BracketsRange,
998 getDerived().getBaseEntity());
999}
1000
1001template<typename Derived>
1002QualType
1003TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
1004 ArrayType::ArraySizeModifier SizeMod,
1005 const llvm::APInt &Size,
1006 unsigned IndexTypeQuals) {
1007 return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
1008 IndexTypeQuals, SourceRange());
1009}
1010
1011template<typename Derived>
1012QualType
1013TreeTransform<Derived>::RebuildConstantArrayWithExprType(QualType ElementType,
1014 ArrayType::ArraySizeModifier SizeMod,
1015 const llvm::APInt &Size,
1016 Expr *SizeExpr,
1017 unsigned IndexTypeQuals,
1018 SourceRange BracketsRange) {
1019 return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, SizeExpr,
1020 IndexTypeQuals, BracketsRange);
1021}
1022
1023template<typename Derived>
1024QualType
1025TreeTransform<Derived>::RebuildConstantArrayWithoutExprType(
1026 QualType ElementType,
1027 ArrayType::ArraySizeModifier SizeMod,
1028 const llvm::APInt &Size,
1029 unsigned IndexTypeQuals) {
1030 return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
1031 IndexTypeQuals, SourceRange());
1032}
1033
1034template<typename Derived>
1035QualType
1036TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,
1037 ArrayType::ArraySizeModifier SizeMod,
1038 unsigned IndexTypeQuals) {
1039 return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0,
1040 IndexTypeQuals, SourceRange());
1041}
1042
1043template<typename Derived>
1044QualType
1045TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType,
1046 ArrayType::ArraySizeModifier SizeMod,
1047 Sema::ExprArg SizeExpr,
1048 unsigned IndexTypeQuals,
1049 SourceRange BracketsRange) {
1050 return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
1051 SizeExpr.takeAs<Expr>(),
1052 IndexTypeQuals, BracketsRange);
1053}
1054
1055template<typename Derived>
1056QualType
1057TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
1058 ArrayType::ArraySizeModifier SizeMod,
1059 Sema::ExprArg SizeExpr,
1060 unsigned IndexTypeQuals,
1061 SourceRange BracketsRange) {
1062 return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
1063 SizeExpr.takeAs<Expr>(),
1064 IndexTypeQuals, BracketsRange);
1065}
1066
1067template<typename Derived>
1068QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
1069 unsigned NumElements) {
1070 // FIXME: semantic checking!
1071 return SemaRef.Context.getVectorType(ElementType, NumElements);
1072}
1073
1074template<typename Derived>
1075QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
1076 unsigned NumElements,
1077 SourceLocation AttributeLoc) {
1078 llvm::APInt numElements(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy),
1079 NumElements, true);
1080 IntegerLiteral *VectorSize
1081 = new (SemaRef.Context) IntegerLiteral(numElements, SemaRef.Context.IntTy,
1082 AttributeLoc);
1083 return SemaRef.BuildExtVectorType(ElementType, SemaRef.Owned(VectorSize),
1084 AttributeLoc);
1085}
1086
1087template<typename Derived>
1088QualType
1089TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType,
1090 Sema::ExprArg SizeExpr,
1091 SourceLocation AttributeLoc) {
1092 return SemaRef.BuildExtVectorType(ElementType, move(SizeExpr), AttributeLoc);
1093}
1094
1095template<typename Derived>
1096QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,
1097 QualType *ParamTypes,
1098 unsigned NumParamTypes,
1099 bool Variadic,
1100 unsigned Quals) {
1101 return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic,
1102 Quals,
1103 getDerived().getBaseLocation(),
1104 getDerived().getBaseEntity());
1105}
1106
1107template<typename Derived>
1108QualType TreeTransform<Derived>::RebuildTypeOfExprType(Sema::ExprArg E) {
1109 return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
1110}
1111
1112template<typename Derived>
1113QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) {
1114 return SemaRef.Context.getTypeOfType(Underlying);
1115}
1116
1117template<typename Derived>
1118QualType TreeTransform<Derived>::RebuildDecltypeType(Sema::ExprArg E) {
1119 return SemaRef.BuildDecltypeType(E.takeAs<Expr>());
1120}
1121
1122template<typename Derived>
1123QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
1124 TemplateName Template,
1125 const TemplateArgument *Args,
1126 unsigned NumArgs) {
1127 // FIXME: Missing source locations for the template name, <, >.
1128 return SemaRef.CheckTemplateIdType(Template, getDerived().getBaseLocation(),
1129 SourceLocation(), Args, NumArgs,
1130 SourceLocation());
1131}
1132
1133} // end namespace clang
1134
1135#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H