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