blob: 0aefda7f11875bac63c0566754fd54bd63cd6561 [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
Douglas Gregor2999faa2009-08-04 22:27:00 +000050/// most coarse-grained transformations involve replacing TransformType(),
Douglas Gregor841324a2009-08-04 16:50:30 +000051/// 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 ///
Douglas Gregor2999faa2009-08-04 22:27:00 +0000175 /// By default, this operation transforms the type, expression, or
176 /// declaration stored within the template argument and constructs a
177 /// new template argument from the transformed result. Subclasses may
178 /// override this function to provide alternate behavior.
Douglas Gregor841324a2009-08-04 16:50:30 +0000179 TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
180
181#define ABSTRACT_TYPE(CLASS, PARENT)
182#define TYPE(CLASS, PARENT) \
183 QualType Transform##CLASS##Type(const CLASS##Type *T);
184#include "clang/AST/TypeNodes.def"
185
186 /// \brief Build a new pointer type given its pointee type.
187 ///
188 /// By default, performs semantic analysis when building the pointer type.
189 /// Subclasses may override this routine to provide different behavior.
190 QualType RebuildPointerType(QualType PointeeType);
191
192 /// \brief Build a new block pointer type given its pointee type.
193 ///
194 /// By default, performs semantic analysis when building the block pointer
195 /// type. Subclasses may override this routine to provide different behavior.
196 QualType RebuildBlockPointerType(QualType PointeeType);
197
198 /// \brief Build a new lvalue reference type given the type it references.
199 ///
200 /// By default, performs semantic analysis when building the lvalue reference
201 /// type. Subclasses may override this routine to provide different behavior.
202 QualType RebuildLValueReferenceType(QualType ReferentType);
203
204 /// \brief Build a new rvalue reference type given the type it references.
205 ///
206 /// By default, performs semantic analysis when building the rvalue reference
207 /// type. Subclasses may override this routine to provide different behavior.
208 QualType RebuildRValueReferenceType(QualType ReferentType);
209
210 /// \brief Build a new member pointer type given the pointee type and the
211 /// class type it refers into.
212 ///
213 /// By default, performs semantic analysis when building the member pointer
214 /// type. Subclasses may override this routine to provide different behavior.
215 QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType);
216
217 /// \brief Build a new array type given the element type, size
218 /// modifier, size of the array (if known), size expression, and index type
219 /// qualifiers.
220 ///
221 /// By default, performs semantic analysis when building the array type.
222 /// Subclasses may override this routine to provide different behavior.
223 /// Also by default, all of the other Rebuild*Array
224 QualType RebuildArrayType(QualType ElementType,
225 ArrayType::ArraySizeModifier SizeMod,
226 const llvm::APInt *Size,
227 Expr *SizeExpr,
228 unsigned IndexTypeQuals,
229 SourceRange BracketsRange);
230
231 /// \brief Build a new constant array type given the element type, size
232 /// modifier, (known) size of the array, and index type qualifiers.
233 ///
234 /// By default, performs semantic analysis when building the array type.
235 /// Subclasses may override this routine to provide different behavior.
236 QualType RebuildConstantArrayType(QualType ElementType,
237 ArrayType::ArraySizeModifier SizeMod,
238 const llvm::APInt &Size,
239 unsigned IndexTypeQuals);
240
241 /// \brief Build a new constant array type given the element type, size
242 /// modifier, (known) size of the array, size expression, and index type
243 /// qualifiers.
244 ///
245 /// By default, performs semantic analysis when building the array type.
246 /// Subclasses may override this routine to provide different behavior.
247 QualType RebuildConstantArrayWithExprType(QualType ElementType,
248 ArrayType::ArraySizeModifier SizeMod,
249 const llvm::APInt &Size,
250 Expr *SizeExpr,
251 unsigned IndexTypeQuals,
252 SourceRange BracketsRange);
253
254 /// \brief Build a new constant array type given the element type, size
255 /// modifier, (known) size of the array, and index type qualifiers.
256 ///
257 /// By default, performs semantic analysis when building the array type.
258 /// Subclasses may override this routine to provide different behavior.
259 QualType RebuildConstantArrayWithoutExprType(QualType ElementType,
260 ArrayType::ArraySizeModifier SizeMod,
261 const llvm::APInt &Size,
262 unsigned IndexTypeQuals);
263
264 /// \brief Build a new incomplete array type given the element type, size
265 /// modifier, and index type qualifiers.
266 ///
267 /// By default, performs semantic analysis when building the array type.
268 /// Subclasses may override this routine to provide different behavior.
269 QualType RebuildIncompleteArrayType(QualType ElementType,
270 ArrayType::ArraySizeModifier SizeMod,
271 unsigned IndexTypeQuals);
272
273 /// \brief Build a new variable-length array type given the element type,
274 /// size modifier, size expression, and index type qualifiers.
275 ///
276 /// By default, performs semantic analysis when building the array type.
277 /// Subclasses may override this routine to provide different behavior.
278 QualType RebuildVariableArrayType(QualType ElementType,
279 ArrayType::ArraySizeModifier SizeMod,
280 Sema::ExprArg SizeExpr,
281 unsigned IndexTypeQuals,
282 SourceRange BracketsRange);
283
284 /// \brief Build a new dependent-sized array type given the element type,
285 /// size modifier, size expression, and index type qualifiers.
286 ///
287 /// By default, performs semantic analysis when building the array type.
288 /// Subclasses may override this routine to provide different behavior.
289 QualType RebuildDependentSizedArrayType(QualType ElementType,
290 ArrayType::ArraySizeModifier SizeMod,
291 Sema::ExprArg SizeExpr,
292 unsigned IndexTypeQuals,
293 SourceRange BracketsRange);
294
295 /// \brief Build a new vector type given the element type and
296 /// number of elements.
297 ///
298 /// By default, performs semantic analysis when building the vector type.
299 /// Subclasses may override this routine to provide different behavior.
300 QualType RebuildVectorType(QualType ElementType, unsigned NumElements);
301
302 /// \brief Build a new extended vector type given the element type and
303 /// number of elements.
304 ///
305 /// By default, performs semantic analysis when building the vector type.
306 /// Subclasses may override this routine to provide different behavior.
307 QualType RebuildExtVectorType(QualType ElementType, unsigned NumElements,
308 SourceLocation AttributeLoc);
309
310 /// \brief Build a new potentially dependently-sized extended vector type
311 /// given the element type and number of elements.
312 ///
313 /// By default, performs semantic analysis when building the vector type.
314 /// Subclasses may override this routine to provide different behavior.
315 QualType RebuildDependentSizedExtVectorType(QualType ElementType,
316 Sema::ExprArg SizeExpr,
317 SourceLocation AttributeLoc);
318
319 /// \brief Build a new function type.
320 ///
321 /// By default, performs semantic analysis when building the function type.
322 /// Subclasses may override this routine to provide different behavior.
323 QualType RebuildFunctionProtoType(QualType T,
324 QualType *ParamTypes,
325 unsigned NumParamTypes,
326 bool Variadic, unsigned Quals);
327
328 /// \brief Build a new typedef type.
329 QualType RebuildTypedefType(TypedefDecl *Typedef) {
330 return SemaRef.Context.getTypeDeclType(Typedef);
331 }
332
333 /// \brief Build a new class/struct/union type.
334 QualType RebuildRecordType(RecordDecl *Record) {
335 return SemaRef.Context.getTypeDeclType(Record);
336 }
337
338 /// \brief Build a new Enum type.
339 QualType RebuildEnumType(EnumDecl *Enum) {
340 return SemaRef.Context.getTypeDeclType(Enum);
341 }
342
343 /// \brief Build a new typeof(expr) type.
344 ///
345 /// By default, performs semantic analysis when building the typeof type.
346 /// Subclasses may override this routine to provide different behavior.
347 QualType RebuildTypeOfExprType(Sema::ExprArg Underlying);
348
349 /// \brief Build a new typeof(type) type.
350 ///
351 /// By default, builds a new TypeOfType with the given underlying type.
352 QualType RebuildTypeOfType(QualType Underlying);
353
354 /// \brief Build a new C++0x decltype type.
355 ///
356 /// By default, performs semantic analysis when building the decltype type.
357 /// Subclasses may override this routine to provide different behavior.
358 QualType RebuildDecltypeType(Sema::ExprArg Underlying);
359
360 /// \brief Build a new template specialization type.
361 ///
362 /// By default, performs semantic analysis when building the template
363 /// specialization type. Subclasses may override this routine to provide
364 /// different behavior.
365 QualType RebuildTemplateSpecializationType(TemplateName Template,
366 const TemplateArgument *Args,
367 unsigned NumArgs);
368
369 /// \brief Build a new qualified name type.
370 ///
371 /// By default, builds a new QualifiedNameType type from the
372 /// nested-name-specifier and the named type. Subclasses may override
373 /// this routine to provide different behavior.
374 QualType RebuildQualifiedNameType(NestedNameSpecifier *NNS, QualType Named) {
375 return SemaRef.Context.getQualifiedNameType(NNS, Named);
376 }
377
378 /// \brief Build a new typename type that refers to a template-id.
379 ///
380 /// By default, builds a new TypenameType type from the nested-name-specifier
381 /// and the given type. Subclasses may override this routine to provide
382 /// different behavior.
383 QualType RebuildTypenameType(NestedNameSpecifier *NNS, QualType T) {
384 if (NNS->isDependent())
385 return SemaRef.Context.getTypenameType(NNS,
386 cast<TemplateSpecializationType>(T));
387
388 return SemaRef.Context.getQualifiedNameType(NNS, T);
389 }
390
391 /// \brief Build a new typename type that refers to an identifier.
392 ///
393 /// By default, performs semantic analysis when building the typename type
394 /// (or qualified name type). Subclasses may override this routine to provide
395 /// different behavior.
396 QualType RebuildTypenameType(NestedNameSpecifier *NNS,
397 const IdentifierInfo *Id) {
398 return SemaRef.CheckTypenameType(NNS, *Id,
399 SourceRange(getDerived().getBaseLocation()));
400 }
401};
402
Douglas Gregor2999faa2009-08-04 22:27:00 +0000403template<typename Derived>
404TemplateArgument
405TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
406 switch (Arg.getKind()) {
407 case TemplateArgument::Null:
408 case TemplateArgument::Integral:
409 return Arg;
410
411 case TemplateArgument::Type: {
412 QualType T = getDerived().TransformType(Arg.getAsType());
413 if (T.isNull())
414 return TemplateArgument();
415 return TemplateArgument(Arg.getLocation(), T);
416 }
417
418 case TemplateArgument::Declaration: {
419 Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
420 if (!D)
421 return TemplateArgument();
422 return TemplateArgument(Arg.getLocation(), D);
423 }
424
425 case TemplateArgument::Expression: {
426 // Template argument expressions are not potentially evaluated.
427 EnterExpressionEvaluationContext Unevaluated(getSema(),
428 Action::Unevaluated);
429
430 Sema::OwningExprResult E = getDerived().TransformExpr(Arg.getAsExpr());
431 if (E.isInvalid())
432 return TemplateArgument();
433 return TemplateArgument(E.takeAs<Expr>());
434 }
435
436 case TemplateArgument::Pack: {
437 llvm::SmallVector<TemplateArgument, 4> TransformedArgs;
438 TransformedArgs.reserve(Arg.pack_size());
439 for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
440 AEnd = Arg.pack_end();
441 A != AEnd; ++A) {
442 TemplateArgument TA = getDerived().TransformTemplateArgument(*A);
443 if (TA.isNull())
444 return TA;
445
446 TransformedArgs.push_back(TA);
447 }
448 TemplateArgument Result;
449 Result.setArgumentPack(TransformedArgs.data(), TransformedArgs.size(),
450 true);
451 return Result;
452 }
453 }
454
455 // Work around bogus GCC warning
456 return TemplateArgument();
457}
458
Douglas Gregor841324a2009-08-04 16:50:30 +0000459//===----------------------------------------------------------------------===//
460// Type transformation
461//===----------------------------------------------------------------------===//
462
463template<typename Derived>
464QualType TreeTransform<Derived>::TransformType(QualType T) {
465 if (getDerived().AlreadyTransformed(T))
466 return T;
467
468 QualType Result;
469 switch (T->getTypeClass()) {
470#define ABSTRACT_TYPE(CLASS, PARENT)
471#define TYPE(CLASS, PARENT) \
472 case Type::CLASS: \
473 Result = getDerived().Transform##CLASS##Type( \
474 static_cast<CLASS##Type*>(T.getTypePtr())); \
475 break;
476#include "clang/AST/TypeNodes.def"
477 }
478
479 if (Result.isNull() || T == Result)
480 return Result;
481
482 return getDerived().AddTypeQualifiers(Result, T.getCVRQualifiers());
483}
484
485template<typename Derived>
486QualType
487TreeTransform<Derived>::AddTypeQualifiers(QualType T, unsigned CVRQualifiers) {
488 if (CVRQualifiers && !T->isFunctionType() && !T->isReferenceType())
489 return T.getWithAdditionalQualifiers(CVRQualifiers);
490
491 return T;
492}
493
494template<typename Derived>
495QualType TreeTransform<Derived>::TransformExtQualType(const ExtQualType *T) {
496 // FIXME: Implement
497 return QualType(T, 0);
498}
499
500template<typename Derived>
501QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) {
502 // Nothing to do
503 return QualType(T, 0);
504}
505
506template<typename Derived>
507QualType TreeTransform<Derived>::TransformFixedWidthIntType(
508 const FixedWidthIntType *T) {
509 // FIXME: Implement
510 return QualType(T, 0);
511}
512
513template<typename Derived>
514QualType TreeTransform<Derived>::TransformComplexType(const ComplexType *T) {
515 // FIXME: Implement
516 return QualType(T, 0);
517}
518
519template<typename Derived>
520QualType TreeTransform<Derived>::TransformPointerType(const PointerType *T) {
521 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
522 if (PointeeType.isNull())
523 return QualType();
524
525 if (!getDerived().AlwaysRebuild() &&
526 PointeeType == T->getPointeeType())
527 return QualType(T, 0);
528
529 return getDerived().RebuildPointerType(PointeeType);
530}
531
532template<typename Derived>
533QualType
534TreeTransform<Derived>::TransformBlockPointerType(const BlockPointerType *T) {
535 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
536 if (PointeeType.isNull())
537 return QualType();
538
539 if (!getDerived().AlwaysRebuild() &&
540 PointeeType == T->getPointeeType())
541 return QualType(T, 0);
542
543 return getDerived().RebuildBlockPointerType(PointeeType);
544}
545
546template<typename Derived>
547QualType
548TreeTransform<Derived>::TransformLValueReferenceType(
549 const LValueReferenceType *T) {
550 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
551 if (PointeeType.isNull())
552 return QualType();
553
554 if (!getDerived().AlwaysRebuild() &&
555 PointeeType == T->getPointeeType())
556 return QualType(T, 0);
557
558 return getDerived().RebuildLValueReferenceType(PointeeType);
559}
560
561template<typename Derived>
562QualType
563TreeTransform<Derived>::TransformRValueReferenceType(
564 const RValueReferenceType *T) {
565 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
566 if (PointeeType.isNull())
567 return QualType();
568
569 if (!getDerived().AlwaysRebuild() &&
570 PointeeType == T->getPointeeType())
571 return QualType(T, 0);
572
573 return getDerived().RebuildRValueReferenceType(PointeeType);
574}
575
576template<typename Derived>
577QualType
578TreeTransform<Derived>::TransformMemberPointerType(const MemberPointerType *T) {
579 QualType PointeeType = getDerived().TransformType(T->getPointeeType());
580 if (PointeeType.isNull())
581 return QualType();
582
583 QualType ClassType = getDerived().TransformType(QualType(T->getClass(), 0));
584 if (ClassType.isNull())
585 return QualType();
586
587 if (!getDerived().AlwaysRebuild() &&
588 PointeeType == T->getPointeeType() &&
589 ClassType == QualType(T->getClass(), 0))
590 return QualType(T, 0);
591
592 return getDerived().RebuildMemberPointerType(PointeeType, ClassType);
593}
594
595template<typename Derived>
596QualType
597TreeTransform<Derived>::TransformConstantArrayType(const ConstantArrayType *T) {
598 QualType ElementType = getDerived().TransformType(T->getElementType());
599 if (ElementType.isNull())
600 return QualType();
601
602 if (!getDerived().AlwaysRebuild() &&
603 ElementType == T->getElementType())
604 return QualType(T, 0);
605
606 return getDerived().RebuildConstantArrayType(ElementType,
607 T->getSizeModifier(),
608 T->getSize(),
609 T->getIndexTypeQualifier());
610}
611
612template<typename Derived>
613QualType
614TreeTransform<Derived>::TransformConstantArrayWithExprType(
615 const ConstantArrayWithExprType *T) {
616 QualType ElementType = getDerived().TransformType(T->getElementType());
617 if (ElementType.isNull())
618 return QualType();
619
Douglas Gregor2999faa2009-08-04 22:27:00 +0000620 // Array bounds are not potentially evaluated contexts
621 EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
622
623 Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
624 if (Size.isInvalid())
625 return QualType();
626
Douglas Gregor841324a2009-08-04 16:50:30 +0000627 if (!getDerived().AlwaysRebuild() &&
Douglas Gregor2999faa2009-08-04 22:27:00 +0000628 ElementType == T->getElementType() &&
629 Size.get() == T->getSizeExpr())
Douglas Gregor841324a2009-08-04 16:50:30 +0000630 return QualType(T, 0);
631
632 return getDerived().RebuildConstantArrayWithExprType(ElementType,
633 T->getSizeModifier(),
634 T->getSize(),
Douglas Gregor2999faa2009-08-04 22:27:00 +0000635 Size.takeAs<Expr>(),
Douglas Gregor841324a2009-08-04 16:50:30 +0000636 T->getIndexTypeQualifier(),
637 T->getBracketsRange());
638}
639
640template<typename Derived>
641QualType
642TreeTransform<Derived>::TransformConstantArrayWithoutExprType(
643 const ConstantArrayWithoutExprType *T) {
644 QualType ElementType = getDerived().TransformType(T->getElementType());
645 if (ElementType.isNull())
646 return QualType();
647
648 if (!getDerived().AlwaysRebuild() &&
649 ElementType == T->getElementType())
650 return QualType(T, 0);
651
652 return getDerived().RebuildConstantArrayWithoutExprType(ElementType,
653 T->getSizeModifier(),
654 T->getSize(),
655 T->getIndexTypeQualifier());
656}
657
658template<typename Derived>
659QualType TreeTransform<Derived>::TransformIncompleteArrayType(
660 const IncompleteArrayType *T) {
661 QualType ElementType = getDerived().TransformType(T->getElementType());
662 if (ElementType.isNull())
663 return QualType();
664
665 if (!getDerived().AlwaysRebuild() &&
666 ElementType == T->getElementType())
667 return QualType(T, 0);
668
669 return getDerived().RebuildIncompleteArrayType(ElementType,
670 T->getSizeModifier(),
671 T->getIndexTypeQualifier());
672}
673
674template<typename Derived>
675QualType TreeTransform<Derived>::TransformVariableArrayType(
676 const VariableArrayType *T) {
677 QualType ElementType = getDerived().TransformType(T->getElementType());
678 if (ElementType.isNull())
679 return QualType();
680
Douglas Gregor2999faa2009-08-04 22:27:00 +0000681 // Array bounds are not potentially evaluated contexts
682 EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
683
Douglas Gregor841324a2009-08-04 16:50:30 +0000684 Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
685 if (Size.isInvalid())
686 return QualType();
687
688 if (!getDerived().AlwaysRebuild() &&
689 ElementType == T->getElementType() &&
690 Size.get() == T->getSizeExpr()) {
691 Size.take();
692 return QualType(T, 0);
693 }
694
695 return getDerived().RebuildVariableArrayType(ElementType,
696 T->getSizeModifier(),
697 move(Size),
698 T->getIndexTypeQualifier(),
699 T->getBracketsRange());
700}
701
702template<typename Derived>
703QualType TreeTransform<Derived>::TransformDependentSizedArrayType(
704 const DependentSizedArrayType *T) {
705 QualType ElementType = getDerived().TransformType(T->getElementType());
706 if (ElementType.isNull())
707 return QualType();
708
Douglas Gregor2999faa2009-08-04 22:27:00 +0000709 // Array bounds are not potentially evaluated contexts
710 EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
711
Douglas Gregor841324a2009-08-04 16:50:30 +0000712 Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
713 if (Size.isInvalid())
714 return QualType();
715
716 if (!getDerived().AlwaysRebuild() &&
717 ElementType == T->getElementType() &&
718 Size.get() == T->getSizeExpr()) {
719 Size.take();
720 return QualType(T, 0);
721 }
722
723 return getDerived().RebuildDependentSizedArrayType(ElementType,
724 T->getSizeModifier(),
725 move(Size),
726 T->getIndexTypeQualifier(),
727 T->getBracketsRange());
728}
729
730template<typename Derived>
731QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
732 const DependentSizedExtVectorType *T) {
733 QualType ElementType = getDerived().TransformType(T->getElementType());
734 if (ElementType.isNull())
735 return QualType();
736
Douglas Gregor2999faa2009-08-04 22:27:00 +0000737 // Vector sizes are not potentially evaluated contexts
738 EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
739
Douglas Gregor841324a2009-08-04 16:50:30 +0000740 Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
741 if (Size.isInvalid())
742 return QualType();
743
744 if (!getDerived().AlwaysRebuild() &&
745 ElementType == T->getElementType() &&
746 Size.get() == T->getSizeExpr()) {
747 Size.take();
748 return QualType(T, 0);
749 }
750
751 return getDerived().RebuildDependentSizedExtVectorType(ElementType,
752 move(Size),
753 T->getAttributeLoc());
754}
755
756template<typename Derived>
757QualType TreeTransform<Derived>::TransformVectorType(const VectorType *T) {
758 QualType ElementType = getDerived().TransformType(T->getElementType());
759 if (ElementType.isNull())
760 return QualType();
761
762 if (!getDerived().AlwaysRebuild() &&
763 ElementType == T->getElementType())
764 return QualType(T, 0);
765
766 return getDerived().RebuildVectorType(ElementType, T->getNumElements());
767}
768
769template<typename Derived>
770QualType
771TreeTransform<Derived>::TransformExtVectorType(const ExtVectorType *T) {
772 QualType ElementType = getDerived().TransformType(T->getElementType());
773 if (ElementType.isNull())
774 return QualType();
775
776 if (!getDerived().AlwaysRebuild() &&
777 ElementType == T->getElementType())
778 return QualType(T, 0);
779
780 return getDerived().RebuildExtVectorType(ElementType, T->getNumElements(),
781 /*FIXME*/SourceLocation());
782}
783
784template<typename Derived>
785QualType TreeTransform<Derived>::TransformFunctionProtoType(
786 const FunctionProtoType *T) {
787 QualType ResultType = getDerived().TransformType(T->getResultType());
788 if (ResultType.isNull())
789 return QualType();
790
791 llvm::SmallVector<QualType, 4> ParamTypes;
792 for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(),
793 ParamEnd = T->arg_type_end();
794 Param != ParamEnd; ++Param) {
795 QualType P = getDerived().TransformType(*Param);
796 if (P.isNull())
797 return QualType();
798
799 ParamTypes.push_back(P);
800 }
801
802 if (!getDerived().AlwaysRebuild() &&
803 ResultType == T->getResultType() &&
804 std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin()))
805 return QualType(T, 0);
806
807 return getDerived().RebuildFunctionProtoType(ResultType, ParamTypes.data(),
808 ParamTypes.size(), T->isVariadic(),
809 T->getTypeQuals());
810}
811
812template<typename Derived>
813QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
814 const FunctionNoProtoType *T) {
815 // FIXME: Implement
816 return QualType(T, 0);
817}
818
819template<typename Derived>
820QualType TreeTransform<Derived>::TransformTypedefType(const TypedefType *T) {
821 TypedefDecl *Typedef
822 = cast_or_null<TypedefDecl>(getDerived().TransformDecl(T->getDecl()));
823 if (!Typedef)
824 return QualType();
825
826 if (!getDerived().AlwaysRebuild() &&
827 Typedef == T->getDecl())
828 return QualType(T, 0);
829
830 return getDerived().RebuildTypedefType(Typedef);
831}
832
833template<typename Derived>
834QualType TreeTransform<Derived>::TransformTypeOfExprType(
835 const TypeOfExprType *T) {
Douglas Gregor2999faa2009-08-04 22:27:00 +0000836 // typeof expressions are not potentially evaluated contexts
837 EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
838
Douglas Gregor841324a2009-08-04 16:50:30 +0000839 Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
840 if (E.isInvalid())
841 return QualType();
842
843 if (!getDerived().AlwaysRebuild() &&
844 E.get() == T->getUnderlyingExpr()) {
845 E.take();
846 return QualType(T, 0);
847 }
848
849 return getDerived().RebuildTypeOfExprType(move(E));
850}
851
852template<typename Derived>
853QualType TreeTransform<Derived>::TransformTypeOfType(const TypeOfType *T) {
854 QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
855 if (Underlying.isNull())
856 return QualType();
857
858 if (!getDerived().AlwaysRebuild() &&
859 Underlying == T->getUnderlyingType())
860 return QualType(T, 0);
861
862 return getDerived().RebuildTypeOfType(Underlying);
863}
864
865template<typename Derived>
866QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) {
Douglas Gregor2999faa2009-08-04 22:27:00 +0000867 // decltype expressions are not potentially evaluated contexts
868 EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
869
Douglas Gregor841324a2009-08-04 16:50:30 +0000870 Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
871 if (E.isInvalid())
872 return QualType();
873
874 if (!getDerived().AlwaysRebuild() &&
875 E.get() == T->getUnderlyingExpr()) {
876 E.take();
877 return QualType(T, 0);
878 }
879
880 return getDerived().RebuildDecltypeType(move(E));
881}
882
883template<typename Derived>
884QualType TreeTransform<Derived>::TransformRecordType(const RecordType *T) {
885 RecordDecl *Record
886 = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
887 if (!Record)
888 return QualType();
889
890 if (!getDerived().AlwaysRebuild() &&
891 Record == T->getDecl())
892 return QualType(T, 0);
893
894 return getDerived().RebuildRecordType(Record);
895}
896
897template<typename Derived>
898QualType TreeTransform<Derived>::TransformEnumType(const EnumType *T) {
899 EnumDecl *Enum
900 = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
901 if (!Enum)
902 return QualType();
903
904 if (!getDerived().AlwaysRebuild() &&
905 Enum == T->getDecl())
906 return QualType(T, 0);
907
908 return getDerived().RebuildEnumType(Enum);
909}
910
911template<typename Derived>
912QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
913 const TemplateTypeParmType *T) {
914 // Nothing to do
915 return QualType(T, 0);
916}
917
918template<typename Derived>
919QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
920 const TemplateSpecializationType *T) {
921 TemplateName Template
922 = getDerived().TransformTemplateName(T->getTemplateName());
923 if (Template.isNull())
924 return QualType();
925
926 llvm::SmallVector<TemplateArgument, 4> NewTemplateArgs;
927 NewTemplateArgs.reserve(T->getNumArgs());
928 for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
929 Arg != ArgEnd; ++Arg) {
930 TemplateArgument NewArg = getDerived().TransformTemplateArgument(*Arg);
931 if (NewArg.isNull())
932 return QualType();
933
934 NewTemplateArgs.push_back(NewArg);
935 }
936
937 // FIXME: early abort if all of the template arguments and such are the
938 // same.
939
940 // FIXME: We're missing the locations of the template name, '<', and '>'.
941 return getDerived().RebuildTemplateSpecializationType(Template,
942 NewTemplateArgs.data(),
943 NewTemplateArgs.size());
944}
945
946template<typename Derived>
947QualType TreeTransform<Derived>::TransformQualifiedNameType(
948 const QualifiedNameType *T) {
949 NestedNameSpecifier *NNS
950 = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
951 SourceRange());
952 if (!NNS)
953 return QualType();
954
955 QualType Named = getDerived().TransformType(T->getNamedType());
956 if (Named.isNull())
957 return QualType();
958
959 if (!getDerived().AlwaysRebuild() &&
960 NNS == T->getQualifier() &&
961 Named == T->getNamedType())
962 return QualType(T, 0);
963
964 return getDerived().RebuildQualifiedNameType(NNS, Named);
965}
966
967template<typename Derived>
968QualType TreeTransform<Derived>::TransformTypenameType(const TypenameType *T) {
969 NestedNameSpecifier *NNS
970 = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
971 SourceRange(getDerived().getBaseLocation()));
972 if (!NNS)
973 return QualType();
974
975 if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
976 QualType NewTemplateId
977 = getDerived().TransformType(QualType(TemplateId, 0));
978 if (NewTemplateId.isNull())
979 return QualType();
980
981 if (!getDerived().AlwaysRebuild() &&
982 NNS == T->getQualifier() &&
983 NewTemplateId == QualType(TemplateId, 0))
984 return QualType(T, 0);
985
986 return getDerived().RebuildTypenameType(NNS, NewTemplateId);
987 }
988
989 return getDerived().RebuildTypenameType(NNS, T->getIdentifier());
990}
991
992template<typename Derived>
993QualType TreeTransform<Derived>::TransformObjCInterfaceType(
994 const ObjCInterfaceType *T) {
995 // FIXME: Implement
996 return QualType(T, 0);
997}
998
999template<typename Derived>
1000QualType TreeTransform<Derived>::TransformObjCObjectPointerType(
1001 const ObjCObjectPointerType *T) {
1002 // FIXME: Implement
1003 return QualType(T, 0);
1004}
1005
1006//===----------------------------------------------------------------------===//
1007// Type reconstruction
1008//===----------------------------------------------------------------------===//
1009
1010template<typename Derived>
1011QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
1012 return SemaRef.BuildPointerType(PointeeType, 0,
1013 getDerived().getBaseLocation(),
1014 getDerived().getBaseEntity());
1015}
1016
1017template<typename Derived>
1018QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
1019 return SemaRef.BuildBlockPointerType(PointeeType, 0,
1020 getDerived().getBaseLocation(),
1021 getDerived().getBaseEntity());
1022}
1023
1024template<typename Derived>
1025QualType
1026TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
1027 return SemaRef.BuildReferenceType(ReferentType, true, 0,
1028 getDerived().getBaseLocation(),
1029 getDerived().getBaseEntity());
1030}
1031
1032template<typename Derived>
1033QualType
1034TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) {
1035 return SemaRef.BuildReferenceType(ReferentType, false, 0,
1036 getDerived().getBaseLocation(),
1037 getDerived().getBaseEntity());
1038}
1039
1040template<typename Derived>
1041QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
1042 QualType ClassType) {
1043 return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0,
1044 getDerived().getBaseLocation(),
1045 getDerived().getBaseEntity());
1046}
1047
1048template<typename Derived>
1049QualType
1050TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
1051 ArrayType::ArraySizeModifier SizeMod,
1052 const llvm::APInt *Size,
1053 Expr *SizeExpr,
1054 unsigned IndexTypeQuals,
1055 SourceRange BracketsRange) {
1056 if (SizeExpr || !Size)
1057 return SemaRef.BuildArrayType(ElementType, SizeMod, SizeExpr,
1058 IndexTypeQuals, BracketsRange,
1059 getDerived().getBaseEntity());
1060
1061 QualType Types[] = {
1062 SemaRef.Context.UnsignedCharTy, SemaRef.Context.UnsignedShortTy,
1063 SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy,
1064 SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty
1065 };
1066 const unsigned NumTypes = sizeof(Types) / sizeof(QualType);
1067 QualType SizeType;
1068 for (unsigned I = 0; I != NumTypes; ++I)
1069 if (Size->getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) {
1070 SizeType = Types[I];
1071 break;
1072 }
1073
1074 if (SizeType.isNull())
1075 SizeType = SemaRef.Context.getFixedWidthIntType(Size->getBitWidth(), false);
1076
1077 IntegerLiteral ArraySize(*Size, SizeType, /*FIXME*/BracketsRange.getBegin());
1078 return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize,
1079 IndexTypeQuals, BracketsRange,
1080 getDerived().getBaseEntity());
1081}
1082
1083template<typename Derived>
1084QualType
1085TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
1086 ArrayType::ArraySizeModifier SizeMod,
1087 const llvm::APInt &Size,
1088 unsigned IndexTypeQuals) {
1089 return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
1090 IndexTypeQuals, SourceRange());
1091}
1092
1093template<typename Derived>
1094QualType
1095TreeTransform<Derived>::RebuildConstantArrayWithExprType(QualType ElementType,
1096 ArrayType::ArraySizeModifier SizeMod,
1097 const llvm::APInt &Size,
1098 Expr *SizeExpr,
1099 unsigned IndexTypeQuals,
1100 SourceRange BracketsRange) {
1101 return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, SizeExpr,
1102 IndexTypeQuals, BracketsRange);
1103}
1104
1105template<typename Derived>
1106QualType
1107TreeTransform<Derived>::RebuildConstantArrayWithoutExprType(
1108 QualType ElementType,
1109 ArrayType::ArraySizeModifier SizeMod,
1110 const llvm::APInt &Size,
1111 unsigned IndexTypeQuals) {
1112 return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
1113 IndexTypeQuals, SourceRange());
1114}
1115
1116template<typename Derived>
1117QualType
1118TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,
1119 ArrayType::ArraySizeModifier SizeMod,
1120 unsigned IndexTypeQuals) {
1121 return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0,
1122 IndexTypeQuals, SourceRange());
1123}
1124
1125template<typename Derived>
1126QualType
1127TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType,
1128 ArrayType::ArraySizeModifier SizeMod,
1129 Sema::ExprArg SizeExpr,
1130 unsigned IndexTypeQuals,
1131 SourceRange BracketsRange) {
1132 return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
1133 SizeExpr.takeAs<Expr>(),
1134 IndexTypeQuals, BracketsRange);
1135}
1136
1137template<typename Derived>
1138QualType
1139TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
1140 ArrayType::ArraySizeModifier SizeMod,
1141 Sema::ExprArg SizeExpr,
1142 unsigned IndexTypeQuals,
1143 SourceRange BracketsRange) {
1144 return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
1145 SizeExpr.takeAs<Expr>(),
1146 IndexTypeQuals, BracketsRange);
1147}
1148
1149template<typename Derived>
1150QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
1151 unsigned NumElements) {
1152 // FIXME: semantic checking!
1153 return SemaRef.Context.getVectorType(ElementType, NumElements);
1154}
1155
1156template<typename Derived>
1157QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
1158 unsigned NumElements,
1159 SourceLocation AttributeLoc) {
1160 llvm::APInt numElements(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy),
1161 NumElements, true);
1162 IntegerLiteral *VectorSize
1163 = new (SemaRef.Context) IntegerLiteral(numElements, SemaRef.Context.IntTy,
1164 AttributeLoc);
1165 return SemaRef.BuildExtVectorType(ElementType, SemaRef.Owned(VectorSize),
1166 AttributeLoc);
1167}
1168
1169template<typename Derived>
1170QualType
1171TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType,
1172 Sema::ExprArg SizeExpr,
1173 SourceLocation AttributeLoc) {
1174 return SemaRef.BuildExtVectorType(ElementType, move(SizeExpr), AttributeLoc);
1175}
1176
1177template<typename Derived>
1178QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,
1179 QualType *ParamTypes,
1180 unsigned NumParamTypes,
1181 bool Variadic,
1182 unsigned Quals) {
1183 return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic,
1184 Quals,
1185 getDerived().getBaseLocation(),
1186 getDerived().getBaseEntity());
1187}
1188
1189template<typename Derived>
1190QualType TreeTransform<Derived>::RebuildTypeOfExprType(Sema::ExprArg E) {
1191 return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
1192}
1193
1194template<typename Derived>
1195QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) {
1196 return SemaRef.Context.getTypeOfType(Underlying);
1197}
1198
1199template<typename Derived>
1200QualType TreeTransform<Derived>::RebuildDecltypeType(Sema::ExprArg E) {
1201 return SemaRef.BuildDecltypeType(E.takeAs<Expr>());
1202}
1203
1204template<typename Derived>
1205QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
1206 TemplateName Template,
1207 const TemplateArgument *Args,
1208 unsigned NumArgs) {
1209 // FIXME: Missing source locations for the template name, <, >.
1210 return SemaRef.CheckTemplateIdType(Template, getDerived().getBaseLocation(),
1211 SourceLocation(), Args, NumArgs,
1212 SourceLocation());
1213}
1214
1215} // end namespace clang
1216
1217#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H