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(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(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, isPromotableIntegerType) |

309 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) |

310 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) |

311 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType) |

312 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType) |

313 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType) |

314 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) |

315 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl) |

316 | |

317 | /// Retrieve the proxy-adaptor type. |

318 | /// |

319 | /// This arrow operator is used when CanProxyAdaptor has been specialized |

320 | /// for the given type T. In that case, we reference members of the |

321 | /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden |

322 | /// by the arrow operator in the primary CanProxyAdaptor template. |

323 | const CanProxyAdaptor<T> *operator->() const { |

324 | return static_cast<const CanProxyAdaptor<T> *>(this); |

325 | } |

326 | }; |

327 | |

328 | /// Replaceable canonical proxy adaptor class that provides the link |

329 | /// between a canonical type and the accessors of the type. |

330 | /// |

331 | /// The CanProxyAdaptor is a replaceable class template that is instantiated |

332 | /// as part of each canonical proxy type. The primary template merely provides |

333 | /// redirection to the underlying type (T), e.g., @c PointerType. One can |

334 | /// provide specializations of this class template for each underlying type |

335 | /// that provide accessors returning canonical types (@c CanQualType) rather |

336 | /// than the more typical @c QualType, to propagate the notion of "canonical" |

337 | /// through the system. |

338 | template<typename T> |

339 | struct CanProxyAdaptor : CanProxyBase<T> {}; |

340 | |

341 | /// Canonical proxy type returned when retrieving the members of a |

342 | /// canonical type or as the result of the @c CanQual<T>::getAs member |

343 | /// function. |

344 | /// |

345 | /// The CanProxy type mainly exists as a proxy through which operator-> will |

346 | /// look to either map down to a raw T* (e.g., PointerType*) or to a proxy |

347 | /// type that provides canonical-type access to the fields of the type. |

348 | template<typename T> |

349 | class CanProxy : public CanProxyAdaptor<T> { |

350 | public: |

351 | /// Build a NULL proxy. |

352 | CanProxy() = default; |

353 | |

354 | /// Build a proxy to the given canonical type. |

355 | CanProxy(CanQual<T> Stored) { this->Stored = Stored; } |

356 | |

357 | /// Implicit conversion to the stored canonical type. |

358 | operator CanQual<T>() const { return this->Stored; } |

359 | }; |

360 | |

361 | } // namespace clang |

362 | |

363 | namespace llvm { |

364 | |

365 | /// Implement simplify_type for CanQual<T>, so that we can dyn_cast from |

366 | /// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. |

367 | /// to return smart pointer (proxies?). |

368 | template<typename T> |

369 | struct simplify_type< ::clang::CanQual<T>> { |

370 | using SimpleType = const T *; |

371 | |

372 | static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) { |

373 | return Val.getTypePtr(); |

374 | } |

375 | }; |

376 | |

377 | // Teach SmallPtrSet that CanQual<T> is "basically a pointer". |

378 | template<typename T> |

379 | struct PointerLikeTypeTraits<clang::CanQual<T>> { |

380 | static void *getAsVoidPointer(clang::CanQual<T> P) { |

381 | return P.getAsOpaquePtr(); |

382 | } |

383 | |

384 | static clang::CanQual<T> getFromVoidPointer(void *P) { |

385 | return clang::CanQual<T>::getFromOpaquePtr(P); |

386 | } |

387 | |

388 | // qualifier information is encoded in the low bits. |

389 | static constexpr int NumLowBitsAvailable = 0; |

390 | }; |

391 | |

392 | } // namespace llvm |

393 | |

394 | namespace clang { |

395 | |

396 | //----------------------------------------------------------------------------// |

397 | // Canonical proxy adaptors for canonical type nodes. |

398 | //----------------------------------------------------------------------------// |

399 | |

400 | /// Iterator adaptor that turns an iterator over canonical QualTypes |

401 | /// into an iterator over CanQualTypes. |

402 | template <typename InputIterator> |

403 | struct CanTypeIterator |

404 | : llvm::iterator_adaptor_base< |

405 | CanTypeIterator<InputIterator>, InputIterator, |

406 | typename std::iterator_traits<InputIterator>::iterator_category, |

407 | CanQualType, |

408 | typename std::iterator_traits<InputIterator>::difference_type, |

409 | CanProxy<Type>, CanQualType> { |

410 | CanTypeIterator() = default; |

411 | explicit CanTypeIterator(InputIterator Iter) |

412 | : CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {} |

413 | |

414 | CanQualType operator*() const { return CanQualType::CreateUnsafe(*this->I); } |

415 | CanProxy<Type> operator->() const; |

416 | }; |

417 | |

418 | template<> |

419 | struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> { |

420 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |

421 | }; |

422 | |

423 | template<> |

424 | struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> { |

425 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |

426 | }; |

427 | |

428 | template<> |

429 | struct CanProxyAdaptor<BlockPointerType> |

430 | : public CanProxyBase<BlockPointerType> { |

431 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |

432 | }; |

433 | |

434 | template<> |

435 | struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> { |

436 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |

437 | }; |

438 | |

439 | template<> |

440 | struct CanProxyAdaptor<LValueReferenceType> |

441 | : public CanProxyBase<LValueReferenceType> { |

442 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |

443 | }; |

444 | |

445 | template<> |

446 | struct CanProxyAdaptor<RValueReferenceType> |

447 | : public CanProxyBase<RValueReferenceType> { |

448 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |

449 | }; |

450 | |

451 | template<> |

452 | struct CanProxyAdaptor<MemberPointerType> |

453 | : public CanProxyBase<MemberPointerType> { |

454 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |

455 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass) |

456 | }; |

457 | |

458 | // CanProxyAdaptors for arrays are intentionally unimplemented because |

459 | // they are not safe. |

460 | template<> struct CanProxyAdaptor<ArrayType>; |

461 | template<> struct CanProxyAdaptor<ConstantArrayType>; |

462 | template<> struct CanProxyAdaptor<IncompleteArrayType>; |

463 | template<> struct CanProxyAdaptor<VariableArrayType>; |

464 | template<> struct CanProxyAdaptor<DependentSizedArrayType>; |

465 | |

466 | template<> |

467 | struct CanProxyAdaptor<DependentSizedExtVectorType> |

468 | : public CanProxyBase<DependentSizedExtVectorType> { |

469 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |

470 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr) |

471 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc) |

472 | }; |

473 | |

474 | template<> |

475 | struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> { |

476 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |

477 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) |

478 | }; |

479 | |

480 | template<> |

481 | struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { |

482 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) |

483 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) |

484 | }; |

485 | |

486 | template<> |

487 | struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { |

488 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) |

489 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) |

490 | }; |

491 | |

492 | template<> |

493 | struct CanProxyAdaptor<FunctionNoProtoType> |

494 | : public CanProxyBase<FunctionNoProtoType> { |

495 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) |

496 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) |

497 | }; |

498 | |

499 | template<> |

500 | struct CanProxyAdaptor<FunctionProtoType> |

501 | : public CanProxyBase<FunctionProtoType> { |

502 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) |

503 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) |

504 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams) |

505 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos) |

506 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR( |

507 | ArrayRef<FunctionProtoType::ExtParameterInfo>, getExtParameterInfos) |

508 | |

509 | CanQualType getParamType(unsigned i) const { |

510 | return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i)); |

511 | } |

512 | |

513 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) |

514 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getMethodQuals) |

515 | |

516 | using param_type_iterator = |

517 | CanTypeIterator<FunctionProtoType::param_type_iterator>; |

518 | |

519 | param_type_iterator param_type_begin() const { |

520 | return param_type_iterator(this->getTypePtr()->param_type_begin()); |

521 | } |

522 | |

523 | param_type_iterator param_type_end() const { |

524 | return param_type_iterator(this->getTypePtr()->param_type_end()); |

525 | } |

526 | |

527 | // Note: canonical function types never have exception specifications |

528 | }; |

529 | |

530 | template<> |

531 | struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> { |

532 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) |

533 | }; |

534 | |

535 | template<> |

536 | struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> { |

537 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr) |

538 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) |

539 | }; |

540 | |

541 | template <> |

542 | struct CanProxyAdaptor<UnaryTransformType> |

543 | : public CanProxyBase<UnaryTransformType> { |

544 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) |

545 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) |

546 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind) |

547 | }; |

548 | |

549 | template<> |

550 | struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> { |

551 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl) |

552 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) |

553 | }; |

554 | |

555 | template<> |

556 | struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> { |

557 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl) |

558 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) |

559 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields) |

560 | }; |

561 | |

562 | template<> |

563 | struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> { |

564 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl) |

565 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) |

566 | }; |

567 | |

568 | template<> |

569 | struct CanProxyAdaptor<TemplateTypeParmType> |

570 | : public CanProxyBase<TemplateTypeParmType> { |

571 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) |

572 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) |

573 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) |

574 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl) |

575 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier) |

576 | }; |

577 | |

578 | template<> |

579 | struct CanProxyAdaptor<ObjCObjectType> |

580 | : public CanProxyBase<ObjCObjectType> { |

581 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) |

582 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *, |

583 | getInterface) |

584 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId) |

585 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass) |

586 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) |

587 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) |

588 | |

589 | using qual_iterator = ObjCObjectPointerType::qual_iterator; |

590 | |

591 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) |

592 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) |

593 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) |

594 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) |

595 | }; |

596 | |

597 | template<> |

598 | struct CanProxyAdaptor<ObjCObjectPointerType> |

599 | : public CanProxyBase<ObjCObjectPointerType> { |

600 | LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) |

601 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *, |

602 | getInterfaceType) |

603 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType) |

604 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType) |

605 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType) |

606 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType) |

607 | |

608 | using qual_iterator = ObjCObjectPointerType::qual_iterator; |

609 | |

610 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) |

611 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) |

612 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) |

613 | LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) |

614 | }; |

615 | |

616 | //----------------------------------------------------------------------------// |

617 | // Method and function definitions |

618 | //----------------------------------------------------------------------------// |

619 | template<typename T> |

620 | inline CanQual<T> CanQual<T>::getUnqualifiedType() const { |

621 | return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType()); |

622 | } |

623 | |

624 | template<typename T> |

625 | inline CanQual<Type> CanQual<T>::getNonReferenceType() const { |

626 | if (CanQual<ReferenceType> RefType = getAs<ReferenceType>()) |

627 | return RefType->getPointeeType(); |

628 | else |

629 | return *this; |

630 | } |

631 | |

632 | template<typename T> |

633 | CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { |

634 | CanQual<T> Result; |

635 | Result.Stored = QualType::getFromOpaquePtr(Ptr); |

636 | assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 || |

637 | Result.Stored.isCanonical()) && "Type is not canonical!"); |

638 | return Result; |

639 | } |

640 | |

641 | template<typename T> |

642 | CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { |

643 | assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!"); |

644 | assert((Other.isNull() || isa<T>(Other.getTypePtr())) && |

645 | "Dynamic type does not meet the static type's requires"); |

646 | CanQual<T> Result; |

647 | Result.Stored = Other; |

648 | return Result; |

649 | } |

650 | |

651 | template<typename T> |

652 | template<typename U> |

653 | CanProxy<U> CanQual<T>::getAs() const { |

654 | static_assert(!TypeIsArrayType<T>::value, |

655 | "ArrayType cannot be used with getAs!"); |

656 | |

657 | if (Stored.isNull()) |

658 | return CanProxy<U>(); |

659 | |

660 | if (isa<U>(Stored.getTypePtr())) |

661 | return CanQual<U>::CreateUnsafe(Stored); |

662 | |

663 | return CanProxy<U>(); |

664 | } |

665 | |

666 | template<typename T> |

667 | template<typename U> |

668 | CanProxy<U> CanQual<T>::castAs() const { |

669 | static_assert(!TypeIsArrayType<U>::value, |

670 | "ArrayType cannot be used with castAs!"); |

671 | |

672 | assert(!Stored.isNull() && isa<U>(Stored.getTypePtr())); |

673 | return CanQual<U>::CreateUnsafe(Stored); |

674 | } |

675 | |

676 | template<typename T> |

677 | CanProxy<T> CanQual<T>::operator->() const { |

678 | return CanProxy<T>(*this); |

679 | } |

680 | |

681 | template <typename InputIterator> |

682 | CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const { |

683 | return CanProxy<Type>(*this); |

684 | } |

685 | |

686 | } // namespace clang |

687 | |

688 | #endif // LLVM_CLANG_AST_CANONICALTYPE_H |

689 |