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, 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(*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(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