1 | //===- CanonicalType.h - C Language Family Type Representation --*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines the CanQual class template, which provides access to |
10 | // canonical types. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_CLANG_AST_CANONICALTYPE_H |
15 | #define LLVM_CLANG_AST_CANONICALTYPE_H |
16 | |
17 | #include "clang/AST/Type.h" |
18 | #include "clang/Basic/Diagnostic.h" |
19 | #include "clang/Basic/SourceLocation.h" |
20 | #include "llvm/ADT/ArrayRef.h" |
21 | #include "llvm/ADT/FoldingSet.h" |
22 | #include "llvm/ADT/iterator.h" |
23 | #include "llvm/Support/Casting.h" |
24 | #include "llvm/Support/PointerLikeTypeTraits.h" |
25 | #include <cassert> |
26 | #include <iterator> |
27 | #include <type_traits> |
28 | |
29 | namespace clang { |
30 | |
31 | template<typename T> class CanProxy; |
32 | template<typename T> struct CanProxyAdaptor; |
33 | class CXXRecordDecl; |
34 | class EnumDecl; |
35 | class Expr; |
36 | class IdentifierInfo; |
37 | class ObjCInterfaceDecl; |
38 | class RecordDecl; |
39 | class TagDecl; |
40 | class TemplateTypeParmDecl; |
41 | |
42 | //----------------------------------------------------------------------------// |
43 | // Canonical, qualified type template |
44 | //----------------------------------------------------------------------------// |
45 | |
46 | /// Represents a canonical, potentially-qualified type. |
47 | /// |
48 | /// The CanQual template is a lightweight smart pointer that provides access |
49 | /// to the canonical representation of a type, where all typedefs and other |
50 | /// syntactic sugar has been eliminated. A CanQualType may also have various |
51 | /// qualifiers (const, volatile, restrict) attached to it. |
52 | /// |
53 | /// The template type parameter @p T is one of the Type classes (PointerType, |
54 | /// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that |
55 | /// type (or some subclass of that type). The typedef @c CanQualType is just |
56 | /// a shorthand for @c CanQual<Type>. |
57 | /// |
58 | /// An instance of @c CanQual<T> can be implicitly converted to a |
59 | /// @c CanQual<U> when T is derived from U, which essentially provides an |
60 | /// implicit upcast. For example, @c CanQual<LValueReferenceType> can be |
61 | /// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can |
62 | /// be implicitly converted to a QualType, but the reverse operation requires |
63 | /// a call to ASTContext::getCanonicalType(). |
64 | template<typename T = Type> |
65 | class CanQual { |
66 | /// The actual, canonical type. |
67 | QualType Stored; |
68 | |
69 | public: |
70 | /// Constructs a NULL canonical type. |
71 | CanQual() = default; |
72 | |
73 | /// Converting constructor that permits implicit upcasting of |
74 | /// canonical type pointers. |
75 | template <typename U> |
76 | CanQual(const CanQual<U> &Other, |
77 | std::enable_if_t<std::is_base_of<T, U>::value, int> = 0); |
78 | |
79 | /// Retrieve the underlying type pointer, which refers to a |
80 | /// canonical type. |
81 | /// |
82 | /// The underlying pointer must not be nullptr. |
83 | const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); } |
84 | |
85 | /// Retrieve the underlying type pointer, which refers to a |
86 | /// canonical type, or nullptr. |
87 | const T *getTypePtrOrNull() const { |
88 | return cast_or_null<T>(Stored.getTypePtrOrNull()); |
89 | } |
90 | |
91 | /// Implicit conversion to a qualified type. |
92 | operator QualType() const { return Stored; } |
93 | |
94 | /// Implicit conversion to bool. |
95 | explicit operator bool() const { return !isNull(); } |
96 | |
97 | bool isNull() const { |
98 | return Stored.isNull(); |
99 | } |
100 | |
101 | SplitQualType split() const { return Stored.split(); } |
102 | |
103 | /// Retrieve a canonical type pointer with a different static type, |
104 | /// upcasting or downcasting as needed. |
105 | /// |
106 | /// The getAs() function is typically used to try to downcast to a |
107 | /// more specific (canonical) type in the type system. For example: |
108 | /// |
109 | /// @code |
110 | /// void f(CanQual<Type> T) { |
111 | /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { |
112 | /// // look at Ptr's pointee type |
113 | /// } |
114 | /// } |
115 | /// @endcode |
116 | /// |
117 | /// \returns A proxy pointer to the same type, but with the specified |
118 | /// static type (@p U). If the dynamic type is not the specified static type |
119 | /// or a derived class thereof, a NULL canonical type. |
120 | template<typename U> CanProxy<U> getAs() const; |
121 | |
122 | template<typename U> CanProxy<U> castAs() const; |
123 | |
124 | /// Overloaded arrow operator that produces a canonical type |
125 | /// proxy. |
126 | CanProxy<T> operator->() const; |
127 | |
128 | /// Retrieve all qualifiers. |
129 | Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); } |
130 | |
131 | /// Retrieve the const/volatile/restrict qualifiers. |
132 | unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); } |
133 | |
134 | /// Determines whether this type has any qualifiers |
135 | bool hasQualifiers() const { return Stored.hasLocalQualifiers(); } |
136 | |
137 | bool isConstQualified() const { |
138 | return Stored.isLocalConstQualified(); |
139 | } |
140 | |
141 | bool isVolatileQualified() const { |
142 | return Stored.isLocalVolatileQualified(); |
143 | } |
144 | |
145 | bool isRestrictQualified() const { |
146 | return Stored.isLocalRestrictQualified(); |
147 | } |
148 | |
149 | /// Determines if this canonical type is furthermore |
150 | /// canonical as a parameter. The parameter-canonicalization |
151 | /// process decays arrays to pointers and drops top-level qualifiers. |
152 | bool isCanonicalAsParam() const { |
153 | return Stored.isCanonicalAsParam(); |
154 | } |
155 | |
156 | /// Retrieve the unqualified form of this type. |
157 | CanQual<T> getUnqualifiedType() const; |
158 | |
159 | /// Retrieves a version of this type with const applied. |
160 | /// Note that this does not always yield a canonical type. |
161 | QualType withConst() const { |
162 | return Stored.withConst(); |
163 | } |
164 | |
165 | /// Determines whether this canonical type is more qualified than |
166 | /// the @p Other canonical type. |
167 | bool isMoreQualifiedThan(CanQual<T> Other) const { |
168 | return Stored.isMoreQualifiedThan(Other.Stored); |
169 | } |
170 | |
171 | /// Determines whether this canonical type is at least as qualified as |
172 | /// the @p Other canonical type. |
173 | bool isAtLeastAsQualifiedAs(CanQual<T> Other) const { |
174 | return Stored.isAtLeastAsQualifiedAs(Other.Stored); |
175 | } |
176 | |
177 | /// If the canonical type is a reference type, returns the type that |
178 | /// it refers to; otherwise, returns the type itself. |
179 | CanQual<Type> getNonReferenceType() const; |
180 | |
181 | /// Retrieve the internal representation of this canonical type. |
182 | void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); } |
183 | |
184 | /// Construct a canonical type from its internal representation. |
185 | static CanQual<T> getFromOpaquePtr(void *Ptr); |
186 | |
187 | /// Builds a canonical type from a QualType. |
188 | /// |
189 | /// This routine is inherently unsafe, because it requires the user to |
190 | /// ensure that the given type is a canonical type with the correct |
191 | // (dynamic) type. |
192 | static CanQual<T> CreateUnsafe(QualType Other); |
193 | |
194 | void dump() const { Stored.dump(); } |
195 | |
196 | void Profile(llvm::FoldingSetNodeID &ID) const { |
197 | ID.AddPointer(Ptr: getAsOpaquePtr()); |
198 | } |
199 | }; |
200 | |
201 | template<typename T, typename U> |
202 | inline bool operator==(CanQual<T> x, CanQual<U> y) { |
203 | return x.getAsOpaquePtr() == y.getAsOpaquePtr(); |
204 | } |
205 | |
206 | template<typename T, typename U> |
207 | inline bool operator!=(CanQual<T> x, CanQual<U> y) { |
208 | return x.getAsOpaquePtr() != y.getAsOpaquePtr(); |
209 | } |
210 | |
211 | /// Represents a canonical, potentially-qualified type. |
212 | using CanQualType = CanQual<Type>; |
213 | |
214 | inline CanQualType Type::getCanonicalTypeUnqualified() const { |
215 | return CanQualType::CreateUnsafe(Other: getCanonicalTypeInternal()); |
216 | } |
217 | |
218 | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
219 | CanQualType T) { |
220 | DB << static_cast<QualType>(T); |
221 | return DB; |
222 | } |
223 | |
224 | //----------------------------------------------------------------------------// |
225 | // Internal proxy classes used by canonical types |
226 | //----------------------------------------------------------------------------// |
227 | |
228 | #define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \ |
229 | CanQualType Accessor() const { \ |
230 | return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \ |
231 | } |
232 | |
233 | #define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \ |
234 | Type Accessor() const { return this->getTypePtr()->Accessor(); } |
235 | |
236 | /// Base class of all canonical proxy types, which is responsible for |
237 | /// storing the underlying canonical type and providing basic conversions. |
238 | template<typename T> |
239 | class CanProxyBase { |
240 | protected: |
241 | CanQual<T> Stored; |
242 | |
243 | public: |
244 | /// Retrieve the pointer to the underlying Type |
245 | const T *getTypePtr() const { return Stored.getTypePtr(); } |
246 | |
247 | /// Implicit conversion to the underlying pointer. |
248 | /// |
249 | /// Also provides the ability to use canonical type proxies in a Boolean |
250 | // context,e.g., |
251 | /// @code |
252 | /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... } |
253 | /// @endcode |
254 | operator const T*() const { return this->Stored.getTypePtrOrNull(); } |
255 | |
256 | /// Try to convert the given canonical type to a specific structural |
257 | /// type. |
258 | template<typename U> CanProxy<U> getAs() const { |
259 | return this->Stored.template getAs<U>(); |
260 | } |
261 | |
262 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass) |
263 | |
264 | // Type predicates |
265 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType) |
266 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType) |
267 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessType) |
268 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessBuiltinType) |
269 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType) |
270 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType) |
271 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType) |
272 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType) |
273 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType) |
274 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType) |
275 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType) |
276 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType) |
277 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType) |
278 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType) |
279 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType) |
280 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType) |
281 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType) |
282 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType) |
283 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType) |
284 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType) |
285 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType) |
286 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType) |
287 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType) |
288 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType) |
289 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType) |
290 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType) |
291 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType) |
292 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType) |
293 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType) |
294 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType) |
295 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType) |
296 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType) |
297 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType) |
298 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType) |
299 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) |
300 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) |
301 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) |
302 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) |
303 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) |
304 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation) |
305 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation) |
306 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation) |
307 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation) |
308 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) |
309 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) |
310 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType) |
311 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType) |
312 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType) |
313 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) |
314 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl) |
315 | |
316 | /// Retrieve the proxy-adaptor type. |
317 | /// |
318 | /// This arrow operator is used when CanProxyAdaptor has been specialized |
319 | /// for the given type T. In that case, we reference members of the |
320 | /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden |
321 | /// by the arrow operator in the primary CanProxyAdaptor template. |
322 | const CanProxyAdaptor<T> *operator->() const { |
323 | return static_cast<const CanProxyAdaptor<T> *>(this); |
324 | } |
325 | }; |
326 | |
327 | /// Replaceable canonical proxy adaptor class that provides the link |
328 | /// between a canonical type and the accessors of the type. |
329 | /// |
330 | /// The CanProxyAdaptor is a replaceable class template that is instantiated |
331 | /// as part of each canonical proxy type. The primary template merely provides |
332 | /// redirection to the underlying type (T), e.g., @c PointerType. One can |
333 | /// provide specializations of this class template for each underlying type |
334 | /// that provide accessors returning canonical types (@c CanQualType) rather |
335 | /// than the more typical @c QualType, to propagate the notion of "canonical" |
336 | /// through the system. |
337 | template<typename T> |
338 | struct CanProxyAdaptor : CanProxyBase<T> {}; |
339 | |
340 | /// Canonical proxy type returned when retrieving the members of a |
341 | /// canonical type or as the result of the @c CanQual<T>::getAs member |
342 | /// function. |
343 | /// |
344 | /// The CanProxy type mainly exists as a proxy through which operator-> will |
345 | /// look to either map down to a raw T* (e.g., PointerType*) or to a proxy |
346 | /// type that provides canonical-type access to the fields of the type. |
347 | template<typename T> |
348 | class CanProxy : public CanProxyAdaptor<T> { |
349 | public: |
350 | /// Build a NULL proxy. |
351 | CanProxy() = default; |
352 | |
353 | /// Build a proxy to the given canonical type. |
354 | CanProxy(CanQual<T> Stored) { this->Stored = Stored; } |
355 | |
356 | /// Implicit conversion to the stored canonical type. |
357 | operator CanQual<T>() const { return this->Stored; } |
358 | }; |
359 | |
360 | } // namespace clang |
361 | |
362 | namespace llvm { |
363 | |
364 | /// Implement simplify_type for CanQual<T>, so that we can dyn_cast from |
365 | /// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. |
366 | /// to return smart pointer (proxies?). |
367 | template<typename T> |
368 | struct simplify_type< ::clang::CanQual<T>> { |
369 | using SimpleType = const T *; |
370 | |
371 | static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) { |
372 | return Val.getTypePtr(); |
373 | } |
374 | }; |
375 | |
376 | // Teach SmallPtrSet that CanQual<T> is "basically a pointer". |
377 | template<typename T> |
378 | struct PointerLikeTypeTraits<clang::CanQual<T>> { |
379 | static void *getAsVoidPointer(clang::CanQual<T> P) { |
380 | return P.getAsOpaquePtr(); |
381 | } |
382 | |
383 | static clang::CanQual<T> getFromVoidPointer(void *P) { |
384 | return clang::CanQual<T>::getFromOpaquePtr(P); |
385 | } |
386 | |
387 | // qualifier information is encoded in the low bits. |
388 | static constexpr int NumLowBitsAvailable = 0; |
389 | }; |
390 | |
391 | } // namespace llvm |
392 | |
393 | namespace clang { |
394 | |
395 | //----------------------------------------------------------------------------// |
396 | // Canonical proxy adaptors for canonical type nodes. |
397 | //----------------------------------------------------------------------------// |
398 | |
399 | /// Iterator adaptor that turns an iterator over canonical QualTypes |
400 | /// into an iterator over CanQualTypes. |
401 | template <typename InputIterator> |
402 | struct CanTypeIterator |
403 | : llvm::iterator_adaptor_base< |
404 | CanTypeIterator<InputIterator>, InputIterator, |
405 | typename std::iterator_traits<InputIterator>::iterator_category, |
406 | CanQualType, |
407 | typename std::iterator_traits<InputIterator>::difference_type, |
408 | CanProxy<Type>, CanQualType> { |
409 | CanTypeIterator() = default; |
410 | explicit CanTypeIterator(InputIterator Iter) |
411 | : CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {} |
412 | |
413 | CanQualType operator*() const { return CanQualType::CreateUnsafe(Other: *this->I); } |
414 | CanProxy<Type> operator->() const; |
415 | }; |
416 | |
417 | template<> |
418 | struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> { |
419 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |
420 | }; |
421 | |
422 | template<> |
423 | struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> { |
424 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
425 | }; |
426 | |
427 | template<> |
428 | struct CanProxyAdaptor<BlockPointerType> |
429 | : public CanProxyBase<BlockPointerType> { |
430 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
431 | }; |
432 | |
433 | template<> |
434 | struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> { |
435 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
436 | }; |
437 | |
438 | template<> |
439 | struct CanProxyAdaptor<LValueReferenceType> |
440 | : public CanProxyBase<LValueReferenceType> { |
441 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
442 | }; |
443 | |
444 | template<> |
445 | struct CanProxyAdaptor<RValueReferenceType> |
446 | : public CanProxyBase<RValueReferenceType> { |
447 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
448 | }; |
449 | |
450 | template<> |
451 | struct CanProxyAdaptor<MemberPointerType> |
452 | : public CanProxyBase<MemberPointerType> { |
453 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
454 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass) |
455 | }; |
456 | |
457 | // CanProxyAdaptors for arrays are intentionally unimplemented because |
458 | // they are not safe. |
459 | template<> struct CanProxyAdaptor<ArrayType>; |
460 | template<> struct CanProxyAdaptor<ConstantArrayType>; |
461 | template<> struct CanProxyAdaptor<IncompleteArrayType>; |
462 | template<> struct CanProxyAdaptor<VariableArrayType>; |
463 | template<> struct CanProxyAdaptor<DependentSizedArrayType>; |
464 | |
465 | template<> |
466 | struct CanProxyAdaptor<DependentSizedExtVectorType> |
467 | : public CanProxyBase<DependentSizedExtVectorType> { |
468 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |
469 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr) |
470 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc) |
471 | }; |
472 | |
473 | template<> |
474 | struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> { |
475 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |
476 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) |
477 | }; |
478 | |
479 | template<> |
480 | struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { |
481 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |
482 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) |
483 | }; |
484 | |
485 | template<> |
486 | struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { |
487 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) |
488 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) |
489 | }; |
490 | |
491 | template<> |
492 | struct CanProxyAdaptor<FunctionNoProtoType> |
493 | : public CanProxyBase<FunctionNoProtoType> { |
494 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) |
495 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) |
496 | }; |
497 | |
498 | template<> |
499 | struct CanProxyAdaptor<FunctionProtoType> |
500 | : public CanProxyBase<FunctionProtoType> { |
501 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) |
502 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) |
503 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams) |
504 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos) |
505 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR( |
506 | ArrayRef<FunctionProtoType::ExtParameterInfo>, getExtParameterInfos) |
507 | |
508 | CanQualType getParamType(unsigned i) const { |
509 | return CanQualType::CreateUnsafe(Other: this->getTypePtr()->getParamType(i)); |
510 | } |
511 | |
512 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) |
513 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getMethodQuals) |
514 | |
515 | using param_type_iterator = |
516 | CanTypeIterator<FunctionProtoType::param_type_iterator>; |
517 | |
518 | param_type_iterator param_type_begin() const { |
519 | return param_type_iterator(this->getTypePtr()->param_type_begin()); |
520 | } |
521 | |
522 | param_type_iterator param_type_end() const { |
523 | return param_type_iterator(this->getTypePtr()->param_type_end()); |
524 | } |
525 | |
526 | // Note: canonical function types never have exception specifications |
527 | }; |
528 | |
529 | template<> |
530 | struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> { |
531 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnmodifiedType) |
532 | }; |
533 | |
534 | template<> |
535 | struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> { |
536 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr) |
537 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) |
538 | }; |
539 | |
540 | template <> |
541 | struct CanProxyAdaptor<UnaryTransformType> |
542 | : public CanProxyBase<UnaryTransformType> { |
543 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) |
544 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) |
545 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind) |
546 | }; |
547 | |
548 | template<> |
549 | struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> { |
550 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl) |
551 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) |
552 | }; |
553 | |
554 | template<> |
555 | struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> { |
556 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl) |
557 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) |
558 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields) |
559 | }; |
560 | |
561 | template<> |
562 | struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> { |
563 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl) |
564 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) |
565 | }; |
566 | |
567 | template<> |
568 | struct CanProxyAdaptor<TemplateTypeParmType> |
569 | : public CanProxyBase<TemplateTypeParmType> { |
570 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) |
571 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) |
572 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) |
573 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl) |
574 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier) |
575 | }; |
576 | |
577 | template<> |
578 | struct CanProxyAdaptor<ObjCObjectType> |
579 | : public CanProxyBase<ObjCObjectType> { |
580 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) |
581 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *, |
582 | getInterface) |
583 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId) |
584 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass) |
585 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) |
586 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) |
587 | |
588 | using qual_iterator = ObjCObjectPointerType::qual_iterator; |
589 | |
590 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) |
591 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) |
592 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) |
593 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) |
594 | }; |
595 | |
596 | template<> |
597 | struct CanProxyAdaptor<ObjCObjectPointerType> |
598 | : public CanProxyBase<ObjCObjectPointerType> { |
599 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |
600 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *, |
601 | getInterfaceType) |
602 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType) |
603 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType) |
604 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType) |
605 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType) |
606 | |
607 | using qual_iterator = ObjCObjectPointerType::qual_iterator; |
608 | |
609 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) |
610 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) |
611 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) |
612 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) |
613 | }; |
614 | |
615 | //----------------------------------------------------------------------------// |
616 | // Method and function definitions |
617 | //----------------------------------------------------------------------------// |
618 | template<typename T> |
619 | inline CanQual<T> CanQual<T>::getUnqualifiedType() const { |
620 | return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType()); |
621 | } |
622 | |
623 | template<typename T> |
624 | inline CanQual<Type> CanQual<T>::getNonReferenceType() const { |
625 | if (CanQual<ReferenceType> RefType = getAs<ReferenceType>()) |
626 | return RefType->getPointeeType(); |
627 | else |
628 | return *this; |
629 | } |
630 | |
631 | template<typename T> |
632 | CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { |
633 | CanQual<T> Result; |
634 | Result.Stored = QualType::getFromOpaquePtr(Ptr); |
635 | assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 || |
636 | Result.Stored.isCanonical()) && "Type is not canonical!" ); |
637 | return Result; |
638 | } |
639 | |
640 | template<typename T> |
641 | CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { |
642 | assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!" ); |
643 | assert((Other.isNull() || isa<T>(Other.getTypePtr())) && |
644 | "Dynamic type does not meet the static type's requires" ); |
645 | CanQual<T> Result; |
646 | Result.Stored = Other; |
647 | return Result; |
648 | } |
649 | |
650 | template<typename T> |
651 | template<typename U> |
652 | CanProxy<U> CanQual<T>::getAs() const { |
653 | static_assert(!TypeIsArrayType<T>::value, |
654 | "ArrayType cannot be used with getAs!" ); |
655 | |
656 | if (Stored.isNull()) |
657 | return CanProxy<U>(); |
658 | |
659 | if (isa<U>(Stored.getTypePtr())) |
660 | return CanQual<U>::CreateUnsafe(Stored); |
661 | |
662 | return CanProxy<U>(); |
663 | } |
664 | |
665 | template<typename T> |
666 | template<typename U> |
667 | CanProxy<U> CanQual<T>::castAs() const { |
668 | static_assert(!TypeIsArrayType<U>::value, |
669 | "ArrayType cannot be used with castAs!" ); |
670 | |
671 | assert(!Stored.isNull() && isa<U>(Stored.getTypePtr())); |
672 | return CanQual<U>::CreateUnsafe(Stored); |
673 | } |
674 | |
675 | template<typename T> |
676 | CanProxy<T> CanQual<T>::operator->() const { |
677 | return CanProxy<T>(*this); |
678 | } |
679 | |
680 | template <typename InputIterator> |
681 | CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const { |
682 | return CanProxy<Type>(*this); |
683 | } |
684 | |
685 | } // namespace clang |
686 | |
687 | #endif // LLVM_CLANG_AST_CANONICALTYPE_H |
688 | |