llvm/clang/include/clang/AST/TypeLoc.h

//===- TypeLoc.h - Type Source Info Wrapper ---------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Defines the clang::TypeLoc interface and its subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_TYPELOC_H
#define LLVM_CLANG_AST_TYPELOC_H

#include "clang/AST/ASTConcept.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>

namespace clang {

class Attr;
class ASTContext;
class CXXRecordDecl;
class ConceptDecl;
class Expr;
class ObjCInterfaceDecl;
class ObjCProtocolDecl;
class ObjCTypeParamDecl;
class ParmVarDecl;
class TemplateTypeParmDecl;
class UnqualTypeLoc;
class UnresolvedUsingTypenameDecl;

// Predeclare all the type nodes.
#define ABSTRACT_TYPELOC
#define TYPELOC
#include "clang/AST/TypeLocNodes.def"

/// Base wrapper for a particular "section" of type source info.
///
/// A client should use the TypeLoc subclasses through castAs()/getAs()
/// in order to get at the actual information.
class TypeLoc {};

inline TypeSourceInfo::TypeSourceInfo(QualType ty, size_t DataSize) :{}

/// Return the TypeLoc for a type source info.
inline TypeLoc TypeSourceInfo::getTypeLoc() const {}

/// Wrapper of type source information for a type with
/// no direct qualifiers.
class UnqualTypeLoc : public TypeLoc {};

/// Wrapper of type source information for a type with
/// non-trivial direct qualifiers.
///
/// Currently, we intentionally do not provide source location for
/// type qualifiers.
class QualifiedTypeLoc : public TypeLoc {};

inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const {}

/// A metaprogramming base class for TypeLoc classes which correspond
/// to a particular Type subclass.  It is accepted for a single
/// TypeLoc class to correspond to multiple Type classes.
///
/// \tparam Base a class from which to derive
/// \tparam Derived the class deriving from this one
/// \tparam TypeClass the concrete Type subclass associated with this
///   location type
/// \tparam LocalData the structure type of local location data for
///   this type
///
/// TypeLocs with non-constant amounts of local data should override
/// getExtraLocalDataSize(); getExtraLocalData() will then point to
/// this extra memory.
///
/// TypeLocs with an inner type should define
///   QualType getInnerType() const
/// and getInnerTypeLoc() will then point to this inner type's
/// location data.
///
/// A word about hierarchies: this template is not designed to be
/// derived from multiple times in a hierarchy.  It is also not
/// designed to be used for classes where subtypes might provide
/// different amounts of source information.  It should be subclassed
/// only at the deepest portion of the hierarchy where all children
/// have identical source information; if that's an abstract type,
/// then further descendents should inherit from
/// InheritingConcreteTypeLoc instead.
template <class Base, class Derived, class TypeClass, class LocalData>
class ConcreteTypeLoc : public Base {};

/// A metaprogramming class designed for concrete subtypes of abstract
/// types where all subtypes share equivalently-structured source
/// information.  See the note on ConcreteTypeLoc.
template <class Base, class Derived, class TypeClass>
class InheritingConcreteTypeLoc : public Base {};

struct TypeSpecLocInfo {};

/// A reasonable base class for TypeLocs that correspond to
/// types that are written as a type-specifier.
class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                               TypeSpecTypeLoc,
                                               Type,
                                               TypeSpecLocInfo> {};

struct BuiltinLocInfo {};

/// Wrapper for source info for builtin types.
class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                              BuiltinTypeLoc,
                                              BuiltinType,
                                              BuiltinLocInfo> {};

/// Wrapper for source info for types used via transparent aliases.
class UsingTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                                      UsingTypeLoc, UsingType> {};

/// Wrapper for source info for typedefs.
class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                                        TypedefTypeLoc,
                                                        TypedefType> {};

/// Wrapper for source info for injected class names of class
/// templates.
class InjectedClassNameTypeLoc :
    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                     InjectedClassNameTypeLoc,
                                     InjectedClassNameType> {};

/// Wrapper for source info for unresolved typename using decls.
class UnresolvedUsingTypeLoc :
    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                     UnresolvedUsingTypeLoc,
                                     UnresolvedUsingType> {};

/// Wrapper for source info for tag types.  Note that this only
/// records source info for the name itself; a type written 'struct foo'
/// should be represented as an ElaboratedTypeLoc.  We currently
/// only do that when C++ is enabled because of the expense of
/// creating an ElaboratedType node for so many type references in C.
class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                                    TagTypeLoc,
                                                    TagType> {};

/// Wrapper for source info for record types.
class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
                                                       RecordTypeLoc,
                                                       RecordType> {};

/// Wrapper for source info for enum types.
class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc,
                                                     EnumTypeLoc,
                                                     EnumType> {};

/// Wrapper for template type parameters.
class TemplateTypeParmTypeLoc :
    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                     TemplateTypeParmTypeLoc,
                                     TemplateTypeParmType> {};

struct ObjCTypeParamTypeLocInfo {};

/// ProtocolLAngleLoc, ProtocolRAngleLoc, and the source locations for
/// protocol qualifiers are stored after Info.
class ObjCTypeParamTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                     ObjCTypeParamTypeLoc,
                                     ObjCTypeParamType,
                                     ObjCTypeParamTypeLocInfo> {};

/// Wrapper for substituted template type parameters.
class SubstTemplateTypeParmTypeLoc :
    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                     SubstTemplateTypeParmTypeLoc,
                                     SubstTemplateTypeParmType> {};

  /// Wrapper for substituted template type parameters.
class SubstTemplateTypeParmPackTypeLoc :
    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                     SubstTemplateTypeParmPackTypeLoc,
                                     SubstTemplateTypeParmPackType> {};

struct AttributedLocInfo {};

/// Type source information for an attributed type.
class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                                 AttributedTypeLoc,
                                                 AttributedType,
                                                 AttributedLocInfo> {};

struct BTFTagAttributedLocInfo {}; // Nothing.

/// Type source information for an btf_tag attributed type.
class BTFTagAttributedTypeLoc
    : public ConcreteTypeLoc<UnqualTypeLoc, BTFTagAttributedTypeLoc,
                             BTFTagAttributedType, BTFTagAttributedLocInfo> {};

struct HLSLAttributedResourceLocInfo {};

/// Type source information for HLSL attributed resource type.
class HLSLAttributedResourceTypeLoc
    : public ConcreteTypeLoc<UnqualTypeLoc, HLSLAttributedResourceTypeLoc,
                             HLSLAttributedResourceType,
                             HLSLAttributedResourceLocInfo> {};

struct ObjCObjectTypeLocInfo {};

// A helper class for defining ObjC TypeLocs that can qualified with
// protocols.
//
// TypeClass basically has to be either ObjCInterfaceType or
// ObjCObjectPointerType.
class ObjCObjectTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                                 ObjCObjectTypeLoc,
                                                 ObjCObjectType,
                                                 ObjCObjectTypeLocInfo> {};

struct ObjCInterfaceLocInfo {};

/// Wrapper for source info for ObjC interfaces.
class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc,
                                                    ObjCInterfaceTypeLoc,
                                                    ObjCInterfaceType,
                                                    ObjCInterfaceLocInfo> {};

struct BoundsAttributedLocInfo {};
class BoundsAttributedTypeLoc
    : public ConcreteTypeLoc<UnqualTypeLoc, BoundsAttributedTypeLoc,
                             BoundsAttributedType, BoundsAttributedLocInfo> {};

class CountAttributedTypeLoc final
    : public InheritingConcreteTypeLoc<BoundsAttributedTypeLoc,
                                       CountAttributedTypeLoc,
                                       CountAttributedType> {};

struct MacroQualifiedLocInfo {};

class MacroQualifiedTypeLoc
    : public ConcreteTypeLoc<UnqualTypeLoc, MacroQualifiedTypeLoc,
                             MacroQualifiedType, MacroQualifiedLocInfo> {};

struct ParenLocInfo {};

class ParenTypeLoc
  : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType,
                           ParenLocInfo> {};

inline TypeLoc TypeLoc::IgnoreParens() const {}

struct AdjustedLocInfo {}; // Nothing.

class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc,
                                               AdjustedType, AdjustedLocInfo> {};

/// Wrapper for source info for pointers decayed from arrays and
/// functions.
class DecayedTypeLoc : public InheritingConcreteTypeLoc<
                           AdjustedTypeLoc, DecayedTypeLoc, DecayedType> {};

struct PointerLikeLocInfo {};

/// A base class for
template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo>
class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived,
                                                  TypeClass, LocalData> {};

/// Wrapper for source info for pointers.
class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc,
                                                 PointerType> {};

/// Wrapper for source info for block pointers.
class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
                                                      BlockPointerType> {};

struct MemberPointerLocInfo : public PointerLikeLocInfo {};

/// Wrapper for source info for member pointers.
class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
                                                       MemberPointerType,
                                                       MemberPointerLocInfo> {};

/// Wraps an ObjCPointerType with source location information.
class ObjCObjectPointerTypeLoc :
    public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc,
                              ObjCObjectPointerType> {};

class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc,
                                                   ReferenceType> {};

class LValueReferenceTypeLoc :
    public InheritingConcreteTypeLoc<ReferenceTypeLoc,
                                     LValueReferenceTypeLoc,
                                     LValueReferenceType> {};

class RValueReferenceTypeLoc :
    public InheritingConcreteTypeLoc<ReferenceTypeLoc,
                                     RValueReferenceTypeLoc,
                                     RValueReferenceType> {};

struct FunctionLocInfo {};

/// Wrapper for source info for functions.
class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                               FunctionTypeLoc,
                                               FunctionType,
                                               FunctionLocInfo> {};

class FunctionProtoTypeLoc :
    public InheritingConcreteTypeLoc<FunctionTypeLoc,
                                     FunctionProtoTypeLoc,
                                     FunctionProtoType> {};

class FunctionNoProtoTypeLoc :
    public InheritingConcreteTypeLoc<FunctionTypeLoc,
                                     FunctionNoProtoTypeLoc,
                                     FunctionNoProtoType> {};

struct ArrayLocInfo {};

/// Wrapper for source info for arrays.
class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                            ArrayTypeLoc,
                                            ArrayType,
                                            ArrayLocInfo> {};

class ConstantArrayTypeLoc :
    public InheritingConcreteTypeLoc<ArrayTypeLoc,
                                     ConstantArrayTypeLoc,
                                     ConstantArrayType> {};

/// Wrapper for source info for array parameter types.
class ArrayParameterTypeLoc
    : public InheritingConcreteTypeLoc<
          ConstantArrayTypeLoc, ArrayParameterTypeLoc, ArrayParameterType> {};

class IncompleteArrayTypeLoc :
    public InheritingConcreteTypeLoc<ArrayTypeLoc,
                                     IncompleteArrayTypeLoc,
                                     IncompleteArrayType> {};

class DependentSizedArrayTypeLoc :
    public InheritingConcreteTypeLoc<ArrayTypeLoc,
                                     DependentSizedArrayTypeLoc,
                                     DependentSizedArrayType> {};

class VariableArrayTypeLoc :
    public InheritingConcreteTypeLoc<ArrayTypeLoc,
                                     VariableArrayTypeLoc,
                                     VariableArrayType> {};

// Location information for a TemplateName.  Rudimentary for now.
struct TemplateNameLocInfo {};

struct TemplateSpecializationLocInfo : TemplateNameLocInfo {};

class TemplateSpecializationTypeLoc :
    public ConcreteTypeLoc<UnqualTypeLoc,
                           TemplateSpecializationTypeLoc,
                           TemplateSpecializationType,
                           TemplateSpecializationLocInfo> {};

struct DependentAddressSpaceLocInfo {};

class DependentAddressSpaceTypeLoc
    : public ConcreteTypeLoc<UnqualTypeLoc,
                             DependentAddressSpaceTypeLoc,
                             DependentAddressSpaceType,
                             DependentAddressSpaceLocInfo> {};

//===----------------------------------------------------------------------===//
//
//  All of these need proper implementations.
//
//===----------------------------------------------------------------------===//

// FIXME: size expression and attribute locations (or keyword if we
// ever fully support altivec syntax).
struct VectorTypeLocInfo {};

class VectorTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, VectorTypeLoc,
                                             VectorType, VectorTypeLocInfo> {};

// FIXME: size expression and attribute locations (or keyword if we
// ever fully support altivec syntax).
class DependentVectorTypeLoc
    : public ConcreteTypeLoc<UnqualTypeLoc, DependentVectorTypeLoc,
                             DependentVectorType, VectorTypeLocInfo> {};

// FIXME: size expression and attribute locations.
class ExtVectorTypeLoc
    : public InheritingConcreteTypeLoc<VectorTypeLoc, ExtVectorTypeLoc,
                                       ExtVectorType> {};

// FIXME: attribute locations.
// For some reason, this isn't a subtype of VectorType.
class DependentSizedExtVectorTypeLoc
    : public ConcreteTypeLoc<UnqualTypeLoc, DependentSizedExtVectorTypeLoc,
                             DependentSizedExtVectorType, VectorTypeLocInfo> {};

struct MatrixTypeLocInfo {};

class MatrixTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, MatrixTypeLoc,
                                             MatrixType, MatrixTypeLocInfo> {};

class ConstantMatrixTypeLoc
    : public InheritingConcreteTypeLoc<MatrixTypeLoc, ConstantMatrixTypeLoc,
                                       ConstantMatrixType> {};

class DependentSizedMatrixTypeLoc
    : public InheritingConcreteTypeLoc<MatrixTypeLoc,
                                       DependentSizedMatrixTypeLoc,
                                       DependentSizedMatrixType> {};

// FIXME: location of the '_Complex' keyword.
class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
                                                        ComplexTypeLoc,
                                                        ComplexType> {};

struct TypeofLocInfo {};

struct TypeOfExprTypeLocInfo : public TypeofLocInfo {};

struct TypeOfTypeLocInfo : public TypeofLocInfo {};

template <class Derived, class TypeClass, class LocalData = TypeofLocInfo>
class TypeofLikeTypeLoc
  : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {};

class TypeOfExprTypeLoc : public TypeofLikeTypeLoc<TypeOfExprTypeLoc,
                                                   TypeOfExprType,
                                                   TypeOfExprTypeLocInfo> {};

class TypeOfTypeLoc
  : public TypeofLikeTypeLoc<TypeOfTypeLoc, TypeOfType, TypeOfTypeLocInfo> {};

// decltype(expression) abc;
// ~~~~~~~~                  DecltypeLoc
//                    ~      RParenLoc
// FIXME: add LParenLoc, it is tricky to support due to the limitation of
// annotated-decltype token.
struct DecltypeTypeLocInfo {};
class DecltypeTypeLoc
    : public ConcreteTypeLoc<UnqualTypeLoc, DecltypeTypeLoc, DecltypeType,
                             DecltypeTypeLocInfo> {};

struct PackIndexingTypeLocInfo {};

class PackIndexingTypeLoc
    : public ConcreteTypeLoc<UnqualTypeLoc, PackIndexingTypeLoc,
                             PackIndexingType, PackIndexingTypeLocInfo> {};

struct UnaryTransformTypeLocInfo {};

class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                                    UnaryTransformTypeLoc,
                                                    UnaryTransformType,
                                                    UnaryTransformTypeLocInfo> {};

class DeducedTypeLoc
    : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc,
                                       DeducedType> {};

struct AutoTypeLocInfo : TypeSpecLocInfo {};

class AutoTypeLoc
    : public ConcreteTypeLoc<DeducedTypeLoc,
                             AutoTypeLoc,
                             AutoType,
                             AutoTypeLocInfo> {};

class DeducedTemplateSpecializationTypeLoc
    : public InheritingConcreteTypeLoc<DeducedTypeLoc,
                                       DeducedTemplateSpecializationTypeLoc,
                                       DeducedTemplateSpecializationType> {};

struct ElaboratedLocInfo {};

class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                                 ElaboratedTypeLoc,
                                                 ElaboratedType,
                                                 ElaboratedLocInfo> {};

// This is exactly the structure of an ElaboratedTypeLoc whose inner
// type is some sort of TypeDeclTypeLoc.
struct DependentNameLocInfo : ElaboratedLocInfo {};

class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                                    DependentNameTypeLoc,
                                                    DependentNameType,
                                                    DependentNameLocInfo> {};

struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo {};

class DependentTemplateSpecializationTypeLoc :
    public ConcreteTypeLoc<UnqualTypeLoc,
                           DependentTemplateSpecializationTypeLoc,
                           DependentTemplateSpecializationType,
                           DependentTemplateSpecializationLocInfo> {};

struct PackExpansionTypeLocInfo {};

class PackExpansionTypeLoc
  : public ConcreteTypeLoc<UnqualTypeLoc, PackExpansionTypeLoc,
                           PackExpansionType, PackExpansionTypeLocInfo> {};

struct AtomicTypeLocInfo {};

class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc,
                                             AtomicType, AtomicTypeLocInfo> {};

struct PipeTypeLocInfo {};

class PipeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, PipeTypeLoc, PipeType,
                                           PipeTypeLocInfo> {};

template <typename T>
inline T TypeLoc::getAsAdjusted() const {}
class BitIntTypeLoc final
    : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, BitIntTypeLoc,
                                       BitIntType> {};
class DependentBitIntTypeLoc final
    : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DependentBitIntTypeLoc,
                                       DependentBitIntType> {};

class ObjCProtocolLoc {};

} // namespace clang

#endif // LLVM_CLANG_AST_TYPELOC_H