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