// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // Type.h -- // // Author : Richard C. Bilson // Created On : Mon May 18 07:44:20 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Fri Feb 8 09:17:09 2019 // Update Count : 164 // #pragma once #include // for ffs #include // for assert, assertf #include #include // for ostream, operator<<, basic_ostream #include // for string #include // for vector #include "BaseSyntaxNode.h" // for BaseSyntaxNode #include "Common/utility.h" // for operator+ #include "Mutator.h" // for Mutator #include "SynTree.h" // for AST nodes #include "Visitor.h" // for Visitor class Type : public BaseSyntaxNode { public: // Simulate inheritance because union does not allow it. // Bug in g++-4.9 prevents static field in union //static const char * Names[]; #define BFCommon( BFType, N ) \ bool operator[]( unsigned int i ) const { return val & (1 << i); } \ bool any() const { return val != 0; } \ void reset() { val = 0; } \ int ffs() { return ::ffs( val ) - 1; } \ BFType operator&=( BFType other ) { \ val &= other.val; return *this; \ } \ BFType operator&( BFType other ) const { \ BFType q = other; \ q &= *this; \ return q; \ } \ BFType operator|=( BFType other ) { \ val |= other.val; return *this; \ } \ BFType operator|( BFType other ) const { \ BFType q = other; \ q |= *this; \ return q; \ } \ BFType operator-=( BFType other ) { \ val &= ~other.val; return *this; \ } \ void print( std::ostream & os ) const { \ if ( (*this).any() ) { \ for ( unsigned int i = 0; i < N; i += 1 ) { \ if ( (*this)[i] ) { \ os << BFType##Names[i] << ' '; \ } \ } \ } \ } // enum must remain in the same order as the corresponding bit fields. enum { Inline = 1 << 0, Noreturn = 1 << 1, Fortran = 1 << 2, NumFuncSpecifier = 3 }; static const char * FuncSpecifiersNames[]; union FuncSpecifiers { unsigned int val; struct { bool is_inline : 1; bool is_noreturn : 1; bool is_fortran : 1; }; FuncSpecifiers() : val( 0 ) {} FuncSpecifiers( unsigned int val ) : val( val ) {} // equality (==, !=) works implicitly on first field "val", relational operations are undefined. BFCommon( FuncSpecifiers, NumFuncSpecifier ) }; // FuncSpecifiers enum { Extern = 1 << 0, Static = 1 << 1, Auto = 1 << 2, Register = 1 << 3, Threadlocal = 1 << 4, NumStorageClass = 5 }; static const char * StorageClassesNames[]; union StorageClasses { unsigned int val; struct { bool is_extern : 1; bool is_static : 1; bool is_auto : 1; bool is_register : 1; bool is_threadlocal : 1; }; StorageClasses() : val( 0 ) {} StorageClasses( unsigned int val ) : val( val ) {} // equality (==, !=) works implicitly on first field "val", relational operations are undefined. BFCommon( StorageClasses, NumStorageClass ) }; // StorageClasses enum { Const = 1 << 0, Restrict = 1 << 1, Volatile = 1 << 2, Lvalue = 1 << 3, Mutex = 1 << 4, Atomic = 1 << 5, NumTypeQualifier = 6 }; static const char * QualifiersNames[]; union Qualifiers { enum { Mask = ~(Restrict | Lvalue) }; unsigned int val; struct { bool is_const : 1; bool is_restrict : 1; bool is_volatile : 1; bool is_lvalue : 1; bool is_mutex : 1; bool is_atomic : 1; }; Qualifiers() : val( 0 ) {} Qualifiers( unsigned int val ) : val( val ) {} // Complex comparisons provide implicit qualifier downcasting, e.g., T downcast to const T. bool operator==( Qualifiers other ) const { return (val & Mask) == (other.val & Mask); } bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); } bool operator<=( Qualifiers other ) const { return is_const <= other.is_const //Any non-const converts to const without cost && is_volatile <= other.is_volatile //Any non-volatile converts to volatile without cost && is_mutex >= other.is_mutex //Any mutex converts to non-mutex without cost && is_atomic == other.is_atomic; //No conversion from atomic to non atomic is free } bool operator<( Qualifiers other ) const { return *this != other && *this <= other; } bool operator>=( Qualifiers other ) const { return ! (*this < other); } bool operator>( Qualifiers other ) const { return *this != other && *this >= other; } BFCommon( Qualifiers, NumTypeQualifier ) }; // Qualifiers typedef std::vector ForallList; Qualifiers tq; ForallList forall; std::vector< Attribute * > attributes; Type( const Qualifiers & tq, const std::vector< Attribute * > & attributes ); Type( const Type & other ); virtual ~Type(); Qualifiers & get_qualifiers() { return tq; } bool get_const() { return tq.is_const; } bool get_volatile() { return tq.is_volatile; } bool get_restrict() { return tq.is_restrict; } bool get_lvalue() { return tq.is_lvalue; } bool get_mutex() { return tq.is_mutex; } bool get_atomic() { return tq.is_atomic; } void set_const( bool newValue ) { tq.is_const = newValue; } void set_volatile( bool newValue ) { tq.is_volatile = newValue; } void set_restrict( bool newValue ) { tq.is_restrict = newValue; } void set_lvalue( bool newValue ) { tq.is_lvalue = newValue; } void set_mutex( bool newValue ) { tq.is_mutex = newValue; } void set_atomic( bool newValue ) { tq.is_atomic = newValue; } ForallList& get_forall() { return forall; } std::vector< Attribute * >& get_attributes() { return attributes; } const std::vector< Attribute * >& get_attributes() const { return attributes; } /// How many elemental types are represented by this type virtual unsigned size() const { return 1; }; virtual bool isVoid() const { return size() == 0; } virtual Type * getComponent( unsigned i ) { assertf( size() == 1 && i == 0, "Type::getComponent was called with size %d and index %d\n", size(), i ); return this; } /// return type without outer pointers and arrays Type * stripDeclarator(); /// return type without outer references Type * stripReferences(); /// return the number of references occuring consecutively on the outermost layer of this type (i.e. do not count references nested within other types) virtual int referenceDepth() const; virtual bool isComplete() const { return true; } virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); } virtual TypeSubstitution genericSubstitution() const; virtual Type *clone() const = 0; virtual void accept( Visitor & v ) = 0; virtual Type *acceptMutator( Mutator & m ) = 0; virtual void print( std::ostream & os, Indenter indent = {} ) const; }; extern const Type::FuncSpecifiers noFuncSpecifiers; extern const Type::StorageClasses noStorageClasses; extern const Type::Qualifiers noQualifiers; // no qualifiers on constants class VoidType : public Type { public: VoidType( const Type::Qualifiers & tq, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); virtual unsigned size() const override { return 0; }; virtual bool isComplete() const override { return false; } virtual VoidType *clone() const override { return new VoidType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; class BasicType : public Type { public: enum Kind { Bool, Char, SignedChar, UnsignedChar, ShortSignedInt, ShortUnsignedInt, SignedInt, UnsignedInt, LongSignedInt, LongUnsignedInt, LongLongSignedInt, LongLongUnsignedInt, Float, Double, LongDouble, FloatComplex, DoubleComplex, LongDoubleComplex, FloatImaginary, DoubleImaginary, LongDoubleImaginary, SignedInt128, UnsignedInt128, Float80, Float128, NUMBER_OF_BASIC_TYPES } kind; static const char *typeNames[]; // string names for basic types, MUST MATCH with Kind BasicType( const Type::Qualifiers & tq, Kind bt, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); Kind get_kind() { return kind; } void set_kind( Kind newValue ) { kind = newValue; } virtual BasicType *clone() const override { return new BasicType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; bool isInteger() const; }; class PointerType : public Type { public: Type *base; // In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] ) Expression *dimension; bool isVarLen; bool isStatic; PointerType( const Type::Qualifiers & tq, Type *base, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); PointerType( const Type::Qualifiers & tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); PointerType( const PointerType& ); virtual ~PointerType(); Type *get_base() { return base; } void set_base( Type *newValue ) { base = newValue; } Expression *get_dimension() { return dimension; } void set_dimension( Expression *newValue ) { dimension = newValue; } bool get_isVarLen() { return isVarLen; } void set_isVarLen( bool newValue ) { isVarLen = newValue; } bool get_isStatic() { return isStatic; } void set_isStatic( bool newValue ) { isStatic = newValue; } bool is_array() const { return isStatic || isVarLen || dimension; } virtual bool isComplete() const override { return ! isVarLen; } virtual PointerType *clone() const override { return new PointerType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; class ArrayType : public Type { public: Type *base; Expression *dimension; bool isVarLen; bool isStatic; ArrayType( const Type::Qualifiers & tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); ArrayType( const ArrayType& ); virtual ~ArrayType(); Type *get_base() { return base; } void set_base( Type *newValue ) { base = newValue; } Expression *get_dimension() { return dimension; } void set_dimension( Expression *newValue ) { dimension = newValue; } bool get_isVarLen() { return isVarLen; } void set_isVarLen( bool newValue ) { isVarLen = newValue; } bool get_isStatic() { return isStatic; } void set_isStatic( bool newValue ) { isStatic = newValue; } // array types are complete if they have a dimension expression or are // VLAs ('*' in parameter declaration), and incomplete otherwise. // See 6.7.6.2 virtual bool isComplete() const override { return dimension || isVarLen; } virtual ArrayType *clone() const override { return new ArrayType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; class QualifiedType : public Type { public: Type * parent; Type * child; QualifiedType( const Type::Qualifiers & tq, Type * parent, Type * child ); QualifiedType( const QualifiedType & tq ); virtual ~QualifiedType(); virtual QualifiedType *clone() const override { return new QualifiedType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; class ReferenceType : public Type { public: Type *base; ReferenceType( const Type::Qualifiers & tq, Type *base, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); ReferenceType( const ReferenceType & ); virtual ~ReferenceType(); Type *get_base() { return base; } void set_base( Type *newValue ) { base = newValue; } virtual int referenceDepth() const override; // Since reference types act like value types, their size is the size of the base. // This makes it simple to cast the empty tuple to a reference type, since casts that increase // the number of values are disallowed. virtual unsigned size() const override { return base->size(); } virtual TypeSubstitution genericSubstitution() const override; virtual ReferenceType *clone() const override { return new ReferenceType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; class FunctionType : public Type { public: std::list returnVals; std::list parameters; // Does the function accept a variable number of arguments following the arguments specified in the parameters list. // This could be because of // - an ellipsis in a prototype declaration // - an unprototyped declaration bool isVarArgs; FunctionType( const Type::Qualifiers & tq, bool isVarArgs, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); FunctionType( const FunctionType& ); virtual ~FunctionType(); std::list & get_returnVals() { return returnVals; } std::list & get_parameters() { return parameters; } bool get_isVarArgs() const { return isVarArgs; } void set_isVarArgs( bool newValue ) { isVarArgs = newValue; } bool isTtype() const; bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; } virtual FunctionType *clone() const override { return new FunctionType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; class ReferenceToType : public Type { public: std::list< Expression* > parameters; std::string name; bool hoistType; ReferenceToType( const Type::Qualifiers & tq, const std::string & name, const std::vector< Attribute * > & attributes ); ReferenceToType( const ReferenceToType & other ); virtual ~ReferenceToType(); const std::string & get_name() const { return name; } void set_name( std::string newValue ) { name = newValue; } std::list< Expression* >& get_parameters() { return parameters; } bool get_hoistType() const { return hoistType; } void set_hoistType( bool newValue ) { hoistType = newValue; } virtual ReferenceToType *clone() const override = 0; virtual void accept( Visitor & v ) override = 0; virtual Type *acceptMutator( Mutator & m ) override = 0; virtual void print( std::ostream & os, Indenter indent = {} ) const override; virtual void lookup( __attribute__((unused)) const std::string & name, __attribute__((unused)) std::list< Declaration* > & foundDecls ) const {} protected: virtual std::string typeString() const = 0; }; class StructInstType : public ReferenceToType { typedef ReferenceToType Parent; public: // this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree, // where the structure used in this type is actually defined StructDecl *baseStruct; StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ) : Parent( tq, name, attributes ), baseStruct( 0 ) {} StructInstType( const Type::Qualifiers & tq, StructDecl * baseStruct, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {} StructDecl *get_baseStruct() const { return baseStruct; } void set_baseStruct( StructDecl *newValue ) { baseStruct = newValue; } /// Accesses generic parameters of base struct (NULL if none such) std::list * get_baseParameters(); const std::list * get_baseParameters() const; virtual bool isComplete() const override; virtual AggregateDecl * getAggr() const override; virtual TypeSubstitution genericSubstitution() const override; /// Looks up the members of this struct named "name" and places them into "foundDecls". /// Clones declarations into "foundDecls", caller responsible for freeing void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; virtual StructInstType *clone() const override { return new StructInstType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; private: virtual std::string typeString() const override; }; class UnionInstType : public ReferenceToType { typedef ReferenceToType Parent; public: // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree, // where the union used in this type is actually defined UnionDecl *baseUnion; UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ) : Parent( tq, name, attributes ), baseUnion( 0 ) {} UnionInstType( const Type::Qualifiers & tq, UnionDecl * baseUnion, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {} UnionDecl *get_baseUnion() const { return baseUnion; } void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; } /// Accesses generic parameters of base union (NULL if none such) std::list * get_baseParameters(); const std::list * get_baseParameters() const; virtual bool isComplete() const override; virtual AggregateDecl * getAggr() const override; virtual TypeSubstitution genericSubstitution() const override; /// looks up the members of this union named "name" and places them into "foundDecls" /// Clones declarations into "foundDecls", caller responsible for freeing void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; virtual UnionInstType *clone() const override { return new UnionInstType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; private: virtual std::string typeString() const override; }; class EnumInstType : public ReferenceToType { typedef ReferenceToType Parent; public: // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree, // where the union used in this type is actually defined EnumDecl *baseEnum = nullptr; EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ) : Parent( tq, name, attributes ) {} EnumInstType( const Type::Qualifiers & tq, EnumDecl * baseEnum, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {} EnumDecl *get_baseEnum() const { return baseEnum; } void set_baseEnum( EnumDecl *newValue ) { baseEnum = newValue; } virtual bool isComplete() const override; virtual AggregateDecl * getAggr() const override; virtual EnumInstType *clone() const override { return new EnumInstType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; private: virtual std::string typeString() const override; }; class TraitInstType : public ReferenceToType { typedef ReferenceToType Parent; public: // this decl is not "owned" by the trait inst; it is merely a pointer to elsewhere in the tree, // where the trait used in this type is actually defined TraitDecl * baseTrait = nullptr; TraitInstType( const Type::Qualifiers & tq, const std::string & name, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ) : Parent( tq, name, attributes ) {} TraitInstType( const Type::Qualifiers & tq, TraitDecl * baseTrait, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); TraitInstType( const TraitInstType & other ); ~TraitInstType(); virtual bool isComplete() const override; virtual TraitInstType *clone() const override { return new TraitInstType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } private: virtual std::string typeString() const override; }; class TypeInstType : public ReferenceToType { typedef ReferenceToType Parent; public: // this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree, // where the type used here is actually defined TypeDecl *baseType; bool isFtype; TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl *baseType, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); TypeInstType( const TypeInstType & other ); ~TypeInstType(); TypeDecl *get_baseType() const { return baseType; } void set_baseType( TypeDecl *newValue ); bool get_isFtype() const { return isFtype; } void set_isFtype( bool newValue ) { isFtype = newValue; } virtual bool isComplete() const override; virtual TypeInstType *clone() const override { return new TypeInstType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; private: virtual std::string typeString() const override; }; class TupleType : public Type { public: std::list types; std::list members; TupleType( const Type::Qualifiers & tq, const std::list< Type * > & types, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); TupleType( const TupleType& ); virtual ~TupleType(); typedef std::list value_type; typedef value_type::iterator iterator; std::list & get_types() { return types; } virtual unsigned size() const override { return types.size(); }; // For now, this is entirely synthetic -- tuple types always have unnamed members. // Eventually, we may allow named tuples, in which case members should subsume types std::list & get_members() { return members; } iterator begin() { return types.begin(); } iterator end() { return types.end(); } virtual Type * getComponent( unsigned i ) override { assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d", i, size() ); return *(begin()+i); } // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness virtual TupleType *clone() const override { return new TupleType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; class TypeofType : public Type { public: Expression *expr; ///< expression to take the type of bool is_basetypeof; ///< true iff is basetypeof type TypeofType( const Type::Qualifiers & tq, Expression *expr, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); TypeofType( const Type::Qualifiers & tq, Expression *expr, bool is_basetypeof, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); TypeofType( const TypeofType& ); virtual ~TypeofType(); Expression *get_expr() const { return expr; } void set_expr( Expression *newValue ) { expr = newValue; } virtual bool isComplete() const override { assert( false ); return false; } virtual TypeofType *clone() const override { return new TypeofType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; class AttrType : public Type { public: std::string name; Expression *expr; Type *type; bool isType; AttrType( const Type::Qualifiers & tq, const std::string & name, Expression *expr, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); AttrType( const Type::Qualifiers & tq, const std::string & name, Type *type, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); AttrType( const AttrType& ); virtual ~AttrType(); const std::string & get_name() const { return name; } void set_name( const std::string & newValue ) { name = newValue; } Expression *get_expr() const { return expr; } void set_expr( Expression *newValue ) { expr = newValue; } Type *get_type() const { return type; } void set_type( Type *newValue ) { type = newValue; } bool get_isType() const { return isType; } void set_isType( bool newValue ) { isType = newValue; } virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here virtual AttrType *clone() const override { return new AttrType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; /// Represents the GCC built-in varargs type class VarArgsType : public Type { public: VarArgsType(); VarArgsType( Type::Qualifiers tq, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); virtual bool isComplete() const override{ return true; } // xxx - is this right? virtual VarArgsType *clone() const override { return new VarArgsType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; /// Represents a zero constant class ZeroType : public Type { public: ZeroType(); ZeroType( Type::Qualifiers tq, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); virtual ZeroType *clone() const override { return new ZeroType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; /// Represents a one constant class OneType : public Type { public: OneType(); OneType( Type::Qualifiers tq, const std::vector< Attribute * > & attributes = std::vector< Attribute * >() ); virtual OneType *clone() const override { return new OneType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; class GlobalScopeType : public Type { public: GlobalScopeType(); virtual GlobalScopeType *clone() const override { return new GlobalScopeType( *this ); } virtual void accept( Visitor & v ) override { v.visit( this ); } virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } virtual void print( std::ostream & os, Indenter indent = {} ) const override; }; // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //