1327952Sdim//===- CanonicalType.h - C Language Family Type Representation --*- C++ -*-===// 2198092Srdivacky// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6198092Srdivacky// 7198092Srdivacky//===----------------------------------------------------------------------===// 8198092Srdivacky// 9198092Srdivacky// This file defines the CanQual class template, which provides access to 10198092Srdivacky// canonical types. 11198092Srdivacky// 12198092Srdivacky//===----------------------------------------------------------------------===// 13198092Srdivacky 14280031Sdim#ifndef LLVM_CLANG_AST_CANONICALTYPE_H 15280031Sdim#define LLVM_CLANG_AST_CANONICALTYPE_H 16198092Srdivacky 17198092Srdivacky#include "clang/AST/Type.h" 18327952Sdim#include "clang/Basic/Diagnostic.h" 19327952Sdim#include "clang/Basic/SourceLocation.h" 20327952Sdim#include "llvm/ADT/ArrayRef.h" 21327952Sdim#include "llvm/ADT/FoldingSet.h" 22288943Sdim#include "llvm/ADT/iterator.h" 23198092Srdivacky#include "llvm/Support/Casting.h" 24327952Sdim#include "llvm/Support/PointerLikeTypeTraits.h" 25327952Sdim#include <cassert> 26327952Sdim#include <iterator> 27327952Sdim#include <type_traits> 28198092Srdivacky 29198092Srdivackynamespace clang { 30198092Srdivacky 31198092Srdivackytemplate<typename T> class CanProxy; 32198092Srdivackytemplate<typename T> struct CanProxyAdaptor; 33327952Sdimclass CXXRecordDecl; 34327952Sdimclass EnumDecl; 35327952Sdimclass Expr; 36327952Sdimclass IdentifierInfo; 37327952Sdimclass ObjCInterfaceDecl; 38327952Sdimclass RecordDecl; 39327952Sdimclass TagDecl; 40327952Sdimclass TemplateTypeParmDecl; 41198092Srdivacky 42198092Srdivacky//----------------------------------------------------------------------------// 43198092Srdivacky// Canonical, qualified type template 44198092Srdivacky//----------------------------------------------------------------------------// 45198092Srdivacky 46341825Sdim/// Represents a canonical, potentially-qualified type. 47198092Srdivacky/// 48198092Srdivacky/// The CanQual template is a lightweight smart pointer that provides access 49198092Srdivacky/// to the canonical representation of a type, where all typedefs and other 50198092Srdivacky/// syntactic sugar has been eliminated. A CanQualType may also have various 51198092Srdivacky/// qualifiers (const, volatile, restrict) attached to it. 52198092Srdivacky/// 53198092Srdivacky/// The template type parameter @p T is one of the Type classes (PointerType, 54198092Srdivacky/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that 55198092Srdivacky/// type (or some subclass of that type). The typedef @c CanQualType is just 56198092Srdivacky/// a shorthand for @c CanQual<Type>. 57198092Srdivacky/// 58198092Srdivacky/// An instance of @c CanQual<T> can be implicitly converted to a 59198092Srdivacky/// @c CanQual<U> when T is derived from U, which essentially provides an 60198092Srdivacky/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be 61198092Srdivacky/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can 62198092Srdivacky/// be implicitly converted to a QualType, but the reverse operation requires 63198092Srdivacky/// a call to ASTContext::getCanonicalType(). 64198092Srdivackytemplate<typename T = Type> 65198092Srdivackyclass CanQual { 66341825Sdim /// The actual, canonical type. 67198092Srdivacky QualType Stored; 68198092Srdivacky 69198092Srdivackypublic: 70341825Sdim /// Constructs a NULL canonical type. 71327952Sdim CanQual() = default; 72198092Srdivacky 73341825Sdim /// Converting constructor that permits implicit upcasting of 74198092Srdivacky /// canonical type pointers. 75276479Sdim template <typename U> 76276479Sdim CanQual(const CanQual<U> &Other, 77276479Sdim typename std::enable_if<std::is_base_of<T, U>::value, int>::type = 0); 78198092Srdivacky 79341825Sdim /// Retrieve the underlying type pointer, which refers to a 80198092Srdivacky /// canonical type. 81218893Sdim /// 82327952Sdim /// The underlying pointer must not be nullptr. 83218893Sdim const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); } 84198092Srdivacky 85341825Sdim /// Retrieve the underlying type pointer, which refers to a 86327952Sdim /// canonical type, or nullptr. 87341825Sdim const T *getTypePtrOrNull() const { 88341825Sdim return cast_or_null<T>(Stored.getTypePtrOrNull()); 89218893Sdim } 90218893Sdim 91341825Sdim /// Implicit conversion to a qualified type. 92198092Srdivacky operator QualType() const { return Stored; } 93198092Srdivacky 94341825Sdim /// Implicit conversion to bool. 95288943Sdim explicit operator bool() const { return !isNull(); } 96341825Sdim 97198893Srdivacky bool isNull() const { 98198893Srdivacky return Stored.isNull(); 99198893Srdivacky } 100198893Srdivacky 101218893Sdim SplitQualType split() const { return Stored.split(); } 102218893Sdim 103341825Sdim /// Retrieve a canonical type pointer with a different static type, 104198092Srdivacky /// upcasting or downcasting as needed. 105198092Srdivacky /// 106198092Srdivacky /// The getAs() function is typically used to try to downcast to a 107198092Srdivacky /// more specific (canonical) type in the type system. For example: 108198092Srdivacky /// 109198092Srdivacky /// @code 110198092Srdivacky /// void f(CanQual<Type> T) { 111198092Srdivacky /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { 112198092Srdivacky /// // look at Ptr's pointee type 113198092Srdivacky /// } 114198092Srdivacky /// } 115198092Srdivacky /// @endcode 116198092Srdivacky /// 117198092Srdivacky /// \returns A proxy pointer to the same type, but with the specified 118198092Srdivacky /// static type (@p U). If the dynamic type is not the specified static type 119198092Srdivacky /// or a derived class thereof, a NULL canonical type. 120198092Srdivacky template<typename U> CanProxy<U> getAs() const; 121198092Srdivacky 122234353Sdim template<typename U> CanProxy<U> castAs() const; 123234353Sdim 124341825Sdim /// Overloaded arrow operator that produces a canonical type 125198092Srdivacky /// proxy. 126198092Srdivacky CanProxy<T> operator->() const; 127198092Srdivacky 128341825Sdim /// Retrieve all qualifiers. 129199482Srdivacky Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); } 130198092Srdivacky 131341825Sdim /// Retrieve the const/volatile/restrict qualifiers. 132199482Srdivacky unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); } 133198092Srdivacky 134341825Sdim /// Determines whether this type has any qualifiers 135199482Srdivacky bool hasQualifiers() const { return Stored.hasLocalQualifiers(); } 136198092Srdivacky 137198092Srdivacky bool isConstQualified() const { 138199482Srdivacky return Stored.isLocalConstQualified(); 139198092Srdivacky } 140327952Sdim 141198092Srdivacky bool isVolatileQualified() const { 142199482Srdivacky return Stored.isLocalVolatileQualified(); 143198092Srdivacky } 144327952Sdim 145198092Srdivacky bool isRestrictQualified() const { 146199482Srdivacky return Stored.isLocalRestrictQualified(); 147198092Srdivacky } 148198092Srdivacky 149341825Sdim /// Determines if this canonical type is furthermore 150204643Srdivacky /// canonical as a parameter. The parameter-canonicalization 151204643Srdivacky /// process decays arrays to pointers and drops top-level qualifiers. 152204643Srdivacky bool isCanonicalAsParam() const { 153204643Srdivacky return Stored.isCanonicalAsParam(); 154204643Srdivacky } 155204643Srdivacky 156341825Sdim /// Retrieve the unqualified form of this type. 157198092Srdivacky CanQual<T> getUnqualifiedType() const; 158198092Srdivacky 159341825Sdim /// Retrieves a version of this type with const applied. 160198893Srdivacky /// Note that this does not always yield a canonical type. 161198893Srdivacky QualType withConst() const { 162198893Srdivacky return Stored.withConst(); 163198092Srdivacky } 164198092Srdivacky 165341825Sdim /// Determines whether this canonical type is more qualified than 166198092Srdivacky /// the @p Other canonical type. 167198092Srdivacky bool isMoreQualifiedThan(CanQual<T> Other) const { 168198092Srdivacky return Stored.isMoreQualifiedThan(Other.Stored); 169198092Srdivacky } 170198092Srdivacky 171341825Sdim /// Determines whether this canonical type is at least as qualified as 172198092Srdivacky /// the @p Other canonical type. 173198092Srdivacky bool isAtLeastAsQualifiedAs(CanQual<T> Other) const { 174198092Srdivacky return Stored.isAtLeastAsQualifiedAs(Other.Stored); 175198092Srdivacky } 176198092Srdivacky 177341825Sdim /// If the canonical type is a reference type, returns the type that 178198092Srdivacky /// it refers to; otherwise, returns the type itself. 179198092Srdivacky CanQual<Type> getNonReferenceType() const; 180198092Srdivacky 181341825Sdim /// Retrieve the internal representation of this canonical type. 182198092Srdivacky void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); } 183198092Srdivacky 184341825Sdim /// Construct a canonical type from its internal representation. 185198092Srdivacky static CanQual<T> getFromOpaquePtr(void *Ptr); 186198092Srdivacky 187341825Sdim /// Builds a canonical type from a QualType. 188198092Srdivacky /// 189198092Srdivacky /// This routine is inherently unsafe, because it requires the user to 190198092Srdivacky /// ensure that the given type is a canonical type with the correct 191198092Srdivacky // (dynamic) type. 192198092Srdivacky static CanQual<T> CreateUnsafe(QualType Other); 193204643Srdivacky 194206084Srdivacky void dump() const { Stored.dump(); } 195206084Srdivacky 196204643Srdivacky void Profile(llvm::FoldingSetNodeID &ID) const { 197204643Srdivacky ID.AddPointer(getAsOpaquePtr()); 198204643Srdivacky } 199198092Srdivacky}; 200198092Srdivacky 201198092Srdivackytemplate<typename T, typename U> 202198092Srdivackyinline bool operator==(CanQual<T> x, CanQual<U> y) { 203198092Srdivacky return x.getAsOpaquePtr() == y.getAsOpaquePtr(); 204198092Srdivacky} 205198092Srdivacky 206198092Srdivackytemplate<typename T, typename U> 207198092Srdivackyinline bool operator!=(CanQual<T> x, CanQual<U> y) { 208198092Srdivacky return x.getAsOpaquePtr() != y.getAsOpaquePtr(); 209198092Srdivacky} 210198092Srdivacky 211341825Sdim/// Represents a canonical, potentially-qualified type. 212327952Sdimusing CanQualType = CanQual<Type>; 213198092Srdivacky 214204643Srdivackyinline CanQualType Type::getCanonicalTypeUnqualified() const { 215204643Srdivacky return CanQualType::CreateUnsafe(getCanonicalTypeInternal()); 216204643Srdivacky} 217204643Srdivacky 218200583Srdivackyinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 219200583Srdivacky CanQualType T) { 220200583Srdivacky DB << static_cast<QualType>(T); 221200583Srdivacky return DB; 222200583Srdivacky} 223200583Srdivacky 224198092Srdivacky//----------------------------------------------------------------------------// 225198092Srdivacky// Internal proxy classes used by canonical types 226198092Srdivacky//----------------------------------------------------------------------------// 227198092Srdivacky 228198092Srdivacky#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \ 229198092SrdivackyCanQualType Accessor() const { \ 230198092Srdivackyreturn CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \ 231198092Srdivacky} 232198092Srdivacky 233198092Srdivacky#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \ 234198092SrdivackyType Accessor() const { return this->getTypePtr()->Accessor(); } 235198092Srdivacky 236341825Sdim/// Base class of all canonical proxy types, which is responsible for 237198092Srdivacky/// storing the underlying canonical type and providing basic conversions. 238198092Srdivackytemplate<typename T> 239198092Srdivackyclass CanProxyBase { 240198092Srdivackyprotected: 241198092Srdivacky CanQual<T> Stored; 242198092Srdivacky 243198092Srdivackypublic: 244341825Sdim /// Retrieve the pointer to the underlying Type 245218893Sdim const T *getTypePtr() const { return Stored.getTypePtr(); } 246198092Srdivacky 247341825Sdim /// Implicit conversion to the underlying pointer. 248198092Srdivacky /// 249198092Srdivacky /// Also provides the ability to use canonical type proxies in a Boolean 250198092Srdivacky // context,e.g., 251198092Srdivacky /// @code 252198092Srdivacky /// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... } 253198092Srdivacky /// @endcode 254218893Sdim operator const T*() const { return this->Stored.getTypePtrOrNull(); } 255198092Srdivacky 256341825Sdim /// Try to convert the given canonical type to a specific structural 257198092Srdivacky /// type. 258198092Srdivacky template<typename U> CanProxy<U> getAs() const { 259198092Srdivacky return this->Stored.template getAs<U>(); 260198092Srdivacky } 261198092Srdivacky 262198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass) 263198092Srdivacky 264198092Srdivacky // Type predicates 265198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType) 266198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType) 267198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType) 268198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType) 269198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType) 270198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType) 271198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType) 272198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType) 273198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType) 274198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType) 275210299Sed LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType) 276198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType) 277198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType) 278198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType) 279198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType) 280198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType) 281198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType) 282198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType) 283198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType) 284198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType) 285198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType) 286198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType) 287198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType) 288198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType) 289198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType) 290198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType) 291198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType) 292243830Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType) 293207619Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType) 294198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType) 295198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType) 296198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType) 297198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) 298198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) 299210299Sed LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) 300198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) 301198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) 302212904Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation) 303212904Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation) 304212904Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation) 305210299Sed LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation) 306198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) 307198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) 308198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) 309223017Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType) 310223017Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType) 311198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType) 312198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) 313224145Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl) 314198092Srdivacky 315341825Sdim /// Retrieve the proxy-adaptor type. 316198092Srdivacky /// 317198092Srdivacky /// This arrow operator is used when CanProxyAdaptor has been specialized 318198092Srdivacky /// for the given type T. In that case, we reference members of the 319198092Srdivacky /// CanProxyAdaptor specialization. Otherwise, this operator will be hidden 320198092Srdivacky /// by the arrow operator in the primary CanProxyAdaptor template. 321198092Srdivacky const CanProxyAdaptor<T> *operator->() const { 322198092Srdivacky return static_cast<const CanProxyAdaptor<T> *>(this); 323198092Srdivacky } 324198092Srdivacky}; 325198092Srdivacky 326341825Sdim/// Replaceable canonical proxy adaptor class that provides the link 327198092Srdivacky/// between a canonical type and the accessors of the type. 328198092Srdivacky/// 329198092Srdivacky/// The CanProxyAdaptor is a replaceable class template that is instantiated 330198092Srdivacky/// as part of each canonical proxy type. The primary template merely provides 331198092Srdivacky/// redirection to the underlying type (T), e.g., @c PointerType. One can 332198092Srdivacky/// provide specializations of this class template for each underlying type 333198092Srdivacky/// that provide accessors returning canonical types (@c CanQualType) rather 334198092Srdivacky/// than the more typical @c QualType, to propagate the notion of "canonical" 335198092Srdivacky/// through the system. 336198092Srdivackytemplate<typename T> 337327952Sdimstruct CanProxyAdaptor : CanProxyBase<T> {}; 338198092Srdivacky 339341825Sdim/// Canonical proxy type returned when retrieving the members of a 340198092Srdivacky/// canonical type or as the result of the @c CanQual<T>::getAs member 341198092Srdivacky/// function. 342198092Srdivacky/// 343198092Srdivacky/// The CanProxy type mainly exists as a proxy through which operator-> will 344198092Srdivacky/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy 345198092Srdivacky/// type that provides canonical-type access to the fields of the type. 346198092Srdivackytemplate<typename T> 347198092Srdivackyclass CanProxy : public CanProxyAdaptor<T> { 348198092Srdivackypublic: 349341825Sdim /// Build a NULL proxy. 350327952Sdim CanProxy() = default; 351198092Srdivacky 352341825Sdim /// Build a proxy to the given canonical type. 353198092Srdivacky CanProxy(CanQual<T> Stored) { this->Stored = Stored; } 354198092Srdivacky 355341825Sdim /// Implicit conversion to the stored canonical type. 356198092Srdivacky operator CanQual<T>() const { return this->Stored; } 357198092Srdivacky}; 358198092Srdivacky 359327952Sdim} // namespace clang 360198092Srdivacky 361198092Srdivackynamespace llvm { 362198092Srdivacky 363198092Srdivacky/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from 364198092Srdivacky/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc. 365198092Srdivacky/// to return smart pointer (proxies?). 366198092Srdivackytemplate<typename T> 367327952Sdimstruct simplify_type< ::clang::CanQual<T>> { 368327952Sdim using SimpleType = const T *; 369327952Sdim 370249423Sdim static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) { 371198092Srdivacky return Val.getTypePtr(); 372198092Srdivacky } 373198092Srdivacky}; 374198092Srdivacky 375198092Srdivacky// Teach SmallPtrSet that CanQual<T> is "basically a pointer". 376198092Srdivackytemplate<typename T> 377327952Sdimstruct PointerLikeTypeTraits<clang::CanQual<T>> { 378327952Sdim static void *getAsVoidPointer(clang::CanQual<T> P) { 379198092Srdivacky return P.getAsOpaquePtr(); 380198092Srdivacky } 381327952Sdim 382327952Sdim static clang::CanQual<T> getFromVoidPointer(void *P) { 383198092Srdivacky return clang::CanQual<T>::getFromOpaquePtr(P); 384198092Srdivacky } 385327952Sdim 386198092Srdivacky // qualifier information is encoded in the low bits. 387198092Srdivacky enum { NumLowBitsAvailable = 0 }; 388198092Srdivacky}; 389198092Srdivacky 390327952Sdim} // namespace llvm 391198092Srdivacky 392198092Srdivackynamespace clang { 393198092Srdivacky 394198092Srdivacky//----------------------------------------------------------------------------// 395198092Srdivacky// Canonical proxy adaptors for canonical type nodes. 396198092Srdivacky//----------------------------------------------------------------------------// 397198092Srdivacky 398341825Sdim/// Iterator adaptor that turns an iterator over canonical QualTypes 399198092Srdivacky/// into an iterator over CanQualTypes. 400288943Sdimtemplate <typename InputIterator> 401288943Sdimstruct CanTypeIterator 402288943Sdim : llvm::iterator_adaptor_base< 403288943Sdim CanTypeIterator<InputIterator>, InputIterator, 404288943Sdim typename std::iterator_traits<InputIterator>::iterator_category, 405288943Sdim CanQualType, 406288943Sdim typename std::iterator_traits<InputIterator>::difference_type, 407288943Sdim CanProxy<Type>, CanQualType> { 408327952Sdim CanTypeIterator() = default; 409288943Sdim explicit CanTypeIterator(InputIterator Iter) 410288943Sdim : CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {} 411198092Srdivacky 412288943Sdim CanQualType operator*() const { return CanQualType::CreateUnsafe(*this->I); } 413288943Sdim CanProxy<Type> operator->() const; 414198092Srdivacky}; 415198092Srdivacky 416198092Srdivackytemplate<> 417198092Srdivackystruct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> { 418198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) 419198092Srdivacky}; 420198092Srdivacky 421198092Srdivackytemplate<> 422198092Srdivackystruct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> { 423198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) 424198092Srdivacky}; 425198092Srdivacky 426198092Srdivackytemplate<> 427198092Srdivackystruct CanProxyAdaptor<BlockPointerType> 428198092Srdivacky : public CanProxyBase<BlockPointerType> { 429198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) 430198092Srdivacky}; 431198092Srdivacky 432198092Srdivackytemplate<> 433198092Srdivackystruct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> { 434198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) 435198092Srdivacky}; 436198092Srdivacky 437198092Srdivackytemplate<> 438198092Srdivackystruct CanProxyAdaptor<LValueReferenceType> 439198092Srdivacky : public CanProxyBase<LValueReferenceType> { 440198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) 441198092Srdivacky}; 442198092Srdivacky 443198092Srdivackytemplate<> 444198092Srdivackystruct CanProxyAdaptor<RValueReferenceType> 445198092Srdivacky : public CanProxyBase<RValueReferenceType> { 446198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) 447198092Srdivacky}; 448198092Srdivacky 449198092Srdivackytemplate<> 450198092Srdivackystruct CanProxyAdaptor<MemberPointerType> 451198092Srdivacky : public CanProxyBase<MemberPointerType> { 452198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) 453198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass) 454198092Srdivacky}; 455198092Srdivacky 456249423Sdim// CanProxyAdaptors for arrays are intentionally unimplemented because 457249423Sdim// they are not safe. 458249423Sdimtemplate<> struct CanProxyAdaptor<ArrayType>; 459249423Sdimtemplate<> struct CanProxyAdaptor<ConstantArrayType>; 460249423Sdimtemplate<> struct CanProxyAdaptor<IncompleteArrayType>; 461249423Sdimtemplate<> struct CanProxyAdaptor<VariableArrayType>; 462249423Sdimtemplate<> struct CanProxyAdaptor<DependentSizedArrayType>; 463198092Srdivacky 464198092Srdivackytemplate<> 465198092Srdivackystruct CanProxyAdaptor<DependentSizedExtVectorType> 466198092Srdivacky : public CanProxyBase<DependentSizedExtVectorType> { 467198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) 468198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr) 469198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc) 470198092Srdivacky}; 471198092Srdivacky 472198092Srdivackytemplate<> 473198092Srdivackystruct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> { 474198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) 475198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) 476198092Srdivacky}; 477198092Srdivacky 478198092Srdivackytemplate<> 479198092Srdivackystruct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { 480198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) 481198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements) 482198092Srdivacky}; 483198092Srdivacky 484198092Srdivackytemplate<> 485198092Srdivackystruct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { 486276479Sdim LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) 487206084Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) 488198092Srdivacky}; 489198092Srdivacky 490198092Srdivackytemplate<> 491198092Srdivackystruct CanProxyAdaptor<FunctionNoProtoType> 492198092Srdivacky : public CanProxyBase<FunctionNoProtoType> { 493276479Sdim LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) 494206084Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) 495198092Srdivacky}; 496198092Srdivacky 497198092Srdivackytemplate<> 498198092Srdivackystruct CanProxyAdaptor<FunctionProtoType> 499198092Srdivacky : public CanProxyBase<FunctionProtoType> { 500276479Sdim LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) 501206084Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) 502276479Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams) 503309124Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos) 504309124Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR( 505309124Sdim ArrayRef<FunctionProtoType::ExtParameterInfo>, getExtParameterInfos) 506327952Sdim 507276479Sdim CanQualType getParamType(unsigned i) const { 508276479Sdim return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i)); 509198092Srdivacky } 510198092Srdivacky 511198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic) 512353358Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getMethodQuals) 513198092Srdivacky 514327952Sdim using param_type_iterator = 515327952Sdim CanTypeIterator<FunctionProtoType::param_type_iterator>; 516198092Srdivacky 517276479Sdim param_type_iterator param_type_begin() const { 518276479Sdim return param_type_iterator(this->getTypePtr()->param_type_begin()); 519198092Srdivacky } 520198092Srdivacky 521276479Sdim param_type_iterator param_type_end() const { 522276479Sdim return param_type_iterator(this->getTypePtr()->param_type_end()); 523198092Srdivacky } 524198092Srdivacky 525198092Srdivacky // Note: canonical function types never have exception specifications 526198092Srdivacky}; 527198092Srdivacky 528198092Srdivackytemplate<> 529198092Srdivackystruct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> { 530198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) 531198092Srdivacky}; 532198092Srdivacky 533198092Srdivackytemplate<> 534198092Srdivackystruct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> { 535198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr) 536198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) 537198092Srdivacky}; 538198092Srdivacky 539223017Sdimtemplate <> 540223017Sdimstruct CanProxyAdaptor<UnaryTransformType> 541223017Sdim : public CanProxyBase<UnaryTransformType> { 542223017Sdim LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) 543223017Sdim LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType) 544223017Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind) 545223017Sdim}; 546223017Sdim 547198092Srdivackytemplate<> 548198092Srdivackystruct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> { 549198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl) 550198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) 551198092Srdivacky}; 552198092Srdivacky 553198092Srdivackytemplate<> 554198092Srdivackystruct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> { 555198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl) 556198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) 557198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields) 558198092Srdivacky}; 559198092Srdivacky 560198092Srdivackytemplate<> 561198092Srdivackystruct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> { 562198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl) 563198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined) 564198092Srdivacky}; 565198092Srdivacky 566198092Srdivackytemplate<> 567198092Srdivackystruct CanProxyAdaptor<TemplateTypeParmType> 568198092Srdivacky : public CanProxyBase<TemplateTypeParmType> { 569198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) 570198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) 571198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) 572221345Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl) 573221345Sdim LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier) 574198092Srdivacky}; 575198092Srdivacky 576198092Srdivackytemplate<> 577208600Srdivackystruct CanProxyAdaptor<ObjCObjectType> 578208600Srdivacky : public CanProxyBase<ObjCObjectType> { 579208600Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType) 580208600Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *, 581208600Srdivacky getInterface) 582208600Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId) 583208600Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass) 584208600Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId) 585208600Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass) 586208600Srdivacky 587327952Sdim using qual_iterator = ObjCObjectPointerType::qual_iterator; 588327952Sdim 589208600Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) 590208600Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) 591208600Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) 592208600Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) 593208600Srdivacky}; 594208600Srdivacky 595208600Srdivackytemplate<> 596198092Srdivackystruct CanProxyAdaptor<ObjCObjectPointerType> 597198092Srdivacky : public CanProxyBase<ObjCObjectPointerType> { 598198092Srdivacky LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) 599198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *, 600198092Srdivacky getInterfaceType) 601198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType) 602198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType) 603198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType) 604198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType) 605198092Srdivacky 606327952Sdim using qual_iterator = ObjCObjectPointerType::qual_iterator; 607327952Sdim 608198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin) 609198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end) 610198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty) 611198092Srdivacky LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols) 612198092Srdivacky}; 613198092Srdivacky 614198092Srdivacky//----------------------------------------------------------------------------// 615198092Srdivacky// Method and function definitions 616198092Srdivacky//----------------------------------------------------------------------------// 617198092Srdivackytemplate<typename T> 618198092Srdivackyinline CanQual<T> CanQual<T>::getUnqualifiedType() const { 619199482Srdivacky return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType()); 620198092Srdivacky} 621198092Srdivacky 622198092Srdivackytemplate<typename T> 623198092Srdivackyinline CanQual<Type> CanQual<T>::getNonReferenceType() const { 624198092Srdivacky if (CanQual<ReferenceType> RefType = getAs<ReferenceType>()) 625198092Srdivacky return RefType->getPointeeType(); 626198092Srdivacky else 627198092Srdivacky return *this; 628198092Srdivacky} 629198092Srdivacky 630198092Srdivackytemplate<typename T> 631198092SrdivackyCanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { 632198092Srdivacky CanQual<T> Result; 633212904Sdim Result.Stored = QualType::getFromOpaquePtr(Ptr); 634212904Sdim assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 || 635212904Sdim Result.Stored.isCanonical()) && "Type is not canonical!"); 636198092Srdivacky return Result; 637198092Srdivacky} 638198092Srdivacky 639198092Srdivackytemplate<typename T> 640198092SrdivackyCanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { 641198398Srdivacky assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!"); 642198092Srdivacky assert((Other.isNull() || isa<T>(Other.getTypePtr())) && 643198092Srdivacky "Dynamic type does not meet the static type's requires"); 644198092Srdivacky CanQual<T> Result; 645198092Srdivacky Result.Stored = Other; 646198092Srdivacky return Result; 647198092Srdivacky} 648198092Srdivacky 649198092Srdivackytemplate<typename T> 650198092Srdivackytemplate<typename U> 651198092SrdivackyCanProxy<U> CanQual<T>::getAs() const { 652314564Sdim static_assert(!TypeIsArrayType<T>::value, 653314564Sdim "ArrayType cannot be used with getAs!"); 654249423Sdim 655198092Srdivacky if (Stored.isNull()) 656198092Srdivacky return CanProxy<U>(); 657198092Srdivacky 658198092Srdivacky if (isa<U>(Stored.getTypePtr())) 659198092Srdivacky return CanQual<U>::CreateUnsafe(Stored); 660198092Srdivacky 661198092Srdivacky return CanProxy<U>(); 662198092Srdivacky} 663198092Srdivacky 664198092Srdivackytemplate<typename T> 665234353Sdimtemplate<typename U> 666234353SdimCanProxy<U> CanQual<T>::castAs() const { 667314564Sdim static_assert(!TypeIsArrayType<U>::value, 668314564Sdim "ArrayType cannot be used with castAs!"); 669249423Sdim 670234353Sdim assert(!Stored.isNull() && isa<U>(Stored.getTypePtr())); 671234353Sdim return CanQual<U>::CreateUnsafe(Stored); 672234353Sdim} 673234353Sdim 674234353Sdimtemplate<typename T> 675198092SrdivackyCanProxy<T> CanQual<T>::operator->() const { 676198092Srdivacky return CanProxy<T>(*this); 677198092Srdivacky} 678198092Srdivacky 679288943Sdimtemplate <typename InputIterator> 680288943SdimCanProxy<Type> CanTypeIterator<InputIterator>::operator->() const { 681198092Srdivacky return CanProxy<Type>(*this); 682198092Srdivacky} 683198092Srdivacky 684327952Sdim} // namespace clang 685198092Srdivacky 686327952Sdim#endif // LLVM_CLANG_AST_CANONICALTYPE_H 687